Merge
This commit is contained in:
commit
11923f546e
@ -66,7 +66,7 @@ int JLI_GetStdArgc();
|
||||
#include <io.h>
|
||||
#define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2))
|
||||
#define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3))
|
||||
#define JLI_Snprintf _snprintf
|
||||
int JLI_Snprintf(char *buffer, size_t size, const char *format, ...);
|
||||
void JLI_CmdToArgs(char *cmdline);
|
||||
#define JLI_Lseek _lseeki64
|
||||
#else /* NIXES */
|
||||
|
@ -569,9 +569,9 @@ JLI_ParseManifest(char *jarfile, manifest_info *info)
|
||||
#ifdef O_BINARY
|
||||
| O_BINARY /* use binary mode on windows */
|
||||
#endif
|
||||
)) == -1)
|
||||
)) == -1) {
|
||||
return (-1);
|
||||
|
||||
}
|
||||
info->manifest_version = NULL;
|
||||
info->main_class = NULL;
|
||||
info->jre_version = NULL;
|
||||
@ -618,15 +618,17 @@ JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) {
|
||||
zentry entry;
|
||||
void *data = NULL;
|
||||
|
||||
fd = open(jarfile, O_RDONLY
|
||||
if ((fd = open(jarfile, O_RDONLY
|
||||
#ifdef O_LARGEFILE
|
||||
| O_LARGEFILE /* large file mode */
|
||||
#endif
|
||||
#ifdef O_BINARY
|
||||
| O_BINARY /* use binary mode on windows */
|
||||
#endif
|
||||
);
|
||||
if (fd != -1 && find_file(fd, &entry, filename) == 0) {
|
||||
)) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
if (find_file(fd, &entry, filename) == 0) {
|
||||
data = inflate_file(fd, &entry, size);
|
||||
}
|
||||
close(fd);
|
||||
@ -671,8 +673,9 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data)
|
||||
#ifdef O_BINARY
|
||||
| O_BINARY /* use binary mode on windows */
|
||||
#endif
|
||||
)) == -1)
|
||||
)) == -1) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (rc = find_file(fd, &entry, manifest_name) != 0) {
|
||||
close(fd);
|
||||
|
@ -66,11 +66,14 @@ public final class MethodFinder extends AbstractFinder<Method> {
|
||||
Signature signature = new Signature(type, name, args);
|
||||
|
||||
Method method = CACHE.get(signature);
|
||||
if (method != null) {
|
||||
boolean cached = method != null;
|
||||
if (cached && isPackageAccessible(method.getDeclaringClass())) {
|
||||
return method;
|
||||
}
|
||||
method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods()));
|
||||
CACHE.put(signature, method);
|
||||
if (!cached) {
|
||||
CACHE.put(signature, method);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,8 @@ import javax.crypto.ShortBufferException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.*;
|
||||
|
||||
import sun.security.util.KeyUtil;
|
||||
|
||||
/**
|
||||
* This class implements the Diffie-Hellman key agreement protocol between
|
||||
* any number of parties.
|
||||
@ -200,6 +202,9 @@ extends KeyAgreementSpi {
|
||||
throw new InvalidKeyException("Incompatible parameters");
|
||||
}
|
||||
|
||||
// validate the Diffie-Hellman public key
|
||||
KeyUtil.validate(dhPubKey);
|
||||
|
||||
// store the y value
|
||||
this.y = dhPubKey.getY();
|
||||
|
||||
|
@ -1000,7 +1000,6 @@ class BandStructure {
|
||||
|
||||
/** Write a constant pool reference. */
|
||||
public void putRef(Entry e) {
|
||||
assert(index != null);
|
||||
addValue(encodeRefOrNull(e, index));
|
||||
}
|
||||
public void putRef(Entry e, Index index) {
|
||||
@ -1052,6 +1051,8 @@ class BandStructure {
|
||||
|
||||
|
||||
int encodeRef(Entry e, Index ix) {
|
||||
if (ix == null)
|
||||
throw new RuntimeException("null index for " + e.stringValue());
|
||||
int coding = ix.indexOf(e);
|
||||
if (verbose > 2)
|
||||
Utils.log.fine("putRef "+coding+" => "+e);
|
||||
|
@ -1405,6 +1405,8 @@ class ConstantPool {
|
||||
|
||||
/** Index of all CP entries of a given tag and class. */
|
||||
public Index getMemberIndex(byte tag, ClassEntry classRef) {
|
||||
if (classRef == null)
|
||||
throw new RuntimeException("missing class reference for " + tagName(tag));
|
||||
if (indexByTagAndClass == null)
|
||||
indexByTagAndClass = new Index[CONSTANT_Limit][];
|
||||
Index allClasses = getIndexByTag(CONSTANT_Class);
|
||||
|
@ -109,6 +109,10 @@ class NativeUnpack {
|
||||
return (p200 == null)? null: p200._nunp;
|
||||
}
|
||||
|
||||
private synchronized long getUnpackerPtr() {
|
||||
return unpackerPtr;
|
||||
}
|
||||
|
||||
// Callback from the unpacker engine to get more data.
|
||||
private long readInputFn(ByteBuffer pbuf, long minlen) throws IOException {
|
||||
if (in == null) return 0; // nothing is readable
|
||||
|
@ -83,7 +83,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
* @param out an OutputStream
|
||||
* @exception IOException if an error is encountered.
|
||||
*/
|
||||
public void pack(JarFile in, OutputStream out) throws IOException {
|
||||
public synchronized void pack(JarFile in, OutputStream out) throws IOException {
|
||||
assert(Utils.currentInstance.get() == null);
|
||||
TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
|
||||
? null
|
||||
@ -118,7 +118,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
* @param out an OutputStream
|
||||
* @exception IOException if an error is encountered.
|
||||
*/
|
||||
public void pack(JarInputStream in, OutputStream out) throws IOException {
|
||||
public synchronized void pack(JarInputStream in, OutputStream out) throws IOException {
|
||||
assert(Utils.currentInstance.get() == null);
|
||||
TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
|
||||
TimeZone.getDefault();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -106,7 +106,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
|
||||
* @param out a JarOutputStream.
|
||||
* @exception IOException if an error is encountered.
|
||||
*/
|
||||
public void unpack(InputStream in, JarOutputStream out) throws IOException {
|
||||
public synchronized void unpack(InputStream in, JarOutputStream out) throws IOException {
|
||||
if (in == null) {
|
||||
throw new NullPointerException("null input");
|
||||
}
|
||||
@ -151,7 +151,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
|
||||
* @param out a JarOutputStream.
|
||||
* @exception IOException if an error is encountered.
|
||||
*/
|
||||
public void unpack(File in, JarOutputStream out) throws IOException {
|
||||
public synchronized void unpack(File in, JarOutputStream out) throws IOException {
|
||||
if (in == null) {
|
||||
throw new NullPointerException("null input");
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import java.util.logging.Level;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.loading.PrivateClassLoader;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* This class keeps the list of Class Loaders registered in the MBean Server.
|
||||
@ -192,6 +193,7 @@ final class ClassLoaderRepositorySupport
|
||||
final ClassLoader without,
|
||||
final ClassLoader stop)
|
||||
throws ClassNotFoundException {
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
final int size = list.length;
|
||||
for(int i=0; i<size; i++) {
|
||||
try {
|
||||
|
@ -54,6 +54,8 @@ import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import sun.reflect.misc.MethodUtil;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* This class contains the methods for performing all the tests needed to verify
|
||||
@ -526,8 +528,10 @@ public class Introspector {
|
||||
// to locate method
|
||||
readMethod = SimpleIntrospector.getReadMethod(clazz, element);
|
||||
}
|
||||
if (readMethod != null)
|
||||
return readMethod.invoke(complex);
|
||||
if (readMethod != null) {
|
||||
ReflectUtil.checkPackageAccess(readMethod.getDeclaringClass());
|
||||
return MethodUtil.invoke(readMethod, complex, new Class[0]);
|
||||
}
|
||||
|
||||
throw new AttributeNotFoundException(
|
||||
"Could not find the getter method for the property " +
|
||||
|
@ -51,6 +51,7 @@ import javax.management.MBeanPermission;
|
||||
import javax.management.MBeanRegistrationException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerDelegate;
|
||||
import javax.management.MBeanServerPermission;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.NotificationFilter;
|
||||
import javax.management.NotificationListener;
|
||||
@ -1409,6 +1410,8 @@ public final class JmxMBeanServer
|
||||
// Default is true.
|
||||
final boolean fairLock = DEFAULT_FAIR_LOCK_POLICY;
|
||||
|
||||
checkNewMBeanServerPermission();
|
||||
|
||||
// This constructor happens to disregard the value of the interceptors
|
||||
// flag - that is, it always uses the default value - false.
|
||||
// This is admitedly a bug, but we chose not to fix it for now
|
||||
@ -1494,4 +1497,11 @@ public final class JmxMBeanServer
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkNewMBeanServerPermission() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
Permission perm = new MBeanServerPermission("newMBeanServer");
|
||||
sm.checkPermission(perm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,13 @@ import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.Permission;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanPermission;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.OperationsException;
|
||||
@ -44,7 +46,7 @@ import javax.management.ReflectionException;
|
||||
import javax.management.RuntimeErrorException;
|
||||
import javax.management.RuntimeMBeanException;
|
||||
import javax.management.RuntimeOperationsException;
|
||||
|
||||
import sun.reflect.misc.ConstructorUtil;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
@ -56,7 +58,6 @@ import sun.reflect.misc.ReflectUtil;
|
||||
* @since 1.5
|
||||
*/
|
||||
public class MBeanInstantiator {
|
||||
|
||||
private final ModifiableClassLoaderRepository clr;
|
||||
// private MetaData meta = null;
|
||||
|
||||
@ -88,6 +89,7 @@ public class MBeanInstantiator {
|
||||
"Exception occurred during object instantiation");
|
||||
}
|
||||
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
try {
|
||||
if (clr == null) throw new ClassNotFoundException(className);
|
||||
theClass = clr.loadClass(className);
|
||||
@ -162,6 +164,7 @@ public class MBeanInstantiator {
|
||||
continue;
|
||||
}
|
||||
|
||||
ReflectUtil.checkPackageAccess(signature[i]);
|
||||
// Ok we do not have a primitive type ! We need to build
|
||||
// the signature of the method
|
||||
//
|
||||
@ -205,6 +208,9 @@ public class MBeanInstantiator {
|
||||
*/
|
||||
public Object instantiate(Class<?> theClass)
|
||||
throws ReflectionException, MBeanException {
|
||||
|
||||
checkMBeanPermission(theClass, null, null, "instantiate");
|
||||
|
||||
Object moi;
|
||||
|
||||
|
||||
@ -260,6 +266,9 @@ public class MBeanInstantiator {
|
||||
public Object instantiate(Class<?> theClass, Object params[],
|
||||
String signature[], ClassLoader loader)
|
||||
throws ReflectionException, MBeanException {
|
||||
|
||||
checkMBeanPermission(theClass, null, null, "instantiate");
|
||||
|
||||
// Instantiate the new object
|
||||
|
||||
// ------------------------------
|
||||
@ -407,6 +416,8 @@ public class MBeanInstantiator {
|
||||
throw new RuntimeOperationsException(new
|
||||
IllegalArgumentException(), "Null className passed in parameter");
|
||||
}
|
||||
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
Class<?> theClass;
|
||||
if (loaderName == null) {
|
||||
// Load the class using the agent class loader
|
||||
@ -619,13 +630,13 @@ public class MBeanInstantiator {
|
||||
**/
|
||||
static Class<?> loadClass(String className, ClassLoader loader)
|
||||
throws ReflectionException {
|
||||
|
||||
Class<?> theClass;
|
||||
if (className == null) {
|
||||
throw new RuntimeOperationsException(new
|
||||
IllegalArgumentException("The class name cannot be null"),
|
||||
"Exception occurred during object instantiation");
|
||||
}
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
try {
|
||||
if (loader == null)
|
||||
loader = MBeanInstantiator.class.getClassLoader();
|
||||
@ -676,6 +687,7 @@ public class MBeanInstantiator {
|
||||
// We need to load the class through the class
|
||||
// loader of the target object.
|
||||
//
|
||||
ReflectUtil.checkPackageAccess(signature[i]);
|
||||
tab[i] = Class.forName(signature[i], false, aLoader);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
@ -701,7 +713,7 @@ public class MBeanInstantiator {
|
||||
|
||||
private Constructor<?> findConstructor(Class<?> c, Class<?>[] params) {
|
||||
try {
|
||||
return c.getConstructor(params);
|
||||
return ConstructorUtil.getConstructor(c, params);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
@ -715,4 +727,18 @@ public class MBeanInstantiator {
|
||||
char.class, boolean.class})
|
||||
primitiveClasses.put(c.getName(), c);
|
||||
}
|
||||
|
||||
private static void checkMBeanPermission(Class<?> clazz,
|
||||
String member,
|
||||
ObjectName objectName,
|
||||
String actions) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (clazz != null && sm != null) {
|
||||
Permission perm = new MBeanPermission(clazz.getName(),
|
||||
member,
|
||||
objectName,
|
||||
actions);
|
||||
sm.checkPermission(perm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ReflectionException;
|
||||
import com.sun.jmx.mbeanserver.MXBeanMappingFactory;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* Base class for MBeans. There is one instance of this class for
|
||||
@ -131,6 +132,7 @@ public abstract class MBeanSupport<M>
|
||||
" is not an instance of " + mbeanInterfaceType.getName();
|
||||
throw new NotCompliantMBeanException(msg);
|
||||
}
|
||||
ReflectUtil.checkPackageAccess(mbeanInterfaceType);
|
||||
this.resource = resource;
|
||||
MBeanIntrospector<M> introspector = getMBeanIntrospector();
|
||||
this.perInterface = introspector.getPerInterface(mbeanInterfaceType);
|
||||
|
@ -39,6 +39,7 @@ import sun.awt.PeerEvent;
|
||||
import sun.awt.util.IdentityArrayList;
|
||||
import sun.awt.util.IdentityLinkedList;
|
||||
import sun.security.util.SecurityConstants;
|
||||
import java.security.AccessControlException;
|
||||
|
||||
/**
|
||||
* A Dialog is a top-level window with a title and a border
|
||||
@ -128,6 +129,8 @@ public class Dialog extends Window {
|
||||
*/
|
||||
boolean undecorated = false;
|
||||
|
||||
private transient boolean initialized = false;
|
||||
|
||||
/**
|
||||
* Modal dialogs block all input to some top-level windows.
|
||||
* Whether a particular window is blocked depends on dialog's type
|
||||
@ -671,6 +674,7 @@ public class Dialog extends Window {
|
||||
this.title = title;
|
||||
setModalityType(modalityType);
|
||||
SunToolkit.checkAndSetPolicy(this);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -722,6 +726,7 @@ public class Dialog extends Window {
|
||||
this.title = title;
|
||||
setModalityType(modalityType);
|
||||
SunToolkit.checkAndSetPolicy(this);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -851,12 +856,9 @@ public class Dialog extends Window {
|
||||
if (modalityType == type) {
|
||||
return;
|
||||
}
|
||||
if (type == ModalityType.TOOLKIT_MODAL) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
checkModalityPermission(type);
|
||||
|
||||
modalityType = type;
|
||||
modal = (modalityType != ModalityType.MODELESS);
|
||||
}
|
||||
@ -1025,6 +1027,11 @@ public class Dialog extends Window {
|
||||
*/
|
||||
@Deprecated
|
||||
public void show() {
|
||||
if (!initialized) {
|
||||
throw new IllegalStateException("The dialog component " +
|
||||
"has not been initialized properly");
|
||||
}
|
||||
|
||||
beforeFirstShow = false;
|
||||
if (!isModal()) {
|
||||
conditionalShow(null, null);
|
||||
@ -1600,18 +1607,51 @@ public class Dialog extends Window {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkModalityPermission(ModalityType mt) {
|
||||
if (mt == ModalityType.TOOLKIT_MODAL) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(
|
||||
SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream s)
|
||||
throws ClassNotFoundException, IOException, HeadlessException
|
||||
{
|
||||
GraphicsEnvironment.checkHeadless();
|
||||
s.defaultReadObject();
|
||||
|
||||
// in 1.5 or earlier modalityType was absent, so use "modal" instead
|
||||
if (modalityType == null) {
|
||||
setModal(modal);
|
||||
java.io.ObjectInputStream.GetField fields =
|
||||
s.readFields();
|
||||
|
||||
ModalityType localModalityType = (ModalityType)fields.get("modalityType", null);
|
||||
|
||||
try {
|
||||
checkModalityPermission(localModalityType);
|
||||
} catch (AccessControlException ace) {
|
||||
localModalityType = DEFAULT_MODALITY_TYPE;
|
||||
}
|
||||
|
||||
// in 1.5 or earlier modalityType was absent, so use "modal" instead
|
||||
if (localModalityType == null) {
|
||||
this.modal = fields.get("modal", false);
|
||||
setModal(modal);
|
||||
} else {
|
||||
this.modalityType = localModalityType;
|
||||
}
|
||||
|
||||
this.resizable = fields.get("resizable", true);
|
||||
this.undecorated = fields.get("undecorated", false);
|
||||
this.title = (String)fields.get("title", "");
|
||||
|
||||
blockedWindows = new IdentityArrayList<>();
|
||||
|
||||
SunToolkit.checkAndSetPolicy(this);
|
||||
|
||||
initialized = true;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -194,7 +194,8 @@ public class EventQueue {
|
||||
}
|
||||
public void removeSourceEvents(EventQueue eventQueue,
|
||||
Object source,
|
||||
boolean removeAllEvents) {
|
||||
boolean removeAllEvents)
|
||||
{
|
||||
eventQueue.removeSourceEvents(source, removeAllEvents);
|
||||
}
|
||||
public boolean noEvents(EventQueue eventQueue) {
|
||||
@ -203,6 +204,11 @@ public class EventQueue {
|
||||
public void wakeup(EventQueue eventQueue, boolean isShutdown) {
|
||||
eventQueue.wakeup(isShutdown);
|
||||
}
|
||||
public void invokeAndWait(Object source, Runnable r)
|
||||
throws InterruptedException, InvocationTargetException
|
||||
{
|
||||
EventQueue.invokeAndWait(source, r);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1245,8 +1251,14 @@ public class EventQueue {
|
||||
* @since 1.2
|
||||
*/
|
||||
public static void invokeAndWait(Runnable runnable)
|
||||
throws InterruptedException, InvocationTargetException {
|
||||
throws InterruptedException, InvocationTargetException
|
||||
{
|
||||
invokeAndWait(Toolkit.getDefaultToolkit(), runnable);
|
||||
}
|
||||
|
||||
static void invokeAndWait(Object source, Runnable runnable)
|
||||
throws InterruptedException, InvocationTargetException
|
||||
{
|
||||
if (EventQueue.isDispatchThread()) {
|
||||
throw new Error("Cannot call invokeAndWait from the event dispatcher thread");
|
||||
}
|
||||
@ -1255,8 +1267,7 @@ public class EventQueue {
|
||||
Object lock = new AWTInvocationLock();
|
||||
|
||||
InvocationEvent event =
|
||||
new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock,
|
||||
true);
|
||||
new InvocationEvent(source, runnable, lock, true);
|
||||
|
||||
synchronized (lock) {
|
||||
Toolkit.getEventQueue().postEvent(event);
|
||||
|
@ -109,12 +109,6 @@ public class TextComponent extends Component implements Accessible {
|
||||
// the background color of non-editable TextComponents.
|
||||
boolean backgroundSetByClientCode = false;
|
||||
|
||||
/**
|
||||
* True if this <code>TextComponent</code> has access
|
||||
* to the System clipboard.
|
||||
*/
|
||||
transient private boolean canAccessClipboard;
|
||||
|
||||
transient protected TextListener textListener;
|
||||
|
||||
/*
|
||||
@ -139,7 +133,6 @@ public class TextComponent extends Component implements Accessible {
|
||||
GraphicsEnvironment.checkHeadless();
|
||||
this.text = (text != null) ? text : "";
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
|
||||
checkSystemClipboardAccess();
|
||||
}
|
||||
|
||||
private void enableInputMethodsIfNecessary() {
|
||||
@ -734,17 +727,14 @@ public class TextComponent extends Component implements Accessible {
|
||||
/**
|
||||
* Assigns a valid value to the canAccessClipboard instance variable.
|
||||
*/
|
||||
private void checkSystemClipboardAccess() {
|
||||
canAccessClipboard = true;
|
||||
private boolean canAccessClipboard() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
try {
|
||||
sm.checkSystemClipboardAccess();
|
||||
}
|
||||
catch (SecurityException e) {
|
||||
canAccessClipboard = false;
|
||||
}
|
||||
}
|
||||
if (sm == null) return true;
|
||||
try {
|
||||
sm.checkSystemClipboardAccess();
|
||||
return true;
|
||||
} catch (SecurityException e) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -827,7 +817,6 @@ public class TextComponent extends Component implements Accessible {
|
||||
}
|
||||
}
|
||||
enableInputMethodsIfNecessary();
|
||||
checkSystemClipboardAccess();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1206,7 +1206,7 @@ public class Window extends Container implements Accessible {
|
||||
}
|
||||
else {
|
||||
try {
|
||||
EventQueue.invokeAndWait(action);
|
||||
EventQueue.invokeAndWait(this, action);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
System.err.println("Disposal was interrupted:");
|
||||
|
@ -1752,6 +1752,12 @@ public class ObjectInputStream
|
||||
ObjectStreamClass desc = readClassDesc(false);
|
||||
desc.checkDeserialize();
|
||||
|
||||
Class<?> cl = desc.forClass();
|
||||
if (cl == String.class || cl == Class.class
|
||||
|| cl == ObjectStreamClass.class) {
|
||||
throw new InvalidClassException("invalid class descriptor");
|
||||
}
|
||||
|
||||
Object obj;
|
||||
try {
|
||||
obj = desc.isInstantiable() ? desc.newInstance() : null;
|
||||
|
@ -63,7 +63,9 @@ import sun.reflect.generics.repository.ConstructorRepository;
|
||||
import sun.reflect.generics.scope.ClassScope;
|
||||
import sun.security.util.SecurityConstants;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Proxy;
|
||||
import sun.reflect.annotation.*;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* Instances of the class {@code Class} represent classes and
|
||||
@ -250,11 +252,11 @@ public final
|
||||
ClassLoader loader)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
if (loader == null) {
|
||||
if (sun.misc.VM.isSystemDomainLoader(loader)) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
ClassLoader ccl = ClassLoader.getCallerClassLoader();
|
||||
if (ccl != null) {
|
||||
if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
|
||||
sm.checkPermission(
|
||||
SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
@ -319,7 +321,7 @@ public final
|
||||
throws InstantiationException, IllegalAccessException
|
||||
{
|
||||
if (System.getSecurityManager() != null) {
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
|
||||
}
|
||||
return newInstance0();
|
||||
}
|
||||
@ -1299,7 +1301,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
|
||||
|
||||
// Privileged so this implementation can look at DECLARED classes,
|
||||
// something the caller might not have privilege to do. The code here
|
||||
@ -1374,7 +1376,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
return copyFields(privateGetPublicFields(null));
|
||||
}
|
||||
|
||||
@ -1425,7 +1427,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
return copyMethods(privateGetPublicMethods());
|
||||
}
|
||||
|
||||
@ -1474,7 +1476,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
return copyConstructors(privateGetDeclaredConstructors(true));
|
||||
}
|
||||
|
||||
@ -1533,7 +1535,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
Field field = getField0(name);
|
||||
if (field == null) {
|
||||
throw new NoSuchFieldException(name);
|
||||
@ -1618,7 +1620,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
Method method = getMethod0(name, parameterTypes);
|
||||
if (method == null) {
|
||||
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
|
||||
@ -1672,7 +1674,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
return getConstructor0(parameterTypes, Member.PUBLIC);
|
||||
}
|
||||
|
||||
@ -1714,7 +1716,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), false);
|
||||
return getDeclaredClasses0();
|
||||
}
|
||||
|
||||
@ -1758,7 +1760,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
return copyFields(privateGetDeclaredFields(false));
|
||||
}
|
||||
|
||||
@ -1806,7 +1808,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
return copyMethods(privateGetDeclaredMethods(false));
|
||||
}
|
||||
|
||||
@ -1851,7 +1853,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
return copyConstructors(privateGetDeclaredConstructors(false));
|
||||
}
|
||||
|
||||
@ -1895,7 +1897,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
Field field = searchFields(privateGetDeclaredFields(false), name);
|
||||
if (field == null) {
|
||||
throw new NoSuchFieldException(name);
|
||||
@ -1950,7 +1952,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
|
||||
if (method == null) {
|
||||
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
|
||||
@ -2000,7 +2002,7 @@ public final
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
return getConstructor0(parameterTypes, Member.DECLARED);
|
||||
}
|
||||
|
||||
@ -2170,18 +2172,26 @@ public final
|
||||
* <p> Default policy: allow all clients access with normal Java access
|
||||
* control.
|
||||
*/
|
||||
private void checkMemberAccess(int which, ClassLoader ccl) {
|
||||
private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) {
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
if (s != null) {
|
||||
s.checkMemberAccess(this, which);
|
||||
ClassLoader cl = getClassLoader0();
|
||||
if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
|
||||
if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
|
||||
String name = this.getName();
|
||||
int i = name.lastIndexOf('.');
|
||||
if (i != -1) {
|
||||
s.checkPackageAccess(name.substring(0, i));
|
||||
// skip the package access check on a proxy class in default proxy package
|
||||
String pkg = name.substring(0, i);
|
||||
if (!Proxy.isProxyClass(this) || !pkg.equals(ReflectUtil.PROXY_PACKAGE)) {
|
||||
s.checkPackageAccess(pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// check package access on the proxy interfaces
|
||||
if (checkProxyInterfaces && Proxy.isProxyClass(this)) {
|
||||
ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,16 @@ class DirectMethodHandle extends MethodHandle {
|
||||
private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
|
||||
super(mtype, form);
|
||||
if (!member.isResolved()) throw new InternalError();
|
||||
|
||||
if (member.getDeclaringClass().isInterface() && !member.isAbstract()) {
|
||||
// Check for corner case: invokeinterface of Object method
|
||||
MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
|
||||
m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
|
||||
if (m != null && m.isPublic()) {
|
||||
member = m;
|
||||
}
|
||||
}
|
||||
|
||||
this.member = member;
|
||||
}
|
||||
|
||||
|
@ -801,12 +801,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
static
|
||||
MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
|
||||
// Do not use this function to inject calls into system classes.
|
||||
if (hostClass == null) {
|
||||
hostClass = C_Trampoline;
|
||||
} else if (hostClass.isArray() ||
|
||||
if (hostClass == null
|
||||
|| (hostClass.isArray() ||
|
||||
hostClass.isPrimitive() ||
|
||||
hostClass.getName().startsWith("java.") ||
|
||||
hostClass.getName().startsWith("sun.")) {
|
||||
hostClass.getName().startsWith("sun."))) {
|
||||
throw new InternalError(); // does not happen, and should not anyway
|
||||
}
|
||||
// For simplicity, convert mh to a varargs-like method.
|
||||
@ -816,23 +815,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
return restoreToType(bccInvoker.bindTo(vamh), mh.type());
|
||||
}
|
||||
|
||||
// This class ("Trampoline") is known to be inside a dead-end class loader.
|
||||
// Inject all doubtful calls into this class.
|
||||
private static Class<?> C_Trampoline;
|
||||
static {
|
||||
Class<?> tramp = null;
|
||||
try {
|
||||
final int FRAME_COUNT_ARG = 1; // [0] Reflection [1] Trampoline
|
||||
java.lang.reflect.Method gcc = sun.reflect.Reflection.class.getMethod("getCallerClass", int.class);
|
||||
tramp = (Class<?>) sun.reflect.misc.MethodUtil.invoke(gcc, null, new Object[]{ FRAME_COUNT_ARG });
|
||||
if (tramp.getClassLoader() == BindCaller.class.getClassLoader())
|
||||
throw new RuntimeException(tramp.getName()+" class loader");
|
||||
} catch (Throwable ex) {
|
||||
throw new InternalError(ex);
|
||||
}
|
||||
C_Trampoline = tramp;
|
||||
}
|
||||
|
||||
private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
|
||||
Class<?> bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null);
|
||||
if (hostClass.getClassLoader() != bcc.getClassLoader())
|
||||
|
@ -393,15 +393,33 @@ class MethodHandleNatives {
|
||||
*/
|
||||
// FIXME: Replace this pattern match by an annotation @sun.reflect.CallerSensitive.
|
||||
static boolean isCallerSensitive(MemberName mem) {
|
||||
assert(mem.isInvocable());
|
||||
if (!mem.isInvocable()) return false; // fields are not caller sensitive
|
||||
Class<?> defc = mem.getDeclaringClass();
|
||||
switch (mem.getName()) {
|
||||
case "doPrivileged":
|
||||
case "doPrivilegedWithCombiner":
|
||||
return defc == java.security.AccessController.class;
|
||||
case "checkMemberAccess":
|
||||
return canBeCalledVirtual(mem, java.lang.SecurityManager.class);
|
||||
case "getUnsafe":
|
||||
return defc == sun.misc.Unsafe.class;
|
||||
case "lookup":
|
||||
return defc == java.lang.invoke.MethodHandles.class;
|
||||
case "findStatic":
|
||||
case "findVirtual":
|
||||
case "findConstructor":
|
||||
case "findSpecial":
|
||||
case "findGetter":
|
||||
case "findSetter":
|
||||
case "findStaticGetter":
|
||||
case "findStaticSetter":
|
||||
case "bind":
|
||||
case "unreflect":
|
||||
case "unreflectSpecial":
|
||||
case "unreflectConstructor":
|
||||
case "unreflectGetter":
|
||||
case "unreflectSetter":
|
||||
return defc == java.lang.invoke.MethodHandles.Lookup.class;
|
||||
case "invoke":
|
||||
return defc == java.lang.reflect.Method.class;
|
||||
case "get":
|
||||
@ -455,7 +473,7 @@ class MethodHandleNatives {
|
||||
if (defc == java.util.concurrent.atomic.AtomicReferenceFieldUpdater.class) return true;
|
||||
break;
|
||||
case "getContextClassLoader":
|
||||
return defc == java.lang.Thread.class;
|
||||
return canBeCalledVirtual(mem, java.lang.Thread.class);
|
||||
case "getPackage":
|
||||
case "getPackages":
|
||||
return defc == java.lang.Package.class;
|
||||
@ -473,9 +491,13 @@ class MethodHandleNatives {
|
||||
break;
|
||||
case "getCallerClassLoader":
|
||||
return defc == java.lang.ClassLoader.class;
|
||||
case "registerAsParallelCapable":
|
||||
return canBeCalledVirtual(mem, java.lang.ClassLoader.class);
|
||||
case "getProxyClass":
|
||||
case "newProxyInstance":
|
||||
return defc == java.lang.reflect.Proxy.class;
|
||||
case "asInterfaceInstance":
|
||||
return defc == java.lang.invoke.MethodHandleProxies.class;
|
||||
case "getBundle":
|
||||
case "clearCache":
|
||||
return defc == java.util.ResourceBundle.class;
|
||||
@ -492,4 +514,11 @@ class MethodHandleNatives {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
static boolean canBeCalledVirtual(MemberName symbolicRef, Class<?> definingClass) {
|
||||
Class<?> symbolicRefClass = symbolicRef.getDeclaringClass();
|
||||
if (symbolicRefClass == definingClass) return true;
|
||||
if (symbolicRef.isStatic() || symbolicRef.isPrivate()) return false;
|
||||
return (definingClass.isAssignableFrom(symbolicRefClass) || // Msym overrides Mdef
|
||||
symbolicRefClass.isInterface()); // Mdef implements Msym
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,12 @@
|
||||
package java.lang.invoke;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import sun.invoke.WrapperInstance;
|
||||
import java.util.ArrayList;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* This class consists exclusively of static methods that help adapt
|
||||
@ -137,6 +141,21 @@ public class MethodHandleProxies {
|
||||
<T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
|
||||
if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
|
||||
throw new IllegalArgumentException("not a public interface: "+intfc.getName());
|
||||
final MethodHandle mh;
|
||||
if (System.getSecurityManager() != null) {
|
||||
final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller
|
||||
final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
|
||||
final ClassLoader ccl = caller != null ? caller.getClassLoader() : null;
|
||||
ReflectUtil.checkProxyPackageAccess(ccl, intfc);
|
||||
mh = ccl != null ? bindCaller(target, caller) : target;
|
||||
} else {
|
||||
mh = target;
|
||||
}
|
||||
ClassLoader proxyLoader = intfc.getClassLoader();
|
||||
if (proxyLoader == null) {
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader(); // avoid use of BCP
|
||||
proxyLoader = cl != null ? cl : ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
final Method[] methods = getSingleNameMethods(intfc);
|
||||
if (methods == null)
|
||||
throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
|
||||
@ -144,31 +163,58 @@ public class MethodHandleProxies {
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
Method sm = methods[i];
|
||||
MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
|
||||
MethodHandle checkTarget = target.asType(smMT); // make throw WMT
|
||||
MethodHandle checkTarget = mh.asType(smMT); // make throw WMT
|
||||
checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
|
||||
vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
|
||||
}
|
||||
return intfc.cast(Proxy.newProxyInstance(
|
||||
intfc.getClassLoader(),
|
||||
new Class<?>[]{ intfc, WrapperInstance.class },
|
||||
new InvocationHandler() {
|
||||
private Object getArg(String name) {
|
||||
if ((Object)name == "getWrapperInstanceTarget") return target;
|
||||
if ((Object)name == "getWrapperInstanceType") return intfc;
|
||||
throw new AssertionError();
|
||||
final InvocationHandler ih = new InvocationHandler() {
|
||||
private Object getArg(String name) {
|
||||
if ((Object)name == "getWrapperInstanceTarget") return target;
|
||||
if ((Object)name == "getWrapperInstanceType") return intfc;
|
||||
throw new AssertionError();
|
||||
}
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (method.equals(methods[i]))
|
||||
return vaTargets[i].invokeExact(args);
|
||||
}
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (method.equals(methods[i]))
|
||||
return vaTargets[i].invokeExact(args);
|
||||
}
|
||||
if (method.getDeclaringClass() == WrapperInstance.class)
|
||||
return getArg(method.getName());
|
||||
if (isObjectMethod(method))
|
||||
return callObjectMethod(proxy, method, args);
|
||||
throw new InternalError("bad proxy method: "+method);
|
||||
}
|
||||
}));
|
||||
if (method.getDeclaringClass() == WrapperInstance.class)
|
||||
return getArg(method.getName());
|
||||
if (isObjectMethod(method))
|
||||
return callObjectMethod(proxy, method, args);
|
||||
throw new InternalError("bad proxy method: "+method);
|
||||
}
|
||||
};
|
||||
|
||||
final Object proxy;
|
||||
if (System.getSecurityManager() != null) {
|
||||
// sun.invoke.WrapperInstance is a restricted interface not accessible
|
||||
// by any non-null class loader.
|
||||
final ClassLoader loader = proxyLoader;
|
||||
proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
return Proxy.newProxyInstance(
|
||||
loader,
|
||||
new Class<?>[]{ intfc, WrapperInstance.class },
|
||||
ih);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
proxy = Proxy.newProxyInstance(proxyLoader,
|
||||
new Class<?>[]{ intfc, WrapperInstance.class },
|
||||
ih);
|
||||
}
|
||||
return intfc.cast(proxy);
|
||||
}
|
||||
|
||||
private static MethodHandle bindCaller(MethodHandle target, Class<?> hostClass) {
|
||||
MethodHandle cbmh = MethodHandleImpl.bindCaller(target, hostClass);
|
||||
if (target.isVarargsCollector()) {
|
||||
MethodType type = cbmh.type();
|
||||
int arity = type.parameterCount();
|
||||
return cbmh.asVarargsCollector(type.parameterType(arity-1));
|
||||
}
|
||||
return cbmh;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -598,7 +598,8 @@ public class MethodHandles {
|
||||
MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
|
||||
MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);
|
||||
checkSecurityManager(refc, method); // stack walk magic: do not refactor
|
||||
return getDirectMethod(REF_invokeStatic, refc, method);
|
||||
Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor
|
||||
return getDirectMethod(REF_invokeStatic, refc, method, callerClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -652,7 +653,8 @@ public class MethodHandles {
|
||||
byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
|
||||
MemberName method = resolveOrFail(refKind, refc, name, type);
|
||||
checkSecurityManager(refc, method); // stack walk magic: do not refactor
|
||||
return getDirectMethod(refKind, refc, method);
|
||||
Class<?> callerClass = findBoundCallerClass(method);
|
||||
return getDirectMethod(refKind, refc, method, callerClass);
|
||||
}
|
||||
private MethodHandle findVirtualForMH(String name, MethodType type) {
|
||||
// these names require special lookups because of the implicit MethodType argument
|
||||
@ -736,7 +738,8 @@ public class MethodHandles {
|
||||
Lookup specialLookup = this.in(specialCaller);
|
||||
MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type);
|
||||
checkSecurityManager(refc, method); // stack walk magic: do not refactor
|
||||
return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method);
|
||||
Class<?> callerClass = findBoundCallerClass(method);
|
||||
return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, callerClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -879,7 +882,8 @@ return mh1;
|
||||
Class<? extends Object> refc = receiver.getClass(); // may get NPE
|
||||
MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
|
||||
checkSecurityManager(refc, method); // stack walk magic: do not refactor
|
||||
MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method);
|
||||
Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor
|
||||
MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, callerClass);
|
||||
return mh.bindReceiver(receiver).setVarargs(method);
|
||||
}
|
||||
|
||||
@ -910,8 +914,9 @@ return mh1;
|
||||
if (refKind == REF_invokeSpecial)
|
||||
refKind = REF_invokeVirtual;
|
||||
assert(method.isMethod());
|
||||
Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor
|
||||
Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this;
|
||||
return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method);
|
||||
return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -940,8 +945,9 @@ return mh1;
|
||||
Lookup specialLookup = this.in(specialCaller);
|
||||
MemberName method = new MemberName(m, true);
|
||||
assert(method.isMethod());
|
||||
Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor
|
||||
// ignore m.isAccessible: this is a new kind of access
|
||||
return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method);
|
||||
return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1039,8 +1045,30 @@ return mh1;
|
||||
throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find my trustable caller class if m is a caller sensitive method.
|
||||
* If this lookup object has private access, then the caller class is the lookupClass.
|
||||
* Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual).
|
||||
* This is the same caller class as is used by checkSecurityManager.
|
||||
* This function performs stack walk magic: do not refactor it.
|
||||
*/
|
||||
Class<?> findBoundCallerClass(MemberName m) {
|
||||
Class<?> callerClass = null;
|
||||
if (MethodHandleNatives.isCallerSensitive(m)) {
|
||||
// Do not refactor this to a more "logical" place, since it is stack walk magic.
|
||||
// Note that this is the same expression as in Step 2 below in checkSecurityManager.
|
||||
callerClass = ((allowedModes & PRIVATE) != 0
|
||||
? lookupClass // for strong access modes, no extra check
|
||||
// next line does stack walk magic; do not refactor:
|
||||
: getCallerClassAtEntryPoint(true));
|
||||
}
|
||||
return callerClass;
|
||||
}
|
||||
/**
|
||||
* Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>.
|
||||
* Determines a trustable caller class to compare with refc, the symbolic reference class.
|
||||
* If this lookup object has private access, then the caller class is the lookupClass.
|
||||
* Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual).
|
||||
* This function performs stack walk magic: do not refactor it.
|
||||
*/
|
||||
void checkSecurityManager(Class<?> refc, MemberName m) {
|
||||
@ -1195,22 +1223,22 @@ return mh1;
|
||||
return mh.viewAsType(narrowType);
|
||||
}
|
||||
|
||||
private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method) throws IllegalAccessException {
|
||||
private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
|
||||
return getDirectMethodCommon(refKind, refc, method,
|
||||
(refKind == REF_invokeSpecial ||
|
||||
(MethodHandleNatives.refKindHasReceiver(refKind) &&
|
||||
restrictProtectedReceiver(method))));
|
||||
restrictProtectedReceiver(method))), callerClass);
|
||||
}
|
||||
private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method) throws IllegalAccessException {
|
||||
return getDirectMethodCommon(refKind, refc, method, false);
|
||||
private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
|
||||
return getDirectMethodCommon(refKind, refc, method, false, callerClass);
|
||||
}
|
||||
private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
|
||||
boolean doRestrict) throws IllegalAccessException {
|
||||
boolean doRestrict, Class<?> callerClass) throws IllegalAccessException {
|
||||
checkMethod(refKind, refc, method);
|
||||
if (method.isMethodHandleInvoke())
|
||||
return fakeMethodHandleInvoke(method);
|
||||
MethodHandle mh = DirectMethodHandle.make(refc, method);
|
||||
mh = maybeBindCaller(method, mh);
|
||||
mh = maybeBindCaller(method, mh, callerClass);
|
||||
mh = mh.setVarargs(method);
|
||||
if (doRestrict)
|
||||
mh = restrictReceiver(method, mh, lookupClass());
|
||||
@ -1219,12 +1247,14 @@ return mh1;
|
||||
private MethodHandle fakeMethodHandleInvoke(MemberName method) {
|
||||
return throwException(method.getReturnType(), UnsupportedOperationException.class);
|
||||
}
|
||||
private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh) throws IllegalAccessException {
|
||||
private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh,
|
||||
Class<?> callerClass)
|
||||
throws IllegalAccessException {
|
||||
if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method))
|
||||
return mh;
|
||||
Class<?> hostClass = lookupClass;
|
||||
if ((allowedModes & PRIVATE) == 0) // caller must use full-power lookup
|
||||
hostClass = null;
|
||||
hostClass = callerClass; // callerClass came from a security manager style stack walk
|
||||
MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass);
|
||||
// Note: caller will apply varargs after this step happens.
|
||||
return cbmh;
|
||||
@ -1262,7 +1292,7 @@ return mh1;
|
||||
} else if (MethodHandleNatives.refKindIsMethod(refKind)) {
|
||||
MemberName method = (resolved != null) ? resolved
|
||||
: resolveOrFail(refKind, defc, name, (MethodType) type);
|
||||
return getDirectMethod(refKind, defc, method);
|
||||
return getDirectMethod(refKind, defc, method, lookupClass);
|
||||
} else if (refKind == REF_newInvokeSpecial) {
|
||||
assert(name == null || name.equals("<init>"));
|
||||
MemberName ctor = (resolved != null) ? resolved
|
||||
|
@ -802,20 +802,20 @@ public class ManagementFactory {
|
||||
*/
|
||||
private static void addMXBean(final MBeanServer mbs, final PlatformManagedObject pmo) {
|
||||
// Make DynamicMBean out of MXBean by wrapping it with a StandardMBean
|
||||
final DynamicMBean dmbean;
|
||||
if (pmo instanceof DynamicMBean) {
|
||||
dmbean = DynamicMBean.class.cast(pmo);
|
||||
} else if (pmo instanceof NotificationEmitter) {
|
||||
dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo);
|
||||
} else {
|
||||
dmbean = new StandardMBean(pmo, null, true);
|
||||
}
|
||||
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws InstanceAlreadyExistsException,
|
||||
MBeanRegistrationException,
|
||||
NotCompliantMBeanException {
|
||||
final DynamicMBean dmbean;
|
||||
if (pmo instanceof DynamicMBean) {
|
||||
dmbean = DynamicMBean.class.cast(pmo);
|
||||
} else if (pmo instanceof NotificationEmitter) {
|
||||
dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo);
|
||||
} else {
|
||||
dmbean = new StandardMBean(pmo, null, true);
|
||||
}
|
||||
|
||||
mbs.registerMBean(dmbean, pmo.getObjectName());
|
||||
return null;
|
||||
}
|
||||
|
@ -27,6 +27,9 @@ package java.lang.reflect;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permission;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -36,6 +39,9 @@ import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.WeakHashMap;
|
||||
import sun.misc.ProxyGenerator;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
/**
|
||||
* {@code Proxy} provides static methods for creating dynamic proxy
|
||||
@ -265,9 +271,69 @@ public class Proxy implements java.io.Serializable {
|
||||
* @param h the invocation handler for this proxy instance
|
||||
*/
|
||||
protected Proxy(InvocationHandler h) {
|
||||
doNewInstanceCheck();
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
private static class ProxyAccessHelper {
|
||||
// The permission is implementation specific.
|
||||
static final Permission PROXY_PERMISSION =
|
||||
new ReflectPermission("proxyConstructorNewInstance");
|
||||
// These system properties are defined to provide a short-term
|
||||
// workaround if customers need to disable the new security checks.
|
||||
static final boolean allowNewInstance;
|
||||
static final boolean allowNullLoader;
|
||||
static {
|
||||
allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance");
|
||||
allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader");
|
||||
}
|
||||
|
||||
private static boolean getBooleanProperty(final String key) {
|
||||
String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
return System.getProperty(key);
|
||||
}
|
||||
});
|
||||
return Boolean.valueOf(s);
|
||||
}
|
||||
|
||||
static boolean needsNewInstanceCheck(Class<?> proxyClass) {
|
||||
if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) {
|
||||
// all proxy interfaces are public
|
||||
return false;
|
||||
}
|
||||
for (Class<?> intf : proxyClass.getInterfaces()) {
|
||||
if (!Modifier.isPublic(intf.getModifiers())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Access check on a proxy class that implements any non-public interface.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists, and
|
||||
* the caller does not have the permission.
|
||||
*/
|
||||
private void doNewInstanceCheck() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
Class<?> proxyClass = this.getClass();
|
||||
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) {
|
||||
try {
|
||||
sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION);
|
||||
} catch (SecurityException e) {
|
||||
throw new SecurityException("Not allowed to construct a Proxy "
|
||||
+ "instance that implements a non-public interface", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code java.lang.Class} object for a proxy class
|
||||
* given a class loader and an array of interfaces. The proxy class
|
||||
@ -346,6 +412,51 @@ public class Proxy implements java.io.Serializable {
|
||||
Class<?>... interfaces)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
|
||||
}
|
||||
|
||||
private static void checkProxyLoader(ClassLoader ccl,
|
||||
ClassLoader loader)
|
||||
{
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
if (loader == null && ccl != null) {
|
||||
if (!ProxyAccessHelper.allowNullLoader) {
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a proxy class (caller-sensitive).
|
||||
*
|
||||
* To define a proxy class, it performs the access checks as in
|
||||
* Class.forName (VM will invoke ClassLoader.checkPackageAccess):
|
||||
* 1. "getClassLoader" permission check if loader == null
|
||||
* 2. checkPackageAccess on the interfaces it implements
|
||||
*
|
||||
* To get a constructor and new instance of a proxy class, it performs
|
||||
* the package access check on the interfaces it implements
|
||||
* as in Class.getConstructor.
|
||||
*
|
||||
* If an interface is non-public, the proxy class must be defined by
|
||||
* the defining loader of the interface. If the caller's class loader
|
||||
* is not the same as the defining loader of the interface, the VM
|
||||
* will throw IllegalAccessError when the generated proxy class is
|
||||
* being defined via the defineClass0 method.
|
||||
*/
|
||||
private static Class<?> getProxyClass0(ClassLoader loader,
|
||||
Class<?>... interfaces) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller
|
||||
final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
|
||||
final ClassLoader ccl = caller.getClassLoader();
|
||||
checkProxyLoader(ccl, loader);
|
||||
ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
|
||||
}
|
||||
|
||||
if (interfaces.length > 65535) {
|
||||
throw new IllegalArgumentException("interface limit exceeded");
|
||||
}
|
||||
@ -497,8 +608,9 @@ public class Proxy implements java.io.Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
if (proxyPkg == null) { // if no non-public proxy interfaces,
|
||||
proxyPkg = ""; // use the unnamed package
|
||||
if (proxyPkg == null) {
|
||||
// if no non-public proxy interfaces, use com.sun.proxy package
|
||||
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
|
||||
}
|
||||
|
||||
{
|
||||
@ -598,22 +710,46 @@ public class Proxy implements java.io.Serializable {
|
||||
/*
|
||||
* Look up or generate the designated proxy class.
|
||||
*/
|
||||
Class<?> cl = getProxyClass(loader, interfaces);
|
||||
Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
|
||||
|
||||
/*
|
||||
* Invoke its constructor with the designated invocation handler.
|
||||
*/
|
||||
try {
|
||||
Constructor<?> cons = cl.getConstructor(constructorParams);
|
||||
return cons.newInstance(new Object[] { h });
|
||||
} catch (NoSuchMethodException |
|
||||
IllegalAccessException |
|
||||
InstantiationException |
|
||||
InvocationTargetException e) {
|
||||
final Constructor<?> cons = cl.getConstructor(constructorParams);
|
||||
final InvocationHandler ih = h;
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
|
||||
// create proxy instance with doPrivilege as the proxy class may
|
||||
// implement non-public interfaces that requires a special permission
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
return newInstance(cons, ih);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return newInstance(cons, ih);
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new InternalError(e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
|
||||
try {
|
||||
return cons.newInstance(new Object[] {h} );
|
||||
} catch (IllegalAccessException | InstantiationException e) {
|
||||
throw new InternalError(e.toString(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable t = e.getCause();
|
||||
if (t instanceof RuntimeException) {
|
||||
throw (RuntimeException) t;
|
||||
} else {
|
||||
throw new InternalError(t.toString(), t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if and only if the specified class was dynamically
|
||||
* generated to be a proxy class using the {@code getProxyClass}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,9 +24,12 @@
|
||||
*/
|
||||
package java.net;
|
||||
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.ObjectStreamField;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -46,23 +49,105 @@ import java.io.InvalidObjectException;
|
||||
* @see java.net.ServerSocket
|
||||
* @since 1.4
|
||||
*/
|
||||
public class InetSocketAddress extends SocketAddress {
|
||||
/* The hostname of the Socket Address
|
||||
* @serial
|
||||
*/
|
||||
private String hostname = null;
|
||||
/* The IP address of the Socket Address
|
||||
* @serial
|
||||
*/
|
||||
private InetAddress addr = null;
|
||||
/* The port number of the Socket Address
|
||||
* @serial
|
||||
*/
|
||||
private int port;
|
||||
public class InetSocketAddress
|
||||
extends SocketAddress
|
||||
{
|
||||
// Private implementation class pointed to by all public methods.
|
||||
private static class InetSocketAddressHolder {
|
||||
// The hostname of the Socket Address
|
||||
private String hostname;
|
||||
// The IP address of the Socket Address
|
||||
private InetAddress addr;
|
||||
// The port number of the Socket Address
|
||||
private int port;
|
||||
|
||||
private InetSocketAddressHolder(String hostname, InetAddress addr, int port) {
|
||||
this.hostname = hostname;
|
||||
this.addr = addr;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
private int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
private InetAddress getAddress() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
private String getHostName() {
|
||||
if (hostname != null)
|
||||
return hostname;
|
||||
if (addr != null)
|
||||
return addr.getHostName();
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getHostString() {
|
||||
if (hostname != null)
|
||||
return hostname;
|
||||
if (addr != null) {
|
||||
if (addr.hostName != null)
|
||||
return addr.hostName;
|
||||
else
|
||||
return addr.getHostAddress();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isUnresolved() {
|
||||
return addr == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isUnresolved()) {
|
||||
return hostname + ":" + port;
|
||||
} else {
|
||||
return addr.toString() + ":" + port;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if (obj == null || !(obj instanceof InetSocketAddressHolder))
|
||||
return false;
|
||||
InetSocketAddressHolder that = (InetSocketAddressHolder)obj;
|
||||
boolean sameIP;
|
||||
if (addr != null)
|
||||
sameIP = addr.equals(that.addr);
|
||||
else if (hostname != null)
|
||||
sameIP = (that.addr == null) &&
|
||||
hostname.equalsIgnoreCase(that.hostname);
|
||||
else
|
||||
sameIP = (that.addr == null) && (that.hostname == null);
|
||||
return sameIP && (port == that.port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
if (addr != null)
|
||||
return addr.hashCode() + port;
|
||||
if (hostname != null)
|
||||
return hostname.toLowerCase().hashCode() + port;
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
private final transient InetSocketAddressHolder holder;
|
||||
|
||||
private static final long serialVersionUID = 5076001401234631237L;
|
||||
|
||||
private InetSocketAddress() {
|
||||
private static int checkPort(int port) {
|
||||
if (port < 0 || port > 0xFFFF)
|
||||
throw new IllegalArgumentException("port out of range:" + port);
|
||||
return port;
|
||||
}
|
||||
|
||||
private static String checkHost(String hostname) {
|
||||
if (hostname == null)
|
||||
throw new IllegalArgumentException("hostname can't be null");
|
||||
return hostname;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,14 +182,10 @@ public class InetSocketAddress extends SocketAddress {
|
||||
* range of valid port values.
|
||||
*/
|
||||
public InetSocketAddress(InetAddress addr, int port) {
|
||||
if (port < 0 || port > 0xFFFF) {
|
||||
throw new IllegalArgumentException("port out of range:" + port);
|
||||
}
|
||||
this.port = port;
|
||||
if (addr == null)
|
||||
this.addr = InetAddress.anyLocalAddress();
|
||||
else
|
||||
this.addr = addr;
|
||||
holder = new InetSocketAddressHolder(
|
||||
null,
|
||||
addr == null ? InetAddress.anyLocalAddress() : addr,
|
||||
checkPort(port));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,19 +213,20 @@ public class InetSocketAddress extends SocketAddress {
|
||||
* @see #isUnresolved()
|
||||
*/
|
||||
public InetSocketAddress(String hostname, int port) {
|
||||
if (port < 0 || port > 0xFFFF) {
|
||||
throw new IllegalArgumentException("port out of range:" + port);
|
||||
}
|
||||
if (hostname == null) {
|
||||
throw new IllegalArgumentException("hostname can't be null");
|
||||
}
|
||||
checkHost(hostname);
|
||||
InetAddress addr = null;
|
||||
String host = null;
|
||||
try {
|
||||
addr = InetAddress.getByName(hostname);
|
||||
} catch(UnknownHostException e) {
|
||||
this.hostname = hostname;
|
||||
addr = null;
|
||||
host = hostname;
|
||||
}
|
||||
this.port = port;
|
||||
holder = new InetSocketAddressHolder(host, addr, checkPort(port));
|
||||
}
|
||||
|
||||
// private constructor for creating unresolved instances
|
||||
private InetSocketAddress(int port, String hostname) {
|
||||
holder = new InetSocketAddressHolder(hostname, null, port);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,31 +251,67 @@ public class InetSocketAddress extends SocketAddress {
|
||||
* @since 1.5
|
||||
*/
|
||||
public static InetSocketAddress createUnresolved(String host, int port) {
|
||||
if (port < 0 || port > 0xFFFF) {
|
||||
throw new IllegalArgumentException("port out of range:" + port);
|
||||
}
|
||||
if (host == null) {
|
||||
throw new IllegalArgumentException("hostname can't be null");
|
||||
}
|
||||
InetSocketAddress s = new InetSocketAddress();
|
||||
s.port = port;
|
||||
s.hostname = host;
|
||||
s.addr = null;
|
||||
return s;
|
||||
return new InetSocketAddress(checkPort(port), checkHost(host));
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream s)
|
||||
throws IOException, ClassNotFoundException {
|
||||
s.defaultReadObject();
|
||||
/**
|
||||
* @serialField hostname String
|
||||
* @serialField addr InetAddress
|
||||
* @serialField port int
|
||||
*/
|
||||
private static final ObjectStreamField[] serialPersistentFields = {
|
||||
new ObjectStreamField("hostname", String.class),
|
||||
new ObjectStreamField("addr", InetAddress.class),
|
||||
new ObjectStreamField("port", int.class)};
|
||||
|
||||
private void writeObject(ObjectOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
// Don't call defaultWriteObject()
|
||||
ObjectOutputStream.PutField pfields = out.putFields();
|
||||
pfields.put("hostname", holder.hostname);
|
||||
pfields.put("addr", holder.addr);
|
||||
pfields.put("port", holder.port);
|
||||
out.writeFields();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
// Don't call defaultReadObject()
|
||||
ObjectInputStream.GetField oisFields = in.readFields();
|
||||
final String oisHostname = (String)oisFields.get("hostname", null);
|
||||
final InetAddress oisAddr = (InetAddress)oisFields.get("addr", null);
|
||||
final int oisPort = oisFields.get("port", -1);
|
||||
|
||||
// Check that our invariants are satisfied
|
||||
if (port < 0 || port > 0xFFFF) {
|
||||
throw new InvalidObjectException("port out of range:" + port);
|
||||
}
|
||||
|
||||
if (hostname == null && addr == null) {
|
||||
checkPort(oisPort);
|
||||
if (oisHostname == null && oisAddr == null)
|
||||
throw new InvalidObjectException("hostname and addr " +
|
||||
"can't both be null");
|
||||
|
||||
InetSocketAddressHolder h = new InetSocketAddressHolder(oisHostname,
|
||||
oisAddr,
|
||||
oisPort);
|
||||
UNSAFE.putObject(this, FIELDS_OFFSET, h);
|
||||
}
|
||||
|
||||
private void readObjectNoData()
|
||||
throws ObjectStreamException
|
||||
{
|
||||
throw new InvalidObjectException("Stream data required");
|
||||
}
|
||||
|
||||
private static final long FIELDS_OFFSET;
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
static {
|
||||
try {
|
||||
sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
|
||||
FIELDS_OFFSET = unsafe.objectFieldOffset(
|
||||
InetSocketAddress.class.getDeclaredField("holder"));
|
||||
UNSAFE = unsafe;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,7 +321,7 @@ public class InetSocketAddress extends SocketAddress {
|
||||
* @return the port number.
|
||||
*/
|
||||
public final int getPort() {
|
||||
return port;
|
||||
return holder.getPort();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,7 +331,7 @@ public class InetSocketAddress extends SocketAddress {
|
||||
* @return the InetAdress or <code>null</code> if it is unresolved.
|
||||
*/
|
||||
public final InetAddress getAddress() {
|
||||
return addr;
|
||||
return holder.getAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,31 +342,19 @@ public class InetSocketAddress extends SocketAddress {
|
||||
* @return the hostname part of the address.
|
||||
*/
|
||||
public final String getHostName() {
|
||||
if (hostname != null)
|
||||
return hostname;
|
||||
if (addr != null)
|
||||
return addr.getHostName();
|
||||
return null;
|
||||
return holder.getHostName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hostname, or the String form of the address if it
|
||||
* doesn't have a hostname (it was created using a literal).
|
||||
* This has the benefit of <b>not</b> attemptimg a reverse lookup.
|
||||
* This has the benefit of <b>not</b> attempting a reverse lookup.
|
||||
*
|
||||
* @return the hostname, or String representation of the address.
|
||||
* @since 1.7
|
||||
*/
|
||||
public final String getHostString() {
|
||||
if (hostname != null)
|
||||
return hostname;
|
||||
if (addr != null) {
|
||||
if (addr.hostName != null)
|
||||
return addr.hostName;
|
||||
else
|
||||
return addr.getHostAddress();
|
||||
}
|
||||
return null;
|
||||
return holder.getHostString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -258,7 +364,7 @@ public class InetSocketAddress extends SocketAddress {
|
||||
* an <code>InetAddress</code>.
|
||||
*/
|
||||
public final boolean isUnresolved() {
|
||||
return addr == null;
|
||||
return holder.isUnresolved();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -269,12 +375,9 @@ public class InetSocketAddress extends SocketAddress {
|
||||
*
|
||||
* @return a string representation of this object.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isUnresolved()) {
|
||||
return hostname + ":" + port;
|
||||
} else {
|
||||
return addr.toString() + ":" + port;
|
||||
}
|
||||
return holder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,19 +400,11 @@ public class InetSocketAddress extends SocketAddress {
|
||||
* <code>false</code> otherwise.
|
||||
* @see java.net.InetAddress#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if (obj == null || !(obj instanceof InetSocketAddress))
|
||||
return false;
|
||||
InetSocketAddress sockAddr = (InetSocketAddress) obj;
|
||||
boolean sameIP = false;
|
||||
if (this.addr != null)
|
||||
sameIP = this.addr.equals(sockAddr.addr);
|
||||
else if (this.hostname != null)
|
||||
sameIP = (sockAddr.addr == null) &&
|
||||
this.hostname.equalsIgnoreCase(sockAddr.hostname);
|
||||
else
|
||||
sameIP = (sockAddr.addr == null) && (sockAddr.hostname == null);
|
||||
return sameIP && (this.port == sockAddr.port);
|
||||
return holder.equals(((InetSocketAddress) obj).holder);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -317,11 +412,8 @@ public class InetSocketAddress extends SocketAddress {
|
||||
*
|
||||
* @return a hash code value for this socket address.
|
||||
*/
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
if (addr != null)
|
||||
return addr.hashCode() + port;
|
||||
if (hostname != null)
|
||||
return hostname.toLowerCase().hashCode() + port;
|
||||
return port;
|
||||
return holder.hashCode();
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,10 @@
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.util.concurrent.locks.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -491,10 +493,15 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
* policy limiting the number of threads. Even though it is not
|
||||
* treated as an error, failure to create threads may result in
|
||||
* new tasks being rejected or existing ones remaining stuck in
|
||||
* the queue. On the other hand, no special precautions exist to
|
||||
* handle OutOfMemoryErrors that might be thrown while trying to
|
||||
* create threads, since there is generally no recourse from
|
||||
* within this class.
|
||||
* the queue.
|
||||
*
|
||||
* We go further and preserve pool invariants even in the face of
|
||||
* errors such as OutOfMemoryError, that might be thrown while
|
||||
* trying to create threads. Such errors are rather common due to
|
||||
* the need to allocate a native stack in Thread#start, and users
|
||||
* will want to perform clean pool shutdown to clean up. There
|
||||
* will likely be enough memory available for the cleanup code to
|
||||
* complete without encountering yet another OutOfMemoryError.
|
||||
*/
|
||||
private volatile ThreadFactory threadFactory;
|
||||
|
||||
@ -568,9 +575,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
* task execution. This protects against interrupts that are
|
||||
* intended to wake up a worker thread waiting for a task from
|
||||
* instead interrupting a task being run. We implement a simple
|
||||
* non-reentrant mutual exclusion lock rather than use ReentrantLock
|
||||
* because we do not want worker tasks to be able to reacquire the
|
||||
* lock when they invoke pool control methods like setCorePoolSize.
|
||||
* non-reentrant mutual exclusion lock rather than use
|
||||
* ReentrantLock because we do not want worker tasks to be able to
|
||||
* reacquire the lock when they invoke pool control methods like
|
||||
* setCorePoolSize. Additionally, to suppress interrupts until
|
||||
* the thread actually starts running tasks, we initialize lock
|
||||
* state to a negative value, and clear it upon start (in
|
||||
* runWorker).
|
||||
*/
|
||||
private final class Worker
|
||||
extends AbstractQueuedSynchronizer
|
||||
@ -594,6 +605,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
* @param firstTask the first task (null if none)
|
||||
*/
|
||||
Worker(Runnable firstTask) {
|
||||
setState(-1); // inhibit interrupts until runWorker
|
||||
this.firstTask = firstTask;
|
||||
this.thread = getThreadFactory().newThread(this);
|
||||
}
|
||||
@ -609,7 +621,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
// The value 1 represents the locked state.
|
||||
|
||||
protected boolean isHeldExclusively() {
|
||||
return getState() == 1;
|
||||
return getState() != 0;
|
||||
}
|
||||
|
||||
protected boolean tryAcquire(int unused) {
|
||||
@ -630,6 +642,16 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
public boolean tryLock() { return tryAcquire(1); }
|
||||
public void unlock() { release(1); }
|
||||
public boolean isLocked() { return isHeldExclusively(); }
|
||||
|
||||
void interruptIfStarted() {
|
||||
Thread t;
|
||||
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
|
||||
try {
|
||||
t.interrupt();
|
||||
} catch (SecurityException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -728,12 +750,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
final ReentrantLock mainLock = this.mainLock;
|
||||
mainLock.lock();
|
||||
try {
|
||||
for (Worker w : workers) {
|
||||
try {
|
||||
w.thread.interrupt();
|
||||
} catch (SecurityException ignore) {
|
||||
}
|
||||
}
|
||||
for (Worker w : workers)
|
||||
w.interruptIfStarted();
|
||||
} finally {
|
||||
mainLock.unlock();
|
||||
}
|
||||
@ -790,19 +808,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
|
||||
private static final boolean ONLY_ONE = true;
|
||||
|
||||
/**
|
||||
* Ensures that unless the pool is stopping, the current thread
|
||||
* does not have its interrupt set. This requires a double-check
|
||||
* of state in case the interrupt was cleared concurrently with a
|
||||
* shutdownNow -- if so, the interrupt is re-enabled.
|
||||
*/
|
||||
private void clearInterruptsForTaskRun() {
|
||||
if (runStateLessThan(ctl.get(), STOP) &&
|
||||
Thread.interrupted() &&
|
||||
runStateAtLeast(ctl.get(), STOP))
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
/*
|
||||
* Misc utilities, most of which are also exported to
|
||||
* ScheduledThreadPoolExecutor
|
||||
@ -862,12 +867,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
* Checks if a new worker can be added with respect to current
|
||||
* pool state and the given bound (either core or maximum). If so,
|
||||
* the worker count is adjusted accordingly, and, if possible, a
|
||||
* new worker is created and started running firstTask as its
|
||||
* new worker is created and started, running firstTask as its
|
||||
* first task. This method returns false if the pool is stopped or
|
||||
* eligible to shut down. It also returns false if the thread
|
||||
* factory fails to create a thread when asked, which requires a
|
||||
* backout of workerCount, and a recheck for termination, in case
|
||||
* the existence of this worker was holding up termination.
|
||||
* factory fails to create a thread when asked. If the thread
|
||||
* creation fails, either due to the thread factory returning
|
||||
* null, or due to an exception (typically OutOfMemoryError in
|
||||
* Thread#start), we roll back cleanly.
|
||||
*
|
||||
* @param firstTask the task the new thread should run first (or
|
||||
* null if none). Workers are created with an initial first task
|
||||
@ -910,46 +916,65 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
}
|
||||
}
|
||||
|
||||
Worker w = new Worker(firstTask);
|
||||
Thread t = w.thread;
|
||||
boolean workerStarted = false;
|
||||
boolean workerAdded = false;
|
||||
Worker w = null;
|
||||
try {
|
||||
final ReentrantLock mainLock = this.mainLock;
|
||||
w = new Worker(firstTask);
|
||||
final Thread t = w.thread;
|
||||
if (t != null) {
|
||||
mainLock.lock();
|
||||
try {
|
||||
// Recheck while holding lock.
|
||||
// Back out on ThreadFactory failure or if
|
||||
// shut down before lock acquired.
|
||||
int c = ctl.get();
|
||||
int rs = runStateOf(c);
|
||||
|
||||
if (rs < SHUTDOWN ||
|
||||
(rs == SHUTDOWN && firstTask == null)) {
|
||||
if (t.isAlive()) // precheck that t is startable
|
||||
throw new IllegalThreadStateException();
|
||||
workers.add(w);
|
||||
int s = workers.size();
|
||||
if (s > largestPoolSize)
|
||||
largestPoolSize = s;
|
||||
workerAdded = true;
|
||||
}
|
||||
} finally {
|
||||
mainLock.unlock();
|
||||
}
|
||||
if (workerAdded) {
|
||||
t.start();
|
||||
workerStarted = true;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (! workerStarted)
|
||||
addWorkerFailed(w);
|
||||
}
|
||||
return workerStarted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rolls back the worker thread creation.
|
||||
* - removes worker from workers, if present
|
||||
* - decrements worker count
|
||||
* - rechecks for termination, in case the existence of this
|
||||
* worker was holding up termination
|
||||
*/
|
||||
private void addWorkerFailed(Worker w) {
|
||||
final ReentrantLock mainLock = this.mainLock;
|
||||
mainLock.lock();
|
||||
try {
|
||||
// Recheck while holding lock.
|
||||
// Back out on ThreadFactory failure or if
|
||||
// shut down before lock acquired.
|
||||
int c = ctl.get();
|
||||
int rs = runStateOf(c);
|
||||
|
||||
if (t == null ||
|
||||
(rs >= SHUTDOWN &&
|
||||
! (rs == SHUTDOWN &&
|
||||
firstTask == null))) {
|
||||
decrementWorkerCount();
|
||||
tryTerminate();
|
||||
return false;
|
||||
}
|
||||
|
||||
workers.add(w);
|
||||
|
||||
int s = workers.size();
|
||||
if (s > largestPoolSize)
|
||||
largestPoolSize = s;
|
||||
if (w != null)
|
||||
workers.remove(w);
|
||||
decrementWorkerCount();
|
||||
tryTerminate();
|
||||
} finally {
|
||||
mainLock.unlock();
|
||||
}
|
||||
|
||||
t.start();
|
||||
// It is possible (but unlikely) for a thread to have been
|
||||
// added to workers, but not yet started, during transition to
|
||||
// STOP, which could result in a rare missed interrupt,
|
||||
// because Thread.interrupt is not guaranteed to have any effect
|
||||
// on a non-yet-started Thread (see Thread#interrupt).
|
||||
if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted())
|
||||
t.interrupt();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1096,15 +1121,25 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
* @param w the worker
|
||||
*/
|
||||
final void runWorker(Worker w) {
|
||||
Thread wt = Thread.currentThread();
|
||||
Runnable task = w.firstTask;
|
||||
w.firstTask = null;
|
||||
w.unlock(); // allow interrupts
|
||||
boolean completedAbruptly = true;
|
||||
try {
|
||||
while (task != null || (task = getTask()) != null) {
|
||||
w.lock();
|
||||
clearInterruptsForTaskRun();
|
||||
// If pool is stopping, ensure thread is interrupted;
|
||||
// if not, ensure thread is not interrupted. This
|
||||
// requires a recheck in second case to deal with
|
||||
// shutdownNow race while clearing interrupt
|
||||
if ((runStateAtLeast(ctl.get(), STOP) ||
|
||||
(Thread.interrupted() &&
|
||||
runStateAtLeast(ctl.get(), STOP))) &&
|
||||
!wt.isInterrupted())
|
||||
wt.interrupt();
|
||||
try {
|
||||
beforeExecute(w.thread, task);
|
||||
beforeExecute(wt, task);
|
||||
Throwable thrown = null;
|
||||
try {
|
||||
task.run();
|
||||
@ -2064,3 +2099,4 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ import java.security.CodeSigner;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import sun.misc.IOUtils;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.security.util.ManifestEntryVerifier;
|
||||
import sun.misc.SharedSecrets;
|
||||
@ -334,6 +335,9 @@ class JarFile extends ZipFile {
|
||||
if (names != null) {
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
JarEntry e = getJarEntry(names[i]);
|
||||
if (e == null) {
|
||||
throw new JarException("corrupted jar file");
|
||||
}
|
||||
if (!e.isDirectory()) {
|
||||
if (mev == null) {
|
||||
mev = new ManifestEntryVerifier
|
||||
@ -353,6 +357,10 @@ class JarFile extends ZipFile {
|
||||
// treat the jar file as being unsigned
|
||||
jv = null;
|
||||
verify = false;
|
||||
if (JarVerifier.debug != null) {
|
||||
JarVerifier.debug.println("jarfile parsing error!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// if after initializing the verifier we have nothing
|
||||
@ -380,11 +388,9 @@ class JarFile extends ZipFile {
|
||||
* META-INF files.
|
||||
*/
|
||||
private byte[] getBytes(ZipEntry ze) throws IOException {
|
||||
byte[] b = new byte[(int)ze.getSize()];
|
||||
try (DataInputStream is = new DataInputStream(super.getInputStream(ze))) {
|
||||
is.readFully(b, 0, b.length);
|
||||
try (InputStream is = super.getInputStream(ze)) {
|
||||
return IOUtils.readFully(is, (int)ze.getSize(), true);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -540,11 +546,7 @@ class JarFile extends ZipFile {
|
||||
if (!isKnownNotToHaveSpecialAttributes()) {
|
||||
JarEntry manEntry = getManEntry();
|
||||
if (manEntry != null) {
|
||||
byte[] b = new byte[(int)manEntry.getSize()];
|
||||
try (DataInputStream dis = new DataInputStream(
|
||||
super.getInputStream(manEntry))) {
|
||||
dis.readFully(b, 0, b.length);
|
||||
}
|
||||
byte[] b = getBytes(manEntry);
|
||||
if (match(CLASSPATH_CHARS, b, CLASSPATH_LASTOCC, CLASSPATH_OPTOSFT))
|
||||
hasClassPathAttribute = true;
|
||||
if (match(PROFILE_CHARS, b, PROFILE_LASTOCC, PROFILE_OPTOSFT))
|
||||
|
@ -24,6 +24,10 @@
|
||||
*/
|
||||
|
||||
package java.util.logging;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
@ -59,7 +63,6 @@ import java.util.ResourceBundle;
|
||||
*/
|
||||
|
||||
public class Level implements java.io.Serializable {
|
||||
private static java.util.ArrayList<Level> known = new java.util.ArrayList<>();
|
||||
private static String defaultBundle = "sun.util.logging.resources.logging";
|
||||
|
||||
/**
|
||||
@ -77,6 +80,9 @@ public class Level implements java.io.Serializable {
|
||||
*/
|
||||
private final String resourceBundleName;
|
||||
|
||||
// localized level name
|
||||
private String localizedLevelName;
|
||||
|
||||
/**
|
||||
* OFF is a special level that can be used to turn off logging.
|
||||
* This level is initialized to <CODE>Integer.MAX_VALUE</CODE>.
|
||||
@ -202,9 +208,8 @@ public class Level implements java.io.Serializable {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.resourceBundleName = resourceBundleName;
|
||||
synchronized (Level.class) {
|
||||
known.add(this);
|
||||
}
|
||||
this.localizedLevelName = resourceBundleName == null ? name : null;
|
||||
KnownLevel.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,12 +241,76 @@ public class Level implements java.io.Serializable {
|
||||
* @return localized name
|
||||
*/
|
||||
public String getLocalizedName() {
|
||||
return getLocalizedLevelName();
|
||||
}
|
||||
|
||||
// package-private getLevelName() is used by the implementation
|
||||
// instead of getName() to avoid calling the subclass's version
|
||||
final String getLevelName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
final synchronized String getLocalizedLevelName() {
|
||||
if (localizedLevelName != null) {
|
||||
return localizedLevelName;
|
||||
}
|
||||
|
||||
try {
|
||||
ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName);
|
||||
return rb.getString(name);
|
||||
localizedLevelName = rb.getString(name);
|
||||
} catch (Exception ex) {
|
||||
return name;
|
||||
localizedLevelName = name;
|
||||
}
|
||||
return localizedLevelName;
|
||||
}
|
||||
|
||||
// Returns a mirrored Level object that matches the given name as
|
||||
// specified in the Level.parse method. Returns null if not found.
|
||||
//
|
||||
// It returns the same Level object as the one returned by Level.parse
|
||||
// method if the given name is a non-localized name or integer.
|
||||
//
|
||||
// If the name is a localized name, findLevel and parse method may
|
||||
// return a different level value if there is a custom Level subclass
|
||||
// that overrides Level.getLocalizedName() to return a different string
|
||||
// than what's returned by the default implementation.
|
||||
//
|
||||
static Level findLevel(String name) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
KnownLevel level;
|
||||
|
||||
// Look for a known Level with the given non-localized name.
|
||||
level = KnownLevel.findByName(name);
|
||||
if (level != null) {
|
||||
return level.mirroredLevel;
|
||||
}
|
||||
|
||||
// Now, check if the given name is an integer. If so,
|
||||
// first look for a Level with the given value and then
|
||||
// if necessary create one.
|
||||
try {
|
||||
int x = Integer.parseInt(name);
|
||||
level = KnownLevel.findByValue(x);
|
||||
if (level == null) {
|
||||
// add new Level
|
||||
Level levelObject = new Level(name, x);
|
||||
level = KnownLevel.findByValue(x);
|
||||
}
|
||||
return level.mirroredLevel;
|
||||
} catch (NumberFormatException ex) {
|
||||
// Not an integer.
|
||||
// Drop through.
|
||||
}
|
||||
|
||||
level = KnownLevel.findByLocalizedLevelName(name);
|
||||
if (level != null) {
|
||||
return level.mirroredLevel;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -268,21 +337,15 @@ public class Level implements java.io.Serializable {
|
||||
// Serialization magic to prevent "doppelgangers".
|
||||
// This is a performance optimization.
|
||||
private Object readResolve() {
|
||||
synchronized (Level.class) {
|
||||
for (int i = 0; i < known.size(); i++) {
|
||||
Level other = known.get(i);
|
||||
if (this.name.equals(other.name) && this.value == other.value
|
||||
&& (this.resourceBundleName == other.resourceBundleName ||
|
||||
(this.resourceBundleName != null &&
|
||||
this.resourceBundleName.equals(other.resourceBundleName)))) {
|
||||
return other;
|
||||
}
|
||||
}
|
||||
// Woops. Whoever sent us this object knows
|
||||
// about a new log level. Add it to our list.
|
||||
known.add(this);
|
||||
return this;
|
||||
KnownLevel o = KnownLevel.matches(this);
|
||||
if (o != null) {
|
||||
return o.levelObject;
|
||||
}
|
||||
|
||||
// Woops. Whoever sent us this object knows
|
||||
// about a new log level. Add it to our list.
|
||||
Level level = new Level(this.name, this.value, this.resourceBundleName);
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -296,6 +359,7 @@ public class Level implements java.io.Serializable {
|
||||
* <li> "SEVERE"
|
||||
* <li> "1000"
|
||||
* </ul>
|
||||
*
|
||||
* @param name string to be parsed
|
||||
* @throws NullPointerException if the name is null
|
||||
* @throws IllegalArgumentException if the value is not valid.
|
||||
@ -315,12 +379,12 @@ public class Level implements java.io.Serializable {
|
||||
// Check that name is not null.
|
||||
name.length();
|
||||
|
||||
KnownLevel level;
|
||||
|
||||
// Look for a known Level with the given non-localized name.
|
||||
for (int i = 0; i < known.size(); i++) {
|
||||
Level l = known.get(i);
|
||||
if (name.equals(l.name)) {
|
||||
return l;
|
||||
}
|
||||
level = KnownLevel.findByName(name);
|
||||
if (level != null) {
|
||||
return level.levelObject;
|
||||
}
|
||||
|
||||
// Now, check if the given name is an integer. If so,
|
||||
@ -328,14 +392,13 @@ public class Level implements java.io.Serializable {
|
||||
// if necessary create one.
|
||||
try {
|
||||
int x = Integer.parseInt(name);
|
||||
for (int i = 0; i < known.size(); i++) {
|
||||
Level l = known.get(i);
|
||||
if (l.value == x) {
|
||||
return l;
|
||||
}
|
||||
level = KnownLevel.findByValue(x);
|
||||
if (level == null) {
|
||||
// add new Level
|
||||
Level levelObject = new Level(name, x);
|
||||
level = KnownLevel.findByValue(x);
|
||||
}
|
||||
// Create a new Level.
|
||||
return new Level(name, x);
|
||||
return level.levelObject;
|
||||
} catch (NumberFormatException ex) {
|
||||
// Not an integer.
|
||||
// Drop through.
|
||||
@ -344,11 +407,9 @@ public class Level implements java.io.Serializable {
|
||||
// Finally, look for a known level with the given localized name,
|
||||
// in the current default locale.
|
||||
// This is relatively expensive, but not excessively so.
|
||||
for (int i = 0; i < known.size(); i++) {
|
||||
Level l = known.get(i);
|
||||
if (name.equals(l.getLocalizedName())) {
|
||||
return l;
|
||||
}
|
||||
level = KnownLevel.findByLocalizedName(name);
|
||||
if (level != null) {
|
||||
return level.levelObject;
|
||||
}
|
||||
|
||||
// OK, we've tried everything and failed
|
||||
@ -375,4 +436,124 @@ public class Level implements java.io.Serializable {
|
||||
public int hashCode() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
// KnownLevel class maintains the global list of all known levels.
|
||||
// The API allows multiple custom Level instances of the same name/value
|
||||
// be created. This class provides convenient methods to find a level
|
||||
// by a given name, by a given value, or by a given localized name.
|
||||
//
|
||||
// KnownLevel wraps the following Level objects:
|
||||
// 1. levelObject: standard Level object or custom Level object
|
||||
// 2. mirroredLevel: Level object representing the level specified in the
|
||||
// logging configuration.
|
||||
//
|
||||
// Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods
|
||||
// are non-final but the name and resource bundle name are parameters to
|
||||
// the Level constructor. Use the mirroredLevel object instead of the
|
||||
// levelObject to prevent the logging framework to execute foreign code
|
||||
// implemented by untrusted Level subclass.
|
||||
//
|
||||
// Implementation Notes:
|
||||
// If Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods
|
||||
// were final, the following KnownLevel implementation can be removed.
|
||||
// Future API change should take this into consideration.
|
||||
static final class KnownLevel {
|
||||
private static Map<String, List<KnownLevel>> nameToLevels = new HashMap<>();
|
||||
private static Map<Integer, List<KnownLevel>> intToLevels = new HashMap<>();
|
||||
final Level levelObject; // instance of Level class or Level subclass
|
||||
final Level mirroredLevel; // instance of Level class
|
||||
KnownLevel(Level l) {
|
||||
this.levelObject = l;
|
||||
if (l.getClass() == Level.class) {
|
||||
this.mirroredLevel = l;
|
||||
} else {
|
||||
this.mirroredLevel = new Level(l.name, l.value, l.resourceBundleName);
|
||||
}
|
||||
}
|
||||
|
||||
static synchronized void add(Level l) {
|
||||
// the mirroredLevel object is always added to the list
|
||||
// before the custom Level instance
|
||||
KnownLevel o = new KnownLevel(l);
|
||||
List<KnownLevel> list = nameToLevels.get(l.name);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
nameToLevels.put(l.name, list);
|
||||
}
|
||||
list.add(o);
|
||||
|
||||
list = intToLevels.get(l.value);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
intToLevels.put(l.value, list);
|
||||
}
|
||||
list.add(o);
|
||||
}
|
||||
|
||||
// Returns a KnownLevel with the given non-localized name.
|
||||
static synchronized KnownLevel findByName(String name) {
|
||||
List<KnownLevel> list = nameToLevels.get(name);
|
||||
if (list != null) {
|
||||
return list.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Returns a KnownLevel with the given value.
|
||||
static synchronized KnownLevel findByValue(int value) {
|
||||
List<KnownLevel> list = intToLevels.get(value);
|
||||
if (list != null) {
|
||||
return list.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Returns a KnownLevel with the given localized name matching
|
||||
// by calling the Level.getLocalizedLevelName() method (i.e. found
|
||||
// from the resourceBundle associated with the Level object).
|
||||
// This method does not call Level.getLocalizedName() that may
|
||||
// be overridden in a subclass implementation
|
||||
static synchronized KnownLevel findByLocalizedLevelName(String name) {
|
||||
for (List<KnownLevel> levels : nameToLevels.values()) {
|
||||
for (KnownLevel l : levels) {
|
||||
String lname = l.levelObject.getLocalizedLevelName();
|
||||
if (name.equals(lname)) {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Returns a KnownLevel with the given localized name matching
|
||||
// by calling the Level.getLocalizedName() method
|
||||
static synchronized KnownLevel findByLocalizedName(String name) {
|
||||
for (List<KnownLevel> levels : nameToLevels.values()) {
|
||||
for (KnownLevel l : levels) {
|
||||
String lname = l.levelObject.getLocalizedName();
|
||||
if (name.equals(lname)) {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static synchronized KnownLevel matches(Level l) {
|
||||
List<KnownLevel> list = nameToLevels.get(l.name);
|
||||
if (list != null) {
|
||||
for (KnownLevel level : list) {
|
||||
Level other = level.mirroredLevel;
|
||||
if (l.value == other.value &&
|
||||
(l.resourceBundleName == other.resourceBundleName ||
|
||||
(l.resourceBundleName != null &&
|
||||
l.resourceBundleName.equals(other.resourceBundleName)))) {
|
||||
return level;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,6 +35,10 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.net.URL;
|
||||
import sun.misc.JavaAWTAccess;
|
||||
import sun.misc.SharedSecrets;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* There is a single global LogManager object that is used to
|
||||
@ -152,10 +156,9 @@ public class LogManager {
|
||||
// count to allow for cases where the same listener is registered many times.
|
||||
private final Map<Object,Integer> listenerMap = new HashMap<>();
|
||||
|
||||
// Table of named Loggers that maps names to Loggers.
|
||||
private Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();
|
||||
// Tree of named Loggers
|
||||
private LogNode root = new LogNode(null);
|
||||
// LoggerContext for system loggers and user loggers
|
||||
private final LoggerContext systemContext = new SystemLoggerContext();
|
||||
private final LoggerContext userContext = new LoggerContext();
|
||||
private Logger rootLogger;
|
||||
|
||||
// Have we done the primordial reading of the configuration file?
|
||||
@ -194,11 +197,12 @@ public class LogManager {
|
||||
// Create and retain Logger for the root of the namespace.
|
||||
manager.rootLogger = manager.new RootLogger();
|
||||
manager.addLogger(manager.rootLogger);
|
||||
manager.systemContext.addLocalLogger(manager.rootLogger);
|
||||
|
||||
// Adding the global Logger. Doing so in the Logger.<clinit>
|
||||
// would deadlock with the LogManager.<clinit>.
|
||||
Logger.getGlobal().setLogManager(manager);
|
||||
manager.addLogger(Logger.getGlobal());
|
||||
Logger.global.setLogManager(manager);
|
||||
manager.addLogger(Logger.global);
|
||||
|
||||
// We don't call readConfiguration() here, as we may be running
|
||||
// very early in the JVM startup sequence. Instead readConfiguration
|
||||
@ -276,14 +280,14 @@ public class LogManager {
|
||||
return;
|
||||
}
|
||||
readPrimordialConfiguration = true;
|
||||
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||
public Object run() throws Exception {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws Exception {
|
||||
readConfiguration();
|
||||
|
||||
// Platform loggers begin to delegate to java.util.logging.Logger
|
||||
sun.util.logging.PlatformLogger.redirectPlatformLoggers();
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@ -375,20 +379,68 @@ public class LogManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Package-level method.
|
||||
// Returns the LoggerContext for the user code (i.e. application or AppContext).
|
||||
// Loggers are isolated from each AppContext.
|
||||
private LoggerContext getUserContext() {
|
||||
LoggerContext context = null;
|
||||
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
JavaAWTAccess javaAwtAccess = SharedSecrets.getJavaAWTAccess();
|
||||
if (sm != null && javaAwtAccess != null) {
|
||||
synchronized (javaAwtAccess) {
|
||||
// AppContext.getAppContext() returns the system AppContext if called
|
||||
// from a system thread but Logger.getLogger might be called from
|
||||
// an applet code. Instead, find the AppContext of the applet code
|
||||
// from the execution stack.
|
||||
Object ecx = javaAwtAccess.getExecutionContext();
|
||||
if (ecx == null) {
|
||||
// fall back to AppContext.getAppContext()
|
||||
ecx = javaAwtAccess.getContext();
|
||||
}
|
||||
context = (LoggerContext)javaAwtAccess.get(ecx, LoggerContext.class);
|
||||
if (context == null) {
|
||||
if (javaAwtAccess.isMainAppContext()) {
|
||||
context = userContext;
|
||||
} else {
|
||||
context = new LoggerContext();
|
||||
// during initialization, rootLogger is null when
|
||||
// instantiating itself RootLogger
|
||||
if (manager.rootLogger != null)
|
||||
context.addLocalLogger(manager.rootLogger);
|
||||
}
|
||||
javaAwtAccess.put(ecx, LoggerContext.class, context);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context = userContext;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
private List<LoggerContext> contexts() {
|
||||
List<LoggerContext> cxs = new ArrayList<>();
|
||||
cxs.add(systemContext);
|
||||
cxs.add(getUserContext());
|
||||
return cxs;
|
||||
}
|
||||
|
||||
// Find or create a specified logger instance. If a logger has
|
||||
// already been created with the given name it is returned.
|
||||
// Otherwise a new logger instance is created and registered
|
||||
// in the LogManager global namespace.
|
||||
|
||||
// This method will always return a non-null Logger object.
|
||||
// Synchronization is not required here. All synchronization for
|
||||
// adding a new Logger object is handled by addLogger().
|
||||
Logger demandLogger(String name) {
|
||||
//
|
||||
// This method must delegate to the LogManager implementation to
|
||||
// add a new Logger or return the one that has been added previously
|
||||
// as a LogManager subclass may override the addLogger, getLogger,
|
||||
// readConfiguration, and other methods.
|
||||
Logger demandLogger(String name, String resourceBundleName) {
|
||||
Logger result = getLogger(name);
|
||||
if (result == null) {
|
||||
// only allocate the new logger once
|
||||
Logger newLogger = new Logger(name, null);
|
||||
Logger newLogger = new Logger(name, resourceBundleName);
|
||||
do {
|
||||
if (addLogger(newLogger)) {
|
||||
// We successfully added the new Logger that we
|
||||
@ -413,24 +465,249 @@ public class LogManager {
|
||||
return result;
|
||||
}
|
||||
|
||||
// If logger.getUseParentHandlers() returns 'true' and any of the logger's
|
||||
// parents have levels or handlers defined, make sure they are instantiated.
|
||||
private void processParentHandlers(Logger logger, String name) {
|
||||
int ix = 1;
|
||||
for (;;) {
|
||||
int ix2 = name.indexOf(".", ix);
|
||||
if (ix2 < 0) {
|
||||
break;
|
||||
}
|
||||
String pname = name.substring(0,ix2);
|
||||
Logger demandSystemLogger(String name, String resourceBundleName) {
|
||||
// Add a system logger in the system context's namespace
|
||||
final Logger sysLogger = systemContext.demandLogger(name, resourceBundleName);
|
||||
|
||||
if (getProperty(pname+".level") != null ||
|
||||
getProperty(pname+".handlers") != null) {
|
||||
// This pname has a level/handlers definition.
|
||||
// Make sure it exists.
|
||||
demandLogger(pname);
|
||||
// Add the system logger to the LogManager's namespace if not exist
|
||||
// so that there is only one single logger of the given name.
|
||||
// System loggers are visible to applications unless a logger of
|
||||
// the same name has been added.
|
||||
Logger logger;
|
||||
do {
|
||||
// First attempt to call addLogger instead of getLogger
|
||||
// This would avoid potential bug in custom LogManager.getLogger
|
||||
// implementation that adds a logger if does not exist
|
||||
if (addLogger(sysLogger)) {
|
||||
// successfully added the new system logger
|
||||
logger = sysLogger;
|
||||
} else {
|
||||
logger = getLogger(name);
|
||||
}
|
||||
ix = ix2+1;
|
||||
} while (logger == null);
|
||||
|
||||
// LogManager will set the sysLogger's handlers via LogManager.addLogger method.
|
||||
if (logger != sysLogger && sysLogger.getHandlers().length == 0) {
|
||||
// if logger already exists but handlers not set
|
||||
final Logger l = logger;
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
for (Handler hdl : l.getHandlers()) {
|
||||
sysLogger.addHandler(hdl);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
return sysLogger;
|
||||
}
|
||||
|
||||
// LoggerContext maintains the logger namespace per context.
|
||||
// The default LogManager implementation has one system context and user
|
||||
// context. The system context is used to maintain the namespace for
|
||||
// all system loggers and is queried by the system code. If a system logger
|
||||
// doesn't exist in the user context, it'll also be added to the user context.
|
||||
// The user context is queried by the user code and all other loggers are
|
||||
// added in the user context.
|
||||
static class LoggerContext {
|
||||
// Table of named Loggers that maps names to Loggers.
|
||||
private final Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();
|
||||
// Tree of named Loggers
|
||||
private final LogNode root;
|
||||
|
||||
private LoggerContext() {
|
||||
this.root = new LogNode(null, this);
|
||||
}
|
||||
|
||||
Logger demandLogger(String name, String resourceBundleName) {
|
||||
// a LogManager subclass may have its own implementation to add and
|
||||
// get a Logger. So delegate to the LogManager to do the work.
|
||||
return manager.demandLogger(name, resourceBundleName);
|
||||
}
|
||||
|
||||
synchronized Logger findLogger(String name) {
|
||||
LoggerWeakRef ref = namedLoggers.get(name);
|
||||
if (ref == null) {
|
||||
return null;
|
||||
}
|
||||
Logger logger = ref.get();
|
||||
if (logger == null) {
|
||||
// Hashtable holds stale weak reference
|
||||
// to a logger which has been GC-ed.
|
||||
removeLogger(name);
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
||||
// Add a logger to this context. This method will only set its level
|
||||
// and process parent loggers. It doesn't set its handlers.
|
||||
synchronized boolean addLocalLogger(Logger logger) {
|
||||
final String name = logger.getName();
|
||||
if (name == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
// cleanup some Loggers that have been GC'ed
|
||||
manager.drainLoggerRefQueueBounded();
|
||||
|
||||
LoggerWeakRef ref = namedLoggers.get(name);
|
||||
if (ref != null) {
|
||||
if (ref.get() == null) {
|
||||
// It's possible that the Logger was GC'ed after the
|
||||
// drainLoggerRefQueueBounded() call above so allow
|
||||
// a new one to be registered.
|
||||
removeLogger(name);
|
||||
} else {
|
||||
// We already have a registered logger with the given name.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We're adding a new logger.
|
||||
// Note that we are creating a weak reference here.
|
||||
ref = manager.new LoggerWeakRef(logger);
|
||||
namedLoggers.put(name, ref);
|
||||
|
||||
// Apply any initial level defined for the new logger.
|
||||
Level level = manager.getLevelProperty(name + ".level", null);
|
||||
if (level != null) {
|
||||
doSetLevel(logger, level);
|
||||
}
|
||||
|
||||
// instantiation of the handler is done in the LogManager.addLogger
|
||||
// implementation as a handler class may be only visible to LogManager
|
||||
// subclass for the custom log manager case
|
||||
processParentHandlers(logger, name);
|
||||
|
||||
// Find the new node and its parent.
|
||||
LogNode node = getNode(name);
|
||||
node.loggerRef = ref;
|
||||
Logger parent = null;
|
||||
LogNode nodep = node.parent;
|
||||
while (nodep != null) {
|
||||
LoggerWeakRef nodeRef = nodep.loggerRef;
|
||||
if (nodeRef != null) {
|
||||
parent = nodeRef.get();
|
||||
if (parent != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
nodep = nodep.parent;
|
||||
}
|
||||
|
||||
if (parent != null) {
|
||||
doSetParent(logger, parent);
|
||||
}
|
||||
// Walk over the children and tell them we are their new parent.
|
||||
node.walkAndSetParent(logger);
|
||||
// new LogNode is ready so tell the LoggerWeakRef about it
|
||||
ref.setNode(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
void removeLogger(String name) {
|
||||
namedLoggers.remove(name);
|
||||
}
|
||||
|
||||
synchronized Enumeration<String> getLoggerNames() {
|
||||
return namedLoggers.keys();
|
||||
}
|
||||
|
||||
// If logger.getUseParentHandlers() returns 'true' and any of the logger's
|
||||
// parents have levels or handlers defined, make sure they are instantiated.
|
||||
private void processParentHandlers(final Logger logger, final String name) {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
if (logger != manager.rootLogger) {
|
||||
boolean useParent = manager.getBooleanProperty(name + ".useParentHandlers", true);
|
||||
if (!useParent) {
|
||||
logger.setUseParentHandlers(false);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
int ix = 1;
|
||||
for (;;) {
|
||||
int ix2 = name.indexOf(".", ix);
|
||||
if (ix2 < 0) {
|
||||
break;
|
||||
}
|
||||
String pname = name.substring(0, ix2);
|
||||
if (manager.getProperty(pname + ".level") != null ||
|
||||
manager.getProperty(pname + ".handlers") != null) {
|
||||
// This pname has a level/handlers definition.
|
||||
// Make sure it exists.
|
||||
demandLogger(pname, null);
|
||||
}
|
||||
ix = ix2+1;
|
||||
}
|
||||
}
|
||||
|
||||
// Gets a node in our tree of logger nodes.
|
||||
// If necessary, create it.
|
||||
LogNode getNode(String name) {
|
||||
if (name == null || name.equals("")) {
|
||||
return root;
|
||||
}
|
||||
LogNode node = root;
|
||||
while (name.length() > 0) {
|
||||
int ix = name.indexOf(".");
|
||||
String head;
|
||||
if (ix > 0) {
|
||||
head = name.substring(0, ix);
|
||||
name = name.substring(ix + 1);
|
||||
} else {
|
||||
head = name;
|
||||
name = "";
|
||||
}
|
||||
if (node.children == null) {
|
||||
node.children = new HashMap<>();
|
||||
}
|
||||
LogNode child = node.children.get(head);
|
||||
if (child == null) {
|
||||
child = new LogNode(node, this);
|
||||
node.children.put(head, child);
|
||||
}
|
||||
node = child;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
static class SystemLoggerContext extends LoggerContext {
|
||||
// Add a system logger in the system context's namespace as well as
|
||||
// in the LogManager's namespace if not exist so that there is only
|
||||
// one single logger of the given name. System loggers are visible
|
||||
// to applications unless a logger of the same name has been added.
|
||||
Logger demandLogger(String name, String resourceBundleName) {
|
||||
Logger result = findLogger(name);
|
||||
if (result == null) {
|
||||
// only allocate the new system logger once
|
||||
Logger newLogger = new Logger(name, resourceBundleName);
|
||||
do {
|
||||
if (addLocalLogger(newLogger)) {
|
||||
// We successfully added the new Logger that we
|
||||
// created above so return it without refetching.
|
||||
result = newLogger;
|
||||
} else {
|
||||
// We didn't add the new Logger that we created above
|
||||
// because another thread added a Logger with the same
|
||||
// name after our null check above and before our call
|
||||
// to addLogger(). We have to refetch the Logger because
|
||||
// addLogger() returns a boolean instead of the Logger
|
||||
// reference itself. However, if the thread that created
|
||||
// the other Logger is not holding a strong reference to
|
||||
// the other Logger, then it is possible for the other
|
||||
// Logger to be GC'ed after we saw it in addLogger() and
|
||||
// before we can refetch it. If it has been GC'ed then
|
||||
// we'll just loop around and try again.
|
||||
result = findLogger(name);
|
||||
}
|
||||
} while (result == null);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -439,32 +716,27 @@ public class LogManager {
|
||||
// be made based on the logging configuration, which can
|
||||
// only be modified by trusted code.
|
||||
private void loadLoggerHandlers(final Logger logger, final String name,
|
||||
final String handlersPropertyName) {
|
||||
final String handlersPropertyName)
|
||||
{
|
||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
if (logger != rootLogger) {
|
||||
boolean useParent = getBooleanProperty(name + ".useParentHandlers", true);
|
||||
if (!useParent) {
|
||||
logger.setUseParentHandlers(false);
|
||||
}
|
||||
}
|
||||
|
||||
String names[] = parseClassNames(handlersPropertyName);
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
String word = names[i];
|
||||
try {
|
||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
|
||||
Handler hdl = (Handler) clz.newInstance();
|
||||
try {
|
||||
// Check if there is a property defining the
|
||||
// this handler's level.
|
||||
String levs = getProperty(word + ".level");
|
||||
if (levs != null) {
|
||||
hdl.setLevel(Level.parse(levs));
|
||||
Handler hdl = (Handler) clz.newInstance();
|
||||
// Check if there is a property defining the
|
||||
// this handler's level.
|
||||
String levs = getProperty(word + ".level");
|
||||
if (levs != null) {
|
||||
Level l = Level.findLevel(levs);
|
||||
if (l != null) {
|
||||
hdl.setLevel(l);
|
||||
} else {
|
||||
// Probably a bad level. Drop through.
|
||||
System.err.println("Can't set level for " + word);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.err.println("Can't set level for " + word);
|
||||
// Probably a bad level. Drop through.
|
||||
}
|
||||
// Add this Handler to the logger
|
||||
logger.addHandler(hdl);
|
||||
@ -475,7 +747,8 @@ public class LogManager {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -520,7 +793,7 @@ public class LogManager {
|
||||
if (node != null) {
|
||||
// if we have a LogNode, then we were a named Logger
|
||||
// so clear namedLoggers weak ref to us
|
||||
manager.namedLoggers.remove(name);
|
||||
node.context.removeLogger(name);
|
||||
name = null; // clear our ref to the Logger's name
|
||||
|
||||
node.loggerRef = null; // clear LogNode's weak ref to us
|
||||
@ -609,73 +882,22 @@ public class LogManager {
|
||||
* false if a logger of that name already exists.
|
||||
* @exception NullPointerException if the logger name is null.
|
||||
*/
|
||||
public synchronized boolean addLogger(Logger logger) {
|
||||
public boolean addLogger(Logger logger) {
|
||||
final String name = logger.getName();
|
||||
if (name == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
// cleanup some Loggers that have been GC'ed
|
||||
drainLoggerRefQueueBounded();
|
||||
|
||||
LoggerWeakRef ref = namedLoggers.get(name);
|
||||
if (ref != null) {
|
||||
if (ref.get() == null) {
|
||||
// It's possible that the Logger was GC'ed after the
|
||||
// drainLoggerRefQueueBounded() call above so allow
|
||||
// a new one to be registered.
|
||||
namedLoggers.remove(name);
|
||||
} else {
|
||||
// We already have a registered logger with the given name.
|
||||
return false;
|
||||
}
|
||||
LoggerContext cx = getUserContext();
|
||||
if (cx.addLocalLogger(logger)) {
|
||||
// Do we have a per logger handler too?
|
||||
// Note: this will add a 200ms penalty
|
||||
loadLoggerHandlers(logger, name, name + ".handlers");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We're adding a new logger.
|
||||
// Note that we are creating a weak reference here.
|
||||
ref = new LoggerWeakRef(logger);
|
||||
namedLoggers.put(name, ref);
|
||||
|
||||
// Apply any initial level defined for the new logger.
|
||||
Level level = getLevelProperty(name+".level", null);
|
||||
if (level != null) {
|
||||
doSetLevel(logger, level);
|
||||
}
|
||||
|
||||
// Do we have a per logger handler too?
|
||||
// Note: this will add a 200ms penalty
|
||||
loadLoggerHandlers(logger, name, name+".handlers");
|
||||
processParentHandlers(logger, name);
|
||||
|
||||
// Find the new node and its parent.
|
||||
LogNode node = findNode(name);
|
||||
node.loggerRef = ref;
|
||||
Logger parent = null;
|
||||
LogNode nodep = node.parent;
|
||||
while (nodep != null) {
|
||||
LoggerWeakRef nodeRef = nodep.loggerRef;
|
||||
if (nodeRef != null) {
|
||||
parent = nodeRef.get();
|
||||
if (parent != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
nodep = nodep.parent;
|
||||
}
|
||||
|
||||
if (parent != null) {
|
||||
doSetParent(logger, parent);
|
||||
}
|
||||
// Walk over the children and tell them we are their new parent.
|
||||
node.walkAndSetParent(logger);
|
||||
|
||||
// new LogNode is ready so tell the LoggerWeakRef about it
|
||||
ref.setNode(node);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Private method to set a level on a logger.
|
||||
// If necessary, we raise privilege before doing the call.
|
||||
private static void doSetLevel(final Logger logger, final Level level) {
|
||||
@ -694,8 +916,6 @@ public class LogManager {
|
||||
}});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Private method to set a parent on a logger.
|
||||
// If necessary, we raise privilege before doing the setParent call.
|
||||
private static void doSetParent(final Logger logger, final Logger parent) {
|
||||
@ -714,36 +934,6 @@ public class LogManager {
|
||||
}});
|
||||
}
|
||||
|
||||
// Find a node in our tree of logger nodes.
|
||||
// If necessary, create it.
|
||||
private LogNode findNode(String name) {
|
||||
if (name == null || name.equals("")) {
|
||||
return root;
|
||||
}
|
||||
LogNode node = root;
|
||||
while (name.length() > 0) {
|
||||
int ix = name.indexOf(".");
|
||||
String head;
|
||||
if (ix > 0) {
|
||||
head = name.substring(0,ix);
|
||||
name = name.substring(ix+1);
|
||||
} else {
|
||||
head = name;
|
||||
name = "";
|
||||
}
|
||||
if (node.children == null) {
|
||||
node.children = new HashMap<>();
|
||||
}
|
||||
LogNode child = node.children.get(head);
|
||||
if (child == null) {
|
||||
child = new LogNode(node);
|
||||
node.children.put(head, child);
|
||||
}
|
||||
node = child;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to find a named logger.
|
||||
* <p>
|
||||
@ -759,18 +949,8 @@ public class LogManager {
|
||||
* @param name name of the logger
|
||||
* @return matching logger or null if none is found
|
||||
*/
|
||||
public synchronized Logger getLogger(String name) {
|
||||
LoggerWeakRef ref = namedLoggers.get(name);
|
||||
if (ref == null) {
|
||||
return null;
|
||||
}
|
||||
Logger logger = ref.get();
|
||||
if (logger == null) {
|
||||
// Hashtable holds stale weak reference
|
||||
// to a logger which has been GC-ed.
|
||||
namedLoggers.remove(name);
|
||||
}
|
||||
return logger;
|
||||
public Logger getLogger(String name) {
|
||||
return getUserContext().findLogger(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -789,8 +969,8 @@ public class LogManager {
|
||||
* <p>
|
||||
* @return enumeration of logger name strings
|
||||
*/
|
||||
public synchronized Enumeration<String> getLoggerNames() {
|
||||
return namedLoggers.keys();
|
||||
public Enumeration<String> getLoggerNames() {
|
||||
return getUserContext().getLoggerNames();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -875,20 +1055,20 @@ public class LogManager {
|
||||
// the global handlers, if they haven't been initialized yet.
|
||||
initializedGlobalHandlers = true;
|
||||
}
|
||||
Enumeration<String> enum_ = getLoggerNames();
|
||||
while (enum_.hasMoreElements()) {
|
||||
String name = enum_.nextElement();
|
||||
resetLogger(name);
|
||||
for (LoggerContext cx : contexts()) {
|
||||
Enumeration<String> enum_ = cx.getLoggerNames();
|
||||
while (enum_.hasMoreElements()) {
|
||||
String name = enum_.nextElement();
|
||||
Logger logger = cx.findLogger(name);
|
||||
if (logger != null) {
|
||||
resetLogger(logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Private method to reset an individual target logger.
|
||||
private void resetLogger(String name) {
|
||||
Logger logger = getLogger(name);
|
||||
if (logger == null) {
|
||||
return;
|
||||
}
|
||||
private void resetLogger(Logger logger) {
|
||||
// Close all the Logger's handlers.
|
||||
Handler[] targets = logger.getHandlers();
|
||||
for (int i = 0; i < targets.length; i++) {
|
||||
@ -900,6 +1080,7 @@ public class LogManager {
|
||||
// Problems closing a handler? Keep going...
|
||||
}
|
||||
}
|
||||
String name = logger.getName();
|
||||
if (name != null && name.equals("")) {
|
||||
// This is the root logger.
|
||||
logger.setLevel(defaultLevel);
|
||||
@ -1065,11 +1246,8 @@ public class LogManager {
|
||||
if (val == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return Level.parse(val.trim());
|
||||
} catch (Exception ex) {
|
||||
return defaultValue;
|
||||
}
|
||||
Level l = Level.findLevel(val.trim());
|
||||
return l != null ? l : defaultValue;
|
||||
}
|
||||
|
||||
// Package private method to get a filter property.
|
||||
@ -1159,9 +1337,11 @@ public class LogManager {
|
||||
HashMap<String,LogNode> children;
|
||||
LoggerWeakRef loggerRef;
|
||||
LogNode parent;
|
||||
final LoggerContext context;
|
||||
|
||||
LogNode(LogNode parent) {
|
||||
LogNode(LogNode parent, LoggerContext context) {
|
||||
this.parent = parent;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
// Recursive method to walk the tree below a node and set
|
||||
@ -1188,7 +1368,6 @@ public class LogManager {
|
||||
// that we only instantiate the global handlers when they
|
||||
// are first needed.
|
||||
private class RootLogger extends Logger {
|
||||
|
||||
private RootLogger() {
|
||||
super("", null);
|
||||
setLevel(defaultLevel);
|
||||
@ -1234,11 +1413,13 @@ public class LogManager {
|
||||
System.err.println("Bad level value for property: " + key);
|
||||
continue;
|
||||
}
|
||||
Logger l = getLogger(name);
|
||||
if (l == null) {
|
||||
continue;
|
||||
for (LoggerContext cx : contexts()) {
|
||||
Logger l = cx.findLogger(name);
|
||||
if (l == null) {
|
||||
continue;
|
||||
}
|
||||
l.setLevel(level);
|
||||
}
|
||||
l.setLevel(level);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,6 +314,40 @@ public class Logger {
|
||||
}
|
||||
}
|
||||
|
||||
// Until all JDK code converted to call sun.util.logging.PlatformLogger
|
||||
// (see 7054233), we need to determine if Logger.getLogger is to add
|
||||
// a system logger or user logger.
|
||||
//
|
||||
// As an interim solution, if the immediate caller whose caller loader is
|
||||
// null, we assume it's a system logger and add it to the system context.
|
||||
// These system loggers only set the resource bundle to the given
|
||||
// resource bundle name (rather than the default system resource bundle).
|
||||
private static class SystemLoggerHelper {
|
||||
static boolean disableCallerCheck = getBooleanProperty("sun.util.logging.disableCallerCheck");
|
||||
private static boolean getBooleanProperty(final String key) {
|
||||
String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
return System.getProperty(key);
|
||||
}
|
||||
});
|
||||
return Boolean.valueOf(s);
|
||||
}
|
||||
}
|
||||
|
||||
private static Logger demandLogger(String name, String resourceBundleName) {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null && !SystemLoggerHelper.disableCallerCheck) {
|
||||
// 0: Reflection 1: Logger.demandLogger 2: Logger.getLogger 3: caller
|
||||
final int SKIP_FRAMES = 3;
|
||||
Class<?> caller = sun.reflect.Reflection.getCallerClass(SKIP_FRAMES);
|
||||
if (caller.getClassLoader() == null) {
|
||||
return manager.demandSystemLogger(name, resourceBundleName);
|
||||
}
|
||||
}
|
||||
return manager.demandLogger(name, resourceBundleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find or create a logger for a named subsystem. If a logger has
|
||||
* already been created with the given name it is returned. Otherwise
|
||||
@ -355,8 +389,7 @@ public class Logger {
|
||||
// would throw an IllegalArgumentException in the second call
|
||||
// because the wrapper would result in an attempt to replace
|
||||
// the existing "resourceBundleForFoo" with null.
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
return manager.demandLogger(name);
|
||||
return demandLogger(name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -403,8 +436,7 @@ public class Logger {
|
||||
// Synchronization is not required here. All synchronization for
|
||||
// adding a new Logger object is handled by LogManager.addLogger().
|
||||
public static Logger getLogger(String name, String resourceBundleName) {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
Logger result = manager.demandLogger(name);
|
||||
Logger result = demandLogger(name, resourceBundleName);
|
||||
|
||||
// MissingResourceException or IllegalArgumentException can be
|
||||
// thrown by setupResourceInfo().
|
||||
@ -412,6 +444,17 @@ public class Logger {
|
||||
return result;
|
||||
}
|
||||
|
||||
// package-private
|
||||
// Add a platform logger to the system context.
|
||||
// i.e. caller of sun.util.logging.PlatformLogger.getLogger
|
||||
static Logger getPlatformLogger(String name) {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
|
||||
// all loggers in the system context will default to
|
||||
// the system logger's resource bundle
|
||||
Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an anonymous Logger. The newly created Logger is not
|
||||
@ -564,7 +607,7 @@ public class Logger {
|
||||
private void doLog(LogRecord lr) {
|
||||
lr.setLoggerName(name);
|
||||
String ebname = getEffectiveResourceBundleName();
|
||||
if (ebname != null) {
|
||||
if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) {
|
||||
lr.setResourceBundleName(ebname);
|
||||
lr.setResourceBundle(findResourceBundle(ebname));
|
||||
}
|
||||
@ -1547,6 +1590,23 @@ public class Logger {
|
||||
// May also return null if we can't find the resource bundle and
|
||||
// there is no suitable previous cached value.
|
||||
|
||||
static final String SYSTEM_LOGGER_RB_NAME = "sun.util.logging.resources.logging";
|
||||
|
||||
private static ResourceBundle findSystemResourceBundle(final Locale locale) {
|
||||
// the resource bundle is in a restricted package
|
||||
return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
|
||||
public ResourceBundle run() {
|
||||
try {
|
||||
return ResourceBundle.getBundle(SYSTEM_LOGGER_RB_NAME,
|
||||
locale,
|
||||
ClassLoader.getSystemClassLoader());
|
||||
} catch (MissingResourceException e) {
|
||||
throw new InternalError(e.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private synchronized ResourceBundle findResourceBundle(String name) {
|
||||
// Return a null bundle for a null name.
|
||||
if (name == null) {
|
||||
@ -1561,6 +1621,13 @@ public class Logger {
|
||||
return catalog;
|
||||
}
|
||||
|
||||
if (name.equals(SYSTEM_LOGGER_RB_NAME)) {
|
||||
catalog = findSystemResourceBundle(currentLocale);
|
||||
catalogName = name;
|
||||
catalogLocale = currentLocale;
|
||||
return catalog;
|
||||
}
|
||||
|
||||
// Use the thread's context ClassLoader. If there isn't one,
|
||||
// use the SystemClassloader.
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
@ -1577,7 +1644,6 @@ public class Logger {
|
||||
// ClassLoader. Drop through.
|
||||
}
|
||||
|
||||
|
||||
// Fall back to searching up the call stack and trying each
|
||||
// calling ClassLoader.
|
||||
for (int ix = 0; ; ix++) {
|
||||
|
@ -34,7 +34,7 @@ import java.util.ArrayList;
|
||||
*
|
||||
* The <tt>LoggingMXBean</tt> interface provides a standard
|
||||
* method for management access to the individual
|
||||
* java.util.Logger objects available at runtime.
|
||||
* {@code Logger} objects available at runtime.
|
||||
*
|
||||
* @author Ron Mann
|
||||
* @author Mandy Chung
|
||||
@ -75,7 +75,7 @@ class Logging implements LoggingMXBean {
|
||||
if (level == null) {
|
||||
return EMPTY_STRING;
|
||||
} else {
|
||||
return level.getName();
|
||||
return level.getLevelName();
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +85,6 @@ class Logging implements LoggingMXBean {
|
||||
}
|
||||
|
||||
Logger logger = logManager.getLogger(loggerName);
|
||||
|
||||
if (logger == null) {
|
||||
throw new IllegalArgumentException("Logger " + loggerName +
|
||||
"does not exist");
|
||||
@ -94,7 +93,10 @@ class Logging implements LoggingMXBean {
|
||||
Level level = null;
|
||||
if (levelName != null) {
|
||||
// parse will throw IAE if logLevel is invalid
|
||||
level = Level.parse(levelName);
|
||||
level = Level.findLevel(levelName);
|
||||
if (level == null) {
|
||||
throw new IllegalArgumentException("Unknown level \"" + levelName + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
logger.setLevel(level);
|
||||
|
@ -37,7 +37,8 @@ class LoggingProxyImpl implements LoggingProxy {
|
||||
|
||||
@Override
|
||||
public Object getLogger(String name) {
|
||||
return Logger.getLogger(name);
|
||||
// always create a platform logger with the resource bundle name
|
||||
return Logger.getPlatformLogger(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -92,12 +93,16 @@ class LoggingProxyImpl implements LoggingProxy {
|
||||
|
||||
@Override
|
||||
public Object parseLevel(String levelName) {
|
||||
return Level.parse(levelName);
|
||||
Level level = Level.findLevel(levelName);
|
||||
if (level == null) {
|
||||
throw new IllegalArgumentException("Unknown level \"" + levelName + "\"");
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLevelName(Object level) {
|
||||
return ((Level) level).getName();
|
||||
return ((Level) level).getLevelName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -162,7 +162,7 @@ public class SimpleFormatter extends Formatter {
|
||||
dat,
|
||||
source,
|
||||
record.getLoggerName(),
|
||||
record.getLevel().getLocalizedName(),
|
||||
record.getLevel().getLocalizedLevelName(),
|
||||
message,
|
||||
throwable);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,11 +39,13 @@ import java.io.PrintStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.logging.Level;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -78,6 +80,8 @@ import javax.management.RuntimeErrorException;
|
||||
import javax.management.RuntimeOperationsException;
|
||||
import javax.management.ServiceNotFoundException;
|
||||
import javax.management.loading.ClassLoaderRepository;
|
||||
import sun.misc.JavaSecurityAccess;
|
||||
import sun.misc.SharedSecrets;
|
||||
|
||||
import sun.reflect.misc.MethodUtil;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
@ -138,6 +142,9 @@ public class RequiredModelMBean
|
||||
private boolean registered = false;
|
||||
private transient MBeanServer server = null;
|
||||
|
||||
private final static JavaSecurityAccess javaSecurityAccess = SharedSecrets.getJavaSecurityAccess();
|
||||
final private AccessControlContext acc = AccessController.getContext();
|
||||
|
||||
/*************************************/
|
||||
/* constructors */
|
||||
/*************************************/
|
||||
@ -1025,10 +1032,31 @@ public class RequiredModelMBean
|
||||
|
||||
if (opClassName != null) {
|
||||
try {
|
||||
final ClassLoader targetClassLoader =
|
||||
targetObject.getClass().getClassLoader();
|
||||
targetClass = Class.forName(opClassName, false,
|
||||
targetClassLoader);
|
||||
AccessControlContext stack = AccessController.getContext();
|
||||
final Object obj = targetObject;
|
||||
final String className = opClassName;
|
||||
final ClassNotFoundException[] caughtException = new ClassNotFoundException[1];
|
||||
|
||||
targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
|
||||
|
||||
@Override
|
||||
public Class<?> run() {
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
final ClassLoader targetClassLoader =
|
||||
obj.getClass().getClassLoader();
|
||||
return Class.forName(className, false,
|
||||
targetClassLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
caughtException[0] = e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, stack, acc);
|
||||
|
||||
if (caughtException[0] != null) {
|
||||
throw caughtException[0];
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
final String msg =
|
||||
"class for invoke " + opName + " not found";
|
||||
@ -1061,9 +1089,9 @@ public class RequiredModelMBean
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Method resolveMethod(Class<?> targetClass,
|
||||
private Method resolveMethod(Class<?> targetClass,
|
||||
String opMethodName,
|
||||
String[] sig)
|
||||
final String[] sig)
|
||||
throws ReflectionException {
|
||||
final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER);
|
||||
|
||||
@ -1078,30 +1106,45 @@ public class RequiredModelMBean
|
||||
if (sig == null)
|
||||
argClasses = null;
|
||||
else {
|
||||
final AccessControlContext stack = AccessController.getContext();
|
||||
final ReflectionException[] caughtException = new ReflectionException[1];
|
||||
final ClassLoader targetClassLoader = targetClass.getClassLoader();
|
||||
argClasses = new Class<?>[sig.length];
|
||||
for (int i = 0; i < sig.length; i++) {
|
||||
if (tracing) {
|
||||
MODELMBEAN_LOGGER.logp(Level.FINER,
|
||||
RequiredModelMBean.class.getName(),"resolveMethod",
|
||||
"resolve type " + sig[i]);
|
||||
}
|
||||
argClasses[i] = (Class<?>) primitiveClassMap.get(sig[i]);
|
||||
if (argClasses[i] == null) {
|
||||
try {
|
||||
argClasses[i] =
|
||||
Class.forName(sig[i], false, targetClassLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
|
||||
javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() {
|
||||
|
||||
@Override
|
||||
public Void run() {
|
||||
for (int i = 0; i < sig.length; i++) {
|
||||
if (tracing) {
|
||||
MODELMBEAN_LOGGER.logp(Level.FINER,
|
||||
RequiredModelMBean.class.getName(),
|
||||
"resolveMethod",
|
||||
"class not found");
|
||||
RequiredModelMBean.class.getName(),"resolveMethod",
|
||||
"resolve type " + sig[i]);
|
||||
}
|
||||
argClasses[i] = (Class<?>) primitiveClassMap.get(sig[i]);
|
||||
if (argClasses[i] == null) {
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(sig[i]);
|
||||
argClasses[i] =
|
||||
Class.forName(sig[i], false, targetClassLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (tracing) {
|
||||
MODELMBEAN_LOGGER.logp(Level.FINER,
|
||||
RequiredModelMBean.class.getName(),
|
||||
"resolveMethod",
|
||||
"class not found");
|
||||
}
|
||||
final String msg = "Parameter class not found";
|
||||
caughtException[0] = new ReflectionException(e, msg);
|
||||
}
|
||||
}
|
||||
final String msg = "Parameter class not found";
|
||||
throw new ReflectionException(e, msg);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, stack, acc);
|
||||
|
||||
if (caughtException[0] != null) {
|
||||
throw caughtException[0];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1133,7 +1176,7 @@ public class RequiredModelMBean
|
||||
/* Find a method in RequiredModelMBean as determined by the given
|
||||
parameters. Return null if there is none, or if the parameters
|
||||
exclude using it. Called from invoke. */
|
||||
private static Method findRMMBMethod(String opMethodName,
|
||||
private Method findRMMBMethod(String opMethodName,
|
||||
Object targetObjectField,
|
||||
String opClassName,
|
||||
String[] sig) {
|
||||
@ -1155,19 +1198,29 @@ public class RequiredModelMBean
|
||||
if (opClassName == null)
|
||||
targetClass = rmmbClass;
|
||||
else {
|
||||
try {
|
||||
final ClassLoader targetClassLoader =
|
||||
rmmbClass.getClassLoader();
|
||||
targetClass = Class.forName(opClassName, false,
|
||||
targetClassLoader);
|
||||
if (!rmmbClass.isAssignableFrom(targetClass))
|
||||
return null;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
AccessControlContext stack = AccessController.getContext();
|
||||
final String className = opClassName;
|
||||
targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
|
||||
|
||||
@Override
|
||||
public Class<?> run() {
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
final ClassLoader targetClassLoader =
|
||||
rmmbClass.getClassLoader();
|
||||
Class clz = Class.forName(className, false,
|
||||
targetClassLoader);
|
||||
if (!rmmbClass.isAssignableFrom(clz))
|
||||
return null;
|
||||
return clz;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}, stack, acc);
|
||||
}
|
||||
try {
|
||||
return resolveMethod(targetClass, opMethodName, sig);
|
||||
return targetClass != null ? resolveMethod(targetClass, opMethodName, sig) : null;
|
||||
} catch (ReflectionException e) {
|
||||
return null;
|
||||
}
|
||||
@ -1177,12 +1230,35 @@ public class RequiredModelMBean
|
||||
* Invoke the given method, and throw the somewhat unpredictable
|
||||
* appropriate exception if the method itself gets an exception.
|
||||
*/
|
||||
private Object invokeMethod(String opName, Method method,
|
||||
Object targetObject, Object[] opArgs)
|
||||
private Object invokeMethod(String opName, final Method method,
|
||||
final Object targetObject, final Object[] opArgs)
|
||||
throws MBeanException, ReflectionException {
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(method.getDeclaringClass());
|
||||
return MethodUtil.invoke(method, targetObject, opArgs);
|
||||
final Throwable[] caughtException = new Throwable[1];
|
||||
AccessControlContext stack = AccessController.getContext();
|
||||
Object rslt = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Object>() {
|
||||
|
||||
@Override
|
||||
public Object run() {
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(method.getDeclaringClass());
|
||||
return MethodUtil.invoke(method, targetObject, opArgs);
|
||||
} catch (InvocationTargetException e) {
|
||||
caughtException[0] = e;
|
||||
} catch (IllegalAccessException e) {
|
||||
caughtException[0] = e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, stack, acc);
|
||||
if (caughtException[0] != null) {
|
||||
if (caughtException[0] instanceof Exception) {
|
||||
throw (Exception)caughtException[0];
|
||||
} else if(caughtException[0] instanceof Error) {
|
||||
throw (Error)caughtException[0];
|
||||
}
|
||||
}
|
||||
return rslt;
|
||||
} catch (RuntimeErrorException ree) {
|
||||
throw new RuntimeOperationsException(ree,
|
||||
"RuntimeException occurred in RequiredModelMBean "+
|
||||
@ -1567,7 +1643,7 @@ public class RequiredModelMBean
|
||||
}
|
||||
|
||||
// make sure response class matches type field
|
||||
String respType = attrInfo.getType();
|
||||
final String respType = attrInfo.getType();
|
||||
if (response != null) {
|
||||
String responseClass = response.getClass().getName();
|
||||
if (!respType.equals(responseClass)) {
|
||||
@ -1590,9 +1666,31 @@ public class RequiredModelMBean
|
||||
// inequality may come from type subclassing
|
||||
boolean subtype;
|
||||
try {
|
||||
ClassLoader cl =
|
||||
response.getClass().getClassLoader();
|
||||
Class<?> c = Class.forName(respType, true, cl);
|
||||
final Class respClass = response.getClass();
|
||||
final Exception[] caughException = new Exception[1];
|
||||
|
||||
AccessControlContext stack = AccessController.getContext();
|
||||
|
||||
Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
|
||||
|
||||
@Override
|
||||
public Class<?> run() {
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(respType);
|
||||
ClassLoader cl =
|
||||
respClass.getClassLoader();
|
||||
return Class.forName(respType, true, cl);
|
||||
} catch (Exception e) {
|
||||
caughException[0] = e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, stack, acc);
|
||||
|
||||
if (caughException[0] != null) {
|
||||
throw caughException[0];
|
||||
}
|
||||
|
||||
subtype = c.isInstance(response);
|
||||
} catch (Exception e) {
|
||||
subtype = false;
|
||||
@ -2745,16 +2843,37 @@ public class RequiredModelMBean
|
||||
return MBeanServerFactory.getClassLoaderRepository(server);
|
||||
}
|
||||
|
||||
private Class<?> loadClass(String className)
|
||||
private Class<?> loadClass(final String className)
|
||||
throws ClassNotFoundException {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
final ClassLoaderRepository clr =
|
||||
getClassLoaderRepository();
|
||||
if (clr == null) throw new ClassNotFoundException(className);
|
||||
return clr.loadClass(className);
|
||||
AccessControlContext stack = AccessController.getContext();
|
||||
final ClassNotFoundException[] caughtException = new ClassNotFoundException[1];
|
||||
|
||||
Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
|
||||
|
||||
@Override
|
||||
public Class<?> run() {
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
return Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
final ClassLoaderRepository clr =
|
||||
getClassLoaderRepository();
|
||||
try {
|
||||
if (clr == null) throw new ClassNotFoundException(className);
|
||||
return clr.loadClass(className);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
caughtException[0] = ex;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, stack, acc);
|
||||
|
||||
if (caughtException[0] != null) {
|
||||
throw caughtException[0];
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
@ -781,15 +781,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable
|
||||
scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER);
|
||||
if (corner == null || corner instanceof UIResource){
|
||||
corner = null;
|
||||
Object componentClass = UIManager.get(
|
||||
"Table.scrollPaneCornerComponent");
|
||||
if (componentClass instanceof Class){
|
||||
try {
|
||||
corner = (Component)
|
||||
((Class)componentClass).newInstance();
|
||||
} catch (Exception e) {
|
||||
// just ignore and don't set corner
|
||||
}
|
||||
try {
|
||||
corner = (Component) UIManager.get(
|
||||
"Table.scrollPaneCornerComponent");
|
||||
} catch (Exception e) {
|
||||
// just ignore and don't set corner
|
||||
}
|
||||
scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER,
|
||||
corner);
|
||||
|
@ -27,11 +27,12 @@ package javax.swing;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.awt.peer.ContainerPeer;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.applet.*;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
@ -39,6 +40,8 @@ import sun.awt.AppContext;
|
||||
import sun.awt.DisplayChangedListener;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.java2d.SunGraphicsEnvironment;
|
||||
import sun.misc.JavaSecurityAccess;
|
||||
import sun.misc.SharedSecrets;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
import com.sun.java.swing.SwingUtilities3;
|
||||
@ -176,6 +179,9 @@ public class RepaintManager
|
||||
*/
|
||||
private final ProcessingRunnable processingRunnable;
|
||||
|
||||
private final static JavaSecurityAccess javaSecurityAccess =
|
||||
SharedSecrets.getJavaSecurityAccess();
|
||||
|
||||
|
||||
static {
|
||||
volatileImageBufferEnabled = "true".equals(AccessController.
|
||||
@ -548,13 +554,26 @@ public class RepaintManager
|
||||
// This is called from the toolkit thread when awt needs to run a
|
||||
// Runnable before we paint.
|
||||
//
|
||||
void nativeQueueSurfaceDataRunnable(AppContext appContext, Component c,
|
||||
Runnable r) {
|
||||
void nativeQueueSurfaceDataRunnable(AppContext appContext,
|
||||
final Component c, final Runnable r)
|
||||
{
|
||||
synchronized(this) {
|
||||
if (runnableList == null) {
|
||||
runnableList = new LinkedList<Runnable>();
|
||||
}
|
||||
runnableList.add(r);
|
||||
runnableList.add(new Runnable() {
|
||||
public void run() {
|
||||
AccessControlContext stack = AccessController.getContext();
|
||||
AccessControlContext acc =
|
||||
AWTAccessor.getComponentAccessor().getAccessControlContext(c);
|
||||
javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
r.run();
|
||||
return null;
|
||||
}
|
||||
}, stack, acc);
|
||||
}
|
||||
});
|
||||
}
|
||||
scheduleProcessingRunnable(appContext);
|
||||
}
|
||||
@ -652,9 +671,9 @@ public class RepaintManager
|
||||
* @see #addInvalidComponent
|
||||
*/
|
||||
public void validateInvalidComponents() {
|
||||
java.util.List<Component> ic;
|
||||
final java.util.List<Component> ic;
|
||||
synchronized(this) {
|
||||
if(invalidComponents == null) {
|
||||
if (invalidComponents == null) {
|
||||
return;
|
||||
}
|
||||
ic = invalidComponents;
|
||||
@ -662,7 +681,17 @@ public class RepaintManager
|
||||
}
|
||||
int n = ic.size();
|
||||
for(int i = 0; i < n; i++) {
|
||||
ic.get(i).validate();
|
||||
final Component c = ic.get(i);
|
||||
AccessControlContext stack = AccessController.getContext();
|
||||
AccessControlContext acc =
|
||||
AWTAccessor.getComponentAccessor().getAccessControlContext(c);
|
||||
javaSecurityAccess.doIntersectionPrivilege(
|
||||
new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
c.validate();
|
||||
return null;
|
||||
}
|
||||
}, stack, acc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -740,78 +769,78 @@ public class RepaintManager
|
||||
paintDirtyRegions(tmpDirtyComponents);
|
||||
}
|
||||
|
||||
private void paintDirtyRegions(Map<Component,Rectangle>
|
||||
tmpDirtyComponents){
|
||||
int i, count;
|
||||
java.util.List<Component> roots;
|
||||
Component dirtyComponent;
|
||||
|
||||
count = tmpDirtyComponents.size();
|
||||
if (count == 0) {
|
||||
private void paintDirtyRegions(
|
||||
final Map<Component,Rectangle> tmpDirtyComponents)
|
||||
{
|
||||
if (tmpDirtyComponents.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rectangle rect;
|
||||
int localBoundsX = 0;
|
||||
int localBoundsY = 0;
|
||||
int localBoundsH;
|
||||
int localBoundsW;
|
||||
|
||||
roots = new ArrayList<Component>(count);
|
||||
|
||||
final java.util.List<Component> roots =
|
||||
new ArrayList<Component>(tmpDirtyComponents.size());
|
||||
for (Component dirty : tmpDirtyComponents.keySet()) {
|
||||
collectDirtyComponents(tmpDirtyComponents, dirty, roots);
|
||||
}
|
||||
|
||||
count = roots.size();
|
||||
final AtomicInteger count = new AtomicInteger(roots.size());
|
||||
painting = true;
|
||||
try {
|
||||
for(i=0 ; i < count ; i++) {
|
||||
dirtyComponent = roots.get(i);
|
||||
rect = tmpDirtyComponents.get(dirtyComponent);
|
||||
// Sometimes when RepaintManager is changed during the painting
|
||||
// we may get null here, see #6995769 for details
|
||||
if (rect == null) {
|
||||
continue;
|
||||
}
|
||||
localBoundsH = dirtyComponent.getHeight();
|
||||
localBoundsW = dirtyComponent.getWidth();
|
||||
|
||||
SwingUtilities.computeIntersection(localBoundsX,
|
||||
localBoundsY,
|
||||
localBoundsW,
|
||||
localBoundsH,
|
||||
rect);
|
||||
if (dirtyComponent instanceof JComponent) {
|
||||
((JComponent)dirtyComponent).paintImmediately(
|
||||
rect.x,rect.y,rect.width, rect.height);
|
||||
}
|
||||
else if (dirtyComponent.isShowing()) {
|
||||
Graphics g = JComponent.safelyGetGraphics(
|
||||
dirtyComponent, dirtyComponent);
|
||||
// If the Graphics goes away, it means someone disposed of
|
||||
// the window, don't do anything.
|
||||
if (g != null) {
|
||||
g.setClip(rect.x, rect.y, rect.width, rect.height);
|
||||
try {
|
||||
dirtyComponent.paint(g);
|
||||
} finally {
|
||||
g.dispose();
|
||||
for (int j=0 ; j < count.get(); j++) {
|
||||
final int i = j;
|
||||
final Component dirtyComponent = roots.get(j);
|
||||
AccessControlContext stack = AccessController.getContext();
|
||||
AccessControlContext acc =
|
||||
AWTAccessor.getComponentAccessor().getAccessControlContext(dirtyComponent);
|
||||
javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
Rectangle rect = tmpDirtyComponents.get(dirtyComponent);
|
||||
// Sometimes when RepaintManager is changed during the painting
|
||||
// we may get null here, see #6995769 for details
|
||||
if (rect == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int localBoundsH = dirtyComponent.getHeight();
|
||||
int localBoundsW = dirtyComponent.getWidth();
|
||||
SwingUtilities.computeIntersection(0,
|
||||
0,
|
||||
localBoundsW,
|
||||
localBoundsH,
|
||||
rect);
|
||||
if (dirtyComponent instanceof JComponent) {
|
||||
((JComponent)dirtyComponent).paintImmediately(
|
||||
rect.x,rect.y,rect.width, rect.height);
|
||||
}
|
||||
else if (dirtyComponent.isShowing()) {
|
||||
Graphics g = JComponent.safelyGetGraphics(
|
||||
dirtyComponent, dirtyComponent);
|
||||
// If the Graphics goes away, it means someone disposed of
|
||||
// the window, don't do anything.
|
||||
if (g != null) {
|
||||
g.setClip(rect.x, rect.y, rect.width, rect.height);
|
||||
try {
|
||||
dirtyComponent.paint(g);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the repaintRoot has been set, service it now and
|
||||
// remove any components that are children of repaintRoot.
|
||||
if (repaintRoot != null) {
|
||||
adjustRoots(repaintRoot, roots, i + 1);
|
||||
count.set(roots.size());
|
||||
paintManager.isRepaintingRoot = true;
|
||||
repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(),
|
||||
repaintRoot.getHeight());
|
||||
paintManager.isRepaintingRoot = false;
|
||||
// Only service repaintRoot once.
|
||||
repaintRoot = null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// If the repaintRoot has been set, service it now and
|
||||
// remove any components that are children of repaintRoot.
|
||||
if (repaintRoot != null) {
|
||||
adjustRoots(repaintRoot, roots, i + 1);
|
||||
count = roots.size();
|
||||
paintManager.isRepaintingRoot = true;
|
||||
repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(),
|
||||
repaintRoot.getHeight());
|
||||
paintManager.isRepaintingRoot = false;
|
||||
// Only service repaintRoot once.
|
||||
repaintRoot = null;
|
||||
}
|
||||
}, stack, acc);
|
||||
}
|
||||
} finally {
|
||||
painting = false;
|
||||
|
@ -677,6 +677,8 @@ public class UIDefaults extends Hashtable<Object,Object>
|
||||
try {
|
||||
String className = (String)get(uiClassID);
|
||||
if (className != null) {
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
|
||||
Class cls = (Class)get(className);
|
||||
if (cls == null) {
|
||||
if (uiClassLoader == null) {
|
||||
|
@ -159,7 +159,12 @@ public class NimbusLookAndFeel extends SynthLookAndFeel {
|
||||
|
||||
// Store Table ScrollPane Corner Component
|
||||
uiDefaults.put("Table.scrollPaneCornerComponent",
|
||||
TableScrollPaneCorner.class);
|
||||
new UIDefaults.ActiveValue() {
|
||||
@Override
|
||||
public Object createValue(UIDefaults table) {
|
||||
return new TableScrollPaneCorner();
|
||||
}
|
||||
});
|
||||
|
||||
// Setup the settings for ToolBarSeparator which is custom
|
||||
// installed for Nimbus
|
||||
|
@ -45,6 +45,7 @@ import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.WeakHashMap;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.EmbeddedFrame;
|
||||
import sun.awt.SunToolkit;
|
||||
@ -448,12 +449,12 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable {
|
||||
// to avoid deadlock.
|
||||
try {
|
||||
final AppletPanel p = this;
|
||||
|
||||
EventQueue.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
p.validate();
|
||||
}
|
||||
});
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
p.validate();
|
||||
}
|
||||
};
|
||||
AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
|
||||
}
|
||||
catch(InterruptedException ie) {
|
||||
}
|
||||
@ -478,18 +479,19 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable {
|
||||
try {
|
||||
final AppletPanel p = this;
|
||||
final Applet a = applet;
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
p.validate();
|
||||
a.setVisible(true);
|
||||
|
||||
EventQueue.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
p.validate();
|
||||
a.setVisible(true);
|
||||
|
||||
// Fix for BugTraq ID 4041703.
|
||||
// Set the default focus for an applet.
|
||||
if (hasInitialFocus())
|
||||
setDefaultFocus();
|
||||
// Fix for BugTraq ID 4041703.
|
||||
// Set the default focus for an applet.
|
||||
if (hasInitialFocus()) {
|
||||
setDefaultFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
|
||||
}
|
||||
catch(InterruptedException ie) {
|
||||
}
|
||||
@ -512,13 +514,12 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable {
|
||||
// to avoid deadlock.
|
||||
try {
|
||||
final Applet a = applet;
|
||||
|
||||
EventQueue.invokeAndWait(new Runnable() {
|
||||
public void run()
|
||||
{
|
||||
a.setVisible(false);
|
||||
}
|
||||
});
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
a.setVisible(false);
|
||||
}
|
||||
};
|
||||
AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
|
||||
}
|
||||
catch(InterruptedException ie) {
|
||||
}
|
||||
@ -570,17 +571,14 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable {
|
||||
}
|
||||
status = APPLET_DISPOSE;
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
final Applet a = applet;
|
||||
|
||||
EventQueue.invokeAndWait(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
remove(a);
|
||||
}
|
||||
});
|
||||
};
|
||||
AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
|
||||
}
|
||||
catch(InterruptedException ie)
|
||||
{
|
||||
|
@ -34,6 +34,8 @@ import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.AccessControlContext;
|
||||
|
||||
import java.io.File;
|
||||
@ -476,6 +478,12 @@ public final class AWTAccessor {
|
||||
* appeared.
|
||||
*/
|
||||
void wakeup(EventQueue eventQueue, boolean isShutdown);
|
||||
|
||||
/**
|
||||
* Static in EventQueue
|
||||
*/
|
||||
void invokeAndWait(Object source, Runnable r)
|
||||
throws InterruptedException, InvocationTargetException;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -327,21 +327,27 @@ public final class AppContext {
|
||||
// Before we return the main "system" AppContext, check to
|
||||
// see if there's an AWTSecurityManager installed. If so,
|
||||
// allow it to choose the AppContext to return.
|
||||
SecurityManager securityManager = System.getSecurityManager();
|
||||
if ((securityManager != null) &&
|
||||
(securityManager instanceof AWTSecurityManager))
|
||||
{
|
||||
AWTSecurityManager awtSecMgr = (AWTSecurityManager)securityManager;
|
||||
AppContext secAppContext = awtSecMgr.getAppContext();
|
||||
if (secAppContext != null) {
|
||||
appContext = secAppContext; // Return what we're told
|
||||
}
|
||||
AppContext secAppContext = getExecutionAppContext();
|
||||
if (secAppContext != null) {
|
||||
appContext = secAppContext; // Return what we're told
|
||||
}
|
||||
}
|
||||
|
||||
return appContext;
|
||||
}
|
||||
|
||||
private final static AppContext getExecutionAppContext() {
|
||||
SecurityManager securityManager = System.getSecurityManager();
|
||||
if ((securityManager != null) &&
|
||||
(securityManager instanceof AWTSecurityManager))
|
||||
{
|
||||
AWTSecurityManager awtSecMgr = (AWTSecurityManager) securityManager;
|
||||
AppContext secAppContext = awtSecMgr.getAppContext();
|
||||
return secAppContext; // Return what we're told
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the main ("system") AppContext.
|
||||
*
|
||||
@ -806,6 +812,21 @@ public final class AppContext {
|
||||
public boolean isMainAppContext() {
|
||||
return (numAppContexts.get() == 1);
|
||||
}
|
||||
public Object getContext() {
|
||||
return getAppContext();
|
||||
}
|
||||
public Object getExecutionContext() {
|
||||
return getExecutionAppContext();
|
||||
}
|
||||
public Object get(Object context, Object key) {
|
||||
return ((AppContext)context).get(key);
|
||||
}
|
||||
public void put(Object context, Object key, Object value) {
|
||||
((AppContext)context).put(key, value);
|
||||
}
|
||||
public void remove(Object context, Object key) {
|
||||
((AppContext)context).remove(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ public class ByteComponentRaster extends SunWritableRaster {
|
||||
}
|
||||
this.bandOffset = this.dataOffsets[0];
|
||||
|
||||
verify(false);
|
||||
verify();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -857,38 +857,68 @@ public class ByteComponentRaster extends SunWritableRaster {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the layout parameters are consistent with
|
||||
* the data. If strictCheck
|
||||
* is false, this method will check for ArrayIndexOutOfBounds conditions. If
|
||||
* strictCheck is true, this method will check for additional error
|
||||
* conditions such as line wraparound (width of a line greater than
|
||||
* the scanline stride).
|
||||
* @return String Error string, if the layout is incompatible with
|
||||
* the data. Otherwise returns null.
|
||||
* Verify that the layout parameters are consistent with the data.
|
||||
*
|
||||
* The method verifies whether scanline stride and pixel stride do not
|
||||
* cause an integer overflow during calculation of a position of the pixel
|
||||
* in data buffer. It also verifies whether the data buffer has enough data
|
||||
* to correspond the raster layout attributes.
|
||||
*
|
||||
* @throws RasterFormatException if an integer overflow is detected,
|
||||
* or if data buffer has not enough capacity.
|
||||
*/
|
||||
private void verify (boolean strictCheck) {
|
||||
// Make sure data for Raster is in a legal range
|
||||
for (int i=0; i < dataOffsets.length; i++) {
|
||||
protected final void verify() {
|
||||
for (int i = 0; i < dataOffsets.length; i++) {
|
||||
if (dataOffsets[i] < 0) {
|
||||
throw new RasterFormatException("Data offsets for band "+i+
|
||||
"("+dataOffsets[i]+
|
||||
") must be >= 0");
|
||||
throw new RasterFormatException("Data offsets for band " + i
|
||||
+ "(" + dataOffsets[i]
|
||||
+ ") must be >= 0");
|
||||
}
|
||||
}
|
||||
|
||||
int maxSize = 0;
|
||||
int size;
|
||||
|
||||
for (int i=0; i < numDataElements; i++) {
|
||||
size = (height-1)*scanlineStride + (width-1)*pixelStride +
|
||||
dataOffsets[i];
|
||||
// we can be sure that width and height are greater than 0
|
||||
if (scanlineStride < 0 ||
|
||||
scanlineStride > (Integer.MAX_VALUE / height))
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
int lastScanOffset = (height - 1) * scanlineStride;
|
||||
|
||||
if (pixelStride < 0 ||
|
||||
pixelStride > (Integer.MAX_VALUE / width))
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect pixel stride: "
|
||||
+ pixelStride);
|
||||
}
|
||||
int lastPixelOffset = (width - 1) * pixelStride;
|
||||
|
||||
if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) {
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect raster attributes");
|
||||
}
|
||||
lastPixelOffset += lastScanOffset;
|
||||
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
size = lastPixelOffset + dataOffsets[i];
|
||||
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
|
||||
throw new RasterFormatException("Incorrect band offset: "
|
||||
+ dataOffsets[i]);
|
||||
|
||||
}
|
||||
|
||||
if (size > maxSize) {
|
||||
maxSize = size;
|
||||
}
|
||||
}
|
||||
if (data.length < maxSize) {
|
||||
throw new RasterFormatException("Data array too small (should be "+
|
||||
maxSize+" )");
|
||||
throw new RasterFormatException("Data array too small (should be "
|
||||
+ maxSize + " )");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,7 +250,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster {
|
||||
}
|
||||
}
|
||||
|
||||
verify(false);
|
||||
verify();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1292,33 +1292,6 @@ public class ByteInterleavedRaster extends ByteComponentRaster {
|
||||
return createCompatibleWritableRaster(width,height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the layout parameters are consistent with
|
||||
* the data. If strictCheck
|
||||
* is false, this method will check for ArrayIndexOutOfBounds conditions. If
|
||||
* strictCheck is true, this method will check for additional error
|
||||
* conditions such as line wraparound (width of a line greater than
|
||||
* the scanline stride).
|
||||
* @return String Error string, if the layout is incompatible with
|
||||
* the data. Otherwise returns null.
|
||||
*/
|
||||
private void verify (boolean strictCheck) {
|
||||
int maxSize = 0;
|
||||
int size;
|
||||
|
||||
for (int i=0; i < numDataElements; i++) {
|
||||
size = (height-1)*scanlineStride + (width-1)*pixelStride +
|
||||
dataOffsets[i];
|
||||
if (size > maxSize) {
|
||||
maxSize = size;
|
||||
}
|
||||
}
|
||||
if (data.length < maxSize) {
|
||||
throw new RasterFormatException("Data array too small (should be "+
|
||||
maxSize+" )");
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String ("ByteInterleavedRaster: width = "+width+" height = "
|
||||
+ height
|
||||
|
@ -198,7 +198,7 @@ public class ShortComponentRaster extends SunWritableRaster {
|
||||
}
|
||||
this.bandOffset = this.dataOffsets[0];
|
||||
|
||||
verify(false);
|
||||
verify();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -791,38 +791,67 @@ public class ShortComponentRaster extends SunWritableRaster {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the layout parameters are consistent with
|
||||
* the data. If strictCheck
|
||||
* is false, this method will check for ArrayIndexOutOfBounds conditions. If
|
||||
* strictCheck is true, this method will check for additional error
|
||||
* conditions such as line wraparound (width of a line greater than
|
||||
* the scanline stride).
|
||||
* @return String Error string, if the layout is incompatible with
|
||||
* the data. Otherwise returns null.
|
||||
* Verify that the layout parameters are consistent with the data.
|
||||
*
|
||||
* The method verifies whether scanline stride and pixel stride do not
|
||||
* cause an integer overflow during calculation of a position of the pixel
|
||||
* in data buffer. It also verifies whether the data buffer has enough data
|
||||
* to correspond the raster layout attributes.
|
||||
*
|
||||
* @throws RasterFormatException if an integer overflow is detected,
|
||||
* or if data buffer has not enough capacity.
|
||||
*/
|
||||
private void verify (boolean strictCheck) {
|
||||
// Make sure data for Raster is in a legal range
|
||||
for (int i=0; i < dataOffsets.length; i++) {
|
||||
protected final void verify() {
|
||||
for (int i = 0; i < dataOffsets.length; i++) {
|
||||
if (dataOffsets[i] < 0) {
|
||||
throw new RasterFormatException("Data offsets for band "+i+
|
||||
"("+dataOffsets[i]+
|
||||
") must be >= 0");
|
||||
throw new RasterFormatException("Data offsets for band " + i
|
||||
+ "(" + dataOffsets[i]
|
||||
+ ") must be >= 0");
|
||||
}
|
||||
}
|
||||
|
||||
int maxSize = 0;
|
||||
int size;
|
||||
|
||||
for (int i=0; i < numDataElements; i++) {
|
||||
size = (height-1)*scanlineStride + (width-1)*pixelStride +
|
||||
dataOffsets[i];
|
||||
// we can be sure that width and height are greater than 0
|
||||
if (scanlineStride < 0 ||
|
||||
scanlineStride > (Integer.MAX_VALUE / height))
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect scanline stride: "
|
||||
+ scanlineStride);
|
||||
}
|
||||
int lastScanOffset = (height - 1) * scanlineStride;
|
||||
|
||||
if (pixelStride < 0 ||
|
||||
pixelStride > (Integer.MAX_VALUE / width))
|
||||
{
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect pixel stride: "
|
||||
+ pixelStride);
|
||||
}
|
||||
int lastPixelOffset = (width - 1) * pixelStride;
|
||||
|
||||
if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) {
|
||||
// integer overflow
|
||||
throw new RasterFormatException("Incorrect raster attributes");
|
||||
}
|
||||
lastPixelOffset += lastScanOffset;
|
||||
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
size = lastPixelOffset + dataOffsets[i];
|
||||
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
|
||||
throw new RasterFormatException("Incorrect band offset: "
|
||||
+ dataOffsets[i]);
|
||||
}
|
||||
|
||||
if (size > maxSize) {
|
||||
maxSize = size;
|
||||
}
|
||||
}
|
||||
if (data.length < maxSize) {
|
||||
throw new RasterFormatException("Data array too small (should be "+
|
||||
maxSize+" )");
|
||||
throw new RasterFormatException("Data array too small (should be "
|
||||
+ maxSize + " )");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster {
|
||||
sampleModel);
|
||||
}
|
||||
this.bandOffset = this.dataOffsets[0];
|
||||
verify(false);
|
||||
verify();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -762,33 +762,6 @@ public class ShortInterleavedRaster extends ShortComponentRaster {
|
||||
return createCompatibleWritableRaster(width,height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the layout parameters are consistent with
|
||||
* the data. If strictCheck
|
||||
* is false, this method will check for ArrayIndexOutOfBounds conditions. If
|
||||
* strictCheck is true, this method will check for additional error
|
||||
* conditions such as line wraparound (width of a line greater than
|
||||
* the scanline stride).
|
||||
* @return String Error string, if the layout is incompatible with
|
||||
* the data. Otherwise returns null.
|
||||
*/
|
||||
private void verify (boolean strictCheck) {
|
||||
int maxSize = 0;
|
||||
int size;
|
||||
|
||||
for (int i=0; i < numDataElements; i++) {
|
||||
size = (height-1)*scanlineStride + (width-1)*pixelStride +
|
||||
dataOffsets[i];
|
||||
if (size > maxSize) {
|
||||
maxSize = size;
|
||||
}
|
||||
}
|
||||
if (data.length < maxSize) {
|
||||
throw new RasterFormatException("Data array too small (should be "+
|
||||
maxSize+" )");
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String ("ShortInterleavedRaster: width = "+width
|
||||
+" height = " + height
|
||||
|
@ -26,6 +26,14 @@
|
||||
package sun.misc;
|
||||
|
||||
public interface JavaAWTAccess {
|
||||
public Object getContext();
|
||||
public Object getExecutionContext();
|
||||
|
||||
public Object get(Object context, Object key);
|
||||
public void put(Object context, Object key, Object value);
|
||||
public void remove(Object context, Object key);
|
||||
|
||||
// convenience methods whose context is the object returned by getContext()
|
||||
public Object get(Object key);
|
||||
public void put(Object key, Object value);
|
||||
public void remove(Object key);
|
||||
|
@ -41,8 +41,12 @@ class ChunkedInputStream extends LeftOverInputStream {
|
||||
|
||||
private boolean needToReadHeader = true;
|
||||
|
||||
static char CR = '\r';
|
||||
static char LF = '\n';
|
||||
final static char CR = '\r';
|
||||
final static char LF = '\n';
|
||||
/*
|
||||
* Maximum chunk header size of 2KB + 2 bytes for CRLF
|
||||
*/
|
||||
private final static int MAX_CHUNK_HEADER_SIZE = 2050;
|
||||
|
||||
private int numeric (char[] arr, int nchars) throws IOException {
|
||||
assert arr.length >= nchars;
|
||||
@ -73,10 +77,14 @@ class ChunkedInputStream extends LeftOverInputStream {
|
||||
char[] len_arr = new char [16];
|
||||
int len_size = 0;
|
||||
boolean end_of_len = false;
|
||||
int read = 0;
|
||||
|
||||
while ((c=in.read())!= -1) {
|
||||
char ch = (char) c;
|
||||
if (len_size == len_arr.length -1) {
|
||||
read++;
|
||||
if ((len_size == len_arr.length -1) ||
|
||||
(read > MAX_CHUNK_HEADER_SIZE))
|
||||
{
|
||||
throw new IOException ("invalid chunk header");
|
||||
}
|
||||
if (gotCR) {
|
||||
|
@ -125,6 +125,11 @@ class ChunkedInputStream extends InputStream implements Hurryable {
|
||||
*/
|
||||
private boolean closed;
|
||||
|
||||
/*
|
||||
* Maximum chunk header size of 2KB + 2 bytes for CRLF
|
||||
*/
|
||||
private final static int MAX_CHUNK_HEADER_SIZE = 2050;
|
||||
|
||||
/**
|
||||
* State to indicate that next field should be :-
|
||||
* chunk-size [ chunk-extension ] CRLF
|
||||
@ -290,6 +295,10 @@ class ChunkedInputStream extends InputStream implements Hurryable {
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
if ((pos - rawPos) >= MAX_CHUNK_HEADER_SIZE) {
|
||||
error = true;
|
||||
throw new IOException("Chunk header too long");
|
||||
}
|
||||
}
|
||||
if (pos >= rawCount) {
|
||||
return;
|
||||
|
@ -421,7 +421,7 @@ class DatagramChannelImpl
|
||||
|
||||
synchronized (writeLock) {
|
||||
ensureOpen();
|
||||
InetSocketAddress isa = (InetSocketAddress)target;
|
||||
InetSocketAddress isa = Net.checkAddress(target);
|
||||
InetAddress ia = isa.getAddress();
|
||||
if (ia == null)
|
||||
throw new IOException("Target address not resolved");
|
||||
@ -432,9 +432,9 @@ class DatagramChannelImpl
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
if (ia.isMulticastAddress()) {
|
||||
sm.checkMulticast(isa.getAddress());
|
||||
sm.checkMulticast(ia);
|
||||
} else {
|
||||
sm.checkConnect(isa.getAddress().getHostAddress(),
|
||||
sm.checkConnect(ia.getHostAddress(),
|
||||
isa.getPort());
|
||||
}
|
||||
}
|
||||
@ -454,7 +454,7 @@ class DatagramChannelImpl
|
||||
return 0;
|
||||
writerThread = NativeThread.current();
|
||||
do {
|
||||
n = send(fd, src, target);
|
||||
n = send(fd, src, isa);
|
||||
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
||||
|
||||
synchronized (stateLock) {
|
||||
@ -471,7 +471,7 @@ class DatagramChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
private int send(FileDescriptor fd, ByteBuffer src, SocketAddress target)
|
||||
private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target)
|
||||
throws IOException
|
||||
{
|
||||
if (src instanceof DirectBuffer)
|
||||
@ -502,7 +502,7 @@ class DatagramChannelImpl
|
||||
}
|
||||
|
||||
private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
|
||||
SocketAddress target)
|
||||
InetSocketAddress target)
|
||||
throws IOException
|
||||
{
|
||||
int pos = bb.position();
|
||||
@ -514,7 +514,7 @@ class DatagramChannelImpl
|
||||
int written;
|
||||
try {
|
||||
written = send0(preferIPv6, fd, ((DirectBuffer)bb).address() + pos,
|
||||
rem, target);
|
||||
rem, target.getAddress(), target.getPort());
|
||||
} catch (PortUnreachableException pue) {
|
||||
if (isConnected())
|
||||
throw pue;
|
||||
@ -1116,8 +1116,8 @@ class DatagramChannelImpl
|
||||
boolean connected)
|
||||
throws IOException;
|
||||
|
||||
private native int send0(boolean preferIPv6, FileDescriptor fd, long address, int len,
|
||||
SocketAddress sa)
|
||||
private native int send0(boolean preferIPv6, FileDescriptor fd, long address,
|
||||
int len, InetAddress addr, int port)
|
||||
throws IOException;
|
||||
|
||||
static {
|
||||
|
@ -252,6 +252,12 @@ public final class MethodUtil extends SecureClassLoader {
|
||||
public static Object invoke(Method m, Object obj, Object[] params)
|
||||
throws InvocationTargetException, IllegalAccessException {
|
||||
if (m.getDeclaringClass().equals(AccessController.class) ||
|
||||
(m.getDeclaringClass().equals(java.lang.invoke.MethodHandles.class)
|
||||
&& m.getName().equals("lookup")) ||
|
||||
(m.getDeclaringClass().equals(java.lang.invoke.MethodHandles.Lookup.class)
|
||||
&& (m.getName().startsWith("find") ||
|
||||
m.getName().startsWith("bind") ||
|
||||
m.getName().startsWith("unreflect"))) ||
|
||||
m.getDeclaringClass().equals(Method.class))
|
||||
throw new InvocationTargetException(
|
||||
new UnsupportedOperationException("invocation not supported"));
|
||||
|
@ -178,4 +178,31 @@ public final class ReflectUtil {
|
||||
|
||||
return !isAncestor(from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access check on the interfaces that a proxy class implements and throw
|
||||
* {@code SecurityException} if it accesses a restricted package.
|
||||
*
|
||||
* @param ccl the caller's class loader
|
||||
* @param interfaces the list of interfaces that a proxy class implements
|
||||
*
|
||||
* @see Proxy#checkProxyAccess
|
||||
*/
|
||||
public static void checkProxyPackageAccess(ClassLoader ccl,
|
||||
Class<?>... interfaces)
|
||||
{
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
for (Class<?> intf : interfaces) {
|
||||
ClassLoader cl = intf.getClassLoader();
|
||||
if (needsPackageAccessCheck(ccl, cl)) {
|
||||
checkPackageAccess(intf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note that bytecode instrumentation tools may exclude 'sun.*'
|
||||
// classes but not generated proxy classes and so keep it in com.sun.*
|
||||
public static final String PROXY_PACKAGE = "com.sun.proxy";
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ public final class CGIHandler {
|
||||
returnServerError(e.getMessage());
|
||||
}
|
||||
else
|
||||
returnClientError("invalid command: " + command);
|
||||
returnClientError("invalid command.");
|
||||
} catch (Exception e) {
|
||||
returnServerError("internal error: " + e.getMessage());
|
||||
}
|
||||
@ -225,7 +225,7 @@ final class CGIForwardCommand implements CGICommandHandler {
|
||||
try {
|
||||
port = Integer.parseInt(param);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new CGIClientException("invalid port number: " + param);
|
||||
throw new CGIClientException("invalid port number.");
|
||||
}
|
||||
if (port <= 0 || port > 0xFFFF)
|
||||
throw new CGIClientException("invalid port: " + port);
|
||||
@ -293,11 +293,14 @@ final class CGIForwardCommand implements CGICommandHandler {
|
||||
"unexpected EOF reading server response");
|
||||
|
||||
if (line.toLowerCase().startsWith(key)) {
|
||||
// if contentLengthFound is true
|
||||
// we should probably do something here
|
||||
responseContentLength =
|
||||
Integer.parseInt(line.substring(key.length()).trim());
|
||||
contentLengthFound = true;
|
||||
if (contentLengthFound) {
|
||||
throw new CGIServerException(
|
||||
"Multiple Content-length entries found.");
|
||||
} else {
|
||||
responseContentLength =
|
||||
Integer.parseInt(line.substring(key.length()).trim());
|
||||
contentLengthFound = true;
|
||||
}
|
||||
}
|
||||
} while ((line.length() != 0) &&
|
||||
(line.charAt(0) != '\r') && (line.charAt(0) != '\n'));
|
||||
|
@ -70,11 +70,14 @@ class HttpInputStream extends FilterInputStream {
|
||||
throw new EOFException();
|
||||
|
||||
if (line.toLowerCase().startsWith(key)) {
|
||||
// if contentLengthFound is true
|
||||
// we should probably do something here
|
||||
bytesLeft =
|
||||
Integer.parseInt(line.substring(key.length()).trim());
|
||||
contentLengthFound = true;
|
||||
if (contentLengthFound) {
|
||||
throw new IOException(
|
||||
"Multiple Content-length entries found.");
|
||||
} else {
|
||||
bytesLeft =
|
||||
Integer.parseInt(line.substring(key.length()).trim());
|
||||
contentLengthFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
// The idea here is to go past the first blank line.
|
||||
|
@ -37,6 +37,7 @@ import javax.crypto.spec.*;
|
||||
import static sun.security.pkcs11.TemplateManager.*;
|
||||
import sun.security.pkcs11.wrapper.*;
|
||||
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||
import sun.security.util.KeyUtil;
|
||||
|
||||
/**
|
||||
* KeyAgreement implementation class. This class currently supports
|
||||
@ -134,6 +135,10 @@ final class P11KeyAgreement extends KeyAgreementSpi {
|
||||
BigInteger p, g, y;
|
||||
if (key instanceof DHPublicKey) {
|
||||
DHPublicKey dhKey = (DHPublicKey)key;
|
||||
|
||||
// validate the Diffie-Hellman public key
|
||||
KeyUtil.validate(dhKey);
|
||||
|
||||
y = dhKey.getY();
|
||||
DHParameterSpec params = dhKey.getParams();
|
||||
p = params.getP();
|
||||
@ -145,6 +150,10 @@ final class P11KeyAgreement extends KeyAgreementSpi {
|
||||
try {
|
||||
DHPublicKeySpec spec = kf.engineGetKeySpec(
|
||||
key, DHPublicKeySpec.class);
|
||||
|
||||
// validate the Diffie-Hellman public key
|
||||
KeyUtil.validate(spec);
|
||||
|
||||
y = spec.getY();
|
||||
p = spec.getP();
|
||||
g = spec.getG();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -392,7 +392,8 @@ final class CipherBox {
|
||||
* uniformly use the bad_record_mac alert to hide the specific type of
|
||||
* the error.
|
||||
*/
|
||||
int decrypt(byte[] buf, int offset, int len) throws BadPaddingException {
|
||||
int decrypt(byte[] buf, int offset, int len,
|
||||
int tagLen) throws BadPaddingException {
|
||||
if (cipher == null) {
|
||||
return len;
|
||||
}
|
||||
@ -416,9 +417,10 @@ final class CipherBox {
|
||||
System.out);
|
||||
} catch (IOException e) { }
|
||||
}
|
||||
|
||||
if (blockSize != 0) {
|
||||
newLen = removePadding(buf, offset, newLen,
|
||||
blockSize, protocolVersion);
|
||||
newLen = removePadding(
|
||||
buf, offset, newLen, tagLen, blockSize, protocolVersion);
|
||||
|
||||
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
|
||||
if (newLen < blockSize) {
|
||||
@ -448,7 +450,7 @@ final class CipherBox {
|
||||
*
|
||||
* @see decrypt(byte[], int, int)
|
||||
*/
|
||||
int decrypt(ByteBuffer bb) throws BadPaddingException {
|
||||
int decrypt(ByteBuffer bb, int tagLen) throws BadPaddingException {
|
||||
|
||||
int len = bb.remaining();
|
||||
|
||||
@ -471,7 +473,6 @@ final class CipherBox {
|
||||
}
|
||||
|
||||
if (debug != null && Debug.isOn("plaintext")) {
|
||||
bb.position(pos);
|
||||
try {
|
||||
HexDumpEncoder hd = new HexDumpEncoder();
|
||||
|
||||
@ -479,7 +480,8 @@ final class CipherBox {
|
||||
"Padded plaintext after DECRYPTION: len = "
|
||||
+ newLen);
|
||||
|
||||
hd.encodeBuffer(bb, System.out);
|
||||
hd.encodeBuffer(
|
||||
(ByteBuffer)bb.duplicate().position(pos), System.out);
|
||||
} catch (IOException e) { }
|
||||
}
|
||||
|
||||
@ -488,7 +490,8 @@ final class CipherBox {
|
||||
*/
|
||||
if (blockSize != 0) {
|
||||
bb.position(pos);
|
||||
newLen = removePadding(bb, blockSize, protocolVersion);
|
||||
newLen = removePadding(
|
||||
bb, tagLen, blockSize, protocolVersion);
|
||||
|
||||
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
|
||||
if (newLen < blockSize) {
|
||||
@ -590,6 +593,65 @@ final class CipherBox {
|
||||
return newlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* A constant-time check of the padding.
|
||||
*
|
||||
* NOTE that we are checking both the padding and the padLen bytes here.
|
||||
*
|
||||
* The caller MUST ensure that the len parameter is a positive number.
|
||||
*/
|
||||
private static int[] checkPadding(
|
||||
byte[] buf, int offset, int len, byte pad) {
|
||||
|
||||
if (len <= 0) {
|
||||
throw new RuntimeException("padding len must be positive");
|
||||
}
|
||||
|
||||
// An array of hits is used to prevent Hotspot optimization for
|
||||
// the purpose of a constant-time check.
|
||||
int[] results = {0, 0}; // {missed #, matched #}
|
||||
for (int i = 0; i <= 256;) {
|
||||
for (int j = 0; j < len && i <= 256; j++, i++) { // j <= i
|
||||
if (buf[offset + j] != pad) {
|
||||
results[0]++; // mismatched padding data
|
||||
} else {
|
||||
results[1]++; // matched padding data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/*
|
||||
* A constant-time check of the padding.
|
||||
*
|
||||
* NOTE that we are checking both the padding and the padLen bytes here.
|
||||
*
|
||||
* The caller MUST ensure that the bb parameter has remaining.
|
||||
*/
|
||||
private static int[] checkPadding(ByteBuffer bb, byte pad) {
|
||||
|
||||
if (!bb.hasRemaining()) {
|
||||
throw new RuntimeException("hasRemaining() must be positive");
|
||||
}
|
||||
|
||||
// An array of hits is used to prevent Hotspot optimization for
|
||||
// the purpose of a constant-time check.
|
||||
int[] results = {0, 0}; // {missed #, matched #}
|
||||
bb.mark();
|
||||
for (int i = 0; i <= 256; bb.reset()) {
|
||||
for (; bb.hasRemaining() && i <= 256; i++) {
|
||||
if (bb.get() != pad) {
|
||||
results[0]++; // mismatched padding data
|
||||
} else {
|
||||
results[1]++; // matched padding data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/*
|
||||
* Typical TLS padding format for a 64 bit block cipher is as follows:
|
||||
@ -602,86 +664,95 @@ final class CipherBox {
|
||||
* as it makes the data a multiple of the block size
|
||||
*/
|
||||
private static int removePadding(byte[] buf, int offset, int len,
|
||||
int blockSize, ProtocolVersion protocolVersion)
|
||||
throws BadPaddingException {
|
||||
int tagLen, int blockSize,
|
||||
ProtocolVersion protocolVersion) throws BadPaddingException {
|
||||
|
||||
// last byte is length byte (i.e. actual padding length - 1)
|
||||
int padOffset = offset + len - 1;
|
||||
int pad = buf[padOffset] & 0x0ff;
|
||||
int padLen = buf[padOffset] & 0xFF;
|
||||
|
||||
int newlen = len - (pad + 1);
|
||||
if (newlen < 0) {
|
||||
throw new BadPaddingException("Padding length invalid: " + pad);
|
||||
int newLen = len - (padLen + 1);
|
||||
if ((newLen - tagLen) < 0) {
|
||||
// If the buffer is not long enough to contain the padding plus
|
||||
// a MAC tag, do a dummy constant-time padding check.
|
||||
//
|
||||
// Note that it is a dummy check, so we won't care about what is
|
||||
// the actual padding data.
|
||||
checkPadding(buf, offset, len, (byte)(padLen & 0xFF));
|
||||
|
||||
throw new BadPaddingException("Invalid Padding length: " + padLen);
|
||||
}
|
||||
|
||||
// The padding data should be filled with the padding length value.
|
||||
int[] results = checkPadding(buf, offset + newLen,
|
||||
padLen + 1, (byte)(padLen & 0xFF));
|
||||
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
|
||||
for (int i = 1; i <= pad; i++) {
|
||||
int val = buf[padOffset - i] & 0xff;
|
||||
if (val != pad) {
|
||||
throw new BadPaddingException
|
||||
("Invalid TLS padding: " + val);
|
||||
}
|
||||
if (results[0] != 0) { // padding data has invalid bytes
|
||||
throw new BadPaddingException("Invalid TLS padding data");
|
||||
}
|
||||
} else { // SSLv3
|
||||
// SSLv3 requires 0 <= length byte < block size
|
||||
// some implementations do 1 <= length byte <= block size,
|
||||
// so accept that as well
|
||||
// v3 does not require any particular value for the other bytes
|
||||
if (pad > blockSize) {
|
||||
throw new BadPaddingException("Invalid SSLv3 padding: " + pad);
|
||||
if (padLen > blockSize) {
|
||||
throw new BadPaddingException("Invalid SSLv3 padding");
|
||||
}
|
||||
}
|
||||
return newlen;
|
||||
return newLen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Position/limit is equal the removed padding.
|
||||
*/
|
||||
private static int removePadding(ByteBuffer bb,
|
||||
int blockSize, ProtocolVersion protocolVersion)
|
||||
throws BadPaddingException {
|
||||
int tagLen, int blockSize,
|
||||
ProtocolVersion protocolVersion) throws BadPaddingException {
|
||||
|
||||
int len = bb.remaining();
|
||||
int offset = bb.position();
|
||||
|
||||
// last byte is length byte (i.e. actual padding length - 1)
|
||||
int padOffset = offset + len - 1;
|
||||
int pad = bb.get(padOffset) & 0x0ff;
|
||||
int padLen = bb.get(padOffset) & 0xFF;
|
||||
|
||||
int newlen = len - (pad + 1);
|
||||
if (newlen < 0) {
|
||||
throw new BadPaddingException("Padding length invalid: " + pad);
|
||||
int newLen = len - (padLen + 1);
|
||||
if ((newLen - tagLen) < 0) {
|
||||
// If the buffer is not long enough to contain the padding plus
|
||||
// a MAC tag, do a dummy constant-time padding check.
|
||||
//
|
||||
// Note that it is a dummy check, so we won't care about what is
|
||||
// the actual padding data.
|
||||
checkPadding(bb.duplicate(), (byte)(padLen & 0xFF));
|
||||
|
||||
throw new BadPaddingException("Invalid Padding length: " + padLen);
|
||||
}
|
||||
|
||||
/*
|
||||
* We could zero the padding area, but not much useful
|
||||
* information there.
|
||||
*/
|
||||
// The padding data should be filled with the padding length value.
|
||||
int[] results = checkPadding(
|
||||
(ByteBuffer)bb.duplicate().position(offset + newLen),
|
||||
(byte)(padLen & 0xFF));
|
||||
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
|
||||
bb.put(padOffset, (byte)0); // zero the padding.
|
||||
for (int i = 1; i <= pad; i++) {
|
||||
int val = bb.get(padOffset - i) & 0xff;
|
||||
if (val != pad) {
|
||||
throw new BadPaddingException
|
||||
("Invalid TLS padding: " + val);
|
||||
}
|
||||
if (results[0] != 0) { // padding data has invalid bytes
|
||||
throw new BadPaddingException("Invalid TLS padding data");
|
||||
}
|
||||
} else { // SSLv3
|
||||
// SSLv3 requires 0 <= length byte < block size
|
||||
// some implementations do 1 <= length byte <= block size,
|
||||
// so accept that as well
|
||||
// v3 does not require any particular value for the other bytes
|
||||
if (pad > blockSize) {
|
||||
throw new BadPaddingException("Invalid SSLv3 padding: " + pad);
|
||||
if (padLen > blockSize) {
|
||||
throw new BadPaddingException("Invalid SSLv3 padding");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset buffer limit to remove padding.
|
||||
*/
|
||||
bb.position(offset + newlen);
|
||||
bb.limit(offset + newlen);
|
||||
bb.position(offset + newLen);
|
||||
bb.limit(offset + newLen);
|
||||
|
||||
return newlen;
|
||||
return newLen;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -708,4 +779,45 @@ final class CipherBox {
|
||||
boolean isCBCMode() {
|
||||
return isCBCMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the cipher null?
|
||||
*
|
||||
* @return true if the cipher is null, false otherwise.
|
||||
*/
|
||||
boolean isNullCipher() {
|
||||
return cipher == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanity check the length of a fragment before decryption.
|
||||
*
|
||||
* In CBC mode, check that the fragment length is one or multiple times
|
||||
* of the block size of the cipher suite, and is at least one (one is the
|
||||
* smallest size of padding in CBC mode) bigger than the tag size of the
|
||||
* MAC algorithm except the explicit IV size for TLS 1.1 or later.
|
||||
*
|
||||
* In non-CBC mode, check that the fragment length is not less than the
|
||||
* tag size of the MAC algorithm.
|
||||
*
|
||||
* @return true if the length of a fragment matches above requirements
|
||||
*/
|
||||
boolean sanityCheck(int tagLen, int fragmentLen) {
|
||||
if (!isCBCMode) {
|
||||
return fragmentLen >= tagLen;
|
||||
}
|
||||
|
||||
if ((fragmentLen % blockSize) == 0) {
|
||||
int minimal = tagLen + 1;
|
||||
minimal = (minimal >= blockSize) ? minimal : blockSize;
|
||||
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
|
||||
minimal += blockSize; // plus the size of the explicit IV
|
||||
}
|
||||
|
||||
return (fragmentLen >= minimal);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -549,9 +549,18 @@ final class CipherSuite implements Comparable<CipherSuite> {
|
||||
// size of the MAC value (and MAC key) in bytes
|
||||
final int size;
|
||||
|
||||
MacAlg(String name, int size) {
|
||||
// block size of the underlying hash algorithm
|
||||
final int hashBlockSize;
|
||||
|
||||
// minimal padding size of the underlying hash algorithm
|
||||
final int minimalPaddingSize;
|
||||
|
||||
MacAlg(String name, int size,
|
||||
int hashBlockSize, int minimalPaddingSize) {
|
||||
this.name = name;
|
||||
this.size = size;
|
||||
this.hashBlockSize = hashBlockSize;
|
||||
this.minimalPaddingSize = minimalPaddingSize;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -596,11 +605,11 @@ final class CipherSuite implements Comparable<CipherSuite> {
|
||||
new BulkCipher(CIPHER_AES, 32, 16, true);
|
||||
|
||||
// MACs
|
||||
final static MacAlg M_NULL = new MacAlg("NULL", 0);
|
||||
final static MacAlg M_MD5 = new MacAlg("MD5", 16);
|
||||
final static MacAlg M_SHA = new MacAlg("SHA", 20);
|
||||
final static MacAlg M_SHA256 = new MacAlg("SHA256", 32);
|
||||
final static MacAlg M_SHA384 = new MacAlg("SHA384", 48);
|
||||
final static MacAlg M_NULL = new MacAlg("NULL", 0, 0, 0);
|
||||
final static MacAlg M_MD5 = new MacAlg("MD5", 16, 64, 9);
|
||||
final static MacAlg M_SHA = new MacAlg("SHA", 20, 64, 9);
|
||||
final static MacAlg M_SHA256 = new MacAlg("SHA256", 32, 64, 9);
|
||||
final static MacAlg M_SHA384 = new MacAlg("SHA384", 48, 128, 17);
|
||||
|
||||
/**
|
||||
* PRFs (PseudoRandom Function) from TLS specifications.
|
||||
|
@ -129,9 +129,8 @@ final class ClientHandshaker extends Handshaker {
|
||||
*/
|
||||
@Override
|
||||
void processMessage(byte type, int messageLen) throws IOException {
|
||||
if (state > type
|
||||
&& (type != HandshakeMessage.ht_hello_request
|
||||
&& state != HandshakeMessage.ht_client_hello)) {
|
||||
if (state >= type
|
||||
&& (type != HandshakeMessage.ht_hello_request)) {
|
||||
throw new SSLProtocolException(
|
||||
"Handshake message sequence violation, " + type);
|
||||
}
|
||||
@ -194,8 +193,12 @@ final class ClientHandshaker extends Handshaker {
|
||||
}
|
||||
break;
|
||||
case K_DH_ANON:
|
||||
this.serverKeyExchange(new DH_ServerKeyExchange(
|
||||
try {
|
||||
this.serverKeyExchange(new DH_ServerKeyExchange(
|
||||
input, protocolVersion));
|
||||
} catch (GeneralSecurityException e) {
|
||||
throwSSLException("Server key", e);
|
||||
}
|
||||
break;
|
||||
case K_DHE_DSS:
|
||||
case K_DHE_RSA:
|
||||
@ -921,7 +924,7 @@ final class ClientHandshaker extends Handshaker {
|
||||
case K_DHE_RSA:
|
||||
case K_DHE_DSS:
|
||||
case K_DH_ANON:
|
||||
preMasterSecret = dh.getAgreedSecret(serverDH);
|
||||
preMasterSecret = dh.getAgreedSecret(serverDH, true);
|
||||
break;
|
||||
case K_ECDHE_RSA:
|
||||
case K_ECDHE_ECDSA:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,7 +29,7 @@ package sun.security.ssl;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
|
||||
/*
|
||||
* Message used by clients to send their Diffie-Hellman public
|
||||
@ -51,7 +51,7 @@ final class DHClientKeyExchange extends HandshakeMessage {
|
||||
private byte dh_Yc[]; // 1 to 2^16 -1 bytes
|
||||
|
||||
BigInteger getClientPublicKey() {
|
||||
return new BigInteger(1, dh_Yc);
|
||||
return dh_Yc == null ? null : new BigInteger(1, dh_Yc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -73,7 +73,14 @@ final class DHClientKeyExchange extends HandshakeMessage {
|
||||
* but that's what the protocol spec requires.)
|
||||
*/
|
||||
DHClientKeyExchange(HandshakeInStream input) throws IOException {
|
||||
dh_Yc = input.getBytes16();
|
||||
if (input.available() >= 2) {
|
||||
dh_Yc = input.getBytes16();
|
||||
} else {
|
||||
// currently, we don't support cipher suites that requires
|
||||
// implicit public key of client.
|
||||
throw new SSLHandshakeException(
|
||||
"Unsupported implicit client DiffieHellman public key");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -87,7 +94,9 @@ final class DHClientKeyExchange extends HandshakeMessage {
|
||||
|
||||
@Override
|
||||
void send(HandshakeOutStream s) throws IOException {
|
||||
s.putBytes16(dh_Yc);
|
||||
if (dh_Yc != null && dh_Yc.length != 0) {
|
||||
s.putBytes16(dh_Yc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,12 +28,15 @@ package sun.security.ssl;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.KeyAgreement;
|
||||
import javax.crypto.interfaces.DHPublicKey;
|
||||
import javax.crypto.spec.*;
|
||||
|
||||
import sun.security.util.KeyUtil;
|
||||
|
||||
/**
|
||||
* This class implements the Diffie-Hellman key exchange algorithm.
|
||||
* D-H means combining your private key with your partners public key to
|
||||
@ -54,7 +57,8 @@ import javax.crypto.spec.*;
|
||||
* . if we are server, call DHCrypt(keyLength,random). This generates
|
||||
* an ephemeral keypair of the request length.
|
||||
* . if we are client, call DHCrypt(modulus, base, random). This
|
||||
* generates an ephemeral keypair using the parameters specified by the server.
|
||||
* generates an ephemeral keypair using the parameters specified by
|
||||
* the server.
|
||||
* . send parameters and public value to remote peer
|
||||
* . receive peers ephemeral public key
|
||||
* . call getAgreedSecret() to calculate the shared secret
|
||||
@ -83,6 +87,9 @@ final class DHCrypt {
|
||||
// public component of our key, X = (g ^ x) mod p
|
||||
private BigInteger publicValue; // X (aka y)
|
||||
|
||||
// the times to recove from failure if public key validation
|
||||
private static int MAX_FAILOVER_TIMES = 2;
|
||||
|
||||
/**
|
||||
* Generate a Diffie-Hellman keypair of the specified size.
|
||||
*/
|
||||
@ -90,9 +97,12 @@ final class DHCrypt {
|
||||
try {
|
||||
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
|
||||
kpg.initialize(keyLength, random);
|
||||
KeyPair kp = kpg.generateKeyPair();
|
||||
privateKey = kp.getPrivate();
|
||||
DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
|
||||
|
||||
DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
|
||||
if (spec == null) {
|
||||
throw new RuntimeException("Could not generate DH keypair");
|
||||
}
|
||||
|
||||
publicValue = spec.getY();
|
||||
modulus = spec.getP();
|
||||
base = spec.getG();
|
||||
@ -115,20 +125,25 @@ final class DHCrypt {
|
||||
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
|
||||
DHParameterSpec params = new DHParameterSpec(modulus, base);
|
||||
kpg.initialize(params, random);
|
||||
KeyPair kp = kpg.generateKeyPair();
|
||||
privateKey = kp.getPrivate();
|
||||
DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
|
||||
|
||||
DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
|
||||
if (spec == null) {
|
||||
throw new RuntimeException("Could not generate DH keypair");
|
||||
}
|
||||
|
||||
publicValue = spec.getY();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new RuntimeException("Could not generate DH keypair", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static DHPublicKeySpec getDHPublicKeySpec(PublicKey key) {
|
||||
if (key instanceof DHPublicKey) {
|
||||
DHPublicKey dhKey = (DHPublicKey)key;
|
||||
DHParameterSpec params = dhKey.getParams();
|
||||
return new DHPublicKeySpec(dhKey.getY(), params.getP(), params.getG());
|
||||
return new DHPublicKeySpec(dhKey.getY(),
|
||||
params.getP(), params.getG());
|
||||
}
|
||||
try {
|
||||
KeyFactory factory = JsseJce.getKeyFactory("DH");
|
||||
@ -166,17 +181,32 @@ final class DHCrypt {
|
||||
* <P>It is illegal to call this member function if the private key
|
||||
* has not been set (or generated).
|
||||
*
|
||||
* @param peerPublicKey the peer's public key.
|
||||
* @returns the secret, which is an unsigned big-endian integer
|
||||
* the same size as the Diffie-Hellman modulus.
|
||||
* @param peerPublicKey the peer's public key.
|
||||
* @param keyIsValidated whether the {@code peerPublicKey} has beed
|
||||
* validated
|
||||
* @return the secret, which is an unsigned big-endian integer
|
||||
* the same size as the Diffie-Hellman modulus.
|
||||
*/
|
||||
SecretKey getAgreedSecret(BigInteger peerPublicValue) {
|
||||
SecretKey getAgreedSecret(BigInteger peerPublicValue,
|
||||
boolean keyIsValidated) throws IOException {
|
||||
try {
|
||||
KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
|
||||
DHPublicKeySpec spec =
|
||||
new DHPublicKeySpec(peerPublicValue, modulus, base);
|
||||
PublicKey publicKey = kf.generatePublic(spec);
|
||||
KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
|
||||
|
||||
// validate the Diffie-Hellman public key
|
||||
if (!keyIsValidated &&
|
||||
!KeyUtil.isOracleJCEProvider(ka.getProvider().getName())) {
|
||||
try {
|
||||
KeyUtil.validate(spec);
|
||||
} catch (InvalidKeyException ike) {
|
||||
// prefer handshake_failure alert to internal_error alert
|
||||
throw new SSLHandshakeException(ike.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
ka.init(privateKey);
|
||||
ka.doPhase(publicKey, true);
|
||||
return ka.generateSecret("TlsPremasterSecret");
|
||||
@ -185,4 +215,33 @@ final class DHCrypt {
|
||||
}
|
||||
}
|
||||
|
||||
// Generate and validate DHPublicKeySpec
|
||||
private DHPublicKeySpec generateDHPublicKeySpec(KeyPairGenerator kpg)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
boolean doExtraValiadtion =
|
||||
(!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName()));
|
||||
for (int i = 0; i <= MAX_FAILOVER_TIMES; i++) {
|
||||
KeyPair kp = kpg.generateKeyPair();
|
||||
privateKey = kp.getPrivate();
|
||||
DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
|
||||
|
||||
// validate the Diffie-Hellman public key
|
||||
if (doExtraValiadtion) {
|
||||
try {
|
||||
KeyUtil.validate(spec);
|
||||
} catch (InvalidKeyException ivke) {
|
||||
if (i == MAX_FAILOVER_TIMES) {
|
||||
throw ivke;
|
||||
}
|
||||
// otherwise, ignore the exception and try the next one
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -177,71 +177,6 @@ final class EngineInputRecord extends InputRecord {
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verifies and removes the MAC value. Returns true if
|
||||
* the MAC checks out OK.
|
||||
*
|
||||
* On entry:
|
||||
* position = beginning of app/MAC data
|
||||
* limit = end of MAC data.
|
||||
*
|
||||
* On return:
|
||||
* position = beginning of app data
|
||||
* limit = end of app data
|
||||
*/
|
||||
boolean checkMAC(MAC signer, ByteBuffer bb) {
|
||||
if (internalData) {
|
||||
return checkMAC(signer);
|
||||
}
|
||||
|
||||
int len = signer.MAClen();
|
||||
if (len == 0) { // no mac
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab the original limit
|
||||
*/
|
||||
int lim = bb.limit();
|
||||
|
||||
/*
|
||||
* Delineate the area to apply a MAC on.
|
||||
*/
|
||||
int macData = lim - len;
|
||||
bb.limit(macData);
|
||||
|
||||
byte[] mac = signer.compute(contentType(), bb);
|
||||
|
||||
if (len != mac.length) {
|
||||
throw new RuntimeException("Internal MAC error");
|
||||
}
|
||||
|
||||
/*
|
||||
* Delineate the MAC values, position was already set
|
||||
* by doing the compute above.
|
||||
*
|
||||
* We could zero the MAC area, but not much useful information
|
||||
* there anyway.
|
||||
*/
|
||||
bb.position(macData);
|
||||
bb.limit(lim);
|
||||
|
||||
try {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (bb.get() != mac[i]) { // No BB.equals(byte []); !
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} finally {
|
||||
/*
|
||||
* Position to the data.
|
||||
*/
|
||||
bb.rewind();
|
||||
bb.limit(macData);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass the data down if it's internally cached, otherwise
|
||||
* do it here.
|
||||
@ -251,20 +186,163 @@ final class EngineInputRecord extends InputRecord {
|
||||
* If external data(app), return a new ByteBuffer with data to
|
||||
* process.
|
||||
*/
|
||||
ByteBuffer decrypt(CipherBox box, ByteBuffer bb)
|
||||
throws BadPaddingException {
|
||||
ByteBuffer decrypt(MAC signer,
|
||||
CipherBox box, ByteBuffer bb) throws BadPaddingException {
|
||||
|
||||
if (internalData) {
|
||||
decrypt(box);
|
||||
decrypt(signer, box); // MAC is checked during decryption
|
||||
return tmpBB;
|
||||
}
|
||||
|
||||
box.decrypt(bb);
|
||||
bb.rewind();
|
||||
BadPaddingException reservedBPE = null;
|
||||
int tagLen = signer.MAClen();
|
||||
int cipheredLength = bb.remaining();
|
||||
|
||||
if (!box.isNullCipher()) {
|
||||
// sanity check length of the ciphertext
|
||||
if (!box.sanityCheck(tagLen, cipheredLength)) {
|
||||
throw new BadPaddingException(
|
||||
"ciphertext sanity check failed");
|
||||
}
|
||||
|
||||
try {
|
||||
// Note that the CipherBox.decrypt() does not change
|
||||
// the capacity of the buffer.
|
||||
box.decrypt(bb, tagLen);
|
||||
} catch (BadPaddingException bpe) {
|
||||
// RFC 2246 states that decryption_failed should be used
|
||||
// for this purpose. However, that allows certain attacks,
|
||||
// so we just send bad record MAC. We also need to make
|
||||
// sure to always check the MAC to avoid a timing attack
|
||||
// for the same issue. See paper by Vaudenay et al and the
|
||||
// update in RFC 4346/5246.
|
||||
//
|
||||
// Failover to message authentication code checking.
|
||||
reservedBPE = bpe;
|
||||
} finally {
|
||||
bb.rewind();
|
||||
}
|
||||
}
|
||||
|
||||
if (tagLen != 0) {
|
||||
int macOffset = bb.limit() - tagLen;
|
||||
|
||||
// Note that although it is not necessary, we run the same MAC
|
||||
// computation and comparison on the payload for both stream
|
||||
// cipher and CBC block cipher.
|
||||
if (bb.remaining() < tagLen) {
|
||||
// negative data length, something is wrong
|
||||
if (reservedBPE == null) {
|
||||
reservedBPE = new BadPaddingException("bad record");
|
||||
}
|
||||
|
||||
// set offset of the dummy MAC
|
||||
macOffset = cipheredLength - tagLen;
|
||||
bb.limit(cipheredLength);
|
||||
}
|
||||
|
||||
// Run MAC computation and comparison on the payload.
|
||||
if (checkMacTags(contentType(), bb, signer, false)) {
|
||||
if (reservedBPE == null) {
|
||||
reservedBPE = new BadPaddingException("bad record MAC");
|
||||
}
|
||||
}
|
||||
|
||||
// Run MAC computation and comparison on the remainder.
|
||||
//
|
||||
// It is only necessary for CBC block cipher. It is used to get a
|
||||
// constant time of MAC computation and comparison on each record.
|
||||
if (box.isCBCMode()) {
|
||||
int remainingLen = calculateRemainingLen(
|
||||
signer, cipheredLength, macOffset);
|
||||
|
||||
// NOTE: here we use the InputRecord.buf because I did not find
|
||||
// an effective way to work on ByteBuffer when its capacity is
|
||||
// less than remainingLen.
|
||||
|
||||
// NOTE: remainingLen may be bigger (less than 1 block of the
|
||||
// hash algorithm of the MAC) than the cipheredLength. However,
|
||||
// We won't need to worry about it because we always use a
|
||||
// maximum buffer for every record. We need a change here if
|
||||
// we use small buffer size in the future.
|
||||
if (remainingLen > buf.length) {
|
||||
// unlikely to happen, just a placehold
|
||||
throw new RuntimeException(
|
||||
"Internal buffer capacity error");
|
||||
}
|
||||
|
||||
// Won't need to worry about the result on the remainder. And
|
||||
// then we won't need to worry about what's actual data to
|
||||
// check MAC tag on. We start the check from the header of the
|
||||
// buffer so that we don't need to construct a new byte buffer.
|
||||
checkMacTags(contentType(), buf, 0, remainingLen, signer, true);
|
||||
}
|
||||
|
||||
bb.limit(macOffset);
|
||||
}
|
||||
|
||||
// Is it a failover?
|
||||
if (reservedBPE != null) {
|
||||
throw reservedBPE;
|
||||
}
|
||||
|
||||
return bb.slice();
|
||||
}
|
||||
|
||||
/*
|
||||
* Run MAC computation and comparison
|
||||
*
|
||||
* Please DON'T change the content of the ByteBuffer parameter!
|
||||
*/
|
||||
private static boolean checkMacTags(byte contentType, ByteBuffer bb,
|
||||
MAC signer, boolean isSimulated) {
|
||||
|
||||
int tagLen = signer.MAClen();
|
||||
int lim = bb.limit();
|
||||
int macData = lim - tagLen;
|
||||
|
||||
bb.limit(macData);
|
||||
byte[] hash = signer.compute(contentType, bb, isSimulated);
|
||||
if (hash == null || tagLen != hash.length) {
|
||||
// Something is wrong with MAC implementation.
|
||||
throw new RuntimeException("Internal MAC error");
|
||||
}
|
||||
|
||||
bb.position(macData);
|
||||
bb.limit(lim);
|
||||
try {
|
||||
int[] results = compareMacTags(bb, hash);
|
||||
return (results[0] != 0);
|
||||
} finally {
|
||||
bb.rewind();
|
||||
bb.limit(macData);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A constant-time comparison of the MAC tags.
|
||||
*
|
||||
* Please DON'T change the content of the ByteBuffer parameter!
|
||||
*/
|
||||
private static int[] compareMacTags(ByteBuffer bb, byte[] tag) {
|
||||
|
||||
// An array of hits is used to prevent Hotspot optimization for
|
||||
// the purpose of a constant-time check.
|
||||
int[] results = {0, 0}; // {missed #, matched #}
|
||||
|
||||
// The caller ensures there are enough bytes available in the buffer.
|
||||
// So we won't need to check the remaining of the buffer.
|
||||
for (int i = 0; i < tag.length; i++) {
|
||||
if (bb.get() != tag[i]) {
|
||||
results[0]++; // mismatched bytes
|
||||
} else {
|
||||
results[1]++; // matched bytes
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/*
|
||||
* Override the actual write below. We do things this way to be
|
||||
* consistent with InputRecord. InputRecord may try to write out
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -118,7 +118,7 @@ final class EngineOutputRecord extends OutputRecord {
|
||||
throws IOException {
|
||||
|
||||
if (signer.MAClen() != 0) {
|
||||
byte[] hash = signer.compute(contentType(), bb);
|
||||
byte[] hash = signer.compute(contentType(), bb, false);
|
||||
|
||||
/*
|
||||
* position was advanced to limit in compute above.
|
||||
|
@ -41,12 +41,14 @@ import javax.security.auth.x500.X500Principal;
|
||||
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.DHPublicKeySpec;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
|
||||
import sun.security.internal.spec.TlsPrfParameterSpec;
|
||||
import sun.security.ssl.CipherSuite.*;
|
||||
import static sun.security.ssl.CipherSuite.PRF.*;
|
||||
import sun.security.util.KeyUtil;
|
||||
|
||||
/**
|
||||
* Many data structures are involved in the handshake messages. These
|
||||
@ -712,6 +714,7 @@ class DH_ServerKeyExchange extends ServerKeyExchange
|
||||
this.protocolVersion = protocolVersion;
|
||||
this.preferableSignatureAlgorithm = null;
|
||||
|
||||
// The DH key has been validated in the constructor of DHCrypt.
|
||||
setValues(obj);
|
||||
signature = null;
|
||||
}
|
||||
@ -728,6 +731,7 @@ class DH_ServerKeyExchange extends ServerKeyExchange
|
||||
|
||||
this.protocolVersion = protocolVersion;
|
||||
|
||||
// The DH key has been validated in the constructor of DHCrypt.
|
||||
setValues(obj);
|
||||
|
||||
Signature sig;
|
||||
@ -754,7 +758,8 @@ class DH_ServerKeyExchange extends ServerKeyExchange
|
||||
* DH_anon key exchange
|
||||
*/
|
||||
DH_ServerKeyExchange(HandshakeInStream input,
|
||||
ProtocolVersion protocolVersion) throws IOException {
|
||||
ProtocolVersion protocolVersion)
|
||||
throws IOException, GeneralSecurityException {
|
||||
|
||||
this.protocolVersion = protocolVersion;
|
||||
this.preferableSignatureAlgorithm = null;
|
||||
@ -762,6 +767,10 @@ class DH_ServerKeyExchange extends ServerKeyExchange
|
||||
dh_p = input.getBytes16();
|
||||
dh_g = input.getBytes16();
|
||||
dh_Ys = input.getBytes16();
|
||||
KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
|
||||
new BigInteger(1, dh_p),
|
||||
new BigInteger(1, dh_g)));
|
||||
|
||||
signature = null;
|
||||
}
|
||||
|
||||
@ -782,6 +791,9 @@ class DH_ServerKeyExchange extends ServerKeyExchange
|
||||
dh_p = input.getBytes16();
|
||||
dh_g = input.getBytes16();
|
||||
dh_Ys = input.getBytes16();
|
||||
KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
|
||||
new BigInteger(1, dh_p),
|
||||
new BigInteger(1, dh_g)));
|
||||
|
||||
// read the signature and hash algorithm
|
||||
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -133,43 +133,173 @@ class InputRecord extends ByteArrayInputStream implements Record {
|
||||
return handshakeHash;
|
||||
}
|
||||
|
||||
void decrypt(MAC signer, CipherBox box) throws BadPaddingException {
|
||||
|
||||
BadPaddingException reservedBPE = null;
|
||||
int tagLen = signer.MAClen();
|
||||
int cipheredLength = count - headerSize;
|
||||
|
||||
if (!box.isNullCipher()) {
|
||||
// sanity check length of the ciphertext
|
||||
if (!box.sanityCheck(tagLen, cipheredLength)) {
|
||||
throw new BadPaddingException(
|
||||
"ciphertext sanity check failed");
|
||||
}
|
||||
|
||||
try {
|
||||
// Note that the CipherBox.decrypt() does not change
|
||||
// the capacity of the buffer.
|
||||
count = headerSize +
|
||||
box.decrypt(buf, headerSize, cipheredLength, tagLen);
|
||||
} catch (BadPaddingException bpe) {
|
||||
// RFC 2246 states that decryption_failed should be used
|
||||
// for this purpose. However, that allows certain attacks,
|
||||
// so we just send bad record MAC. We also need to make
|
||||
// sure to always check the MAC to avoid a timing attack
|
||||
// for the same issue. See paper by Vaudenay et al and the
|
||||
// update in RFC 4346/5246.
|
||||
//
|
||||
// Failover to message authentication code checking.
|
||||
reservedBPE = bpe;
|
||||
}
|
||||
}
|
||||
|
||||
if (tagLen != 0) {
|
||||
int macOffset = count - tagLen;
|
||||
int contentLen = macOffset - headerSize;
|
||||
|
||||
// Note that although it is not necessary, we run the same MAC
|
||||
// computation and comparison on the payload for both stream
|
||||
// cipher and CBC block cipher.
|
||||
if (contentLen < 0) {
|
||||
// negative data length, something is wrong
|
||||
if (reservedBPE == null) {
|
||||
reservedBPE = new BadPaddingException("bad record");
|
||||
}
|
||||
|
||||
// set offset of the dummy MAC
|
||||
macOffset = headerSize + cipheredLength - tagLen;
|
||||
contentLen = macOffset - headerSize;
|
||||
}
|
||||
|
||||
count -= tagLen; // Set the count before any MAC checking
|
||||
// exception occurs, so that the following
|
||||
// process can read the actual decrypted
|
||||
// content (minus the MAC) in the fragment
|
||||
// if necessary.
|
||||
|
||||
// Run MAC computation and comparison on the payload.
|
||||
if (checkMacTags(contentType(),
|
||||
buf, headerSize, contentLen, signer, false)) {
|
||||
if (reservedBPE == null) {
|
||||
reservedBPE = new BadPaddingException("bad record MAC");
|
||||
}
|
||||
}
|
||||
|
||||
// Run MAC computation and comparison on the remainder.
|
||||
//
|
||||
// It is only necessary for CBC block cipher. It is used to get a
|
||||
// constant time of MAC computation and comparison on each record.
|
||||
if (box.isCBCMode()) {
|
||||
int remainingLen = calculateRemainingLen(
|
||||
signer, cipheredLength, contentLen);
|
||||
|
||||
// NOTE: remainingLen may be bigger (less than 1 block of the
|
||||
// hash algorithm of the MAC) than the cipheredLength. However,
|
||||
// We won't need to worry about it because we always use a
|
||||
// maximum buffer for every record. We need a change here if
|
||||
// we use small buffer size in the future.
|
||||
if (remainingLen > buf.length) {
|
||||
// unlikely to happen, just a placehold
|
||||
throw new RuntimeException(
|
||||
"Internal buffer capacity error");
|
||||
}
|
||||
|
||||
// Won't need to worry about the result on the remainder. And
|
||||
// then we won't need to worry about what's actual data to
|
||||
// check MAC tag on. We start the check from the header of the
|
||||
// buffer so that we don't need to construct a new byte buffer.
|
||||
checkMacTags(contentType(), buf, 0, remainingLen, signer, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Is it a failover?
|
||||
if (reservedBPE != null) {
|
||||
throw reservedBPE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify and remove the MAC ... used for all records.
|
||||
* Run MAC computation and comparison
|
||||
*
|
||||
* Please DON'T change the content of the byte buffer parameter!
|
||||
*/
|
||||
boolean checkMAC(MAC signer) {
|
||||
int len = signer.MAClen();
|
||||
if (len == 0) { // no mac
|
||||
return true;
|
||||
}
|
||||
static boolean checkMacTags(byte contentType, byte[] buffer,
|
||||
int offset, int contentLen, MAC signer, boolean isSimulated) {
|
||||
|
||||
int offset = count - len;
|
||||
|
||||
if (offset < headerSize) {
|
||||
// data length would be negative, something is wrong
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] mac = signer.compute(contentType(), buf,
|
||||
headerSize, offset - headerSize);
|
||||
|
||||
if (len != mac.length) {
|
||||
int tagLen = signer.MAClen();
|
||||
byte[] hash = signer.compute(
|
||||
contentType, buffer, offset, contentLen, isSimulated);
|
||||
if (hash == null || tagLen != hash.length) {
|
||||
// Something is wrong with MAC implementation.
|
||||
throw new RuntimeException("Internal MAC error");
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (buf[offset + i] != mac[i]) {
|
||||
return false;
|
||||
int[] results = compareMacTags(buffer, offset + contentLen, hash);
|
||||
return (results[0] != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* A constant-time comparison of the MAC tags.
|
||||
*
|
||||
* Please DON'T change the content of the byte buffer parameter!
|
||||
*/
|
||||
private static int[] compareMacTags(
|
||||
byte[] buffer, int offset, byte[] tag) {
|
||||
|
||||
// An array of hits is used to prevent Hotspot optimization for
|
||||
// the purpose of a constant-time check.
|
||||
int[] results = {0, 0}; // {missed #, matched #}
|
||||
|
||||
// The caller ensures there are enough bytes available in the buffer.
|
||||
// So we won't need to check the length of the buffer.
|
||||
for (int i = 0; i < tag.length; i++) {
|
||||
if (buffer[offset + i] != tag[i]) {
|
||||
results[0]++; // mismatched bytes
|
||||
} else {
|
||||
results[1]++; // matched bytes
|
||||
}
|
||||
}
|
||||
count -= len;
|
||||
return true;
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
void decrypt(CipherBox box) throws BadPaddingException {
|
||||
int len = count - headerSize;
|
||||
count = headerSize + box.decrypt(buf, headerSize, len);
|
||||
}
|
||||
/*
|
||||
* Calculate the length of a dummy buffer to run MAC computation
|
||||
* and comparison on the remainder.
|
||||
*
|
||||
* The caller MUST ensure that the fullLen is not less than usedLen.
|
||||
*/
|
||||
static int calculateRemainingLen(
|
||||
MAC signer, int fullLen, int usedLen) {
|
||||
|
||||
int blockLen = signer.hashBlockLen();
|
||||
int minimalPaddingLen = signer.minimalPaddingLen();
|
||||
|
||||
// (blockLen - minimalPaddingLen) is the maximum message size of
|
||||
// the last block of hash function operation. See FIPS 180-4, or
|
||||
// MD5 specification.
|
||||
fullLen += 13 - (blockLen - minimalPaddingLen);
|
||||
usedLen += 13 - (blockLen - minimalPaddingLen);
|
||||
|
||||
// Note: fullLen is always not less than usedLen, and blockLen
|
||||
// is always bigger than minimalPaddingLen, so we don't worry
|
||||
// about negative values. 0x01 is added to the result to ensure
|
||||
// that the return value is positive. The extra one byte does
|
||||
// not impact the overall MAC compression function evaluations.
|
||||
return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) -
|
||||
Math.ceil(usedLen/(1.0d * blockLen))) * signer.hashBlockLen();
|
||||
}
|
||||
|
||||
/*
|
||||
* Well ... hello_request messages are _never_ hashed since we can't
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -43,8 +43,8 @@ import static sun.security.ssl.CipherSuite.*;
|
||||
* provide integrity protection for SSL messages. The MAC is actually
|
||||
* one of several keyed hashes, as associated with the cipher suite and
|
||||
* protocol version. (SSL v3.0 uses one construct, TLS uses another.)
|
||||
*
|
||||
* <P>NOTE: MAC computation is the only place in the SSL protocol that the
|
||||
* <P>
|
||||
* NOTE: MAC computation is the only place in the SSL protocol that the
|
||||
* sequence number is used. It's also reset to zero with each change of
|
||||
* a cipher spec, so this is the only place this state is needed.
|
||||
*
|
||||
@ -58,6 +58,9 @@ final class MAC {
|
||||
// Value of the null MAC is fixed
|
||||
private static final byte nullMAC[] = new byte[0];
|
||||
|
||||
// internal identifier for the MAC algorithm
|
||||
private final MacAlg macAlg;
|
||||
|
||||
// stuff defined by the kind of MAC algorithm
|
||||
private final int macSize;
|
||||
|
||||
@ -82,6 +85,7 @@ final class MAC {
|
||||
|
||||
private MAC() {
|
||||
macSize = 0;
|
||||
macAlg = M_NULL;
|
||||
mac = null;
|
||||
block = null;
|
||||
}
|
||||
@ -91,6 +95,7 @@ final class MAC {
|
||||
*/
|
||||
MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key)
|
||||
throws NoSuchAlgorithmException, InvalidKeyException {
|
||||
this.macAlg = macAlg;
|
||||
this.macSize = macAlg.size;
|
||||
|
||||
String algorithm;
|
||||
@ -127,6 +132,20 @@ final class MAC {
|
||||
return macSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash function block length of the MAC alorithm.
|
||||
*/
|
||||
int hashBlockLen() {
|
||||
return macAlg.hashBlockSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash function minimal padding length of the MAC alorithm.
|
||||
*/
|
||||
int minimalPaddingLen() {
|
||||
return macAlg.minimalPaddingSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes and returns the MAC for the data in this byte array.
|
||||
*
|
||||
@ -134,9 +153,11 @@ final class MAC {
|
||||
* @param buf compressed record on which the MAC is computed
|
||||
* @param offset start of compressed record data
|
||||
* @param len the size of the compressed record
|
||||
* @param isSimulated if true, simulate the the MAC computation
|
||||
*/
|
||||
final byte[] compute(byte type, byte buf[], int offset, int len) {
|
||||
return compute(type, null, buf, offset, len);
|
||||
final byte[] compute(byte type, byte buf[],
|
||||
int offset, int len, boolean isSimulated) {
|
||||
return compute(type, null, buf, offset, len, isSimulated);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,9 +170,10 @@ final class MAC {
|
||||
* @param type record type
|
||||
* @param bb a ByteBuffer in which the position and limit
|
||||
* demarcate the data to be MAC'd.
|
||||
* @param isSimulated if true, simulate the the MAC computation
|
||||
*/
|
||||
final byte[] compute(byte type, ByteBuffer bb) {
|
||||
return compute(type, bb, null, 0, bb.remaining());
|
||||
final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) {
|
||||
return compute(type, bb, null, 0, bb.remaining(), isSimulated);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,18 +226,21 @@ final class MAC {
|
||||
* or buf/offset/len.
|
||||
*/
|
||||
private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
|
||||
int offset, int len) {
|
||||
int offset, int len, boolean isSimulated) {
|
||||
|
||||
if (macSize == 0) {
|
||||
return nullMAC;
|
||||
}
|
||||
|
||||
block[BLOCK_OFFSET_TYPE] = type;
|
||||
block[block.length - 2] = (byte)(len >> 8);
|
||||
block[block.length - 1] = (byte)(len );
|
||||
// MUST NOT increase the sequence number for a simulated computation.
|
||||
if (!isSimulated) {
|
||||
block[BLOCK_OFFSET_TYPE] = type;
|
||||
block[block.length - 2] = (byte)(len >> 8);
|
||||
block[block.length - 1] = (byte)(len );
|
||||
|
||||
mac.update(block);
|
||||
incrementSequenceNumber();
|
||||
mac.update(block);
|
||||
incrementSequenceNumber();
|
||||
}
|
||||
|
||||
// content
|
||||
if (bb != null) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -205,7 +205,7 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
|
||||
}
|
||||
if (signer.MAClen() != 0) {
|
||||
byte[] hash = signer.compute(contentType, buf,
|
||||
headerSize, count - headerSize);
|
||||
headerSize, count - headerSize, false);
|
||||
write(hash);
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ import javax.crypto.*;
|
||||
import javax.net.ssl.*;
|
||||
|
||||
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
|
||||
import sun.security.util.KeyLength;
|
||||
import sun.security.util.KeyUtil;
|
||||
|
||||
/**
|
||||
* This is the client key exchange message (CLIENT --> SERVER) used with
|
||||
@ -191,7 +191,7 @@ final class RSAClientKeyExchange extends HandshakeMessage {
|
||||
"unable to get the plaintext of the premaster secret");
|
||||
}
|
||||
|
||||
int keySize = KeyLength.getKeySize(secretKey);
|
||||
int keySize = KeyUtil.getKeySize(secretKey);
|
||||
if (keySize > 0 && keySize != 384) { // 384 = 48 * 8
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println(
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -958,35 +958,15 @@ final public class SSLEngineImpl extends SSLEngine {
|
||||
* throw a fatal alert if the integrity check fails.
|
||||
*/
|
||||
try {
|
||||
decryptedBB = inputRecord.decrypt(readCipher, readBB);
|
||||
decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB);
|
||||
} catch (BadPaddingException e) {
|
||||
// RFC 2246 states that decryption_failed should be used
|
||||
// for this purpose. However, that allows certain attacks,
|
||||
// so we just send bad record MAC. We also need to make
|
||||
// sure to always check the MAC to avoid a timing attack
|
||||
// for the same issue. See paper by Vaudenay et al.
|
||||
//
|
||||
// rewind the BB if necessary.
|
||||
readBB.rewind();
|
||||
|
||||
inputRecord.checkMAC(readMAC, readBB);
|
||||
|
||||
// use the same alert types as for MAC failure below
|
||||
byte alertType = (inputRecord.contentType() ==
|
||||
Record.ct_handshake) ?
|
||||
Alerts.alert_handshake_failure :
|
||||
Alerts.alert_bad_record_mac;
|
||||
fatal(alertType, "Invalid padding", e);
|
||||
fatal(alertType, e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (!inputRecord.checkMAC(readMAC, decryptedBB)) {
|
||||
if (inputRecord.contentType() == Record.ct_handshake) {
|
||||
fatal(Alerts.alert_handshake_failure,
|
||||
"bad handshake record MAC");
|
||||
} else {
|
||||
fatal(Alerts.alert_bad_record_mac, "bad record MAC");
|
||||
}
|
||||
}
|
||||
|
||||
// if (!inputRecord.decompress(c))
|
||||
// fatal(Alerts.alert_decompression_failure,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -986,29 +986,13 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
* throw a fatal alert if the integrity check fails.
|
||||
*/
|
||||
try {
|
||||
r.decrypt(readCipher);
|
||||
r.decrypt(readMAC, readCipher);
|
||||
} catch (BadPaddingException e) {
|
||||
// RFC 2246 states that decryption_failed should be used
|
||||
// for this purpose. However, that allows certain attacks,
|
||||
// so we just send bad record MAC. We also need to make
|
||||
// sure to always check the MAC to avoid a timing attack
|
||||
// for the same issue. See paper by Vaudenay et al.
|
||||
r.checkMAC(readMAC);
|
||||
// use the same alert types as for MAC failure below
|
||||
byte alertType = (r.contentType() == Record.ct_handshake)
|
||||
? Alerts.alert_handshake_failure
|
||||
: Alerts.alert_bad_record_mac;
|
||||
fatal(alertType, "Invalid padding", e);
|
||||
fatal(alertType, e.getMessage(), e);
|
||||
}
|
||||
if (!r.checkMAC(readMAC)) {
|
||||
if (r.contentType() == Record.ct_handshake) {
|
||||
fatal(Alerts.alert_handshake_failure,
|
||||
"bad handshake record MAC");
|
||||
} else {
|
||||
fatal(Alerts.alert_bad_record_mac, "bad record MAC");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if (!r.decompress(c))
|
||||
// fatal(Alerts.alert_decompression_failure,
|
||||
|
@ -150,7 +150,7 @@ final class ServerHandshaker extends Handshaker {
|
||||
// In SSLv3 and TLS, messages follow strictly increasing
|
||||
// numerical order _except_ for one annoying special case.
|
||||
//
|
||||
if ((state > type)
|
||||
if ((state >= type)
|
||||
&& (state != HandshakeMessage.ht_client_key_exchange
|
||||
&& type != HandshakeMessage.ht_certificate_verify)) {
|
||||
throw new SSLProtocolException(
|
||||
@ -250,13 +250,15 @@ final class ServerHandshaker extends Handshaker {
|
||||
}
|
||||
|
||||
//
|
||||
// Move the state machine forward except for that annoying
|
||||
// special case. This means that clients could send extra
|
||||
// cert verify messages; not a problem so long as all of
|
||||
// them actually check out.
|
||||
// Move state machine forward if the message handling
|
||||
// code didn't already do so
|
||||
//
|
||||
if (state < type && type != HandshakeMessage.ht_certificate_verify) {
|
||||
state = type;
|
||||
if (state < type) {
|
||||
if(type == HandshakeMessage.ht_certificate_verify) {
|
||||
state = type + 2; // an annoying special case
|
||||
} else {
|
||||
state = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1406,7 +1408,7 @@ final class ServerHandshaker extends Handshaker {
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
mesg.print(System.out);
|
||||
}
|
||||
return dh.getAgreedSecret(mesg.getClientPublicKey());
|
||||
return dh.getAgreedSecret(mesg.getClientPublicKey(), false);
|
||||
}
|
||||
|
||||
private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg)
|
||||
|
@ -38,7 +38,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import sun.security.util.KeyLength;
|
||||
import sun.security.util.KeyUtil;
|
||||
|
||||
/**
|
||||
* Signature and hash algorithm.
|
||||
@ -274,7 +274,7 @@ final class SignatureAndHashAlgorithm {
|
||||
* If key size is less than 512, the digest length should be
|
||||
* less than or equal to 20 bytes.
|
||||
*/
|
||||
int keySize = KeyLength.getKeySize(signingKey);
|
||||
int keySize = KeyUtil.getKeySize(signingKey);
|
||||
if (keySize >= 768) {
|
||||
maxDigestLength = HashAlgorithm.SHA512.length;
|
||||
} else if ((keySize >= 512) && (keySize < 768)) {
|
||||
|
@ -325,6 +325,10 @@ class DerIndefLenConverter {
|
||||
}
|
||||
}
|
||||
|
||||
if (unresolved != 0) {
|
||||
throw new IOException("not all indef len BER resolved");
|
||||
}
|
||||
|
||||
newData = new byte[dataSize + numOfTotalLenBytes + unused];
|
||||
dataPos=0; newDataPos=0; index=0;
|
||||
|
||||
|
@ -440,7 +440,7 @@ public class DisabledAlgorithmConstraints implements AlgorithmConstraints {
|
||||
|
||||
// Does this key constraint disable the specified key?
|
||||
public boolean disables(Key key) {
|
||||
int size = KeyLength.getKeySize(key);
|
||||
int size = KeyUtil.getKeySize(key);
|
||||
|
||||
if (size == 0) {
|
||||
return true; // we don't allow any key of size 0.
|
||||
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.util;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.AccessController;
|
||||
import java.security.interfaces.ECKey;
|
||||
import java.security.interfaces.RSAKey;
|
||||
import java.security.interfaces.DSAKey;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.interfaces.DHKey;
|
||||
|
||||
/**
|
||||
* A utility class to get key length
|
||||
*/
|
||||
public final class KeyLength {
|
||||
|
||||
/**
|
||||
* Returns the key size of the given key object in bits.
|
||||
*
|
||||
* @param key the key object, cannot be null
|
||||
* @return the key size of the given key object in bits, or -1 if the
|
||||
* key size is not accessible
|
||||
*/
|
||||
final public static int getKeySize(Key key) {
|
||||
int size = -1;
|
||||
|
||||
if (key instanceof Length) {
|
||||
try {
|
||||
Length ruler = (Length)key;
|
||||
size = ruler.length();
|
||||
} catch (UnsupportedOperationException usoe) {
|
||||
// ignore the exception
|
||||
}
|
||||
|
||||
if (size >= 0) {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
// try to parse the length from key specification
|
||||
if (key instanceof SecretKey) {
|
||||
SecretKey sk = (SecretKey)key;
|
||||
String format = sk.getFormat();
|
||||
if ("RAW".equals(format) && sk.getEncoded() != null) {
|
||||
size = (sk.getEncoded().length * 8);
|
||||
} // Otherwise, it may be a unextractable key of PKCS#11, or
|
||||
// a key we are not able to handle.
|
||||
} else if (key instanceof RSAKey) {
|
||||
RSAKey pubk = (RSAKey)key;
|
||||
size = pubk.getModulus().bitLength();
|
||||
} else if (key instanceof ECKey) {
|
||||
ECKey pubk = (ECKey)key;
|
||||
size = pubk.getParams().getOrder().bitLength();
|
||||
} else if (key instanceof DSAKey) {
|
||||
DSAKey pubk = (DSAKey)key;
|
||||
size = pubk.getParams().getP().bitLength();
|
||||
} else if (key instanceof DHKey) {
|
||||
DHKey pubk = (DHKey)key;
|
||||
size = pubk.getParams().getP().bitLength();
|
||||
} // Otherwise, it may be a unextractable key of PKCS#11, or
|
||||
// a key we are not able to handle.
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
204
jdk/src/share/classes/sun/security/util/KeyUtil.java
Normal file
204
jdk/src/share/classes/sun/security/util/KeyUtil.java
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.util;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.AccessController;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.interfaces.ECKey;
|
||||
import java.security.interfaces.RSAKey;
|
||||
import java.security.interfaces.DSAKey;
|
||||
import java.security.spec.KeySpec;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.interfaces.DHKey;
|
||||
import javax.crypto.interfaces.DHPublicKey;
|
||||
import javax.crypto.spec.DHParameterSpec;
|
||||
import javax.crypto.spec.DHPublicKeySpec;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* A utility class to get key length, valiate keys, etc.
|
||||
*/
|
||||
public final class KeyUtil {
|
||||
|
||||
/**
|
||||
* Returns the key size of the given key object in bits.
|
||||
*
|
||||
* @param key the key object, cannot be null
|
||||
* @return the key size of the given key object in bits, or -1 if the
|
||||
* key size is not accessible
|
||||
*/
|
||||
public static final int getKeySize(Key key) {
|
||||
int size = -1;
|
||||
|
||||
if (key instanceof Length) {
|
||||
try {
|
||||
Length ruler = (Length)key;
|
||||
size = ruler.length();
|
||||
} catch (UnsupportedOperationException usoe) {
|
||||
// ignore the exception
|
||||
}
|
||||
|
||||
if (size >= 0) {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
// try to parse the length from key specification
|
||||
if (key instanceof SecretKey) {
|
||||
SecretKey sk = (SecretKey)key;
|
||||
String format = sk.getFormat();
|
||||
if ("RAW".equals(format) && sk.getEncoded() != null) {
|
||||
size = (sk.getEncoded().length * 8);
|
||||
} // Otherwise, it may be a unextractable key of PKCS#11, or
|
||||
// a key we are not able to handle.
|
||||
} else if (key instanceof RSAKey) {
|
||||
RSAKey pubk = (RSAKey)key;
|
||||
size = pubk.getModulus().bitLength();
|
||||
} else if (key instanceof ECKey) {
|
||||
ECKey pubk = (ECKey)key;
|
||||
size = pubk.getParams().getOrder().bitLength();
|
||||
} else if (key instanceof DSAKey) {
|
||||
DSAKey pubk = (DSAKey)key;
|
||||
size = pubk.getParams().getP().bitLength();
|
||||
} else if (key instanceof DHKey) {
|
||||
DHKey pubk = (DHKey)key;
|
||||
size = pubk.getParams().getP().bitLength();
|
||||
} // Otherwise, it may be a unextractable key of PKCS#11, or
|
||||
// a key we are not able to handle.
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the key is valid or not.
|
||||
* <P>
|
||||
* Note that this method is only apply to DHPublicKey at present.
|
||||
*
|
||||
* @param publicKey
|
||||
* the key object, cannot be null
|
||||
*
|
||||
* @throws NullPointerException if {@code publicKey} is null
|
||||
* @throws InvalidKeyException if {@code publicKey} is invalid
|
||||
*/
|
||||
public static final void validate(Key key)
|
||||
throws InvalidKeyException {
|
||||
if (key == null) {
|
||||
throw new NullPointerException(
|
||||
"The key to be validated cannot be null");
|
||||
}
|
||||
|
||||
if (key instanceof DHPublicKey) {
|
||||
validateDHPublicKey((DHPublicKey)key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the key spec is valid or not.
|
||||
* <P>
|
||||
* Note that this method is only apply to DHPublicKeySpec at present.
|
||||
*
|
||||
* @param keySpec
|
||||
* the key spec object, cannot be null
|
||||
*
|
||||
* @throws NullPointerException if {@code keySpec} is null
|
||||
* @throws InvalidKeyException if {@code keySpec} is invalid
|
||||
*/
|
||||
public static final void validate(KeySpec keySpec)
|
||||
throws InvalidKeyException {
|
||||
if (keySpec == null) {
|
||||
throw new NullPointerException(
|
||||
"The key spec to be validated cannot be null");
|
||||
}
|
||||
|
||||
if (keySpec instanceof DHPublicKeySpec) {
|
||||
validateDHPublicKey((DHPublicKeySpec)keySpec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified provider is Oracle provider or not.
|
||||
* <P>
|
||||
* Note that this method is only apply to SunJCE and SunPKCS11 at present.
|
||||
*
|
||||
* @param providerName
|
||||
* the provider name
|
||||
* @return true if, and only if, the provider of the specified
|
||||
* {@code providerName} is Oracle provider
|
||||
*/
|
||||
public static final boolean isOracleJCEProvider(String providerName) {
|
||||
return providerName != null && (providerName.equals("SunJCE") ||
|
||||
providerName.startsWith("SunPKCS11"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the Diffie-Hellman public key is valid or not.
|
||||
*
|
||||
* Per RFC 2631 and NIST SP800-56A, the following algorithm is used to
|
||||
* validate Diffie-Hellman public keys:
|
||||
* 1. Verify that y lies within the interval [2,p-1]. If it does not,
|
||||
* the key is invalid.
|
||||
* 2. Compute y^q mod p. If the result == 1, the key is valid.
|
||||
* Otherwise the key is invalid.
|
||||
*/
|
||||
private static void validateDHPublicKey(DHPublicKey publicKey)
|
||||
throws InvalidKeyException {
|
||||
DHParameterSpec paramSpec = publicKey.getParams();
|
||||
|
||||
BigInteger p = paramSpec.getP();
|
||||
BigInteger g = paramSpec.getG();
|
||||
BigInteger y = publicKey.getY();
|
||||
|
||||
validateDHPublicKey(p, g, y);
|
||||
}
|
||||
|
||||
private static void validateDHPublicKey(DHPublicKeySpec publicKeySpec)
|
||||
throws InvalidKeyException {
|
||||
validateDHPublicKey(publicKeySpec.getP(),
|
||||
publicKeySpec.getG(), publicKeySpec.getY());
|
||||
}
|
||||
|
||||
private static void validateDHPublicKey(BigInteger p,
|
||||
BigInteger g, BigInteger y) throws InvalidKeyException {
|
||||
|
||||
// For better interoperability, the interval is limited to [2, p-2].
|
||||
BigInteger leftOpen = BigInteger.ONE;
|
||||
BigInteger rightOpen = p.subtract(BigInteger.ONE);
|
||||
if (y.compareTo(leftOpen) <= 0) {
|
||||
throw new InvalidKeyException(
|
||||
"Diffie-Hellman public key is too small");
|
||||
}
|
||||
if (y.compareTo(rightOpen) >= 0) {
|
||||
throw new InvalidKeyException(
|
||||
"Diffie-Hellman public key is too large");
|
||||
}
|
||||
|
||||
// Don't bother to check against the y^q mod p if safe primes are used.
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -737,5 +737,111 @@ public final class UntrustedCertificates {
|
||||
"B8WfedLHjFW/TMcnXlEWKz4=\n" +
|
||||
"-----END CERTIFICATE-----");
|
||||
|
||||
//
|
||||
// Revoked DigiCert code signing certificates used to sign malware
|
||||
//
|
||||
|
||||
// Subject: CN=Buster Paper Comercial Ltda,
|
||||
// O=Buster Paper Comercial Ltda,
|
||||
// L=S?o Jos? Dos Campos,
|
||||
// ST=S?o Paulo,
|
||||
// C=BR
|
||||
// Issuer: CN=DigiCert Assured ID Code Signing CA-1,
|
||||
// OU=www.digicert.com,
|
||||
// O=DigiCert Inc,
|
||||
// C=US
|
||||
// Serial: 07:b4:4c:db:ff:fb:78:de:05:f4:26:16:72:a6:73:12
|
||||
add("buster-paper-comercial-ltda-72A67312",
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIGwzCCBaugAwIBAgIQB7RM2//7eN4F9CYWcqZzEjANBgkqhkiG9w0BAQUFADBv\n" +
|
||||
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" +
|
||||
"d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" +
|
||||
"ZGUgU2lnbmluZyBDQS0xMB4XDTEzMDExNzAwMDAwMFoXDTE0MDEyMjEyMDAwMFow\n" +
|
||||
"gY4xCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMR4wHAYDVQQHDBVT\n" +
|
||||
"w6NvIEpvc8OpIERvcyBDYW1wb3MxJDAiBgNVBAoTG0J1c3RlciBQYXBlciBDb21l\n" +
|
||||
"cmNpYWwgTHRkYTEkMCIGA1UEAxMbQnVzdGVyIFBhcGVyIENvbWVyY2lhbCBMdGRh\n" +
|
||||
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzO0l6jWIpEfO2oUpVHpL\n" +
|
||||
"HETj5lzivNb0S9jKHgGJax917czh81PnGTxwxFXd6gLJuy/XFHvmiSi8g8jzlymn\n" +
|
||||
"2Ji5zQ3CPaz7nomJokSUDlMVJ2qYWtctw4jrdjuI4qtn+koXXUFkWjkf8h8251I4\n" +
|
||||
"tUs7S49HE2Go5owCYP3byajj7fsFAYR/Xb7TdVtndkZsUB/YgOjHovyACjouaNCi\n" +
|
||||
"mDiRyQ6zLLjZGiyeD65Yiseuhp5b8/BL5h1p7w76QYMYMVQNAdtDKut2R8MBpuWf\n" +
|
||||
"Ny7Eoi0x/gm1p9X5Rcl5aN7K0G4UtTAJKbkuUfXddsyFoM0Nx8uo8SgNQ8Y/X5Jx\n" +
|
||||
"BwIDAQABo4IDOTCCAzUwHwYDVR0jBBgwFoAUe2jOKarAF75JeuHlP9an90WPNTIw\n" +
|
||||
"HQYDVR0OBBYEFFLZ3n5nt/Eer7n1bvtOqMb1qKO5MA4GA1UdDwEB/wQEAwIHgDAT\n" +
|
||||
"BgNVHSUEDDAKBggrBgEFBQcDAzBzBgNVHR8EbDBqMDOgMaAvhi1odHRwOi8vY3Js\n" +
|
||||
"My5kaWdpY2VydC5jb20vYXNzdXJlZC1jcy0yMDExYS5jcmwwM6AxoC+GLWh0dHA6\n" +
|
||||
"Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9hc3N1cmVkLWNzLTIwMTFhLmNybDCCAcQGA1Ud\n" +
|
||||
"IASCAbswggG3MIIBswYJYIZIAYb9bAMBMIIBpDA6BggrBgEFBQcCARYuaHR0cDov\n" +
|
||||
"L3d3dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsG\n" +
|
||||
"AQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABD\n" +
|
||||
"AGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABh\n" +
|
||||
"AGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQBy\n" +
|
||||
"AHQAIABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBn\n" +
|
||||
"ACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABs\n" +
|
||||
"AGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABp\n" +
|
||||
"AG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBl\n" +
|
||||
"AGYAZQByAGUAbgBjAGUALjCBggYIKwYBBQUHAQEEdjB0MCQGCCsGAQUFBzABhhho\n" +
|
||||
"dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTAYIKwYBBQUHMAKGQGh0dHA6Ly9jYWNl\n" +
|
||||
"cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENvZGVTaWduaW5nQ0Et\n" +
|
||||
"MS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOCAQEAPTTQvpOIikXI\n" +
|
||||
"hTLnNbajaFRR5GhQpTzUNgBfF9VYSlNw/wMjpGsrh5RxaJCip52jbehmTgjMRhft\n" +
|
||||
"jRYyml44PAVsCcR9uEoDpCZYpI1fHI1R+F8jd1C9rqprbSwwOG4xlg4SmvTHYs6e\n" +
|
||||
"gBItQ/1p9XY+Sf4Wv1qOuOFL1qvV/5VyR2zdlOQCmKCeMgxt6a/tHLBDiAA67D44\n" +
|
||||
"/vfdoNJl0CU2It0PO60jdCPFNWIRcxL+OSDqAoePeUC7xQ+JsTEIxuUE8+d6w6fc\n" +
|
||||
"BV2mYb1flh22t46GLjh4gyo7xw3aL6L0L0jzlTT6IcEw6NIbaPbIKj/npQnHobYj\n" +
|
||||
"XMuKLxbh7g==\n" +
|
||||
"-----END CERTIFICATE-----");
|
||||
|
||||
// Subject: CN=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME,
|
||||
// O=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME,
|
||||
// L=S?o Paulo,
|
||||
// ST=S?o Paulo,
|
||||
// C=BR
|
||||
// Issuer: CN=DigiCert Assured ID Code Signing CA-1,
|
||||
// OU=www.digicert.com,
|
||||
// O=DigiCert Inc,
|
||||
// C=US
|
||||
// Serial: 0a:38:9b:95:ee:73:6d:d1:3b:c0:ed:74:3f:d7:4d:2f
|
||||
add("buster-assistencia-tecnica-electronica-ltda-3FD74D2F",
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIG4DCCBcigAwIBAgIQCjible5zbdE7wO10P9dNLzANBgkqhkiG9w0BAQUFADBv\n" +
|
||||
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" +
|
||||
"d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" +
|
||||
"ZGUgU2lnbmluZyBDQS0xMB4XDTEyMTEwOTAwMDAwMFoXDTEzMTExNDEyMDAwMFow\n" +
|
||||
"gasxCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMRMwEQYDVQQHDApT\n" +
|
||||
"w6NvIFBhdWxvMTgwNgYDVQQKEy9CVVNURVIgQVNTSVNURU5DSUEgVEVDTklDQSBF\n" +
|
||||
"TEVUUk9OSUNBIExUREEgLSBNRTE4MDYGA1UEAxMvQlVTVEVSIEFTU0lTVEVOQ0lB\n" +
|
||||
"IFRFQ05JQ0EgRUxFVFJPTklDQSBMVERBIC0gTUUwggEiMA0GCSqGSIb3DQEBAQUA\n" +
|
||||
"A4IBDwAwggEKAoIBAQDAqNeEs5/B2CTXGjTOkUIdu6jV6qulOZwdw4sefHWYj1UR\n" +
|
||||
"4z6zPk9kjpUgbnb402RFq88QtfInwddZ/wXn9OxMtDd/3TnC7HrhNS7ga79ZFL2V\n" +
|
||||
"JnmzKHum2Yvh0q82QEJ9tHBR2X9VdKpUIH08Zs3k6cWWM1H0YX0cxA/HohhesQJW\n" +
|
||||
"kwJ3urOIJiH/HeByDk8a1NS8safcCxk5vxvW4WvCg43iT09LeHY5Aa8abKw8lqVb\n" +
|
||||
"0tD5ZSIjdmdj3TT1U37iAHLLRM2DXbxfdbhouUX1c5U1ZHAMA67HwjKiseOiDaHj\n" +
|
||||
"NUGbC37C+cgbc9VVM/cURD8WvS0Kj6fQv7F2QtJDAgMBAAGjggM5MIIDNTAfBgNV\n" +
|
||||
"HSMEGDAWgBR7aM4pqsAXvkl64eU/1qf3RY81MjAdBgNVHQ4EFgQU88EXKAyDsh30\n" +
|
||||
"o9+Gu9a4xUy+FSMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMD\n" +
|
||||
"MHMGA1UdHwRsMGowM6AxoC+GLWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9hc3N1\n" +
|
||||
"cmVkLWNzLTIwMTFhLmNybDAzoDGgL4YtaHR0cDovL2NybDQuZGlnaWNlcnQuY29t\n" +
|
||||
"L2Fzc3VyZWQtY3MtMjAxMWEuY3JsMIIBxAYDVR0gBIIBuzCCAbcwggGzBglghkgB\n" +
|
||||
"hv1sAwEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9z\n" +
|
||||
"c2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4A\n" +
|
||||
"eQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQA\n" +
|
||||
"ZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUA\n" +
|
||||
"IABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAA\n" +
|
||||
"YQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcA\n" +
|
||||
"cgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIA\n" +
|
||||
"aQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQA\n" +
|
||||
"ZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMIGC\n" +
|
||||
"BggrBgEFBQcBAQR2MHQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0\n" +
|
||||
"LmNvbTBMBggrBgEFBQcwAoZAaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp\n" +
|
||||
"Z2lDZXJ0QXNzdXJlZElEQ29kZVNpZ25pbmdDQS0xLmNydDAMBgNVHRMBAf8EAjAA\n" +
|
||||
"MA0GCSqGSIb3DQEBBQUAA4IBAQAei1QmiXepje8OIfo/WonD4MIXgpPr2dfRaquQ\n" +
|
||||
"A8q63OpTRSveyqdQDCSPpDRF/nvO1Y30yksZvIH1tNBsW5LBdxAKN3lFdBlqBwtE\n" +
|
||||
"Q3jHc0KVVYRJ0FBaGE/PJHmRajscdAhYIcMPhTga0u0tDK+wOHEq3993dfl6yHjA\n" +
|
||||
"XHU2iW5pnk75ZoE39zALD5eKXT8ZXrET5c3XUFJKWA+XuGmdmyzqo0Au49PanBv9\n" +
|
||||
"UlZnabYfqoMArqMS0tGSX4cGgi9/2E+pHG9BX4sFW+ZDumroOA2pxyMWEKjxePEL\n" +
|
||||
"zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" +
|
||||
"-----END CERTIFICATE-----");
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,19 @@ keystore.type=jks
|
||||
# passed to checkPackageAccess unless the
|
||||
# corresponding RuntimePermission ("accessClassInPackage."+package) has
|
||||
# been granted.
|
||||
package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
|
||||
package.access=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
com.sun.proxy.,\
|
||||
com.sun.org.apache.xerces.internal.utils.,\
|
||||
com.sun.org.apache.xalan.internal.utils.,\
|
||||
com.sun.org.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
jdk.internal.
|
||||
|
||||
#
|
||||
# List of comma-separated packages that start with or equal this string
|
||||
@ -157,7 +169,19 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.
|
||||
# by default, none of the class loaders supplied with the JDK call
|
||||
# checkPackageDefinition.
|
||||
#
|
||||
package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
|
||||
package.definition=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
com.sun.proxy.,\
|
||||
com.sun.org.apache.xerces.internal.utils.,\
|
||||
com.sun.org.apache.xalan.internal.utils.,\
|
||||
com.sun.org.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
jdk.internal.
|
||||
|
||||
#
|
||||
# Determines whether this properties file can be appended to
|
||||
|
@ -146,7 +146,20 @@ keystore.type=jks
|
||||
# passed to checkPackageAccess unless the
|
||||
# corresponding RuntimePermission ("accessClassInPackage."+package) has
|
||||
# been granted.
|
||||
package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
|
||||
package.access=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
com.sun.proxy.,\
|
||||
com.sun.org.apache.xerces.internal.utils.,\
|
||||
com.sun.org.apache.xalan.internal.utils.,\
|
||||
com.sun.org.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
jdk.internal.,\
|
||||
apple.
|
||||
|
||||
#
|
||||
# List of comma-separated packages that start with or equal this string
|
||||
@ -158,7 +171,20 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.
|
||||
# by default, none of the class loaders supplied with the JDK call
|
||||
# checkPackageDefinition.
|
||||
#
|
||||
package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
|
||||
package.definition=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
com.sun.proxy.,\
|
||||
com.sun.org.apache.xerces.internal.utils.,\
|
||||
com.sun.org.apache.xalan.internal.utils.,\
|
||||
com.sun.org.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
jdk.internal.,\
|
||||
apple.
|
||||
|
||||
#
|
||||
# Determines whether this properties file can be appended to
|
||||
|
@ -147,7 +147,19 @@ keystore.type=jks
|
||||
# passed to checkPackageAccess unless the
|
||||
# corresponding RuntimePermission ("accessClassInPackage."+package) has
|
||||
# been granted.
|
||||
package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
|
||||
package.access=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
com.sun.proxy.,\
|
||||
com.sun.org.apache.xerces.internal.utils.,\
|
||||
com.sun.org.apache.xalan.internal.utils.,\
|
||||
com.sun.org.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
jdk.internal.
|
||||
|
||||
#
|
||||
# List of comma-separated packages that start with or equal this string
|
||||
@ -159,7 +171,19 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.
|
||||
# by default, none of the class loaders supplied with the JDK call
|
||||
# checkPackageDefinition.
|
||||
#
|
||||
package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
|
||||
package.definition=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
com.sun.proxy.,\
|
||||
com.sun.org.apache.xerces.internal.utils.,\
|
||||
com.sun.org.apache.xalan.internal.utils.,\
|
||||
com.sun.org.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
jdk.internal.
|
||||
|
||||
#
|
||||
# Determines whether this properties file can be appended to
|
||||
|
@ -146,7 +146,19 @@ keystore.type=jks
|
||||
# passed to checkPackageAccess unless the
|
||||
# corresponding RuntimePermission ("accessClassInPackage."+package) has
|
||||
# been granted.
|
||||
package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
|
||||
package.access=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
com.sun.proxy.,\
|
||||
com.sun.org.apache.xerces.internal.utils.,\
|
||||
com.sun.org.apache.xalan.internal.utils.,\
|
||||
com.sun.org.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
jdk.internal.
|
||||
|
||||
#
|
||||
# List of comma-separated packages that start with or equal this string
|
||||
@ -158,7 +170,19 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.
|
||||
# by default, none of the class loaders supplied with the JDK call
|
||||
# checkPackageDefinition.
|
||||
#
|
||||
package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
|
||||
package.definition=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
com.sun.proxy.,\
|
||||
com.sun.org.apache.xerces.internal.utils.,\
|
||||
com.sun.org.apache.xalan.internal.utils.,\
|
||||
com.sun.org.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
jdk.internal.
|
||||
|
||||
#
|
||||
# Determines whether this properties file can be appended to
|
||||
|
@ -187,6 +187,10 @@ void band::setIndexByTag(byte tag) {
|
||||
|
||||
entry* band::getRefCommon(cpindex* ix_, bool nullOKwithCaller) {
|
||||
CHECK_0;
|
||||
if (ix_ == NULL) {
|
||||
abort("no index");
|
||||
return NULL;
|
||||
}
|
||||
assert(ix_->ixTag == ixTag
|
||||
|| ((ixTag == CONSTANT_All ||
|
||||
ixTag == CONSTANT_LoadableValue ||
|
||||
|
@ -99,8 +99,8 @@ struct band {
|
||||
|
||||
int getByte() { assert(ix == null); return vs[0].getByte(); }
|
||||
int getInt() { assert(ix == null); return vs[0].getInt(); }
|
||||
entry* getRefN() { assert(ix != null); return getRefCommon(ix, true); }
|
||||
entry* getRef() { assert(ix != null); return getRefCommon(ix, false); }
|
||||
entry* getRefN() { return getRefCommon(ix, true); }
|
||||
entry* getRef() { return getRefCommon(ix, false); }
|
||||
entry* getRefUsing(cpindex* ix2)
|
||||
{ assert(ix == null); return getRefCommon(ix2, true); }
|
||||
entry* getRefCommon(cpindex* ix, bool nullOK);
|
||||
|
@ -50,6 +50,7 @@ static jfieldID unpackerPtrFID;
|
||||
static jmethodID currentInstMID;
|
||||
static jmethodID readInputMID;
|
||||
static jclass NIclazz;
|
||||
static jmethodID getUnpackerPtrMID;
|
||||
|
||||
static char* dbg = null;
|
||||
|
||||
@ -60,8 +61,8 @@ static jlong read_input_via_jni(unpacker* self,
|
||||
|
||||
static unpacker* get_unpacker(JNIEnv *env, jobject pObj, bool noCreate=false) {
|
||||
unpacker* uPtr;
|
||||
uPtr = (unpacker*)jlong2ptr(env->GetLongField(pObj, unpackerPtrFID));
|
||||
//fprintf(stderr, "get_unpacker(%p) uPtr=%p\n", pObj, uPtr);
|
||||
jlong p = env->CallLongMethod(pObj, getUnpackerPtrMID);
|
||||
uPtr = (unpacker*)jlong2ptr(p);
|
||||
if (uPtr == null) {
|
||||
if (noCreate) return null;
|
||||
uPtr = new unpacker();
|
||||
@ -94,11 +95,15 @@ static unpacker* get_unpacker() {
|
||||
if (env == null)
|
||||
return null;
|
||||
jobject pObj = env->CallStaticObjectMethod(NIclazz, currentInstMID);
|
||||
//fprintf(stderr, "get_unpacker() pObj=%p\n", pObj);
|
||||
if (pObj == null)
|
||||
return null;
|
||||
// Got pObj and env; now do it the easy way.
|
||||
return get_unpacker(env, pObj);
|
||||
//fprintf(stderr, "get_unpacker0() pObj=%p\n", pObj);
|
||||
if (pObj != null) {
|
||||
// Got pObj and env; now do it the easy way.
|
||||
return get_unpacker(env, pObj);
|
||||
}
|
||||
// this should really not happen, if it does something is seriously
|
||||
// wrong throw an exception
|
||||
THROW_IOE(ERROR_INTERNAL);
|
||||
return null;
|
||||
}
|
||||
|
||||
static void free_unpacker(JNIEnv *env, jobject pObj, unpacker* uPtr) {
|
||||
@ -127,18 +132,23 @@ static jlong read_input_via_jni(unpacker* self,
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) {
|
||||
#ifndef PRODUCT
|
||||
dbg = getenv("DEBUG_ATTACH");
|
||||
while( dbg != null) { sleep(10); }
|
||||
#endif
|
||||
NIclazz = (jclass) env->NewGlobalRef(clazz);
|
||||
unpackerPtrFID = env->GetFieldID(clazz, "unpackerPtr", "J");
|
||||
currentInstMID = env->GetStaticMethodID(clazz, "currentInstance",
|
||||
"()Ljava/lang/Object;");
|
||||
readInputMID = env->GetMethodID(clazz, "readInputFn",
|
||||
"(Ljava/nio/ByteBuffer;J)J");
|
||||
getUnpackerPtrMID = env->GetMethodID(clazz, "getUnpackerPtr", "()J");
|
||||
|
||||
if (unpackerPtrFID == null ||
|
||||
currentInstMID == null ||
|
||||
readInputMID == null ||
|
||||
NIclazz == null) {
|
||||
NIclazz == null ||
|
||||
getUnpackerPtrMID == null) {
|
||||
THROW_IOE("cannot init class members");
|
||||
}
|
||||
}
|
||||
@ -146,8 +156,13 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz)
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj,
|
||||
jobject pBuf, jlong offset) {
|
||||
unpacker* uPtr = get_unpacker(env, pObj);
|
||||
|
||||
// try to get the unpacker pointer the hard way first, we do this to ensure
|
||||
// valid object pointers and env is intact, if not now is good time to bail.
|
||||
unpacker* uPtr = get_unpacker();
|
||||
//fprintf(stderr, "start(%p) uPtr=%p initializing\n", pObj, uPtr);
|
||||
if (uPtr == null) {
|
||||
return -1;
|
||||
}
|
||||
// redirect our io to the default log file or whatever.
|
||||
uPtr->redirect_stdio();
|
||||
|
||||
@ -163,7 +178,12 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj,
|
||||
else
|
||||
{ buf = (char*)buf + (size_t)offset; buflen -= (size_t)offset; }
|
||||
}
|
||||
|
||||
// before we start off we make sure there is no other error by the time we
|
||||
// get here
|
||||
if (uPtr->aborting()) {
|
||||
THROW_IOE(uPtr->get_abort_message());
|
||||
return 0;
|
||||
}
|
||||
uPtr->start(buf, buflen);
|
||||
if (uPtr->aborting()) {
|
||||
THROW_IOE(uPtr->get_abort_message());
|
||||
@ -230,11 +250,14 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject
|
||||
|
||||
// We have fetched all the files.
|
||||
// Now swallow up any remaining input.
|
||||
if (uPtr->input_remaining() == 0)
|
||||
if (uPtr->input_remaining() == 0) {
|
||||
return null;
|
||||
else
|
||||
return env->NewDirectByteBuffer(uPtr->input_scan(),
|
||||
uPtr->input_remaining());
|
||||
} else {
|
||||
bytes remaining_bytes;
|
||||
remaining_bytes.malloc(uPtr->input_remaining());
|
||||
remaining_bytes.copyFrom(uPtr->input_scan(), uPtr->input_remaining());
|
||||
return env->NewDirectByteBuffer(remaining_bytes.ptr, remaining_bytes.len);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
|
@ -281,11 +281,13 @@ int entry::typeSize() {
|
||||
}
|
||||
|
||||
inline cpindex* cpool::getFieldIndex(entry* classRef) {
|
||||
if (classRef == NULL) { abort("missing class reference"); return NULL; }
|
||||
assert(classRef->tagMatches(CONSTANT_Class));
|
||||
assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]);
|
||||
return &member_indexes[classRef->inord*2+0];
|
||||
}
|
||||
inline cpindex* cpool::getMethodIndex(entry* classRef) {
|
||||
if (classRef == NULL) { abort("missing class reference"); return NULL; }
|
||||
assert(classRef->tagMatches(CONSTANT_Class));
|
||||
assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]);
|
||||
return &member_indexes[classRef->inord*2+1];
|
||||
@ -1291,6 +1293,7 @@ void unpacker::read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag,
|
||||
entry& e = cpMap[i];
|
||||
e.refs = U_NEW(entry*, e.nrefs = 2);
|
||||
e.refs[0] = cp_band1.getRef();
|
||||
CHECK;
|
||||
e.refs[1] = cp_band2.getRef();
|
||||
CHECK;
|
||||
}
|
||||
@ -1371,6 +1374,7 @@ void unpacker::read_method_type(entry* cpMap, int len) {
|
||||
entry& e = cpMap[i];
|
||||
e.refs = U_NEW(entry*, e.nrefs = 1);
|
||||
e.refs[0] = cp_MethodType.getRef();
|
||||
CHECK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2106,6 +2110,7 @@ void unpacker::read_attr_defs() {
|
||||
int attrc = ADH_BYTE_CONTEXT(header);
|
||||
int idx = ADH_BYTE_INDEX(header);
|
||||
entry* name = attr_definition_name.getRef();
|
||||
CHECK;
|
||||
entry* layout = attr_definition_layout.getRef();
|
||||
CHECK;
|
||||
attr_defs[attrc].defineLayout(idx, name, layout->value.b.strval());
|
||||
@ -2210,7 +2215,9 @@ void unpacker::read_ics() {
|
||||
if (ics[i].name == NO_ENTRY_YET) {
|
||||
// Long form.
|
||||
ics[i].outer = ic_outer_class.getRefN();
|
||||
CHECK;
|
||||
ics[i].name = ic_name.getRefN();
|
||||
CHECK;
|
||||
} else {
|
||||
// Fill in outer and name based on inner.
|
||||
bytes& n = ics[i].inner->value.b;
|
||||
@ -2733,6 +2740,7 @@ void unpacker::putlayout(band** body) {
|
||||
e = b.getRefUsing(cp.getKQIndex());
|
||||
else
|
||||
e = b.getRefN();
|
||||
CHECK;
|
||||
switch (b.le_len) {
|
||||
case 0: break;
|
||||
case 1: putu1ref(e); break;
|
||||
@ -3118,7 +3126,7 @@ void unpacker::read_bcs() {
|
||||
|
||||
void unpacker::read_bands() {
|
||||
byte* rp0 = rp;
|
||||
|
||||
CHECK;
|
||||
read_file_header();
|
||||
CHECK;
|
||||
|
||||
@ -3880,10 +3888,12 @@ void unpacker::dump_options() {
|
||||
// packed file and len is the length of the buffer.
|
||||
// If null, the callback is used to fill an internal buffer.
|
||||
void unpacker::start(void* packptr, size_t len) {
|
||||
CHECK;
|
||||
NOT_PRODUCT(debug_u = this);
|
||||
if (packptr != null && len != 0) {
|
||||
inbytes.set((byte*) packptr, len);
|
||||
}
|
||||
CHECK;
|
||||
read_bands();
|
||||
}
|
||||
|
||||
@ -4015,6 +4025,7 @@ void unpacker::write_bc_ops() {
|
||||
NOT_PRODUCT(bc_superfield.setIndex(null));
|
||||
NOT_PRODUCT(bc_supermethod.setIndex(null));
|
||||
}
|
||||
CHECK;
|
||||
|
||||
for (int curIP = 0; ; curIP++) {
|
||||
int curPC = (int)(wpoffset() - codeBase);
|
||||
@ -4128,7 +4139,8 @@ void unpacker::write_bc_ops() {
|
||||
int coding = bc_initref.getInt();
|
||||
// Find the nth overloading of <init> in classRef.
|
||||
entry* ref = null;
|
||||
cpindex* ix = (classRef == null)? null: cp.getMethodIndex(classRef);
|
||||
cpindex* ix = cp.getMethodIndex(classRef);
|
||||
CHECK;
|
||||
for (int j = 0, which_init = 0; ; j++) {
|
||||
ref = (ix == null)? null: ix->get(j);
|
||||
if (ref == null) break; // oops, bad input
|
||||
@ -4405,6 +4417,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) {
|
||||
case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_EnclosingMethod):
|
||||
aname = cp.sym[cpool::s_EnclosingMethod];
|
||||
putref(class_EnclosingMethod_RC.getRefN());
|
||||
CHECK_0;
|
||||
putref(class_EnclosingMethod_RDN.getRefN());
|
||||
break;
|
||||
|
||||
@ -4423,6 +4436,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) {
|
||||
putu2(count = method_Exceptions_N.getInt());
|
||||
for (j = 0; j < count; j++) {
|
||||
putref(method_Exceptions_RC.getRefN());
|
||||
CHECK_0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -4455,16 +4469,18 @@ int unpacker::write_attrs(int attrc, julong indexBits) {
|
||||
// (253) [(1)(2)(2)]
|
||||
// (254) [(1)(2)(2)(2)]
|
||||
putu2(code_StackMapTable_offset.getInt());
|
||||
CHECK_0;
|
||||
for (int k = (tag - 251); k > 0; k--) {
|
||||
put_stackmap_type();
|
||||
CHECK_0;
|
||||
}
|
||||
} else {
|
||||
// (255) [(1)NH[(2)]NH[(2)]]
|
||||
putu2(code_StackMapTable_offset.getInt());
|
||||
putu2(j2 = code_StackMapTable_local_N.getInt());
|
||||
while (j2-- > 0) put_stackmap_type();
|
||||
while (j2-- > 0) {put_stackmap_type(); CHECK_0;}
|
||||
putu2(j2 = code_StackMapTable_stack_N.getInt());
|
||||
while (j2-- > 0) put_stackmap_type();
|
||||
while (j2-- > 0) {put_stackmap_type(); CHECK_0;}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -4488,7 +4504,9 @@ int unpacker::write_attrs(int attrc, julong indexBits) {
|
||||
bii += code_LocalVariableTable_span_O.getInt();
|
||||
putu2(to_bci(bii) - bci);
|
||||
putref(code_LocalVariableTable_name_RU.getRefN());
|
||||
CHECK_0;
|
||||
putref(code_LocalVariableTable_type_RS.getRefN());
|
||||
CHECK_0;
|
||||
putu2(code_LocalVariableTable_slot.getInt());
|
||||
}
|
||||
break;
|
||||
@ -4503,7 +4521,9 @@ int unpacker::write_attrs(int attrc, julong indexBits) {
|
||||
bii += code_LocalVariableTypeTable_span_O.getInt();
|
||||
putu2(to_bci(bii) - bci);
|
||||
putref(code_LocalVariableTypeTable_name_RU.getRefN());
|
||||
CHECK_0;
|
||||
putref(code_LocalVariableTypeTable_type_RS.getRefN());
|
||||
CHECK_0;
|
||||
putu2(code_LocalVariableTypeTable_slot.getInt());
|
||||
}
|
||||
break;
|
||||
@ -4531,7 +4551,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_0;
|
||||
if (aname == null) {
|
||||
// Unparse a compressor-defined attribute.
|
||||
layout_definition* lo = ad.getLayout(idx);
|
||||
@ -4687,7 +4707,9 @@ int unpacker::write_ics(int naOffset, int na) {
|
||||
flags &= ~ACC_IC_LONG_FORM; // clear high bit if set to get clean zero
|
||||
extra_ic.flags = flags;
|
||||
extra_ic.outer = class_InnerClasses_outer_RCN.getRefN();
|
||||
CHECK_0;
|
||||
extra_ic.name = class_InnerClasses_name_RUN.getRefN();
|
||||
CHECK_0;
|
||||
// Detect if this is an exact copy of the global tuple.
|
||||
if (global_ic != null) {
|
||||
if (global_ic->flags != extra_ic.flags ||
|
||||
@ -4797,6 +4819,7 @@ void unpacker::write_classfile_tail() {
|
||||
julong indexMask = ad.flagIndexMask();
|
||||
|
||||
cur_class = class_this.getRef();
|
||||
CHECK;
|
||||
cur_super = class_super.getRef();
|
||||
CHECK;
|
||||
|
||||
@ -4810,6 +4833,7 @@ void unpacker::write_classfile_tail() {
|
||||
putu2(num = class_interface_count.getInt());
|
||||
for (i = 0; i < num; i++) {
|
||||
putref(class_interface.getRef());
|
||||
CHECK;
|
||||
}
|
||||
|
||||
write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD);
|
||||
|
@ -114,6 +114,62 @@ int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP,
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Verifies whether the channel offsets are sane and correspond to the type of
|
||||
* the raster.
|
||||
*
|
||||
* Return value:
|
||||
* 0: Failure: channel offsets are invalid
|
||||
* 1: Success
|
||||
*/
|
||||
static int checkChannelOffsets(RasterS_t *rasterP, int dataArrayLength) {
|
||||
int i, lastPixelOffset, lastScanOffset;
|
||||
switch (rasterP->rasterType) {
|
||||
case COMPONENT_RASTER_TYPE:
|
||||
if (!SAFE_TO_MULT(rasterP->height, rasterP->scanlineStride)) {
|
||||
return 0;
|
||||
}
|
||||
if (!SAFE_TO_MULT(rasterP->width, rasterP->pixelStride)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
lastScanOffset = (rasterP->height - 1) * rasterP->scanlineStride;
|
||||
lastPixelOffset = (rasterP->width - 1) * rasterP->pixelStride;
|
||||
|
||||
|
||||
if (!SAFE_TO_ADD(lastPixelOffset, lastScanOffset)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
lastPixelOffset += lastScanOffset;
|
||||
|
||||
for (i = 0; i < rasterP->numDataElements; i++) {
|
||||
int off = rasterP->chanOffsets[i];
|
||||
int size = lastPixelOffset + off;
|
||||
|
||||
if (off < 0 || !SAFE_TO_ADD(lastPixelOffset, off)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size < lastPixelOffset || size >= dataArrayLength) {
|
||||
// an overflow, or insufficient buffer capacity
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case BANDED_RASTER_TYPE:
|
||||
// NB:caller does not support the banded rasters yet,
|
||||
// so this branch of the code must be re-defined in
|
||||
// order to provide valid criteria for the data offsets
|
||||
// verification, when/if banded rasters will be supported.
|
||||
// At the moment, we prohibit banded rasters as well.
|
||||
return 0;
|
||||
default:
|
||||
// PACKED_RASTER_TYPE: does not support channel offsets
|
||||
// UNKNOWN_RASTER_TYPE: should not be used, likely indicates an error
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the raster. All of the raster information is returned in the
|
||||
* rasterP structure.
|
||||
*
|
||||
@ -125,7 +181,6 @@ int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP,
|
||||
int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) {
|
||||
jobject joffs = NULL;
|
||||
/* int status;*/
|
||||
int isDiscrete = TRUE;
|
||||
|
||||
if (JNU_IsNull(env, jraster)) {
|
||||
JNU_ThrowNullPointerException(env, "null Raster object");
|
||||
@ -155,6 +210,9 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// make sure that the raster type is initialized
|
||||
rasterP->rasterType = UNKNOWN_RASTER_TYPE;
|
||||
|
||||
if (rasterP->numBands <= 0 ||
|
||||
rasterP->numBands > MAX_NUMBANDS)
|
||||
{
|
||||
@ -165,9 +223,14 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rasterP->sppsm.isUsed = 0;
|
||||
|
||||
if ((*env)->IsInstanceOf(env, rasterP->jsampleModel,
|
||||
(*env)->FindClass(env,"java/awt/image/SinglePixelPackedSampleModel"))) {
|
||||
jobject jmask, joffs, jnbits;
|
||||
|
||||
rasterP->sppsm.isUsed = 1;
|
||||
|
||||
rasterP->sppsm.maxBitSize = (*env)->GetIntField(env,
|
||||
rasterP->jsampleModel,
|
||||
g_SPPSMmaxBitID);
|
||||
@ -254,7 +317,6 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) {
|
||||
}
|
||||
rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID);
|
||||
rasterP->dataType = BYTE_DATA_TYPE;
|
||||
isDiscrete = FALSE;
|
||||
}
|
||||
else {
|
||||
rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM;
|
||||
@ -265,7 +327,19 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isDiscrete) {
|
||||
// do basic validation of the raster structure
|
||||
if (rasterP->width <= 0 || rasterP->height <= 0 ||
|
||||
rasterP->pixelStride <= 0 || rasterP->scanlineStride <= 0)
|
||||
{
|
||||
// invalid raster
|
||||
return -1;
|
||||
}
|
||||
|
||||
// channel (data) offsets
|
||||
switch (rasterP->rasterType) {
|
||||
case COMPONENT_RASTER_TYPE:
|
||||
case BANDED_RASTER_TYPE: // note that this routine does not support banded rasters at the moment
|
||||
// get channel (data) offsets
|
||||
rasterP->chanOffsets = NULL;
|
||||
if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) {
|
||||
rasterP->chanOffsets =
|
||||
@ -278,10 +352,21 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) {
|
||||
}
|
||||
(*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements,
|
||||
rasterP->chanOffsets);
|
||||
if (rasterP->jdata == NULL) {
|
||||
// unable to verify the raster
|
||||
return -1;
|
||||
}
|
||||
// verify whether channel offsets look sane
|
||||
if (!checkChannelOffsets(rasterP, (*env)->GetArrayLength(env, rasterP->jdata))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
; // PACKED_RASTER_TYPE does not use the channel offsets.
|
||||
}
|
||||
|
||||
/* additioanl check for sppsm fields validity: make sure that
|
||||
* size of raster samples doesn't exceed the data type cpacity.
|
||||
/* additional check for sppsm fields validity: make sure that
|
||||
* size of raster samples doesn't exceed the data type capacity.
|
||||
*/
|
||||
if (rasterP->dataType > UNKNOWN_DATA_TYPE && /* data type has been recognized */
|
||||
rasterP->sppsm.maxBitSize > 0 && /* raster has SPP sample model */
|
||||
@ -696,6 +781,21 @@ setHints(JNIEnv *env, BufImageS_t *imageP) {
|
||||
}
|
||||
else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) {
|
||||
int i;
|
||||
|
||||
/* do some sanity check first: make sure that
|
||||
* - sample model is SinglePixelPackedSampleModel
|
||||
* - number of bands in the raster corresponds to the number
|
||||
* of color components in the color model
|
||||
*/
|
||||
if (!rasterP->sppsm.isUsed ||
|
||||
rasterP->numBands != cmodelP->numComponents)
|
||||
{
|
||||
/* given raster is not compatible with the color model,
|
||||
* so the operation has to be aborted.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cmodelP->maxNbits > 8) {
|
||||
hintP->needToExpand = TRUE;
|
||||
hintP->expandToNbits = cmodelP->maxNbits;
|
||||
|
@ -95,6 +95,7 @@ typedef struct {
|
||||
jint offsets[MAX_NUMBANDS];
|
||||
jint nBits[MAX_NUMBANDS];
|
||||
jint maxBitSize;
|
||||
jint isUsed; // flag to indicate whether the raster sample model is SPPSM
|
||||
} SPPSampleModelS_t;
|
||||
|
||||
/* Struct that holds information for the Raster object */
|
||||
|
@ -41,5 +41,10 @@
|
||||
(((w) > 0) && ((h) > 0) && ((sz) > 0) && \
|
||||
(((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz))))
|
||||
|
||||
#define SAFE_TO_MULT(a, b) \
|
||||
(((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b)))
|
||||
|
||||
#define SAFE_TO_ADD(a, b) \
|
||||
(((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b)))
|
||||
|
||||
#endif // __SAFE_ALLOC_H__
|
||||
|
@ -133,6 +133,10 @@ SplashDecodeJpeg(Splash * splash, struct jpeg_decompress_struct *cinfo)
|
||||
ImageFormat srcFormat;
|
||||
|
||||
jpeg_read_header(cinfo, TRUE);
|
||||
|
||||
// SplashScreen jpeg converter expects data in RGB format only
|
||||
cinfo->out_color_space = JCS_RGB;
|
||||
|
||||
jpeg_start_decompress(cinfo);
|
||||
|
||||
SplashCleanup(splash);
|
||||
|
@ -1026,13 +1026,21 @@ public class SctpChannelImpl extends SctpChannel
|
||||
boolean unordered,
|
||||
int ppid)
|
||||
throws IOException {
|
||||
InetAddress addr = null; // no preferred address
|
||||
int port = 0;
|
||||
if (target != null) {
|
||||
InetSocketAddress isa = Net.checkAddress(target);
|
||||
addr = isa.getAddress();
|
||||
port = isa.getPort();
|
||||
}
|
||||
|
||||
int pos = bb.position();
|
||||
int lim = bb.limit();
|
||||
assert (pos <= lim);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
|
||||
int written = send0(fd, ((DirectBuffer)bb).address() + pos,
|
||||
rem, target, -1 /*121*/, streamNumber, unordered, ppid);
|
||||
int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr,
|
||||
port, -1 /*121*/, streamNumber, unordered, ppid);
|
||||
if (written > 0)
|
||||
bb.position(pos + written);
|
||||
return written;
|
||||
@ -1091,7 +1099,7 @@ public class SctpChannelImpl extends SctpChannel
|
||||
long address, int length, boolean peek) throws IOException;
|
||||
|
||||
static native int send0(int fd, long address, int length,
|
||||
SocketAddress target, int assocId, int streamNumber,
|
||||
InetAddress addr, int port, int assocId, int streamNumber,
|
||||
boolean unordered, int ppid) throws IOException;
|
||||
|
||||
private static native int checkConnect(FileDescriptor fd, boolean block,
|
||||
|
@ -889,13 +889,20 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
|
||||
boolean unordered,
|
||||
int ppid)
|
||||
throws IOException {
|
||||
InetAddress addr = null; // no preferred address
|
||||
int port = 0;
|
||||
if (target != null) {
|
||||
InetSocketAddress isa = Net.checkAddress(target);
|
||||
addr = isa.getAddress();
|
||||
port = isa.getPort();
|
||||
}
|
||||
int pos = bb.position();
|
||||
int lim = bb.limit();
|
||||
assert (pos <= lim);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
|
||||
int written = send0(fd, ((DirectBuffer)bb).address() + pos,
|
||||
rem, target, assocId, streamNumber, unordered, ppid);
|
||||
int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr,
|
||||
port, assocId, streamNumber, unordered, ppid);
|
||||
if (written > 0)
|
||||
bb.position(pos + written);
|
||||
return written;
|
||||
@ -976,13 +983,14 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
|
||||
private static int send0(int fd,
|
||||
long address,
|
||||
int length,
|
||||
SocketAddress target,
|
||||
InetAddress addr,
|
||||
int port,
|
||||
int assocId,
|
||||
int streamNumber,
|
||||
boolean unordered,
|
||||
int ppid)
|
||||
throws IOException {
|
||||
return SctpChannelImpl.send0(fd, address, length, target, assocId,
|
||||
return SctpChannelImpl.send0(fd, address, length, addr, port, assocId,
|
||||
streamNumber, unordered, ppid);
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,6 @@
|
||||
|
||||
#include "sun_nio_ch_DatagramChannelImpl.h"
|
||||
|
||||
static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */
|
||||
static jfieldID isa_portID; /* port in java.net.InetSocketAddress */
|
||||
static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */
|
||||
static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */
|
||||
static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */
|
||||
@ -61,9 +59,6 @@ Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz)
|
||||
isa_class = (*env)->NewGlobalRef(env, clazz);
|
||||
isa_ctorID = (*env)->GetMethodID(env, clazz, "<init>",
|
||||
"(Ljava/net/InetAddress;I)V");
|
||||
isa_addrID = (*env)->GetFieldID(env, clazz, "addr",
|
||||
"Ljava/net/InetAddress;");
|
||||
isa_portID = (*env)->GetFieldID(env, clazz, "port", "I");
|
||||
|
||||
clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl");
|
||||
dci_senderID = (*env)->GetFieldID(env, clazz, "sender",
|
||||
@ -212,15 +207,13 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
|
||||
jboolean preferIPv6, jobject fdo, jlong address,
|
||||
jint len, jobject dest)
|
||||
jint len, jobject destAddress, jint destPort)
|
||||
{
|
||||
jint fd = fdval(env, fdo);
|
||||
void *buf = (void *)jlong_to_ptr(address);
|
||||
SOCKADDR sa;
|
||||
int sa_len = SOCKADDR_LEN;
|
||||
jint n = 0;
|
||||
jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID);
|
||||
jint destPort = (*env)->GetIntField(env, dest, isa_portID);
|
||||
|
||||
if (len > MAX_PACKET_LEN) {
|
||||
len = MAX_PACKET_LEN;
|
||||
|
@ -67,8 +67,6 @@ static jclass spc_class; /* sun.nio.ch.sctp.PeerAddressChanged */
|
||||
static jmethodID spc_ctrID; /* sun.nio.ch.sctp.PeerAddressChanged.<init> */
|
||||
static jclass ss_class; /* sun.nio.ch.sctp.Shutdown */
|
||||
static jmethodID ss_ctrID; /* sun.nio.ch.sctp.Shutdown.<init> */
|
||||
static jfieldID isa_addrID; /* java.net.InetSocketAddress.addr */
|
||||
static jfieldID isa_portID; /* java.net.InetSocketAddress.port */
|
||||
|
||||
/* defined in SctpNet.c */
|
||||
jobject SockAddrToInetSocketAddress(JNIEnv* env, struct sockaddr* addr);
|
||||
@ -138,13 +136,6 @@ JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_initIDs
|
||||
CHECK_NULL(ss_class);
|
||||
ss_ctrID = (*env)->GetMethodID(env, cls, "<init>", "(I)V");
|
||||
CHECK_NULL(ss_ctrID);
|
||||
|
||||
/* InetSocketAddress */
|
||||
cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
|
||||
CHECK_NULL(cls);
|
||||
isa_addrID = (*env)->GetFieldID(env, cls, "addr", "Ljava/net/InetAddress;");
|
||||
CHECK_NULL(isa_addrID);
|
||||
isa_portID = (*env)->GetFieldID(env, cls, "port", "I");
|
||||
}
|
||||
|
||||
void getControlData
|
||||
@ -509,12 +500,12 @@ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_receive0
|
||||
/*
|
||||
* Class: sun_nio_ch_sctp_SctpChannelImpl
|
||||
* Method: send0
|
||||
* Signature: (IJILjava/net/SocketAddress;IIZI)I
|
||||
* Signature: (IJILjava/net/InetAddress;IIIZI)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0
|
||||
(JNIEnv *env, jclass klass, jint fd, jlong address, jint length,
|
||||
jobject saTarget, jint assocId, jint streamNumber, jboolean unordered,
|
||||
jint ppid) {
|
||||
jobject targetAddress, jint targetPort, jint assocId, jint streamNumber,
|
||||
jboolean unordered, jint ppid) {
|
||||
SOCKADDR sa;
|
||||
int sa_len = sizeof(sa);
|
||||
ssize_t rv = 0;
|
||||
@ -526,17 +517,13 @@ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0
|
||||
struct controlData cdata[1];
|
||||
|
||||
/* SctpChannel:
|
||||
* saTarget may contain the preferred address or NULL to use primary,
|
||||
* targetAddress may contain the preferred address or NULL to use primary,
|
||||
* assocId will always be -1
|
||||
* SctpMultiChannell:
|
||||
* Setup new association, saTarget will contain address, assocId = -1
|
||||
* Association already existing, assocId != -1, saTarget = preferred addr
|
||||
* Setup new association, targetAddress will contain address, assocId = -1
|
||||
* Association already existing, assocId != -1, targetAddress = preferred addr
|
||||
*/
|
||||
if (saTarget != NULL /*&& assocId <= 0*/) {
|
||||
|
||||
jobject targetAddress = (*env)->GetObjectField(env, saTarget, isa_addrID);
|
||||
jint targetPort = (*env)->GetIntField(env, saTarget, isa_portID);
|
||||
|
||||
if (targetAddress != NULL /*&& assocId <= 0*/) {
|
||||
if (NET_InetAddressToSockaddr(env, targetAddress, targetPort,
|
||||
(struct sockaddr *)&sa,
|
||||
&sa_len, JNI_TRUE) != 0) {
|
||||
|
@ -101,7 +101,6 @@ int awtPreloadD3D = -1;
|
||||
/* funtion in awt.dll (src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp) */
|
||||
#define D3D_PRELOAD_FUNC "preloadD3D"
|
||||
|
||||
|
||||
/* Extracts value of a parameter with the specified name
|
||||
* from command line argument (returns pointer in the argument).
|
||||
* Returns NULL if the argument does not contains the parameter.
|
||||
@ -276,7 +275,8 @@ LoadMSVCRT()
|
||||
#endif
|
||||
#ifdef CRT_DLL
|
||||
if (GetJREPath(crtpath, MAXPATHLEN)) {
|
||||
if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") + JLI_StrLen(CRT_DLL) >= MAXPATHLEN) {
|
||||
if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") +
|
||||
JLI_StrLen(CRT_DLL) >= MAXPATHLEN) {
|
||||
JLI_ReportErrorMessage(JRE_ERROR11);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
@ -347,7 +347,8 @@ GetJVMPath(const char *jrepath, const char *jvmtype,
|
||||
if (JLI_StrChr(jvmtype, '/') || JLI_StrChr(jvmtype, '\\')) {
|
||||
JLI_Snprintf(jvmpath, jvmpathsize, "%s\\" JVM_DLL, jvmtype);
|
||||
} else {
|
||||
JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype);
|
||||
JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL,
|
||||
jrepath, jvmtype);
|
||||
}
|
||||
if (stat(jvmpath, &s) == 0) {
|
||||
return JNI_TRUE;
|
||||
@ -525,6 +526,37 @@ jlong Counter2Micros(jlong counts)
|
||||
}
|
||||
return (counts * 1000 * 1000)/counterFrequency.QuadPart;
|
||||
}
|
||||
/*
|
||||
* windows snprintf does not guarantee a null terminator in the buffer,
|
||||
* if the computed size is equal to or greater than the buffer size,
|
||||
* as well as error conditions. This function guarantees a null terminator
|
||||
* under all these conditions. An unreasonable buffer or size will return
|
||||
* an error value. Under all other conditions this function will return the
|
||||
* size of the bytes actually written minus the null terminator, similar
|
||||
* to ansi snprintf api. Thus when calling this function the caller must
|
||||
* ensure storage for the null terminator.
|
||||
*/
|
||||
int
|
||||
JLI_Snprintf(char* buffer, size_t size, const char* format, ...) {
|
||||
int rc;
|
||||
va_list vl;
|
||||
if (size == 0 || buffer == NULL)
|
||||
return -1;
|
||||
buffer[0] = '\0';
|
||||
va_start(vl, format);
|
||||
rc = vsnprintf(buffer, size, format, vl);
|
||||
va_end(vl);
|
||||
/* force a null terminator, if something is amiss */
|
||||
if (rc < 0) {
|
||||
/* apply ansi semantics */
|
||||
buffer[size - 1] = '\0';
|
||||
return size;
|
||||
} else if (rc == size) {
|
||||
/* force a null terminator */
|
||||
buffer[size - 1] = '\0';
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
JLI_ReportErrorMessage(const char* fmt, ...) {
|
||||
@ -880,7 +912,7 @@ unquote(const char *s) {
|
||||
*/
|
||||
void
|
||||
ExecJRE(char *jre, char **argv) {
|
||||
int len;
|
||||
jint len;
|
||||
char path[MAXPATHLEN + 1];
|
||||
|
||||
const char *progname = GetProgramName();
|
||||
@ -1417,7 +1449,10 @@ CreateApplicationArgs(JNIEnv *env, char **strv, int argc)
|
||||
// we add the indicator
|
||||
tlen = 1 + JLI_StrLen(strv[i]) + 1;
|
||||
nargv[i] = (char *) JLI_MemAlloc(tlen);
|
||||
JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', strv[i]);
|
||||
if (JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F',
|
||||
strv[i]) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
JLI_TraceLauncher("%s\n", nargv[i]);
|
||||
}
|
||||
|
||||
|
@ -488,14 +488,15 @@ public abstract class WComponentPeer extends WObjectPeer
|
||||
try {
|
||||
replaceSurfaceData();
|
||||
} catch (InvalidPipeException e) {
|
||||
// REMIND : what do we do if our surface creation failed?
|
||||
// REMIND : what do we do if our surface creation failed?
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Component c = (Component)target;
|
||||
// Fix 6255371.
|
||||
if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing((Component)target, r)) {
|
||||
postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), r));
|
||||
if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) {
|
||||
postEvent(new InvocationEvent(c, r));
|
||||
}
|
||||
}
|
||||
|
||||
@ -618,7 +619,7 @@ public abstract class WComponentPeer extends WObjectPeer
|
||||
}
|
||||
|
||||
public void disposeLater() {
|
||||
postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), new Runnable() {
|
||||
postEvent(new InvocationEvent(target, new Runnable() {
|
||||
public void run() {
|
||||
dispose();
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ package sun.awt.windows;
|
||||
|
||||
import sun.awt.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InvocationEvent;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.awt.image.*;
|
||||
import sun.awt.image.ByteInterleavedRaster;
|
||||
@ -232,11 +233,13 @@ public class WEmbeddedFrame extends EmbeddedFrame {
|
||||
} else {
|
||||
// To avoid focus concurrence b/w IE and EmbeddedFrame
|
||||
// activation is postponed by means of posting it to EDT.
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true);
|
||||
}
|
||||
});
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true);
|
||||
}
|
||||
};
|
||||
WToolkit.postEvent(WToolkit.targetToAppContext(this),
|
||||
new InvocationEvent(this, r));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,6 @@
|
||||
#include "net_util.h"
|
||||
#include <winsock2.h>
|
||||
|
||||
static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */
|
||||
static jfieldID isa_portID; /* port in java.net.InetSocketAddress */
|
||||
static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */
|
||||
static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */
|
||||
static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */
|
||||
@ -50,9 +48,6 @@ Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz)
|
||||
isa_class = (*env)->NewGlobalRef(env, clazz);
|
||||
isa_ctorID = (*env)->GetMethodID(env, clazz, "<init>",
|
||||
"(Ljava/net/InetAddress;I)V");
|
||||
isa_addrID = (*env)->GetFieldID(env, clazz, "addr",
|
||||
"Ljava/net/InetAddress;");
|
||||
isa_portID = (*env)->GetFieldID(env, clazz, "port", "I");
|
||||
|
||||
clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl");
|
||||
dci_senderID = (*env)->GetFieldID(env, clazz, "sender",
|
||||
@ -214,15 +209,14 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
|
||||
jboolean preferIPv6, jobject fdo,
|
||||
jlong address, jint len, jobject dest)
|
||||
jlong address, jint len,
|
||||
jobject destAddress, jint destPort)
|
||||
{
|
||||
jint fd = fdval(env, fdo);
|
||||
void *buf = (void *)jlong_to_ptr(address);
|
||||
SOCKETADDRESS sa;
|
||||
int sa_len;
|
||||
jint rv = 0;
|
||||
jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID);
|
||||
jint destPort = (*env)->GetIntField(env, dest, isa_portID);
|
||||
|
||||
if (NET_InetAddressToSockaddr(env, destAddress, destPort,
|
||||
(struct sockaddr *)&sa,
|
||||
|
@ -53,14 +53,12 @@ struct EnableEditingStruct {
|
||||
* AwtTextComponent fields
|
||||
*/
|
||||
|
||||
/* java.awt.TextComponent fields */
|
||||
jfieldID AwtTextComponent::canAccessClipboardID;
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* AwtTextComponent methods
|
||||
*/
|
||||
|
||||
jmethodID AwtTextComponent::canAccessClipboardMID;
|
||||
|
||||
AwtTextComponent::AwtTextComponent() {
|
||||
m_synthetic = FALSE;
|
||||
m_lStartPos = -1;
|
||||
@ -367,8 +365,7 @@ AwtTextComponent::WmPaste()
|
||||
}
|
||||
jobject target = GetTarget(env);
|
||||
jboolean canAccessClipboard =
|
||||
env->GetBooleanField(target,
|
||||
AwtTextComponent::canAccessClipboardID);
|
||||
env->CallBooleanMethod (target, AwtTextComponent::canAccessClipboardMID);
|
||||
env->DeleteLocalRef(target);
|
||||
return (canAccessClipboard) ? mrDoDefault : mrConsume;
|
||||
}
|
||||
@ -854,12 +851,13 @@ Java_sun_awt_windows_WTextComponentPeer_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
TRY;
|
||||
|
||||
cls = env->FindClass("java/awt/TextComponent");
|
||||
if (cls != NULL) {
|
||||
AwtTextComponent::canAccessClipboardID =
|
||||
env->GetFieldID(cls, "canAccessClipboard", "Z");
|
||||
DASSERT(AwtTextComponent::canAccessClipboardID != NULL);
|
||||
}
|
||||
jclass textComponentClassID = env->FindClass("java/awt/TextComponent");
|
||||
AwtTextComponent::canAccessClipboardMID =
|
||||
env->GetMethodID(textComponentClassID,
|
||||
"canAccessClipboard", "()Z");
|
||||
env->DeleteLocalRef(textComponentClassID);
|
||||
|
||||
DASSERT(AwtTextComponent::canAccessClipboardMID != NULL);
|
||||
|
||||
CATCH_BAD_ALLOC;
|
||||
}
|
||||
|
@ -42,8 +42,7 @@
|
||||
|
||||
class AwtTextComponent : public AwtComponent {
|
||||
public:
|
||||
/* java.awt.TextComponent canAccessClipboard field ID */
|
||||
static jfieldID canAccessClipboardID;
|
||||
static jmethodID canAccessClipboardMID;
|
||||
|
||||
AwtTextComponent();
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user