Merge
authordfuchs
Tue, 10 Mar 2009 12:55:40 +0100
changeset 2620 505c8053dae2
parent 2619 cc0bbd192d1a (current diff)
parent 2618 cf8969529599 (diff)
child 2622 559fae6ca888
Merge
jdk/src/share/classes/javax/management/monitor/Monitor.java
--- a/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java	Mon Mar 09 22:49:21 2009 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java	Tue Mar 10 12:55:40 2009 +0100
@@ -22,7 +22,6 @@
  * CA 95054 USA or visit www.sun.com if you need additional information or
  * have any questions.
  */
-
 package com.sun.jmx.remote.internal;
 
 import java.io.IOException;
@@ -34,6 +33,7 @@
 import java.util.Map;
 import java.util.concurrent.Executor;
 
+import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import javax.security.auth.Subject;
@@ -54,6 +54,9 @@
 
 
 public abstract class ClientNotifForwarder {
+
+    private final AccessControlContext acc;
+
     public ClientNotifForwarder(Map env) {
         this(null, env);
     }
@@ -87,6 +90,8 @@
             this.command = command;
             if (thread == null) {
                 thread = new Thread() {
+
+                    @Override
                     public void run() {
                         while (true) {
                             Runnable r;
@@ -130,6 +135,7 @@
 
         this.defaultClassLoader = defaultClassLoader;
         this.executor = ex;
+        this.acc = AccessController.getContext();
     }
 
     /**
@@ -390,28 +396,85 @@
         setState(TERMINATED);
     }
 
-// -------------------------------------------------
-// private classes
-// -------------------------------------------------
+
+    // -------------------------------------------------
+    // private classes
+    // -------------------------------------------------
     //
+
     private class NotifFetcher implements Runnable {
+
+        private volatile boolean alreadyLogged = false;
+
+        private void logOnce(String msg, SecurityException x) {
+            if (alreadyLogged) return;
+            // Log only once.
+            logger.config("setContextClassLoader",msg);
+            if (x != null) logger.fine("setContextClassLoader", x);
+            alreadyLogged = true;
+        }
+
+        // Set new context class loader, returns previous one.
+        private final ClassLoader setContextClassLoader(final ClassLoader loader) {
+            final AccessControlContext ctxt = ClientNotifForwarder.this.acc;
+            // if ctxt is null, log a config message and throw a
+            // SecurityException.
+            if (ctxt == null) {
+                logOnce("AccessControlContext must not be null.",null);
+                throw new SecurityException("AccessControlContext must not be null");
+            }
+            return AccessController.doPrivileged(
+                new PrivilegedAction<ClassLoader>() {
+                    public ClassLoader run() {
+                        try {
+                            // get context class loader - may throw
+                            // SecurityException - though unlikely.
+                            final ClassLoader previous =
+                                Thread.currentThread().getContextClassLoader();
+
+                            // if nothing needs to be done, break here...
+                            if (loader == previous) return previous;
+
+                            // reset context class loader - may throw
+                            // SecurityException
+                            Thread.currentThread().setContextClassLoader(loader);
+                            return previous;
+                        } catch (SecurityException x) {
+                            logOnce("Permission to set ContextClassLoader missing. " +
+                                    "Notifications will not be dispatched. " +
+                                    "Please check your Java policy configuration: " +
+                                    x, x);
+                            throw x;
+                        }
+                    }
+                }, ctxt);
+        }
+
         public void run() {
+            final ClassLoader previous;
+            if (defaultClassLoader != null) {
+                previous = setContextClassLoader(defaultClassLoader);
+            } else {
+                previous = null;
+            }
+            try {
+                doRun();
+            } finally {
+                if (defaultClassLoader != null) {
+                    setContextClassLoader(previous);
+                }
+            }
+        }
+
+        private void doRun() {
             synchronized (ClientNotifForwarder.this) {
                 currentFetchThread = Thread.currentThread();
 
-                if (state == STARTING)
+                if (state == STARTING) {
                     setState(STARTED);
+                }
             }
 
-            if (defaultClassLoader != null) {
-                AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                        public Void run() {
-                            Thread.currentThread().
-                                setContextClassLoader(defaultClassLoader);
-                            return null;
-                        }
-                    });
-            }
 
             NotificationResult nr = null;
             if (!shouldStop() && (nr = fetchNotifs()) != null) {
@@ -444,8 +507,9 @@
                         // check if an mbean unregistration notif
                         if (!listenerID.equals(mbeanRemovedNotifID)) {
                             final ClientListenerInfo li = infoList.get(listenerID);
-                            if (li != null)
-                                listeners.put(listenerID,li);
+                            if (li != null) {
+                                listeners.put(listenerID, li);
+                            }
                             continue;
                         }
                         final Notification notif = tn.getNotification();
@@ -786,9 +850,7 @@
     private long clientSequenceNumber = -1;
     private final int maxNotifications;
     private final long timeout;
-
     private Integer mbeanRemovedNotifID = null;
-
     private Thread currentFetchThread;
 
     // state
--- a/jdk/src/share/classes/javax/management/monitor/CounterMonitor.java	Mon Mar 09 22:49:21 2009 +0100
+++ b/jdk/src/share/classes/javax/management/monitor/CounterMonitor.java	Tue Mar 10 12:55:40 2009 +0100
@@ -596,7 +596,7 @@
      * types sent by the counter monitor.
      */
     public MBeanNotificationInfo[] getNotificationInfo() {
-        return notifsInfo;
+        return notifsInfo.clone();
     }
 
     /*
--- a/jdk/src/share/classes/javax/management/monitor/GaugeMonitor.java	Mon Mar 09 22:49:21 2009 +0100
+++ b/jdk/src/share/classes/javax/management/monitor/GaugeMonitor.java	Tue Mar 10 12:55:40 2009 +0100
@@ -478,7 +478,7 @@
      * types sent by the gauge monitor.
      */
     public MBeanNotificationInfo[] getNotificationInfo() {
-        return notifsInfo;
+        return notifsInfo.clone();
     }
 
     /*
--- a/jdk/src/share/classes/javax/management/monitor/Monitor.java	Mon Mar 09 22:49:21 2009 +0100
+++ b/jdk/src/share/classes/javax/management/monitor/Monitor.java	Tue Mar 10 12:55:40 2009 +0100
@@ -32,6 +32,7 @@
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
 import java.util.List;
 import java.util.Map;
 import java.util.WeakHashMap;
@@ -165,7 +166,10 @@
     /**
      * AccessControlContext of the Monitor.start() caller.
      */
-    private AccessControlContext acc;
+    private static final AccessControlContext noPermissionsACC =
+            new AccessControlContext(
+            new ProtectionDomain[] {new ProtectionDomain(null, null)});
+    private volatile AccessControlContext acc = noPermissionsACC;
 
     /**
      * Scheduler Service.
@@ -744,7 +748,7 @@
 
             // Reset the AccessControlContext.
             //
-            acc = null;
+            acc = noPermissionsACC;
 
             // Reset the complex type attribute information
             // such that it is recalculated again.
@@ -1560,10 +1564,12 @@
 
         public void run() {
             final ScheduledFuture<?> sf;
+            final AccessControlContext ac;
             synchronized (Monitor.this) {
                 sf = Monitor.this.schedulerFuture;
+                ac = Monitor.this.acc;
             }
-            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
                 public Void run() {
                     if (Monitor.this.isActive()) {
                         final int an[] = alreadyNotifieds;
@@ -1576,7 +1582,11 @@
                     }
                     return null;
                 }
-            }, Monitor.this.acc);
+            };
+            if (ac == null) {
+                throw new SecurityException("AccessControlContext cannot be null");
+            }
+            AccessController.doPrivileged(action, ac);
             synchronized (Monitor.this) {
                 if (Monitor.this.isActive() &&
                     Monitor.this.schedulerFuture == sf) {
--- a/jdk/src/share/classes/javax/management/monitor/StringMonitor.java	Mon Mar 09 22:49:21 2009 +0100
+++ b/jdk/src/share/classes/javax/management/monitor/StringMonitor.java	Tue Mar 10 12:55:40 2009 +0100
@@ -184,6 +184,7 @@
      * @return The derived gauge of the specified object.
      *
      */
+    @Override
     public synchronized String getDerivedGauge(ObjectName object) {
         return (String) super.getDerivedGauge(object);
     }
@@ -199,6 +200,7 @@
      * @return The derived gauge timestamp of the specified object.
      *
      */
+    @Override
     public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
         return super.getDerivedGaugeTimeStamp(object);
     }
@@ -341,8 +343,9 @@
      * the Java class of the notification and the notification types sent by
      * the string monitor.
      */
+    @Override
     public MBeanNotificationInfo[] getNotificationInfo() {
-        return notifsInfo;
+        return notifsInfo.clone();
     }
 
     /*
--- a/jdk/src/share/classes/sun/net/httpserver/Request.java	Mon Mar 09 22:49:21 2009 +0100
+++ b/jdk/src/share/classes/sun/net/httpserver/Request.java	Tue Mar 10 12:55:40 2009 +0100
@@ -52,6 +52,9 @@
         os = rawout;
         do {
             startLine = readLine();
+            if (startLine == null) {
+                return;
+            }
             /* skip blank lines */
         } while (startLine.equals (""));
     }
--- a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java	Mon Mar 09 22:49:21 2009 +0100
+++ b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java	Tue Mar 10 12:55:40 2009 +0100
@@ -441,6 +441,7 @@
                         rawin = sslStreams.getInputStream();
                         rawout = sslStreams.getOutputStream();
                         engine = sslStreams.getSSLEngine();
+                        connection.sslStreams = sslStreams;
                     } else {
                         rawin = new BufferedInputStream(
                             new Request.ReadStream (
@@ -450,6 +451,8 @@
                             ServerImpl.this, chan
                         );
                     }
+                    connection.raw = rawin;
+                    connection.rawout = rawout;
                 }
                 Request req = new Request (rawin, rawout);
                 requestLine = req.requestLine();