KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > management > remote > JMXConnectorServer


1 /*
2  * @(#)JMXConnectorServer.java 1.30 04/05/05
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8
9 package javax.management.remote;
10
11 import java.io.IOException JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.Map JavaDoc;
15 import java.util.SortedMap JavaDoc;
16
17 import javax.management.MBeanNotificationInfo JavaDoc;
18 import javax.management.MBeanServer JavaDoc;
19 import javax.management.MBeanRegistration JavaDoc;
20 import javax.management.Notification JavaDoc;
21 import javax.management.NotificationBroadcasterSupport JavaDoc;
22 import javax.management.ObjectName JavaDoc;
23
24 /**
25  * <p>Superclass of every connector server. A connector server is
26  * attached to an MBean server. It listens for client connection
27  * requests and creates a connection for each one.</p>
28  *
29  * <p>A connector server is associated with an MBean server either by
30  * registering it in that MBean server, or by passing the MBean server
31  * to its constructor.</p>
32  *
33  * <p>A connector server is inactive when created. It only starts
34  * listening for client connections when the {@link #start() start}
35  * method is called. A connector server stops listening for client
36  * connections when the {@link #stop() stop} method is called or when
37  * the connector server is unregistered from its MBean server.</p>
38  *
39  * <p>Stopping a connector server does not unregister it from its
40  * MBean server. A connector server once stopped cannot be
41  * restarted.</p>
42  *
43  * <p>Each time a client connection is made or broken, a notification
44  * of class {@link JMXConnectionNotification} is emitted.</p>
45  *
46  * @since 1.5
47  * @since.unbundled 1.0
48  */

49 public abstract class JMXConnectorServer
50     extends NotificationBroadcasterSupport JavaDoc
51     implements JMXConnectorServerMBean JavaDoc, MBeanRegistration JavaDoc {
52
53     /**
54      * <p>Name of the attribute that specifies the authenticator for a
55      * connector server. The value associated with this attribute, if
56      * any, must be an object that implements the interface {@link
57      * JMXAuthenticator}.</p>
58      */

59     public static final String JavaDoc AUTHENTICATOR =
60     "jmx.remote.authenticator";
61
62     /**
63      * <p>Constructs a connector server that will be registered as an
64      * MBean in the MBean server it is attached to. This constructor
65      * is typically called by one of the <code>createMBean</code>
66      * methods when creating, within an MBean server, a connector
67      * server that makes it available remotely.</p>
68      */

69     public JMXConnectorServer() {
70     this(null);
71     }
72
73     /**
74      * <p>Constructs a connector server that is attached to the given
75      * MBean server. A connector server that is created in this way
76      * can be registered in a different MBean server.</p>
77      *
78      * @param mbeanServer the MBean server that this connector server
79      * is attached to. Null if this connector server will be attached
80      * to an MBean server by being registered in it.
81      */

82     public JMXConnectorServer(MBeanServer JavaDoc mbeanServer) {
83     this.mbeanServer = mbeanServer;
84     }
85
86     /**
87      * <p>Returns the MBean server that this connector server is
88      * attached to.</p>
89      *
90      * @return the MBean server that this connector server is attached
91      * to, or null if it is not yet attached to an MBean server.
92      */

93     public synchronized MBeanServer JavaDoc getMBeanServer() {
94     return mbeanServer;
95     }
96
97     public synchronized void setMBeanServerForwarder(MBeanServerForwarder JavaDoc mbsf)
98     {
99     if (mbsf == null)
100         throw new IllegalArgumentException JavaDoc("Invalid null argument: mbsf");
101
102         if (mbeanServer != null) mbsf.setMBeanServer(mbeanServer);
103         mbeanServer = mbsf;
104     }
105
106     public String JavaDoc[] getConnectionIds() {
107     synchronized (connectionIds) {
108         return (String JavaDoc[])
109         connectionIds.toArray(new String JavaDoc[connectionIds.size()]);
110     }
111     }
112
113     /**
114      * <p>Returns a client stub for this connector server. A client
115      * stub is a serializable object whose {@link
116      * JMXConnector#connect(Map) connect} method can be used to make
117      * one new connection to this connector server.</p>
118      *
119      * <p>A given connector need not support the generation of client
120      * stubs. However, the connectors specified by the JMX Remote API do
121      * (JMXMP Connector and RMI Connector).</p>
122      *
123      * <p>The default implementation of this method uses {@link
124      * #getAddress} and {@link JMXConnectorFactory} to generate the
125      * stub, with code equivalent to the following:</p>
126      *
127      * <pre>
128      * JMXServiceURL addr = {@link #getAddress() getAddress()};
129      * return {@link JMXConnectorFactory#newJMXConnector(JMXServiceURL, Map)
130      * JMXConnectorFactory.newJMXConnector(addr, env)};
131      * </pre>
132      *
133      * <p>A connector server for which this is inappropriate must
134      * override this method so that it either implements the
135      * appropriate logic or throws {@link
136      * UnsupportedOperationException}.</p>
137      *
138      * @param env client connection parameters of the same sort that
139      * could be provided to {@link JMXConnector#connect(Map)
140      * JMXConnector.connect(Map)}. Can be null, which is equivalent
141      * to an empty map.
142      *
143      * @return a client stub that can be used to make a new connection
144      * to this connector server.
145      *
146      * @exception UnsupportedOperationException if this connector
147      * server does not support the generation of client stubs.
148      *
149      * @exception IllegalStateException if the JMXConnectorServer is
150      * not started (see {@link JMXConnectorServerMBean#isActive()}).
151      *
152      * @exception IOException if a communications problem means that a
153      * stub cannot be created.
154      **/

155     public JMXConnector JavaDoc toJMXConnector(Map JavaDoc<String JavaDoc,?> env)
156     throws IOException JavaDoc
157     {
158     if (!isActive()) throw new
159         IllegalStateException JavaDoc("Connector is not active");
160     JMXServiceURL JavaDoc addr = getAddress();
161     return JMXConnectorFactory.newJMXConnector(addr, env);
162     }
163
164     /**
165      * <p>Returns an array indicating the notifications that this MBean
166      * sends. The implementation in <code>JMXConnectorServer</code>
167      * returns an array with one element, indicating that it can emit
168      * notifications of class {@link JMXConnectionNotification} with
169      * the types defined in that class. A subclass that can emit other
170      * notifications should return an array that contains this element
171      * plus descriptions of the other notifications.</p>
172      *
173      * @return the array of possible notifications.
174      */

175     public MBeanNotificationInfo JavaDoc[] getNotificationInfo() {
176     final String JavaDoc[] types = {
177         JMXConnectionNotification.OPENED,
178         JMXConnectionNotification.CLOSED,
179         JMXConnectionNotification.FAILED,
180     };
181     final String JavaDoc className = JMXConnectionNotification JavaDoc.class.getName();
182     final String JavaDoc description =
183         "A client connection has been opened or closed";
184     return new MBeanNotificationInfo JavaDoc[] {
185         new MBeanNotificationInfo JavaDoc(types, className, description),
186     };
187     }
188
189     /**
190      * <p>Called by a subclass when a new client connection is opened.
191      * Adds <code>connectionId</code> to the list returned by {@link
192      * #getConnectionIds()}, then emits a {@link
193      * JMXConnectionNotification} with type {@link
194      * JMXConnectionNotification#OPENED}.</p>
195      *
196      * @param connectionId the ID of the new connection. This must be
197      * different from the ID of any connection previously opened by
198      * this connector server.
199      *
200      * @param message the message for the emitted {@link
201      * JMXConnectionNotification}. Can be null. See {@link
202      * Notification#getMessage()}.
203      *
204      * @param userData the <code>userData</code> for the emitted
205      * {@link JMXConnectionNotification}. Can be null. See {@link
206      * Notification#getUserData()}.
207      *
208      * @exception NullPointerException if <code>connectionId</code> is
209      * null.
210      */

211     protected void connectionOpened(String JavaDoc connectionId,
212                     String JavaDoc message,
213                     Object JavaDoc userData) {
214
215     if (connectionId == null)
216         throw new NullPointerException JavaDoc("Illegal null argument");
217
218     synchronized (connectionIds) {
219         connectionIds.add(connectionId);
220     }
221
222     sendNotification(JMXConnectionNotification.OPENED, connectionId,
223              message, userData);
224     }
225
226     /**
227      * <p>Called by a subclass when a client connection is closed
228      * normally. Removes <code>connectionId</code> from the list returned
229      * by {@link #getConnectionIds()}, then emits a {@link
230      * JMXConnectionNotification} with type {@link
231      * JMXConnectionNotification#CLOSED}.</p>
232      *
233      * @param connectionId the ID of the closed connection.
234      *
235      * @param message the message for the emitted {@link
236      * JMXConnectionNotification}. Can be null. See {@link
237      * Notification#getMessage()}.
238      *
239      * @param userData the <code>userData</code> for the emitted
240      * {@link JMXConnectionNotification}. Can be null. See {@link
241      * Notification#getUserData()}.
242      *
243      * @exception NullPointerException if <code>connectionId</code>
244      * is null.
245      */

246     protected void connectionClosed(String JavaDoc connectionId,
247                     String JavaDoc message,
248                     Object JavaDoc userData) {
249
250     if (connectionId == null)
251         throw new NullPointerException JavaDoc("Illegal null argument");
252
253     synchronized (connectionIds) {
254         connectionIds.remove(connectionId);
255     }
256
257     sendNotification(JMXConnectionNotification.CLOSED, connectionId,
258              message, userData);
259     }
260
261     /**
262      * <p>Called by a subclass when a client connection fails.
263      * Removes <code>connectionId</code> from the list returned by
264      * {@link #getConnectionIds()}, then emits a {@link
265      * JMXConnectionNotification} with type {@link
266      * JMXConnectionNotification#FAILED}.</p>
267      *
268      * @param connectionId the ID of the failed connection.
269      *
270      * @param message the message for the emitted {@link
271      * JMXConnectionNotification}. Can be null. See {@link
272      * Notification#getMessage()}.
273      *
274      * @param userData the <code>userData</code> for the emitted
275      * {@link JMXConnectionNotification}. Can be null. See {@link
276      * Notification#getUserData()}.
277      *
278      * @exception NullPointerException if <code>connectionId</code> is
279      * null.
280      */

281     protected void connectionFailed(String JavaDoc connectionId,
282                     String JavaDoc message,
283                     Object JavaDoc userData) {
284
285     if (connectionId == null)
286         throw new NullPointerException JavaDoc("Illegal null argument");
287
288     synchronized (connectionIds) {
289         connectionIds.remove(connectionId);
290     }
291
292     sendNotification(JMXConnectionNotification.FAILED, connectionId,
293              message, userData);
294     }
295
296     private void sendNotification(String JavaDoc type, String JavaDoc connectionId,
297                   String JavaDoc message, Object JavaDoc userData) {
298     Notification JavaDoc notif =
299         new JMXConnectionNotification JavaDoc(type,
300                       getNotificationSource(),
301                       connectionId,
302                       nextSequenceNumber(),
303                       message,
304                       userData);
305     sendNotification(notif);
306     }
307
308     private synchronized Object JavaDoc getNotificationSource() {
309     if (myName != null)
310         return myName;
311     else
312         return this;
313     }
314
315     private static long nextSequenceNumber() {
316     synchronized (sequenceNumberLock) {
317         return sequenceNumber++;
318     }
319     }
320
321     // implements MBeanRegistration
322
/**
323      * <p>Called by an MBean server when this connector server is
324      * registered in that MBean server. This connector server becomes
325      * attached to the MBean server and its {@link #getMBeanServer()}
326      * method will return <code>mbs</code>.</p>
327      *
328      * <p>If this connector server is already attached to an MBean
329      * server, this method has no effect. The MBean server it is
330      * attached to is not necessarily the one it is being registered
331      * in.</p>
332      *
333      * @param mbs the MBean server in which this connection server is
334      * being registered.
335      *
336      * @param name The object name of the MBean.
337      *
338      * @return The name under which the MBean is to be registered.
339      *
340      * @exception NullPointerException if <code>mbs</code> or
341      * <code>name</code> is null.
342      */

343     public synchronized ObjectName JavaDoc preRegister(MBeanServer JavaDoc mbs,
344                            ObjectName JavaDoc name) {
345     if (mbs == null || name == null)
346         throw new NullPointerException JavaDoc("Null MBeanServer or ObjectName");
347     if (mbeanServer == null) {
348         mbeanServer = mbs;
349         myName = name;
350     }
351     return name;
352     }
353
354     public void postRegister(Boolean JavaDoc registrationDone) {
355     // do nothing
356
}
357
358     /**
359      * <p>Called by an MBean server when this connector server is
360      * unregistered from that MBean server. If this connector server
361      * was attached to that MBean server by being registered in it,
362      * and if the connector server is still active,
363      * then unregistering it will call the {@link #stop stop} method.
364      * If the <code>stop</code> method throws an exception, the
365      * unregistration attempt will fail. It is recommended to call
366      * the <code>stop</code> method explicitly before unregistering
367      * the MBean.</p>
368      *
369      * @exception IOException if thrown by the {@link #stop stop} method.
370      */

371     public synchronized void preDeregister() throws Exception JavaDoc {
372     if (myName != null && isActive()) {
373         stop();
374         myName = null; // just in case stop is buggy and doesn't stop
375
}
376     }
377
378     public void postDeregister() {
379     myName = null;
380     }
381
382     /**
383      * The MBeanServer used by this server to execute a client request.
384      */

385     private MBeanServer JavaDoc mbeanServer = null;
386
387     /**
388      * The name used to registered this server in an MBeanServer.
389      * It is null if the this server is not registered or has been unregistered.
390      */

391     private ObjectName JavaDoc myName;
392
393     private final int[] lock = new int[0];
394
395     private List JavaDoc /* of String */ connectionIds = new ArrayList JavaDoc();
396
397     private static final int[] sequenceNumberLock = new int[0];
398     private static long sequenceNumber;
399 }
400
Popular Tags