KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jmx > remote > internal > ServerNotifForwarder


1 /*
2  * @(#)ServerNotifForwarder.java 1.45 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.jmx.remote.internal;
9
10 import java.io.IOException JavaDoc;
11 import java.security.AccessControlContext JavaDoc;
12 import java.security.AccessController JavaDoc;
13 import java.security.PrivilegedAction JavaDoc;
14 import java.security.PrivilegedActionException JavaDoc;
15 import java.security.PrivilegedExceptionAction JavaDoc;
16 import java.util.Set JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import javax.management.ObjectInstance JavaDoc;
21 import javax.management.ObjectName JavaDoc;
22 import javax.management.MBeanPermission JavaDoc;
23 import javax.management.MBeanServer JavaDoc;
24 import javax.management.Notification JavaDoc;
25 import javax.management.NotificationBroadcaster JavaDoc;
26 import javax.management.NotificationListener JavaDoc;
27 import javax.management.NotificationFilter JavaDoc;
28 import javax.management.MBeanServerNotification JavaDoc;
29 import javax.management.NotificationFilterSupport JavaDoc;
30 import javax.management.ListenerNotFoundException JavaDoc;
31 import javax.management.InstanceNotFoundException JavaDoc;
32
33 import javax.management.remote.TargetedNotification JavaDoc;
34 import javax.management.remote.NotificationResult JavaDoc;
35
36 import javax.security.auth.Subject JavaDoc;
37
38 import com.sun.jmx.remote.util.ClassLogger;
39 import com.sun.jmx.remote.util.EnvHelp;
40 import com.sun.jmx.remote.internal.ListenerInfo;
41
42 public class ServerNotifForwarder {
43
44     public ServerNotifForwarder(MBeanServer JavaDoc mbeanServer,
45                 Map JavaDoc env,
46                 NotificationBuffer notifBuffer) {
47     this.mbeanServer = mbeanServer;
48
49     this.notifBuffer = notifBuffer;
50
51
52     connectionTimeout = EnvHelp.getServerConnectionTimeout(env);
53     }
54
55     public Integer JavaDoc addNotificationListener(final ObjectName JavaDoc name,
56                                            final NotificationFilter JavaDoc filter)
57         throws InstanceNotFoundException JavaDoc, IOException JavaDoc {
58          
59         if (logger.traceOn()) {
60             logger.trace("addNotificationListener",
61                          "Add a listener at " + name);
62         }
63
64         checkState();
65
66         // Explicitly check MBeanPermission for addNotificationListener
67
//
68
checkMBeanPermission(name, "addNotificationListener");
69
70     try {
71         Boolean JavaDoc instanceOf = (Boolean JavaDoc)
72         AccessController.doPrivileged(new PrivilegedExceptionAction JavaDoc() {
73             public Object JavaDoc run() throws InstanceNotFoundException JavaDoc {
74                 return new Boolean JavaDoc(
75                            mbeanServer.isInstanceOf(name,
76                                     broadcasterClass));
77             }
78                     });
79         if (!instanceOf.booleanValue()) {
80         throw new IllegalArgumentException JavaDoc("The specified MBean [" +
81                            name + "] is not a " +
82                            "NotificationBroadcaster " +
83                            "object.");
84         }
85     } catch (PrivilegedActionException JavaDoc e) {
86         throw (InstanceNotFoundException JavaDoc) extractException(e);
87     }
88
89         final Integer JavaDoc id = getListenerID();
90         synchronized(listenerList) {
91             listenerList.add(new ListenerInfo(id, name, filter));
92         }
93
94         return id;
95     }
96
97     public void removeNotificationListener(ObjectName JavaDoc name,
98                                            Integer JavaDoc[] listenerIDs)
99         throws Exception JavaDoc {
100
101         if (logger.traceOn()) {
102             logger.trace("removeNotificationListener",
103                          "Remove some listeners from " + name);
104         }
105
106         checkState();
107
108         // Explicitly check MBeanPermission for removeNotificationListener
109
//
110
checkMBeanPermission(name, "removeNotificationListener");
111
112         Exception JavaDoc re = null;
113         for (int i = 0 ; i < listenerIDs.length ; i++) {
114             try {
115                 removeNotificationListener(name, listenerIDs[i]);
116             } catch (Exception JavaDoc e) {
117                 // Give back the first exception
118
//
119
if (re != null) {
120                     re = e;
121                 }
122             }
123         }
124         if (re != null) {
125             throw re;
126         }
127     }
128
129     public void removeNotificationListener(ObjectName JavaDoc name, Integer JavaDoc listenerID)
130         throws
131         InstanceNotFoundException JavaDoc,
132         ListenerNotFoundException JavaDoc,
133         IOException JavaDoc {
134
135         if (logger.traceOn()) {
136             logger.trace("removeNotificationListener",
137                          "Remove the listener " + listenerID + " from " + name);
138         }
139
140         checkState();
141
142     if (name != null && !name.isPattern()) {
143         if (!mbeanServer.isRegistered(name)) {
144         throw new InstanceNotFoundException JavaDoc("The MBean " + name +
145                             " is not registered.");
146         }
147     }
148
149         synchronized(listenerList) {
150             if (!listenerList.remove(new ListenerInfo(listenerID,name,null))) {
151                 throw new ListenerNotFoundException JavaDoc("Listener not found!");
152             }
153         }
154     }
155
156     public NotificationResult JavaDoc fetchNotifs(long startSequenceNumber,
157                                           long timeout,
158                                           int maxNotifications) {
159         if (logger.traceOn()) {
160             logger.trace("fetchNotifs", "Fetching notifications, the " +
161                          "startSequenceNumber is " + startSequenceNumber +
162                          ", the timeout is " + timeout +
163                          ", the maxNotifications is " + maxNotifications);
164         }
165
166         NotificationResult JavaDoc nr = null;
167     final long t = Math.min(connectionTimeout, timeout);
168         try {
169             nr = notifBuffer.fetchNotifications(listenerList,
170                                                 startSequenceNumber,
171                                                 t, maxNotifications);
172         } catch (InterruptedException JavaDoc ire) {
173             nr = new NotificationResult JavaDoc(0L, 0L, new TargetedNotification JavaDoc[0]);
174         }
175
176         if (logger.traceOn()) {
177             logger.trace("fetchNotifs", "Forwarding the notifs: "+nr);
178         }
179
180         return nr;
181     }
182
183     public void terminate() {
184         if (logger.traceOn()) {
185             logger.trace("terminate", "Be called.");
186         }
187
188         synchronized(terminationLock) {
189             if (terminated) {
190                 return;
191             }
192
193             terminated = true;
194
195             synchronized(listenerList) {
196                 listenerList.clear();
197             }
198         }
199
200         if (logger.traceOn()) {
201             logger.trace("terminate", "Terminated.");
202         }
203     }
204
205     //----------------
206
// PRIVATE METHODS
207
//----------------
208

209     private void checkState() throws IOException JavaDoc {
210         synchronized(terminationLock) {
211             if (terminated) {
212                 throw new IOException JavaDoc("The connection has been terminated.");
213             }
214         }
215     }
216
217     private Integer JavaDoc getListenerID() {
218         synchronized(listenerCounterLock) {
219             return new Integer JavaDoc(listenerCounter++);
220         }
221     }
222
223     /**
224      * Explicitly check the MBeanPermission for
225      * the current access control context.
226      */

227     private void checkMBeanPermission(final ObjectName JavaDoc name,
228                                       final String JavaDoc actions)
229         throws InstanceNotFoundException JavaDoc, SecurityException JavaDoc {
230         SecurityManager JavaDoc sm = System.getSecurityManager();
231         if (sm != null) {
232             AccessControlContext JavaDoc acc = AccessController.getContext();
233             ObjectInstance JavaDoc oi = null;
234             try {
235                 oi = (ObjectInstance JavaDoc) AccessController.doPrivileged(
236                     new PrivilegedExceptionAction JavaDoc() {
237                             public Object JavaDoc run()
238                                 throws InstanceNotFoundException JavaDoc {
239                                 return mbeanServer.getObjectInstance(name);
240                             }
241                         });
242             } catch (PrivilegedActionException JavaDoc e) {
243                 throw (InstanceNotFoundException JavaDoc) extractException(e);
244             }
245             String JavaDoc classname = oi.getClassName();
246             MBeanPermission JavaDoc perm = new MBeanPermission JavaDoc(classname,
247                                                        null,
248                                                        name,
249                                                        actions);
250             sm.checkPermission(perm, acc);
251         }
252     }
253
254     /**
255      * Iterate until we extract the real exception
256      * from a stack of PrivilegedActionExceptions.
257      */

258     private static Exception JavaDoc extractException(Exception JavaDoc e) {
259         while (e instanceof PrivilegedActionException JavaDoc) {
260             e = ((PrivilegedActionException JavaDoc)e).getException();
261         }
262         return e;
263     }
264
265     //------------------
266
// PRIVATE VARIABLES
267
//------------------
268

269     private MBeanServer JavaDoc mbeanServer;
270
271     private final long connectionTimeout;
272
273     private static int listenerCounter = 0;
274     private final static int[] listenerCounterLock = new int[0];
275
276     private NotificationBuffer notifBuffer;
277     private Set JavaDoc listenerList = new HashSet JavaDoc();
278
279     private boolean terminated = false;
280     private final int[] terminationLock = new int[0];
281
282     static final String JavaDoc broadcasterClass =
283         NotificationBroadcaster JavaDoc.class.getName();
284
285     private static final ClassLogger logger =
286         new ClassLogger("javax.management.remote.misc", "ServerNotifForwarder");
287 }
288
Popular Tags