- /*
- * @(#)JMXConnectorServer.java 1.30 04/05/05
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
-
- package javax.management.remote;
-
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Map;
- import java.util.SortedMap;
-
- import javax.management.MBeanNotificationInfo;
- import javax.management.MBeanServer;
- import javax.management.MBeanRegistration;
- import javax.management.Notification;
- import javax.management.NotificationBroadcasterSupport;
- import javax.management.ObjectName;
-
- /**
- * <p>Superclass of every connector server. A connector server is
- * attached to an MBean server. It listens for client connection
- * requests and creates a connection for each one.</p>
- *
- * <p>A connector server is associated with an MBean server either by
- * registering it in that MBean server, or by passing the MBean server
- * to its constructor.</p>
- *
- * <p>A connector server is inactive when created. It only starts
- * listening for client connections when the {@link #start() start}
- * method is called. A connector server stops listening for client
- * connections when the {@link #stop() stop} method is called or when
- * the connector server is unregistered from its MBean server.</p>
- *
- * <p>Stopping a connector server does not unregister it from its
- * MBean server. A connector server once stopped cannot be
- * restarted.</p>
- *
- * <p>Each time a client connection is made or broken, a notification
- * of class {@link JMXConnectionNotification} is emitted.</p>
- *
- * @since 1.5
- * @since.unbundled 1.0
- */
- public abstract class JMXConnectorServer
- extends NotificationBroadcasterSupport
- implements JMXConnectorServerMBean, MBeanRegistration {
-
- /**
- * <p>Name of the attribute that specifies the authenticator for a
- * connector server. The value associated with this attribute, if
- * any, must be an object that implements the interface {@link
- * JMXAuthenticator}.</p>
- */
- public static final String AUTHENTICATOR =
- "jmx.remote.authenticator";
-
- /**
- * <p>Constructs a connector server that will be registered as an
- * MBean in the MBean server it is attached to. This constructor
- * is typically called by one of the <code>createMBean</code>
- * methods when creating, within an MBean server, a connector
- * server that makes it available remotely.</p>
- */
- public JMXConnectorServer() {
- this(null);
- }
-
- /**
- * <p>Constructs a connector server that is attached to the given
- * MBean server. A connector server that is created in this way
- * can be registered in a different MBean server.</p>
- *
- * @param mbeanServer the MBean server that this connector server
- * is attached to. Null if this connector server will be attached
- * to an MBean server by being registered in it.
- */
- public JMXConnectorServer(MBeanServer mbeanServer) {
- this.mbeanServer = mbeanServer;
- }
-
- /**
- * <p>Returns the MBean server that this connector server is
- * attached to.</p>
- *
- * @return the MBean server that this connector server is attached
- * to, or null if it is not yet attached to an MBean server.
- */
- public synchronized MBeanServer getMBeanServer() {
- return mbeanServer;
- }
-
- public synchronized void setMBeanServerForwarder(MBeanServerForwarder mbsf)
- {
- if (mbsf == null)
- throw new IllegalArgumentException("Invalid null argument: mbsf");
-
- if (mbeanServer != null) mbsf.setMBeanServer(mbeanServer);
- mbeanServer = mbsf;
- }
-
- public String[] getConnectionIds() {
- synchronized (connectionIds) {
- return (String[])
- connectionIds.toArray(new String[connectionIds.size()]);
- }
- }
-
- /**
- * <p>Returns a client stub for this connector server. A client
- * stub is a serializable object whose {@link
- * JMXConnector#connect(Map) connect} method can be used to make
- * one new connection to this connector server.</p>
- *
- * <p>A given connector need not support the generation of client
- * stubs. However, the connectors specified by the JMX Remote API do
- * (JMXMP Connector and RMI Connector).</p>
- *
- * <p>The default implementation of this method uses {@link
- * #getAddress} and {@link JMXConnectorFactory} to generate the
- * stub, with code equivalent to the following:</p>
- *
- * <pre>
- * JMXServiceURL addr = {@link #getAddress() getAddress()};
- * return {@link JMXConnectorFactory#newJMXConnector(JMXServiceURL, Map)
- * JMXConnectorFactory.newJMXConnector(addr, env)};
- * </pre>
- *
- * <p>A connector server for which this is inappropriate must
- * override this method so that it either implements the
- * appropriate logic or throws {@link
- * UnsupportedOperationException}.</p>
- *
- * @param env client connection parameters of the same sort that
- * could be provided to {@link JMXConnector#connect(Map)
- * JMXConnector.connect(Map)}. Can be null, which is equivalent
- * to an empty map.
- *
- * @return a client stub that can be used to make a new connection
- * to this connector server.
- *
- * @exception UnsupportedOperationException if this connector
- * server does not support the generation of client stubs.
- *
- * @exception IllegalStateException if the JMXConnectorServer is
- * not started (see {@link JMXConnectorServerMBean#isActive()}).
- *
- * @exception IOException if a communications problem means that a
- * stub cannot be created.
- **/
- public JMXConnector toJMXConnector(Map<String,?> env)
- throws IOException
- {
- if (!isActive()) throw new
- IllegalStateException("Connector is not active");
- JMXServiceURL addr = getAddress();
- return JMXConnectorFactory.newJMXConnector(addr, env);
- }
-
- /**
- * <p>Returns an array indicating the notifications that this MBean
- * sends. The implementation in <code>JMXConnectorServer</code>
- * returns an array with one element, indicating that it can emit
- * notifications of class {@link JMXConnectionNotification} with
- * the types defined in that class. A subclass that can emit other
- * notifications should return an array that contains this element
- * plus descriptions of the other notifications.</p>
- *
- * @return the array of possible notifications.
- */
- public MBeanNotificationInfo[] getNotificationInfo() {
- final String[] types = {
- JMXConnectionNotification.OPENED,
- JMXConnectionNotification.CLOSED,
- JMXConnectionNotification.FAILED,
- };
- final String className = JMXConnectionNotification.class.getName();
- final String description =
- "A client connection has been opened or closed";
- return new MBeanNotificationInfo[] {
- new MBeanNotificationInfo(types, className, description),
- };
- }
-
- /**
- * <p>Called by a subclass when a new client connection is opened.
- * Adds <code>connectionId</code> to the list returned by {@link
- * #getConnectionIds()}, then emits a {@link
- * JMXConnectionNotification} with type {@link
- * JMXConnectionNotification#OPENED}.</p>
- *
- * @param connectionId the ID of the new connection. This must be
- * different from the ID of any connection previously opened by
- * this connector server.
- *
- * @param message the message for the emitted {@link
- * JMXConnectionNotification}. Can be null. See {@link
- * Notification#getMessage()}.
- *
- * @param userData the <code>userData</code> for the emitted
- * {@link JMXConnectionNotification}. Can be null. See {@link
- * Notification#getUserData()}.
- *
- * @exception NullPointerException if <code>connectionId</code> is
- * null.
- */
- protected void connectionOpened(String connectionId,
- String message,
- Object userData) {
-
- if (connectionId == null)
- throw new NullPointerException("Illegal null argument");
-
- synchronized (connectionIds) {
- connectionIds.add(connectionId);
- }
-
- sendNotification(JMXConnectionNotification.OPENED, connectionId,
- message, userData);
- }
-
- /**
- * <p>Called by a subclass when a client connection is closed
- * normally. Removes <code>connectionId</code> from the list returned
- * by {@link #getConnectionIds()}, then emits a {@link
- * JMXConnectionNotification} with type {@link
- * JMXConnectionNotification#CLOSED}.</p>
- *
- * @param connectionId the ID of the closed connection.
- *
- * @param message the message for the emitted {@link
- * JMXConnectionNotification}. Can be null. See {@link
- * Notification#getMessage()}.
- *
- * @param userData the <code>userData</code> for the emitted
- * {@link JMXConnectionNotification}. Can be null. See {@link
- * Notification#getUserData()}.
- *
- * @exception NullPointerException if <code>connectionId</code>
- * is null.
- */
- protected void connectionClosed(String connectionId,
- String message,
- Object userData) {
-
- if (connectionId == null)
- throw new NullPointerException("Illegal null argument");
-
- synchronized (connectionIds) {
- connectionIds.remove(connectionId);
- }
-
- sendNotification(JMXConnectionNotification.CLOSED, connectionId,
- message, userData);
- }
-
- /**
- * <p>Called by a subclass when a client connection fails.
- * Removes <code>connectionId</code> from the list returned by
- * {@link #getConnectionIds()}, then emits a {@link
- * JMXConnectionNotification} with type {@link
- * JMXConnectionNotification#FAILED}.</p>
- *
- * @param connectionId the ID of the failed connection.
- *
- * @param message the message for the emitted {@link
- * JMXConnectionNotification}. Can be null. See {@link
- * Notification#getMessage()}.
- *
- * @param userData the <code>userData</code> for the emitted
- * {@link JMXConnectionNotification}. Can be null. See {@link
- * Notification#getUserData()}.
- *
- * @exception NullPointerException if <code>connectionId</code> is
- * null.
- */
- protected void connectionFailed(String connectionId,
- String message,
- Object userData) {
-
- if (connectionId == null)
- throw new NullPointerException("Illegal null argument");
-
- synchronized (connectionIds) {
- connectionIds.remove(connectionId);
- }
-
- sendNotification(JMXConnectionNotification.FAILED, connectionId,
- message, userData);
- }
-
- private void sendNotification(String type, String connectionId,
- String message, Object userData) {
- Notification notif =
- new JMXConnectionNotification(type,
- getNotificationSource(),
- connectionId,
- nextSequenceNumber(),
- message,
- userData);
- sendNotification(notif);
- }
-
- private synchronized Object getNotificationSource() {
- if (myName != null)
- return myName;
- else
- return this;
- }
-
- private static long nextSequenceNumber() {
- synchronized (sequenceNumberLock) {
- return sequenceNumber++;
- }
- }
-
- // implements MBeanRegistration
- /**
- * <p>Called by an MBean server when this connector server is
- * registered in that MBean server. This connector server becomes
- * attached to the MBean server and its {@link #getMBeanServer()}
- * method will return <code>mbs</code>.</p>
- *
- * <p>If this connector server is already attached to an MBean
- * server, this method has no effect. The MBean server it is
- * attached to is not necessarily the one it is being registered
- * in.</p>
- *
- * @param mbs the MBean server in which this connection server is
- * being registered.
- *
- * @param name The object name of the MBean.
- *
- * @return The name under which the MBean is to be registered.
- *
- * @exception NullPointerException if <code>mbs</code> or
- * <code>name</code> is null.
- */
- public synchronized ObjectName preRegister(MBeanServer mbs,
- ObjectName name) {
- if (mbs == null || name == null)
- throw new NullPointerException("Null MBeanServer or ObjectName");
- if (mbeanServer == null) {
- mbeanServer = mbs;
- myName = name;
- }
- return name;
- }
-
- public void postRegister(Boolean registrationDone) {
- // do nothing
- }
-
- /**
- * <p>Called by an MBean server when this connector server is
- * unregistered from that MBean server. If this connector server
- * was attached to that MBean server by being registered in it,
- * and if the connector server is still active,
- * then unregistering it will call the {@link #stop stop} method.
- * If the <code>stop</code> method throws an exception, the
- * unregistration attempt will fail. It is recommended to call
- * the <code>stop</code> method explicitly before unregistering
- * the MBean.</p>
- *
- * @exception IOException if thrown by the {@link #stop stop} method.
- */
- public synchronized void preDeregister() throws Exception {
- if (myName != null && isActive()) {
- stop();
- myName = null; // just in case stop is buggy and doesn't stop
- }
- }
-
- public void postDeregister() {
- myName = null;
- }
-
- /**
- * The MBeanServer used by this server to execute a client request.
- */
- private MBeanServer mbeanServer = null;
-
- /**
- * The name used to registered this server in an MBeanServer.
- * It is null if the this server is not registered or has been unregistered.
- */
- private ObjectName myName;
-
- private final int[] lock = new int[0];
-
- private List /* of String */ connectionIds = new ArrayList();
-
- private static final int[] sequenceNumberLock = new int[0];
- private static long sequenceNumber;
- }