feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2005, 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 javax.management.remote;
/**
* <p>Implemented by objects that can have a {@code JMXServiceURL} address.
* All {@link JMXConnectorServer} objects implement this interface.
* Depending on the connector implementation, a {@link JMXConnector}
* object may implement this interface too. {@code JMXConnector}
* objects for the RMI Connector are instances of
* {@link javax.management.remote.rmi.RMIConnector RMIConnector} which
* implements this interface.</p>
*
* <p>An object implementing this interface might not have an address
* at a given moment. This is indicated by a null return value from
* {@link #getAddress()}.</p>
*
* @since 1.6
*/
public interface JMXAddressable {
/**
* <p>The address of this object.</p>
*
* @return the address of this object, or null if it
* does not have one.
*/
public JMXServiceURL getAddress();
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2003, 2007, 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 javax.management.remote;
import java.security.Principal;
import javax.security.auth.Subject;
/**
* <p>Interface to define how remote credentials are converted into a
* JAAS Subject. This interface is used by the RMI Connector Server,
* and can be used by other connector servers.</p>
*
* <p>The user-defined authenticator instance is passed to the
* connector server in the environment map as the value of the
* attribute {@link JMXConnectorServer#AUTHENTICATOR}. For connector
* servers that use only this authentication system, if this attribute
* is not present or its value is <code>null</code> then no user
* authentication will be performed and full access to the methods
* exported by the <code>MBeanServerConnection</code> object will be
* allowed.</p>
*
* <p>If authentication is successful then an authenticated
* {@link Subject subject} filled in with its associated
* {@link Principal principals} is returned. Authorization checks
* will be then performed based on the given set of principals.</p>
*
* @since 1.5
*/
public interface JMXAuthenticator {
/**
* <p>Authenticates the <code>MBeanServerConnection</code> client
* with the given client credentials.</p>
*
* @param credentials the user-defined credentials to be passed
* into the server in order to authenticate the user before
* creating the <code>MBeanServerConnection</code>. The actual
* type of this parameter, and whether it can be null, depends on
* the connector.
*
* @return the authenticated subject containing its associated principals.
*
* @exception SecurityException if the server cannot authenticate the user
* with the provided credentials.
*/
public Subject authenticate(Object credentials);
}

View File

@@ -0,0 +1,197 @@
/*
* 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
* 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 javax.management.remote;
import javax.management.Notification;
import javax.management.ObjectName;
/**
* <p>Notification emitted when a client connection is opened or
* closed or when notifications are lost. These notifications are
* sent by connector servers (instances of {@link JMXConnectorServer})
* and by connector clients (instances of {@link JMXConnector}). For
* certain connectors, a session can consist of a sequence of
* connections. Connection-opened and connection-closed notifications
* will be sent for each one.</p>
*
* <p>The notification type is one of the following:</p>
*
* <table summary="JMXConnectionNotification Types">
*
* <tr>
* <th align=left>Type</th>
* <th align=left>Meaning</th>
* </tr>
*
* <tr>
* <td><code>jmx.remote.connection.opened</code></td>
* <td>A new client connection has been opened.</td>
* </tr>
*
* <tr>
* <td><code>jmx.remote.connection.closed</code></td>
* <td>A client connection has been closed.</td>
* </tr>
*
* <tr>
* <td><code>jmx.remote.connection.failed</code></td>
* <td>A client connection has failed unexpectedly.</td>
* </tr>
*
* <tr>
* <td><code>jmx.remote.connection.notifs.lost</code></td>
* <td>A client connection has potentially lost notifications. This
* notification only appears on the client side.</td>
* </tr>
* </table>
*
* <p>The <code>timeStamp</code> of the notification is a time value
* (consistent with {@link System#currentTimeMillis()}) indicating
* when the notification was constructed.</p>
*
* @since 1.5
*/
public class JMXConnectionNotification extends Notification {
private static final long serialVersionUID = -2331308725952627538L;
/**
* <p>Notification type string for a connection-opened notification.
*/
public static final String OPENED = "jmx.remote.connection.opened";
/**
* <p>Notification type string for a connection-closed notification.
*/
public static final String CLOSED = "jmx.remote.connection.closed";
/**
* <p>Notification type string for a connection-failed notification.
*/
public static final String FAILED = "jmx.remote.connection.failed";
/**
* <p>Notification type string for a connection that has possibly
* lost notifications.</p>
*/
public static final String NOTIFS_LOST =
"jmx.remote.connection.notifs.lost";
/**
* Constructs a new connection notification. The {@link
* #getSource() source} of the notification depends on whether it
* is being sent by a connector server or a connector client:
*
* <ul>
*
* <li>For a connector server, if it is registered in an MBean
* server, the source is the {@link ObjectName} under which it is
* registered. Otherwise, it is a reference to the connector
* server object itself, an instance of a subclass of {@link
* JMXConnectorServer}.
*
* <li>For a connector client, the source is a reference to the
* connector client object, an instance of a class implementing
* {@link JMXConnector}.
*
* </ul>
*
* @param type the type of the notification. This is usually one
* of the constants {@link #OPENED}, {@link #CLOSED}, {@link
* #FAILED}, {@link #NOTIFS_LOST}. It is not an error for it to
* be a different string.
*
* @param source the connector server or client emitting the
* notification.
*
* @param connectionId the ID of the connection within its
* connector server.
*
* @param sequenceNumber a non-negative integer. It is expected
* but not required that this number will be greater than any
* previous <code>sequenceNumber</code> in a notification from
* this source.
*
* @param message an unspecified text message, typically containing
* a human-readable description of the event. Can be null.
*
* @param userData an object whose type and meaning is defined by
* the connector server. Can be null.
*
* @exception NullPointerException if <code>type</code>,
* <code>source</code>, or <code>connectionId</code> is null.
*
* @exception IllegalArgumentException if
* <code>sequenceNumber</code> is negative.
*/
public JMXConnectionNotification(String type,
Object source,
String connectionId,
long sequenceNumber,
String message,
Object userData) {
/* We don't know whether the parent class (Notification) will
throw an exception if the type or source is null, because
JMX 1.2 doesn't specify that. So we make sure it is not
null, in case it would throw the wrong exception
(e.g. IllegalArgumentException instead of
NullPointerException). Likewise for the sequence number. */
super((String) nonNull(type),
nonNull(source),
Math.max(0, sequenceNumber),
System.currentTimeMillis(),
message);
if (type == null || source == null || connectionId == null)
throw new NullPointerException("Illegal null argument");
if (sequenceNumber < 0)
throw new IllegalArgumentException("Negative sequence number");
this.connectionId = connectionId;
setUserData(userData);
}
private static Object nonNull(Object arg) {
if (arg == null)
return "";
else
return arg;
}
/**
* <p>The connection ID to which this notification pertains.
*
* @return the connection ID.
*/
public String getConnectionId() {
return connectionId;
}
/**
* @serial The connection ID to which this notification pertains.
* @see #getConnectionId()
**/
private final String connectionId;
}

View File

@@ -0,0 +1,299 @@
/*
* 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
* 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 javax.management.remote;
import java.io.Closeable;
import java.io.IOException;
import java.util.Map;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanServerConnection;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.security.auth.Subject;
/**
* <p>The client end of a JMX API connector. An object of this type can
* be used to establish a connection to a connector server.</p>
*
* <p>A newly-created object of this type is unconnected. Its {@link
* #connect connect} method must be called before it can be used.
* However, objects created by {@link
* JMXConnectorFactory#connect(JMXServiceURL, Map)
* JMXConnectorFactory.connect} are already connected.</p>
*
* @since 1.5
*/
public interface JMXConnector extends Closeable {
/**
* <p>Name of the attribute that specifies the credentials to send
* to the connector server during connection. The value
* associated with this attribute, if any, is a serializable
* object of an appropriate type for the server's {@link
* JMXAuthenticator}.
*/
public static final String CREDENTIALS =
"jmx.remote.credentials";
/**
* <p>Establishes the connection to the connector server. This
* method is equivalent to {@link #connect(Map)
* connect(null)}.</p>
*
* @exception IOException if the connection could not be made
* because of a communication problem.
*
* @exception SecurityException if the connection could not be
* made for security reasons.
*/
public void connect() throws IOException;
/**
* <p>Establishes the connection to the connector server.</p>
*
* <p>If <code>connect</code> has already been called successfully
* on this object, calling it again has no effect. If, however,
* {@link #close} was called after <code>connect</code>, the new
* <code>connect</code> will throw an <code>IOException</code>.
*
* <p>Otherwise, either <code>connect</code> has never been called
* on this object, or it has been called but produced an
* exception. Then calling <code>connect</code> will attempt to
* establish a connection to the connector server.</p>
*
* @param env the properties of the connection. Properties in
* this map override properties in the map specified when the
* <code>JMXConnector</code> was created, if any. This parameter
* can be null, which is equivalent to an empty map.
*
* @exception IOException if the connection could not be made
* because of a communication problem.
*
* @exception SecurityException if the connection could not be
* made for security reasons.
*/
public void connect(Map<String,?> env) throws IOException;
/**
* <p>Returns an <code>MBeanServerConnection</code> object
* representing a remote MBean server. For a given
* <code>JMXConnector</code>, two successful calls to this method
* will usually return the same <code>MBeanServerConnection</code>
* object, though this is not required.</p>
*
* <p>For each method in the returned
* <code>MBeanServerConnection</code>, calling the method causes
* the corresponding method to be called in the remote MBean
* server. The value returned by the MBean server method is the
* value returned to the client. If the MBean server method
* produces an <code>Exception</code>, the same
* <code>Exception</code> is seen by the client. If the MBean
* server method, or the attempt to call it, produces an
* <code>Error</code>, the <code>Error</code> is wrapped in a
* {@link JMXServerErrorException}, which is seen by the
* client.</p>
*
* <p>Calling this method is equivalent to calling
* {@link #getMBeanServerConnection(Subject) getMBeanServerConnection(null)}
* meaning that no delegation subject is specified and that all the
* operations called on the <code>MBeanServerConnection</code> must
* use the authenticated subject, if any.</p>
*
* @return an object that implements the
* <code>MBeanServerConnection</code> interface by forwarding its
* methods to the remote MBean server.
*
* @exception IOException if a valid
* <code>MBeanServerConnection</code> cannot be created, for
* instance because the connection to the remote MBean server has
* not yet been established (with the {@link #connect(Map)
* connect} method), or it has been closed, or it has broken.
*/
public MBeanServerConnection getMBeanServerConnection()
throws IOException;
/**
* <p>Returns an <code>MBeanServerConnection</code> object representing
* a remote MBean server on which operations are performed on behalf of
* the supplied delegation subject. For a given <code>JMXConnector</code>
* and <code>Subject</code>, two successful calls to this method will
* usually return the same <code>MBeanServerConnection</code> object,
* though this is not required.</p>
*
* <p>For each method in the returned
* <code>MBeanServerConnection</code>, calling the method causes
* the corresponding method to be called in the remote MBean
* server on behalf of the given delegation subject instead of the
* authenticated subject. The value returned by the MBean server
* method is the value returned to the client. If the MBean server
* method produces an <code>Exception</code>, the same
* <code>Exception</code> is seen by the client. If the MBean
* server method, or the attempt to call it, produces an
* <code>Error</code>, the <code>Error</code> is wrapped in a
* {@link JMXServerErrorException}, which is seen by the
* client.</p>
*
* @param delegationSubject the <code>Subject</code> on behalf of
* which requests will be performed. Can be null, in which case
* requests will be performed on behalf of the authenticated
* Subject, if any.
*
* @return an object that implements the <code>MBeanServerConnection</code>
* interface by forwarding its methods to the remote MBean server on behalf
* of a given delegation subject.
*
* @exception IOException if a valid <code>MBeanServerConnection</code>
* cannot be created, for instance because the connection to the remote
* MBean server has not yet been established (with the {@link #connect(Map)
* connect} method), or it has been closed, or it has broken.
*/
public MBeanServerConnection getMBeanServerConnection(
Subject delegationSubject)
throws IOException;
/**
* <p>Closes the client connection to its server. Any ongoing or new
* request using the MBeanServerConnection returned by {@link
* #getMBeanServerConnection()} will get an
* <code>IOException</code>.</p>
*
* <p>If <code>close</code> has already been called successfully
* on this object, calling it again has no effect. If
* <code>close</code> has never been called, or if it was called
* but produced an exception, an attempt will be made to close the
* connection. This attempt can succeed, in which case
* <code>close</code> will return normally, or it can generate an
* exception.</p>
*
* <p>Closing a connection is a potentially slow operation. For
* example, if the server has crashed, the close operation might
* have to wait for a network protocol timeout. Callers that do
* not want to block in a close operation should do it in a
* separate thread.</p>
*
* @exception IOException if the connection cannot be closed
* cleanly. If this exception is thrown, it is not known whether
* the server end of the connection has been cleanly closed.
*/
public void close() throws IOException;
/**
* <p>Adds a listener to be informed of changes in connection
* status. The listener will receive notifications of type {@link
* JMXConnectionNotification}. An implementation can send other
* types of notifications too.</p>
*
* <p>Any number of listeners can be added with this method. The
* same listener can be added more than once with the same or
* different values for the filter and handback. There is no
* special treatment of a duplicate entry. For example, if a
* listener is registered twice with no filter, then its
* <code>handleNotification</code> method will be called twice for
* each notification.</p>
*
* @param listener a listener to receive connection status
* notifications.
* @param filter a filter to select which notifications are to be
* delivered to the listener, or null if all notifications are to
* be delivered.
* @param handback an object to be given to the listener along
* with each notification. Can be null.
*
* @exception NullPointerException if <code>listener</code> is
* null.
*
* @see #removeConnectionNotificationListener
* @see javax.management.NotificationBroadcaster#addNotificationListener
*/
public void
addConnectionNotificationListener(NotificationListener listener,
NotificationFilter filter,
Object handback);
/**
* <p>Removes a listener from the list to be informed of changes
* in status. The listener must previously have been added. If
* there is more than one matching listener, all are removed.</p>
*
* @param listener a listener to receive connection status
* notifications.
*
* @exception NullPointerException if <code>listener</code> is
* null.
*
* @exception ListenerNotFoundException if the listener is not
* registered with this <code>JMXConnector</code>.
*
* @see #removeConnectionNotificationListener(NotificationListener,
* NotificationFilter, Object)
* @see #addConnectionNotificationListener
* @see javax.management.NotificationEmitter#removeNotificationListener
*/
public void
removeConnectionNotificationListener(NotificationListener listener)
throws ListenerNotFoundException;
/**
* <p>Removes a listener from the list to be informed of changes
* in status. The listener must previously have been added with
* the same three parameters. If there is more than one matching
* listener, only one is removed.</p>
*
* @param l a listener to receive connection status notifications.
* @param f a filter to select which notifications are to be
* delivered to the listener. Can be null.
* @param handback an object to be given to the listener along
* with each notification. Can be null.
*
* @exception ListenerNotFoundException if the listener is not
* registered with this <code>JMXConnector</code>, or is not
* registered with the given filter and handback.
*
* @see #removeConnectionNotificationListener(NotificationListener)
* @see #addConnectionNotificationListener
* @see javax.management.NotificationEmitter#removeNotificationListener
*/
public void removeConnectionNotificationListener(NotificationListener l,
NotificationFilter f,
Object handback)
throws ListenerNotFoundException;
/**
* <p>Gets this connection's ID from the connector server. For a
* given connector server, every connection will have a unique id
* which does not change during the lifetime of the
* connection.</p>
*
* @return the unique ID of this connection. This is the same as
* the ID that the connector server includes in its {@link
* JMXConnectionNotification}s. The {@link
* javax.management.remote package description} describes the
* conventions for connection IDs.
*
* @exception IOException if the connection ID cannot be obtained,
* for instance because the connection is closed or broken.
*/
public String getConnectionId() throws IOException;
}

View File

@@ -0,0 +1,574 @@
/*
* 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
* 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 javax.management.remote;
import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.ServiceLoader;
import java.util.StringTokenizer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
import sun.reflect.misc.ReflectUtil;
/**
* <p>Factory to create JMX API connector clients. There
* are no instances of this class.</p>
*
* <p>Connections are usually made using the {@link
* #connect(JMXServiceURL) connect} method of this class. More
* advanced applications can separate the creation of the connector
* client, using {@link #newJMXConnector(JMXServiceURL, Map)
* newJMXConnector} and the establishment of the connection itself, using
* {@link JMXConnector#connect(Map)}.</p>
*
* <p>Each client is created by an instance of {@link
* JMXConnectorProvider}. This instance is found as follows. Suppose
* the given {@link JMXServiceURL} looks like
* <code>"service:jmx:<em>protocol</em>:<em>remainder</em>"</code>.
* Then the factory will attempt to find the appropriate {@link
* JMXConnectorProvider} for <code><em>protocol</em></code>. Each
* occurrence of the character <code>+</code> or <code>-</code> in
* <code><em>protocol</em></code> is replaced by <code>.</code> or
* <code>_</code>, respectively.</p>
*
* <p>A <em>provider package list</em> is searched for as follows:</p>
*
* <ol>
*
* <li>If the <code>environment</code> parameter to {@link
* #newJMXConnector(JMXServiceURL, Map) newJMXConnector} contains the
* key <code>jmx.remote.protocol.provider.pkgs</code> then the
* associated value is the provider package list.
*
* <li>Otherwise, if the system property
* <code>jmx.remote.protocol.provider.pkgs</code> exists, then its value
* is the provider package list.
*
* <li>Otherwise, there is no provider package list.
*
* </ol>
*
* <p>The provider package list is a string that is interpreted as a
* list of non-empty Java package names separated by vertical bars
* (<code>|</code>). If the string is empty, then so is the provider
* package list. If the provider package list is not a String, or if
* it contains an element that is an empty string, a {@link
* JMXProviderException} is thrown.</p>
*
* <p>If the provider package list exists and is not empty, then for
* each element <code><em>pkg</em></code> of the list, the factory
* will attempt to load the class
*
* <blockquote>
* <code><em>pkg</em>.<em>protocol</em>.ClientProvider</code>
* </blockquote>
* <p>If the <code>environment</code> parameter to {@link
* #newJMXConnector(JMXServiceURL, Map) newJMXConnector} contains the
* key <code>jmx.remote.protocol.provider.class.loader</code> then the
* associated value is the class loader to use to load the provider.
* If the associated value is not an instance of {@link
* java.lang.ClassLoader}, an {@link
* java.lang.IllegalArgumentException} is thrown.</p>
*
* <p>If the <code>jmx.remote.protocol.provider.class.loader</code>
* key is not present in the <code>environment</code> parameter, the
* calling thread's context class loader is used.</p>
*
* <p>If the attempt to load this class produces a {@link
* ClassNotFoundException}, the search for a handler continues with
* the next element of the list.</p>
*
* <p>Otherwise, a problem with the provider found is signalled by a
* {@link JMXProviderException} whose {@link
* JMXProviderException#getCause() <em>cause</em>} indicates the underlying
* exception, as follows:</p>
*
* <ul>
*
* <li>if the attempt to load the class produces an exception other
* than <code>ClassNotFoundException</code>, that is the
* <em>cause</em>;
*
* <li>if {@link Class#newInstance()} for the class produces an
* exception, that is the <em>cause</em>.
*
* </ul>
*
* <p>If no provider is found by the above steps, including the
* default case where there is no provider package list, then the
* implementation will use its own provider for
* <code><em>protocol</em></code>, or it will throw a
* <code>MalformedURLException</code> if there is none. An
* implementation may choose to find providers by other means. For
* example, it may support the <a
* href="{@docRoot}/../technotes/guides/jar/jar.html#Service Provider">
* JAR conventions for service providers</a>, where the service
* interface is <code>JMXConnectorProvider</code>.</p>
*
* <p>Every implementation must support the RMI connector protocol with
* the default RMI transport, specified with string <code>rmi</code>.
* An implementation may optionally support the RMI connector protocol
* with the RMI/IIOP transport, specified with the string
* <code>iiop</code>.</p>
*
* <p>Once a provider is found, the result of the
* <code>newJMXConnector</code> method is the result of calling {@link
* JMXConnectorProvider#newJMXConnector(JMXServiceURL,Map) newJMXConnector}
* on the provider.</p>
*
* <p>The <code>Map</code> parameter passed to the
* <code>JMXConnectorProvider</code> is a new read-only
* <code>Map</code> that contains all the entries that were in the
* <code>environment</code> parameter to {@link
* #newJMXConnector(JMXServiceURL,Map)
* JMXConnectorFactory.newJMXConnector}, if there was one.
* Additionally, if the
* <code>jmx.remote.protocol.provider.class.loader</code> key is not
* present in the <code>environment</code> parameter, it is added to
* the new read-only <code>Map</code>. The associated value is the
* calling thread's context class loader.</p>
*
* @since 1.5
*/
public class JMXConnectorFactory {
/**
* <p>Name of the attribute that specifies the default class
* loader. This class loader is used to deserialize return values and
* exceptions from remote <code>MBeanServerConnection</code>
* calls. The value associated with this attribute is an instance
* of {@link ClassLoader}.</p>
*/
public static final String DEFAULT_CLASS_LOADER =
"jmx.remote.default.class.loader";
/**
* <p>Name of the attribute that specifies the provider packages
* that are consulted when looking for the handler for a protocol.
* The value associated with this attribute is a string with
* package names separated by vertical bars (<code>|</code>).</p>
*/
public static final String PROTOCOL_PROVIDER_PACKAGES =
"jmx.remote.protocol.provider.pkgs";
/**
* <p>Name of the attribute that specifies the class
* loader for loading protocol providers.
* The value associated with this attribute is an instance
* of {@link ClassLoader}.</p>
*/
public static final String PROTOCOL_PROVIDER_CLASS_LOADER =
"jmx.remote.protocol.provider.class.loader";
private static final String PROTOCOL_PROVIDER_DEFAULT_PACKAGE =
"com.sun.jmx.remote.protocol";
private static final ClassLogger logger =
new ClassLogger("javax.management.remote.misc", "JMXConnectorFactory");
/** There are no instances of this class. */
private JMXConnectorFactory() {
}
/**
* <p>Creates a connection to the connector server at the given
* address.</p>
*
* <p>This method is equivalent to {@link
* #connect(JMXServiceURL,Map) connect(serviceURL, null)}.</p>
*
* @param serviceURL the address of the connector server to
* connect to.
*
* @return a <code>JMXConnector</code> whose {@link
* JMXConnector#connect connect} method has been called.
*
* @exception NullPointerException if <code>serviceURL</code> is null.
*
* @exception IOException if the connector client or the
* connection cannot be made because of a communication problem.
*
* @exception SecurityException if the connection cannot be made
* for security reasons.
*/
public static JMXConnector connect(JMXServiceURL serviceURL)
throws IOException {
return connect(serviceURL, null);
}
/**
* <p>Creates a connection to the connector server at the given
* address.</p>
*
* <p>This method is equivalent to:</p>
*
* <pre>
* JMXConnector conn = JMXConnectorFactory.newJMXConnector(serviceURL,
* environment);
* conn.connect(environment);
* </pre>
*
* @param serviceURL the address of the connector server to connect to.
*
* @param environment a set of attributes to determine how the
* connection is made. This parameter can be null. Keys in this
* map must be Strings. The appropriate type of each associated
* value depends on the attribute. The contents of
* <code>environment</code> are not changed by this call.
*
* @return a <code>JMXConnector</code> representing the newly-made
* connection. Each successful call to this method produces a
* different object.
*
* @exception NullPointerException if <code>serviceURL</code> is null.
*
* @exception IOException if the connector client or the
* connection cannot be made because of a communication problem.
*
* @exception SecurityException if the connection cannot be made
* for security reasons.
*/
public static JMXConnector connect(JMXServiceURL serviceURL,
Map<String,?> environment)
throws IOException {
if (serviceURL == null)
throw new NullPointerException("Null JMXServiceURL");
JMXConnector conn = newJMXConnector(serviceURL, environment);
conn.connect(environment);
return conn;
}
private static <K,V> Map<K,V> newHashMap() {
return new HashMap<K,V>();
}
private static <K> Map<K,Object> newHashMap(Map<K,?> map) {
return new HashMap<K,Object>(map);
}
/**
* <p>Creates a connector client for the connector server at the
* given address. The resultant client is not connected until its
* {@link JMXConnector#connect(Map) connect} method is called.</p>
*
* @param serviceURL the address of the connector server to connect to.
*
* @param environment a set of attributes to determine how the
* connection is made. This parameter can be null. Keys in this
* map must be Strings. The appropriate type of each associated
* value depends on the attribute. The contents of
* <code>environment</code> are not changed by this call.
*
* @return a <code>JMXConnector</code> representing the new
* connector client. Each successful call to this method produces
* a different object.
*
* @exception NullPointerException if <code>serviceURL</code> is null.
*
* @exception IOException if the connector client cannot be made
* because of a communication problem.
*
* @exception MalformedURLException if there is no provider for the
* protocol in <code>serviceURL</code>.
*
* @exception JMXProviderException if there is a provider for the
* protocol in <code>serviceURL</code> but it cannot be used for
* some reason.
*/
public static JMXConnector newJMXConnector(JMXServiceURL serviceURL,
Map<String,?> environment)
throws IOException {
final Map<String,Object> envcopy;
if (environment == null)
envcopy = newHashMap();
else {
EnvHelp.checkAttributes(environment);
envcopy = newHashMap(environment);
}
final ClassLoader loader = resolveClassLoader(envcopy);
final Class<JMXConnectorProvider> targetInterface =
JMXConnectorProvider.class;
final String protocol = serviceURL.getProtocol();
final String providerClassName = "ClientProvider";
final JMXServiceURL providerURL = serviceURL;
JMXConnectorProvider provider = getProvider(providerURL, envcopy,
providerClassName,
targetInterface,
loader);
IOException exception = null;
if (provider == null) {
// Loader is null when context class loader is set to null
// and no loader has been provided in map.
// com.sun.jmx.remote.util.Service class extracted from j2se
// provider search algorithm doesn't handle well null classloader.
if (loader != null) {
try {
JMXConnector connection =
getConnectorAsService(loader, providerURL, envcopy);
if (connection != null)
return connection;
} catch (JMXProviderException e) {
throw e;
} catch (IOException e) {
exception = e;
}
}
provider = getProvider(protocol, PROTOCOL_PROVIDER_DEFAULT_PACKAGE,
JMXConnectorFactory.class.getClassLoader(),
providerClassName, targetInterface);
}
if (provider == null) {
MalformedURLException e =
new MalformedURLException("Unsupported protocol: " + protocol);
if (exception == null) {
throw e;
} else {
throw EnvHelp.initCause(e, exception);
}
}
final Map<String,Object> fixedenv =
Collections.unmodifiableMap(envcopy);
return provider.newJMXConnector(serviceURL, fixedenv);
}
private static String resolvePkgs(Map<String, ?> env)
throws JMXProviderException {
Object pkgsObject = null;
if (env != null)
pkgsObject = env.get(PROTOCOL_PROVIDER_PACKAGES);
if (pkgsObject == null)
pkgsObject =
AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty(PROTOCOL_PROVIDER_PACKAGES);
}
});
if (pkgsObject == null)
return null;
if (!(pkgsObject instanceof String)) {
final String msg = "Value of " + PROTOCOL_PROVIDER_PACKAGES +
" parameter is not a String: " +
pkgsObject.getClass().getName();
throw new JMXProviderException(msg);
}
final String pkgs = (String) pkgsObject;
if (pkgs.trim().equals(""))
return null;
// pkgs may not contain an empty element
if (pkgs.startsWith("|") || pkgs.endsWith("|") ||
pkgs.indexOf("||") >= 0) {
final String msg = "Value of " + PROTOCOL_PROVIDER_PACKAGES +
" contains an empty element: " + pkgs;
throw new JMXProviderException(msg);
}
return pkgs;
}
static <T> T getProvider(JMXServiceURL serviceURL,
final Map<String, Object> environment,
String providerClassName,
Class<T> targetInterface,
final ClassLoader loader)
throws IOException {
final String protocol = serviceURL.getProtocol();
final String pkgs = resolvePkgs(environment);
T instance = null;
if (pkgs != null) {
instance =
getProvider(protocol, pkgs, loader, providerClassName,
targetInterface);
if (instance != null) {
boolean needsWrap = (loader != instance.getClass().getClassLoader());
environment.put(PROTOCOL_PROVIDER_CLASS_LOADER, needsWrap ? wrap(loader) : loader);
}
}
return instance;
}
static <T> Iterator<T> getProviderIterator(final Class<T> providerClass,
final ClassLoader loader) {
ServiceLoader<T> serviceLoader =
ServiceLoader.load(providerClass, loader);
return serviceLoader.iterator();
}
private static ClassLoader wrap(final ClassLoader parent) {
return parent != null ? AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return new ClassLoader(parent) {
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
ReflectUtil.checkPackageAccess(name);
return super.loadClass(name, resolve);
}
};
}
}) : null;
}
private static JMXConnector getConnectorAsService(ClassLoader loader,
JMXServiceURL url,
Map<String, ?> map)
throws IOException {
Iterator<JMXConnectorProvider> providers =
getProviderIterator(JMXConnectorProvider.class, loader);
JMXConnector connection;
IOException exception = null;
while (providers.hasNext()) {
JMXConnectorProvider provider = providers.next();
try {
connection = provider.newJMXConnector(url, map);
return connection;
} catch (JMXProviderException e) {
throw e;
} catch (Exception e) {
if (logger.traceOn())
logger.trace("getConnectorAsService",
"URL[" + url +
"] Service provider exception: " + e);
if (!(e instanceof MalformedURLException)) {
if (exception == null) {
if (e instanceof IOException) {
exception = (IOException) e;
} else {
exception = EnvHelp.initCause(
new IOException(e.getMessage()), e);
}
}
}
continue;
}
}
if (exception == null)
return null;
else
throw exception;
}
static <T> T getProvider(String protocol,
String pkgs,
ClassLoader loader,
String providerClassName,
Class<T> targetInterface)
throws IOException {
StringTokenizer tokenizer = new StringTokenizer(pkgs, "|");
while (tokenizer.hasMoreTokens()) {
String pkg = tokenizer.nextToken();
String className = (pkg + "." + protocol2package(protocol) +
"." + providerClassName);
Class<?> providerClass;
try {
providerClass = Class.forName(className, true, loader);
} catch (ClassNotFoundException e) {
//Add trace.
continue;
}
if (!targetInterface.isAssignableFrom(providerClass)) {
final String msg =
"Provider class does not implement " +
targetInterface.getName() + ": " +
providerClass.getName();
throw new JMXProviderException(msg);
}
// We have just proved that this cast is correct
Class<? extends T> providerClassT = Util.cast(providerClass);
try {
return providerClassT.newInstance();
} catch (Exception e) {
final String msg =
"Exception when instantiating provider [" + className +
"]";
throw new JMXProviderException(msg, e);
}
}
return null;
}
static ClassLoader resolveClassLoader(Map<String, ?> environment) {
ClassLoader loader = null;
if (environment != null) {
try {
loader = (ClassLoader)
environment.get(PROTOCOL_PROVIDER_CLASS_LOADER);
} catch (ClassCastException e) {
final String msg =
"The ClassLoader supplied in the environment map using " +
"the " + PROTOCOL_PROVIDER_CLASS_LOADER +
" attribute is not an instance of java.lang.ClassLoader";
throw new IllegalArgumentException(msg);
}
}
if (loader == null) {
loader = Thread.currentThread().getContextClassLoader();
}
return loader;
}
private static String protocol2package(String protocol) {
return protocol.replace('+', '.').replace('-', '_');
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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
* 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 javax.management.remote;
import java.io.IOException;
import java.util.Map;
/**
* <p>A provider for creating JMX API connector clients using a given
* protocol. Instances of this interface are created by {@link
* JMXConnectorFactory} as part of its {@link
* JMXConnectorFactory#newJMXConnector(JMXServiceURL, Map)
* newJMXConnector} method.</p>
*
* @since 1.5
*/
public interface JMXConnectorProvider {
/**
* <p>Creates a new connector client that is ready to connect
* to the connector server at the given address. Each successful
* call to this method produces a different
* <code>JMXConnector</code> object.</p>
*
* @param serviceURL the address of the connector server to connect to.
*
* @param environment a read-only Map containing named attributes
* to determine how the connection is made. Keys in this map must
* be Strings. The appropriate type of each associated value
* depends on the attribute.
*
* @return a <code>JMXConnector</code> representing the new
* connector client. Each successful call to this method produces
* a different object.
*
* @exception NullPointerException if <code>serviceURL</code> or
* <code>environment</code> is null.
*
* @exception IOException It is recommended for a provider
* implementation to throw {@code MalformedURLException} if the
* protocol in the {@code serviceURL} is not recognized by this
* provider, {@code JMXProviderException} if this is a provider
* for the protocol in {@code serviceURL} but it cannot be used
* for some reason or any other {@code IOException} if the
* connection cannot be made because of a communication problem.
*/
public JMXConnector newJMXConnector(JMXServiceURL serviceURL,
Map<String,?> environment)
throws IOException;
}

View File

@@ -0,0 +1,414 @@
/*
* Copyright (c) 2003, 2008, 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 javax.management.remote;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
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
*/
public abstract class JMXConnectorServer
extends NotificationBroadcasterSupport
implements JMXConnectorServerMBean, MBeanRegistration, JMXAddressable {
/**
* <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, or not registered
* in any 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 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.
*/
@Override
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 List<String> connectionIds = new ArrayList<String>();
private static final int[] sequenceNumberLock = new int[0];
private static long sequenceNumber;
}

View File

@@ -0,0 +1,359 @@
/*
* 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
* 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 javax.management.remote;
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.management.MBeanServer;
/**
* <p>Factory to create JMX API connector servers. There
* are no instances of this class.</p>
*
* <p>Each connector server is created by an instance of {@link
* JMXConnectorServerProvider}. This instance is found as follows. Suppose
* the given {@link JMXServiceURL} looks like
* <code>"service:jmx:<em>protocol</em>:<em>remainder</em>"</code>.
* Then the factory will attempt to find the appropriate {@link
* JMXConnectorServerProvider} for <code><em>protocol</em></code>. Each
* occurrence of the character <code>+</code> or <code>-</code> in
* <code><em>protocol</em></code> is replaced by <code>.</code> or
* <code>_</code>, respectively.</p>
*
* <p>A <em>provider package list</em> is searched for as follows:</p>
*
* <ol>
*
* <li>If the <code>environment</code> parameter to {@link
* #newJMXConnectorServer(JMXServiceURL,Map,MBeanServer)
* newJMXConnectorServer} contains the key
* <code>jmx.remote.protocol.provider.pkgs</code> then the associated
* value is the provider package list.
*
* <li>Otherwise, if the system property
* <code>jmx.remote.protocol.provider.pkgs</code> exists, then its value
* is the provider package list.
*
* <li>Otherwise, there is no provider package list.
*
* </ol>
*
* <p>The provider package list is a string that is interpreted as a
* list of non-empty Java package names separated by vertical bars
* (<code>|</code>). If the string is empty, then so is the provider
* package list. If the provider package list is not a String, or if
* it contains an element that is an empty string, a {@link
* JMXProviderException} is thrown.</p>
*
* <p>If the provider package list exists and is not empty, then for
* each element <code><em>pkg</em></code> of the list, the factory
* will attempt to load the class
*
* <blockquote>
* <code><em>pkg</em>.<em>protocol</em>.ServerProvider</code>
* </blockquote>
* <p>If the <code>environment</code> parameter to {@link
* #newJMXConnectorServer(JMXServiceURL, Map, MBeanServer)
* newJMXConnectorServer} contains the key
* <code>jmx.remote.protocol.provider.class.loader</code> then the
* associated value is the class loader to use to load the provider.
* If the associated value is not an instance of {@link
* java.lang.ClassLoader}, an {@link
* java.lang.IllegalArgumentException} is thrown.</p>
*
* <p>If the <code>jmx.remote.protocol.provider.class.loader</code>
* key is not present in the <code>environment</code> parameter, the
* calling thread's context class loader is used.</p>
*
* <p>If the attempt to load this class produces a {@link
* ClassNotFoundException}, the search for a handler continues with
* the next element of the list.</p>
*
* <p>Otherwise, a problem with the provider found is signalled by a
* {@link JMXProviderException} whose {@link
* JMXProviderException#getCause() <em>cause</em>} indicates the
* underlying exception, as follows:</p>
*
* <ul>
*
* <li>if the attempt to load the class produces an exception other
* than <code>ClassNotFoundException</code>, that is the
* <em>cause</em>;
*
* <li>if {@link Class#newInstance()} for the class produces an
* exception, that is the <em>cause</em>.
*
* </ul>
*
* <p>If no provider is found by the above steps, including the
* default case where there is no provider package list, then the
* implementation will use its own provider for
* <code><em>protocol</em></code>, or it will throw a
* <code>MalformedURLException</code> if there is none. An
* implementation may choose to find providers by other means. For
* example, it may support the <a
* href="{@docRoot}/../technotes/guides/jar/jar.html#Service Provider">
* JAR conventions for service providers</a>, where the service
* interface is <code>JMXConnectorServerProvider</code>.</p>
*
* <p>Every implementation must support the RMI connector protocol with
* the default RMI transport, specified with string <code>rmi</code>.
* An implementation may optionally support the RMI connector protocol
* with the RMI/IIOP transport, specified with the string
* <code>iiop</code>.</p>
*
* <p>Once a provider is found, the result of the
* <code>newJMXConnectorServer</code> method is the result of calling
* {@link
* JMXConnectorServerProvider#newJMXConnectorServer(JMXServiceURL,
* Map, MBeanServer) newJMXConnectorServer} on the provider.</p>
*
* <p>The <code>Map</code> parameter passed to the
* <code>JMXConnectorServerProvider</code> is a new read-only
* <code>Map</code> that contains all the entries that were in the
* <code>environment</code> parameter to {@link
* #newJMXConnectorServer(JMXServiceURL,Map,MBeanServer)
* JMXConnectorServerFactory.newJMXConnectorServer}, if there was one.
* Additionally, if the
* <code>jmx.remote.protocol.provider.class.loader</code> key is not
* present in the <code>environment</code> parameter, it is added to
* the new read-only <code>Map</code>. The associated value is the
* calling thread's context class loader.</p>
*
* @since 1.5
*/
public class JMXConnectorServerFactory {
/**
* <p>Name of the attribute that specifies the default class
* loader. This class loader is used to deserialize objects in
* requests received from the client, possibly after consulting an
* MBean-specific class loader. The value associated with this
* attribute is an instance of {@link ClassLoader}.</p>
*/
public static final String DEFAULT_CLASS_LOADER =
JMXConnectorFactory.DEFAULT_CLASS_LOADER;
/**
* <p>Name of the attribute that specifies the default class
* loader MBean name. This class loader is used to deserialize objects in
* requests received from the client, possibly after consulting an
* MBean-specific class loader. The value associated with this
* attribute is an instance of {@link javax.management.ObjectName
* ObjectName}.</p>
*/
public static final String DEFAULT_CLASS_LOADER_NAME =
"jmx.remote.default.class.loader.name";
/**
* <p>Name of the attribute that specifies the provider packages
* that are consulted when looking for the handler for a protocol.
* The value associated with this attribute is a string with
* package names separated by vertical bars (<code>|</code>).</p>
*/
public static final String PROTOCOL_PROVIDER_PACKAGES =
"jmx.remote.protocol.provider.pkgs";
/**
* <p>Name of the attribute that specifies the class
* loader for loading protocol providers.
* The value associated with this attribute is an instance
* of {@link ClassLoader}.</p>
*/
public static final String PROTOCOL_PROVIDER_CLASS_LOADER =
"jmx.remote.protocol.provider.class.loader";
private static final String PROTOCOL_PROVIDER_DEFAULT_PACKAGE =
"com.sun.jmx.remote.protocol";
private static final ClassLogger logger =
new ClassLogger("javax.management.remote.misc","JMXConnectorServerFactory");
/** There are no instances of this class. */
private JMXConnectorServerFactory() {
}
private static JMXConnectorServer
getConnectorServerAsService(ClassLoader loader,
JMXServiceURL url,
Map<String, ?> map,
MBeanServer mbs)
throws IOException {
Iterator<JMXConnectorServerProvider> providers =
JMXConnectorFactory.
getProviderIterator(JMXConnectorServerProvider.class, loader);
IOException exception = null;
while (providers.hasNext()) {
try {
return providers.next().newJMXConnectorServer(url, map, mbs);
} catch (JMXProviderException e) {
throw e;
} catch (Exception e) {
if (logger.traceOn())
logger.trace("getConnectorAsService",
"URL[" + url +
"] Service provider exception: " + e);
if (!(e instanceof MalformedURLException)) {
if (exception == null) {
if (e instanceof IOException) {
exception = (IOException) e;
} else {
exception = EnvHelp.initCause(
new IOException(e.getMessage()), e);
}
}
}
continue;
}
}
if (exception == null)
return null;
else
throw exception;
}
/**
* <p>Creates a connector server at the given address. The
* resultant server is not started until its {@link
* JMXConnectorServer#start() start} method is called.</p>
*
* @param serviceURL the address of the new connector server. The
* actual address of the new connector server, as returned by its
* {@link JMXConnectorServer#getAddress() getAddress} method, will
* not necessarily be exactly the same. For example, it might
* include a port number if the original address did not.
*
* @param environment a set of attributes to control the new
* connector server's behavior. This parameter can be null.
* Keys in this map must be Strings. The appropriate type of each
* associated value depends on the attribute. The contents of
* <code>environment</code> are not changed by this call.
*
* @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.
*
* @return a <code>JMXConnectorServer</code> representing the new
* connector server. Each successful call to this method produces
* a different object.
*
* @exception NullPointerException if <code>serviceURL</code> is null.
*
* @exception IOException if the connector server cannot be made
* because of a communication problem.
*
* @exception MalformedURLException if there is no provider for the
* protocol in <code>serviceURL</code>.
*
* @exception JMXProviderException if there is a provider for the
* protocol in <code>serviceURL</code> but it cannot be used for
* some reason.
*/
public static JMXConnectorServer
newJMXConnectorServer(JMXServiceURL serviceURL,
Map<String,?> environment,
MBeanServer mbeanServer)
throws IOException {
Map<String, Object> envcopy;
if (environment == null)
envcopy = new HashMap<String, Object>();
else {
EnvHelp.checkAttributes(environment);
envcopy = new HashMap<String, Object>(environment);
}
final Class<JMXConnectorServerProvider> targetInterface =
JMXConnectorServerProvider.class;
final ClassLoader loader =
JMXConnectorFactory.resolveClassLoader(envcopy);
final String protocol = serviceURL.getProtocol();
final String providerClassName = "ServerProvider";
JMXConnectorServerProvider provider =
JMXConnectorFactory.getProvider(serviceURL,
envcopy,
providerClassName,
targetInterface,
loader);
IOException exception = null;
if (provider == null) {
// Loader is null when context class loader is set to null
// and no loader has been provided in map.
// com.sun.jmx.remote.util.Service class extracted from j2se
// provider search algorithm doesn't handle well null classloader.
if (loader != null) {
try {
JMXConnectorServer connection =
getConnectorServerAsService(loader,
serviceURL,
envcopy,
mbeanServer);
if (connection != null)
return connection;
} catch (JMXProviderException e) {
throw e;
} catch (IOException e) {
exception = e;
}
}
provider =
JMXConnectorFactory.getProvider(
protocol,
PROTOCOL_PROVIDER_DEFAULT_PACKAGE,
JMXConnectorFactory.class.getClassLoader(),
providerClassName,
targetInterface);
}
if (provider == null) {
MalformedURLException e =
new MalformedURLException("Unsupported protocol: " + protocol);
if (exception == null) {
throw e;
} else {
throw EnvHelp.initCause(e, exception);
}
}
envcopy = Collections.unmodifiableMap(envcopy);
return provider.newJMXConnectorServer(serviceURL,
envcopy,
mbeanServer);
}
}

View File

@@ -0,0 +1,212 @@
/*
* Copyright (c) 2002, 2008, 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 javax.management.remote;
import java.io.IOException;
import java.util.Map;
/**
* <p>MBean interface for connector servers. A JMX API connector server
* is attached to an MBean server, and establishes connections to that
* MBean server for remote clients.</p>
*
* <p>A newly-created connector server is <em>inactive</em>, and does
* not yet listen for connections. Only when its {@link #start start}
* method has been called does it start listening for connections.</p>
*
* @since 1.5
*/
public interface JMXConnectorServerMBean {
/**
* <p>Activates the connector server, that is, starts listening for
* client connections. Calling this method when the connector
* server is already active has no effect. Calling this method
* when the connector server has been stopped will generate an
* {@link IOException}.</p>
*
* @exception IOException if it is not possible to start listening
* or if the connector server has been stopped.
*
* @exception IllegalStateException if the connector server has
* not been attached to an MBean server.
*/
public void start() throws IOException;
/**
* <p>Deactivates the connector server, that is, stops listening for
* client connections. Calling this method will also close all
* client connections that were made by this server. After this
* method returns, whether normally or with an exception, the
* connector server will not create any new client
* connections.</p>
*
* <p>Once a connector server has been stopped, it cannot be started
* again.</p>
*
* <p>Calling this method when the connector server has already
* been stopped has no effect. Calling this method when the
* connector server has not yet been started will disable the
* connector server object permanently.</p>
*
* <p>If closing a client connection produces an exception, that
* exception is not thrown from this method. A {@link
* JMXConnectionNotification} with type {@link
* JMXConnectionNotification#FAILED} is emitted from this MBean
* with the connection ID of the connection that could not be
* closed.</p>
*
* <p>Closing a connector server is a potentially slow operation.
* For example, if a client machine with an open connection has
* crashed, the close operation might have to wait for a network
* protocol timeout. Callers that do not want to block in a close
* operation should do it in a separate thread.</p>
*
* @exception IOException if the server cannot be closed cleanly.
* When this exception is thrown, the server has already attempted
* to close all client connections. All client connections are
* closed except possibly those that generated exceptions when the
* server attempted to close them.
*/
public void stop() throws IOException;
/**
* <p>Determines whether the connector server is active. A connector
* server starts being active when its {@link #start start} method
* returns successfully and remains active until either its
* {@link #stop stop} method is called or the connector server
* fails.</p>
*
* @return true if the connector server is active.
*/
public boolean isActive();
/**
* <p>Inserts an object that intercepts requests for the MBean server
* that arrive through this connector server. This object will be
* supplied as the <code>MBeanServer</code> for any new connection
* created by this connector server. Existing connections are
* unaffected.</p>
*
* <p>This method can be called more than once with different
* {@link MBeanServerForwarder} objects. The result is a chain
* of forwarders. The last forwarder added is the first in the chain.
* In more detail:</p>
*
* <ul>
* <li><p>If this connector server is already associated with an
* <code>MBeanServer</code> object, then that object is given to
* {@link MBeanServerForwarder#setMBeanServer
* mbsf.setMBeanServer}. If doing so produces an exception, this
* method throws the same exception without any other effect.</p>
*
* <li><p>If this connector is not already associated with an
* <code>MBeanServer</code> object, or if the
* <code>mbsf.setMBeanServer</code> call just mentioned succeeds,
* then <code>mbsf</code> becomes this connector server's
* <code>MBeanServer</code>.</p>
* </ul>
*
* @param mbsf the new <code>MBeanServerForwarder</code>.
*
* @exception IllegalArgumentException if the call to {@link
* MBeanServerForwarder#setMBeanServer mbsf.setMBeanServer} fails
* with <code>IllegalArgumentException</code>. This includes the
* case where <code>mbsf</code> is null.
*/
public void setMBeanServerForwarder(MBeanServerForwarder mbsf);
/**
* <p>The list of IDs for currently-open connections to this
* connector server.</p>
*
* @return a new string array containing the list of IDs. If
* there are no currently-open connections, this array will be
* empty.
*/
public String[] getConnectionIds();
/**
* <p>The address of this connector server.</p>
* <p>
* The address returned may not be the exact original {@link JMXServiceURL}
* that was supplied when creating the connector server, since the original
* address may not always be complete. For example the port number may be
* dynamically allocated when starting the connector server. Instead the
* address returned is the actual {@link JMXServiceURL} of the
* {@link JMXConnectorServer}. This is the address that clients supply
* to {@link JMXConnectorFactory#connect(JMXServiceURL)}.
* </p>
* <p>Note that the address returned may be {@code null} if
* the {@code JMXConnectorServer} is not yet {@link #isActive active}.
* </p>
*
* @return the address of this connector server, or null if it
* does not have one.
*/
public JMXServiceURL getAddress();
/**
* <p>The attributes for this connector server.</p>
*
* @return a read-only map containing the attributes for this
* connector server. Attributes whose values are not serializable
* are omitted from this map. If there are no serializable
* attributes, the returned map is empty.
*/
public Map<String,?> getAttributes();
/**
* <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>
*
* @param env client connection parameters of the same sort that
* can 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;
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2003, 2007, 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 javax.management.remote;
import java.io.IOException;
import java.util.Map;
import javax.management.MBeanServer;
/**
* <p>A provider for creating JMX API connector servers using a given
* protocol. Instances of this interface are created by {@link
* JMXConnectorServerFactory} as part of its {@link
* JMXConnectorServerFactory#newJMXConnectorServer(JMXServiceURL,Map,MBeanServer)
* newJMXConnectorServer} method.</p>
*
* @since 1.5
*/
public interface JMXConnectorServerProvider {
/**
* <p>Creates a new connector server at the given address. Each
* successful call to this method produces a different
* <code>JMXConnectorServer</code> object.</p>
*
* @param serviceURL the address of the new connector server. The
* actual address of the new connector server, as returned by its
* {@link JMXConnectorServer#getAddress() getAddress} method, will
* not necessarily be exactly the same. For example, it might
* include a port number if the original address did not.
*
* @param environment a read-only Map containing named attributes
* to control the new connector server's behavior. Keys in this
* map must be Strings. The appropriate type of each associated
* value depends on the attribute.
*
* @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.
*
* @return a <code>JMXConnectorServer</code> representing the new
* connector server. Each successful call to this method produces
* a different object.
*
* @exception NullPointerException if <code>serviceURL</code> or
* <code>environment</code> is null.
*
* @exception IOException It is recommended for a provider
* implementation to throw {@code MalformedURLException} if the
* protocol in the {@code serviceURL} is not recognized by this
* provider, {@code JMXProviderException} if this is a provider
* for the protocol in {@code serviceURL} but it cannot be used
* for some reason or any other {@code IOException} if the
* connector server cannot be created.
*/
public JMXConnectorServer newJMXConnectorServer(JMXServiceURL serviceURL,
Map<String,?> environment,
MBeanServer mbeanServer)
throws IOException;
}

View File

@@ -0,0 +1,150 @@
/*
* 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
* 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 javax.management.remote;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.security.Principal;
/**
* <p>The identity of a remote client of the JMX Remote API.</p>
*
* <p>Principals such as this <code>JMXPrincipal</code>
* may be associated with a particular <code>Subject</code>
* to augment that <code>Subject</code> with an additional
* identity. Refer to the {@link javax.security.auth.Subject}
* class for more information on how to achieve this.
* Authorization decisions can then be based upon
* the Principals associated with a <code>Subject</code>.
*
* @see java.security.Principal
* @see javax.security.auth.Subject
* @since 1.5
*/
public class JMXPrincipal implements Principal, Serializable {
private static final long serialVersionUID = -4184480100214577411L;
/**
* @serial The JMX Remote API name for the identity represented by
* this <code>JMXPrincipal</code> object.
* @see #getName()
*/
private String name;
/**
* <p>Creates a JMXPrincipal for a given identity.</p>
*
* @param name the JMX Remote API name for this identity.
*
* @exception NullPointerException if the <code>name</code> is
* <code>null</code>.
*/
public JMXPrincipal(String name) {
validate(name);
this.name = name;
}
/**
* Returns the name of this principal.
*
* <p>
*
* @return the name of this <code>JMXPrincipal</code>.
*/
public String getName() {
return name;
}
/**
* Returns a string representation of this <code>JMXPrincipal</code>.
*
* <p>
*
* @return a string representation of this <code>JMXPrincipal</code>.
*/
public String toString() {
return("JMXPrincipal: " + name);
}
/**
* Compares the specified Object with this <code>JMXPrincipal</code>
* for equality. Returns true if the given object is also a
* <code>JMXPrincipal</code> and the two JMXPrincipals
* have the same name.
*
* <p>
*
* @param o Object to be compared for equality with this
* <code>JMXPrincipal</code>.
*
* @return true if the specified Object is equal to this
* <code>JMXPrincipal</code>.
*/
public boolean equals(Object o) {
if (o == null)
return false;
if (this == o)
return true;
if (!(o instanceof JMXPrincipal))
return false;
JMXPrincipal that = (JMXPrincipal)o;
return (this.getName().equals(that.getName()));
}
/**
* Returns a hash code for this <code>JMXPrincipal</code>.
*
* <p>
*
* @return a hash code for this <code>JMXPrincipal</code>.
*/
public int hashCode() {
return name.hashCode();
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = ois.readFields();
String principalName = (String)gf.get("name", null);
try {
validate(principalName);
this.name = principalName;
} catch (NullPointerException e) {
throw new InvalidObjectException(e.getMessage());
}
}
private static void validate(String name) throws NullPointerException {
if (name == null)
throw new NullPointerException("illegal null input");
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2002, 2007, 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 javax.management.remote;
import java.io.IOException;
/**
* <p>Exception thrown by {@link JMXConnectorFactory} and
* {@link JMXConnectorServerFactory} when a provider exists for
* the required protocol but cannot be used for some reason.</p>
*
* @see JMXConnectorFactory#newJMXConnector
* @see JMXConnectorServerFactory#newJMXConnectorServer
* @since 1.5
*/
public class JMXProviderException extends IOException {
private static final long serialVersionUID = -3166703627550447198L;
/**
* <p>Constructs a <code>JMXProviderException</code> with no
* specified detail message.</p>
*/
public JMXProviderException() {
}
/**
* <p>Constructs a <code>JMXProviderException</code> with the
* specified detail message.</p>
*
* @param message the detail message
*/
public JMXProviderException(String message) {
super(message);
}
/**
* <p>Constructs a <code>JMXProviderException</code> with the
* specified detail message and nested exception.</p>
*
* @param message the detail message
* @param cause the nested exception
*/
public JMXProviderException(String message, Throwable cause) {
super(message);
this.cause = cause;
}
public Throwable getCause() {
return cause;
}
/**
* @serial An exception that caused this exception to be thrown.
* This field may be null.
* @see #getCause()
**/
private Throwable cause = null;
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2002, 2007, 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 javax.management.remote;
import java.io.IOException;
// imports for javadoc
import javax.management.MBeanServer;
/**
* Exception thrown as the result of a remote {@link MBeanServer}
* method invocation when an <code>Error</code> is thrown while
* processing the invocation in the remote MBean server. A
* <code>JMXServerErrorException</code> instance contains the original
* <code>Error</code> that occurred as its cause.
*
* @see java.rmi.ServerError
* @since 1.5
*/
public class JMXServerErrorException extends IOException {
private static final long serialVersionUID = 3996732239558744666L;
/**
* Constructs a <code>JMXServerErrorException</code> with the specified
* detail message and nested error.
*
* @param s the detail message.
* @param err the nested error. An instance of this class can be
* constructed where this parameter is null, but the standard
* connectors will never do so.
*/
public JMXServerErrorException(String s, Error err) {
super(s);
cause = err;
}
public Throwable getCause() {
return cause;
}
/**
* @serial An {@link Error} that caused this exception to be thrown.
* @see #getCause()
**/
private final Error cause;
}

View File

@@ -0,0 +1,733 @@
/*
* 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
* 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 javax.management.remote;
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.util.BitSet;
import java.util.StringTokenizer;
/**
* <p>The address of a JMX API connector server. Instances of this class
* are immutable.</p>
*
* <p>The address is an <em>Abstract Service URL</em> for SLP, as
* defined in RFC 2609 and amended by RFC 3111. It must look like
* this:</p>
*
* <blockquote>
*
* <code>service:jmx:<em>protocol</em>:<em>sap</em></code>
*
* </blockquote>
*
* <p>Here, <code><em>protocol</em></code> is the transport
* protocol to be used to connect to the connector server. It is
* a string of one or more ASCII characters, each of which is a
* letter, a digit, or one of the characters <code>+</code> or
* <code>-</code>. The first character must be a letter.
* Uppercase letters are converted into lowercase ones.</p>
*
* <p><code><em>sap</em></code> is the address at which the connector
* server is found. This address uses a subset of the syntax defined
* by RFC 2609 for IP-based protocols. It is a subset because the
* <code>user@host</code> syntax is not supported.</p>
*
* <p>The other syntaxes defined by RFC 2609 are not currently
* supported by this class.</p>
*
* <p>The supported syntax is:</p>
*
* <blockquote>
*
* <code>//<em>[host[</em>:<em>port]][url-path]</em></code>
*
* </blockquote>
*
* <p>Square brackets <code>[]</code> indicate optional parts of
* the address. Not all protocols will recognize all optional
* parts.</p>
*
* <p>The <code><em>host</em></code> is a host name, an IPv4 numeric
* host address, or an IPv6 numeric address enclosed in square
* brackets.</p>
*
* <p>The <code><em>port</em></code> is a decimal port number. 0
* means a default or anonymous port, depending on the protocol.</p>
*
* <p>The <code><em>host</em></code> and <code><em>port</em></code>
* can be omitted. The <code><em>port</em></code> cannot be supplied
* without a <code><em>host</em></code>.</p>
*
* <p>The <code><em>url-path</em></code>, if any, begins with a slash
* (<code>/</code>) or a semicolon (<code>;</code>) and continues to
* the end of the address. It can contain attributes using the
* semicolon syntax specified in RFC 2609. Those attributes are not
* parsed by this class and incorrect attribute syntax is not
* detected.</p>
*
* <p>Although it is legal according to RFC 2609 to have a
* <code><em>url-path</em></code> that begins with a semicolon, not
* all implementations of SLP allow it, so it is recommended to avoid
* that syntax.</p>
*
* <p>Case is not significant in the initial
* <code>service:jmx:<em>protocol</em></code> string or in the host
* part of the address. Depending on the protocol, case can be
* significant in the <code><em>url-path</em></code>.</p>
*
* @see <a
* href="http://www.ietf.org/rfc/rfc2609.txt">RFC 2609,
* "Service Templates and <code>Service:</code> Schemes"</a>
* @see <a
* href="http://www.ietf.org/rfc/rfc3111.txt">RFC 3111,
* "Service Location Protocol Modifications for IPv6"</a>
*
* @since 1.5
*/
public class JMXServiceURL implements Serializable {
private static final long serialVersionUID = 8173364409860779292L;
/**
* <p>Constructs a <code>JMXServiceURL</code> by parsing a Service URL
* string.</p>
*
* @param serviceURL the URL string to be parsed.
*
* @exception NullPointerException if <code>serviceURL</code> is
* null.
*
* @exception MalformedURLException if <code>serviceURL</code>
* does not conform to the syntax for an Abstract Service URL or
* if it is not a valid name for a JMX Remote API service. A
* <code>JMXServiceURL</code> must begin with the string
* <code>"service:jmx:"</code> (case-insensitive). It must not
* contain any characters that are not printable ASCII characters.
*/
public JMXServiceURL(String serviceURL) throws MalformedURLException {
final int serviceURLLength = serviceURL.length();
/* Check that there are no non-ASCII characters in the URL,
following RFC 2609. */
for (int i = 0; i < serviceURLLength; i++) {
char c = serviceURL.charAt(i);
if (c < 32 || c >= 127) {
throw new MalformedURLException("Service URL contains " +
"non-ASCII character 0x" +
Integer.toHexString(c));
}
}
// Parse the required prefix
final String requiredPrefix = "service:jmx:";
final int requiredPrefixLength = requiredPrefix.length();
if (!serviceURL.regionMatches(true, // ignore case
0, // serviceURL offset
requiredPrefix,
0, // requiredPrefix offset
requiredPrefixLength)) {
throw new MalformedURLException("Service URL must start with " +
requiredPrefix);
}
// Parse the protocol name
final int protoStart = requiredPrefixLength;
final int protoEnd = indexOf(serviceURL, ':', protoStart);
this.protocol =
serviceURL.substring(protoStart, protoEnd).toLowerCase();
if (!serviceURL.regionMatches(protoEnd, "://", 0, 3)) {
throw new MalformedURLException("Missing \"://\" after " +
"protocol name");
}
// Parse the host name
final int hostStart = protoEnd + 3;
final int hostEnd;
if (hostStart < serviceURLLength
&& serviceURL.charAt(hostStart) == '[') {
hostEnd = serviceURL.indexOf(']', hostStart) + 1;
if (hostEnd == 0)
throw new MalformedURLException("Bad host name: [ without ]");
this.host = serviceURL.substring(hostStart + 1, hostEnd - 1);
if (!isNumericIPv6Address(this.host)) {
throw new MalformedURLException("Address inside [...] must " +
"be numeric IPv6 address");
}
} else {
hostEnd =
indexOfFirstNotInSet(serviceURL, hostNameBitSet, hostStart);
this.host = serviceURL.substring(hostStart, hostEnd);
}
// Parse the port number
final int portEnd;
if (hostEnd < serviceURLLength && serviceURL.charAt(hostEnd) == ':') {
if (this.host.length() == 0) {
throw new MalformedURLException("Cannot give port number " +
"without host name");
}
final int portStart = hostEnd + 1;
portEnd =
indexOfFirstNotInSet(serviceURL, numericBitSet, portStart);
final String portString = serviceURL.substring(portStart, portEnd);
try {
this.port = Integer.parseInt(portString);
} catch (NumberFormatException e) {
throw new MalformedURLException("Bad port number: \"" +
portString + "\": " + e);
}
} else {
portEnd = hostEnd;
this.port = 0;
}
// Parse the URL path
final int urlPathStart = portEnd;
if (urlPathStart < serviceURLLength)
this.urlPath = serviceURL.substring(urlPathStart);
else
this.urlPath = "";
validate();
}
/**
* <p>Constructs a <code>JMXServiceURL</code> with the given protocol,
* host, and port. This constructor is equivalent to
* {@link #JMXServiceURL(String, String, int, String)
* JMXServiceURL(protocol, host, port, null)}.</p>
*
* @param protocol the protocol part of the URL. If null, defaults
* to <code>jmxmp</code>.
*
* @param host the host part of the URL. If null, defaults to the
* local host name, as determined by
* <code>InetAddress.getLocalHost().getHostName()</code>. If it
* is a numeric IPv6 address, it can optionally be enclosed in
* square brackets <code>[]</code>.
*
* @param port the port part of the URL.
*
* @exception MalformedURLException if one of the parts is
* syntactically incorrect, or if <code>host</code> is null and it
* is not possible to find the local host name, or if
* <code>port</code> is negative.
*/
public JMXServiceURL(String protocol, String host, int port)
throws MalformedURLException {
this(protocol, host, port, null);
}
/**
* <p>Constructs a <code>JMXServiceURL</code> with the given parts.
*
* @param protocol the protocol part of the URL. If null, defaults
* to <code>jmxmp</code>.
*
* @param host the host part of the URL. If null, defaults to the
* local host name, as determined by
* <code>InetAddress.getLocalHost().getHostName()</code>. If it
* is a numeric IPv6 address, it can optionally be enclosed in
* square brackets <code>[]</code>.
*
* @param port the port part of the URL.
*
* @param urlPath the URL path part of the URL. If null, defaults to
* the empty string.
*
* @exception MalformedURLException if one of the parts is
* syntactically incorrect, or if <code>host</code> is null and it
* is not possible to find the local host name, or if
* <code>port</code> is negative.
*/
public JMXServiceURL(String protocol, String host, int port,
String urlPath)
throws MalformedURLException {
if (protocol == null)
protocol = "jmxmp";
if (host == null) {
InetAddress local;
try {
local = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
throw new MalformedURLException("Local host name unknown: " +
e);
}
host = local.getHostName();
/* We might have a hostname that violates DNS naming
rules, for example that contains an `_'. While we
could be strict and throw an exception, this is rather
user-hostile. Instead we use its numerical IP address.
We can only reasonably do this for the host==null case.
If we're given an explicit host name that is illegal we
have to reject it. (Bug 5057532.) */
try {
validateHost(host, port);
} catch (MalformedURLException e) {
if (logger.fineOn()) {
logger.fine("JMXServiceURL",
"Replacing illegal local host name " +
host + " with numeric IP address " +
"(see RFC 1034)", e);
}
host = local.getHostAddress();
/* Use the numeric address, which could be either IPv4
or IPv6. validateHost will accept either. */
}
}
if (host.startsWith("[")) {
if (!host.endsWith("]")) {
throw new MalformedURLException("Host starts with [ but " +
"does not end with ]");
}
host = host.substring(1, host.length() - 1);
if (!isNumericIPv6Address(host)) {
throw new MalformedURLException("Address inside [...] must " +
"be numeric IPv6 address");
}
if (host.startsWith("["))
throw new MalformedURLException("More than one [[...]]");
}
this.protocol = protocol.toLowerCase();
this.host = host;
this.port = port;
if (urlPath == null)
urlPath = "";
this.urlPath = urlPath;
validate();
}
private static final String INVALID_INSTANCE_MSG =
"Trying to deserialize an invalid instance of JMXServiceURL";
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = inputStream.readFields();
String h = (String)gf.get("host", null);
int p = (int)gf.get("port", -1);
String proto = (String)gf.get("protocol", null);
String url = (String)gf.get("urlPath", null);
if (proto == null || url == null || h == null) {
StringBuilder sb = new StringBuilder(INVALID_INSTANCE_MSG).append('[');
boolean empty = true;
if (proto == null) {
sb.append("protocol=null");
empty = false;
}
if (h == null) {
sb.append(empty ? "" : ",").append("host=null");
empty = false;
}
if (url == null) {
sb.append(empty ? "" : ",").append("urlPath=null");
}
sb.append(']');
throw new InvalidObjectException(sb.toString());
}
if (h.contains("[") || h.contains("]")) {
throw new InvalidObjectException("Invalid host name: " + h);
}
try {
validate(proto, h, p, url);
this.protocol = proto;
this.host = h;
this.port = p;
this.urlPath = url;
} catch (MalformedURLException e) {
throw new InvalidObjectException(INVALID_INSTANCE_MSG + ": " +
e.getMessage());
}
}
private void validate(String proto, String h, int p, String url)
throws MalformedURLException {
// Check protocol
final int protoEnd = indexOfFirstNotInSet(proto, protocolBitSet, 0);
if (protoEnd == 0 || protoEnd < proto.length()
|| !alphaBitSet.get(proto.charAt(0))) {
throw new MalformedURLException("Missing or invalid protocol " +
"name: \"" + proto + "\"");
}
// Check host
validateHost(h, p);
// Check port
if (p < 0)
throw new MalformedURLException("Bad port: " + p);
// Check URL path
if (url.length() > 0) {
if (!url.startsWith("/") && !url.startsWith(";"))
throw new MalformedURLException("Bad URL path: " + url);
}
}
private void validate() throws MalformedURLException {
validate(this.protocol, this.host, this.port, this.urlPath);
}
private static void validateHost(String h, int port)
throws MalformedURLException {
if (h.length() == 0) {
if (port != 0) {
throw new MalformedURLException("Cannot give port number " +
"without host name");
}
return;
}
if (isNumericIPv6Address(h)) {
/* We assume J2SE >= 1.4 here. Otherwise you can't
use the address anyway. We can't call
InetAddress.getByName without checking for a
numeric IPv6 address, because we mustn't try to do
a DNS lookup in case the address is not actually
numeric. */
try {
InetAddress.getByName(h);
} catch (Exception e) {
/* We should really catch UnknownHostException
here, but a bug in JDK 1.4 causes it to throw
ArrayIndexOutOfBoundsException, e.g. if the
string is ":". */
MalformedURLException bad =
new MalformedURLException("Bad IPv6 address: " + h);
EnvHelp.initCause(bad, e);
throw bad;
}
} else {
/* Tiny state machine to check valid host name. This
checks the hostname grammar from RFC 1034 (DNS),
page 11. A hostname is a dot-separated list of one
or more labels, where each label consists of
letters, numbers, or hyphens. A label cannot begin
or end with a hyphen. Empty hostnames are not
allowed. Note that numeric IPv4 addresses are a
special case of this grammar.
The state is entirely captured by the last
character seen, with a virtual `.' preceding the
name. We represent any alphanumeric character by
`a'.
We need a special hack to check, as required by the
RFC 2609 (SLP) grammar, that the last component of
the hostname begins with a letter. Respecting the
intent of the RFC, we only do this if there is more
than one component. If your local hostname begins
with a digit, we don't reject it. */
final int hostLen = h.length();
char lastc = '.';
boolean sawDot = false;
char componentStart = 0;
loop:
for (int i = 0; i < hostLen; i++) {
char c = h.charAt(i);
boolean isAlphaNumeric = alphaNumericBitSet.get(c);
if (lastc == '.')
componentStart = c;
if (isAlphaNumeric)
lastc = 'a';
else if (c == '-') {
if (lastc == '.')
break; // will throw exception
lastc = '-';
} else if (c == '.') {
sawDot = true;
if (lastc != 'a')
break; // will throw exception
lastc = '.';
} else {
lastc = '.'; // will throw exception
break;
}
}
try {
if (lastc != 'a')
throw randomException;
if (sawDot && !alphaBitSet.get(componentStart)) {
/* Must be a numeric IPv4 address. In addition to
the explicitly-thrown exceptions, we can get
NoSuchElementException from the calls to
tok.nextToken and NumberFormatException from
the call to Integer.parseInt. Using exceptions
for control flow this way is a bit evil but it
does simplify things enormously. */
StringTokenizer tok = new StringTokenizer(h, ".", true);
for (int i = 0; i < 4; i++) {
String ns = tok.nextToken();
int n = Integer.parseInt(ns);
if (n < 0 || n > 255)
throw randomException;
if (i < 3 && !tok.nextToken().equals("."))
throw randomException;
}
if (tok.hasMoreTokens())
throw randomException;
}
} catch (Exception e) {
throw new MalformedURLException("Bad host: \"" + h + "\"");
}
}
}
private static final Exception randomException = new Exception();
/**
* <p>The protocol part of the Service URL.
*
* @return the protocol part of the Service URL. This is never null.
*/
public String getProtocol() {
return protocol;
}
/**
* <p>The host part of the Service URL. If the Service URL was
* constructed with the constructor that takes a URL string
* parameter, the result is the substring specifying the host in
* that URL. If the Service URL was constructed with a
* constructor that takes a separate host parameter, the result is
* the string that was specified. If that string was null, the
* result is
* <code>InetAddress.getLocalHost().getHostName()</code>.</p>
*
* <p>In either case, if the host was specified using the
* <code>[...]</code> syntax for numeric IPv6 addresses, the
* square brackets are not included in the return value here.</p>
*
* @return the host part of the Service URL. This is never null.
*/
public String getHost() {
return host;
}
/**
* <p>The port of the Service URL. If no port was
* specified, the returned value is 0.</p>
*
* @return the port of the Service URL, or 0 if none.
*/
public int getPort() {
return port;
}
/**
* <p>The URL Path part of the Service URL. This is an empty
* string, or a string beginning with a slash (<code>/</code>), or
* a string beginning with a semicolon (<code>;</code>).
*
* @return the URL Path part of the Service URL. This is never
* null.
*/
public String getURLPath() {
return urlPath;
}
/**
* <p>The string representation of this Service URL. If the value
* returned by this method is supplied to the
* <code>JMXServiceURL</code> constructor, the resultant object is
* equal to this one.</p>
*
* <p>The <code><em>host</em></code> part of the returned string
* is the value returned by {@link #getHost()}. If that value
* specifies a numeric IPv6 address, it is surrounded by square
* brackets <code>[]</code>.</p>
*
* <p>The <code><em>port</em></code> part of the returned string
* is the value returned by {@link #getPort()} in its shortest
* decimal form. If the value is zero, it is omitted.</p>
*
* @return the string representation of this Service URL.
*/
public String toString() {
/* We don't bother synchronizing the access to toString. At worst,
n threads will independently compute and store the same value. */
if (toString != null)
return toString;
StringBuilder buf = new StringBuilder("service:jmx:");
buf.append(getProtocol()).append("://");
final String getHost = getHost();
if (isNumericIPv6Address(getHost))
buf.append('[').append(getHost).append(']');
else
buf.append(getHost);
final int getPort = getPort();
if (getPort != 0)
buf.append(':').append(getPort);
buf.append(getURLPath());
toString = buf.toString();
return toString;
}
/**
* <p>Indicates whether some other object is equal to this one.
* This method returns true if and only if <code>obj</code> is an
* instance of <code>JMXServiceURL</code> whose {@link
* #getProtocol()}, {@link #getHost()}, {@link #getPort()}, and
* {@link #getURLPath()} methods return the same values as for
* this object. The values for {@link #getProtocol()} and {@link
* #getHost()} can differ in case without affecting equality.
*
* @param obj the reference object with which to compare.
*
* @return <code>true</code> if this object is the same as the
* <code>obj</code> argument; <code>false</code> otherwise.
*/
public boolean equals(Object obj) {
if (!(obj instanceof JMXServiceURL))
return false;
JMXServiceURL u = (JMXServiceURL) obj;
return
(u.getProtocol().equalsIgnoreCase(getProtocol()) &&
u.getHost().equalsIgnoreCase(getHost()) &&
u.getPort() == getPort() &&
u.getURLPath().equals(getURLPath()));
}
public int hashCode() {
return toString().hashCode();
}
/* True if this string, assumed to be a valid argument to
* InetAddress.getByName, is a numeric IPv6 address.
*/
private static boolean isNumericIPv6Address(String s) {
// address contains colon if and only if it's a numeric IPv6 address
return (s.indexOf(':') >= 0);
}
// like String.indexOf but returns string length not -1 if not present
private static int indexOf(String s, char c, int fromIndex) {
int index = s.indexOf(c, fromIndex);
if (index < 0)
return s.length();
else
return index;
}
private static int indexOfFirstNotInSet(String s, BitSet set,
int fromIndex) {
final int slen = s.length();
int i = fromIndex;
while (true) {
if (i >= slen)
break;
char c = s.charAt(i);
if (c >= 128)
break; // not ASCII
if (!set.get(c))
break;
i++;
}
return i;
}
private final static BitSet alphaBitSet = new BitSet(128);
private final static BitSet numericBitSet = new BitSet(128);
private final static BitSet alphaNumericBitSet = new BitSet(128);
private final static BitSet protocolBitSet = new BitSet(128);
private final static BitSet hostNameBitSet = new BitSet(128);
static {
/* J2SE 1.4 adds lots of handy methods to BitSet that would
allow us to simplify here, e.g. by not writing loops, but
we want to work on J2SE 1.3 too. */
for (char c = '0'; c <= '9'; c++)
numericBitSet.set(c);
for (char c = 'A'; c <= 'Z'; c++)
alphaBitSet.set(c);
for (char c = 'a'; c <= 'z'; c++)
alphaBitSet.set(c);
alphaNumericBitSet.or(alphaBitSet);
alphaNumericBitSet.or(numericBitSet);
protocolBitSet.or(alphaNumericBitSet);
protocolBitSet.set('+');
protocolBitSet.set('-');
hostNameBitSet.or(alphaNumericBitSet);
hostNameBitSet.set('-');
hostNameBitSet.set('.');
}
/**
* The value returned by {@link #getProtocol()}.
*/
private String protocol;
/**
* The value returned by {@link #getHost()}.
*/
private String host;
/**
* The value returned by {@link #getPort()}.
*/
private int port;
/**
* The value returned by {@link #getURLPath()}.
*/
private String urlPath;
/**
* Cached result of {@link #toString()}.
*/
private transient String toString;
private static final ClassLogger logger =
new ClassLogger("javax.management.remote.misc", "JMXServiceURL");
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2003, 2007, 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 javax.management.remote;
import javax.management.MBeanServer;
/**
* <p>An object of this class implements the MBeanServer interface and
* wraps another object that also implements that interface.
* Typically, an implementation of this interface performs some action
* in some or all methods of the <code>MBeanServer</code> interface
* before and/or after forwarding the method to the wrapped object.
* Examples include security checking and logging.</p>
*
* @since 1.5
*/
public interface MBeanServerForwarder extends MBeanServer {
/**
* Returns the MBeanServer object to which requests will be forwarded.
*
* @return the MBeanServer object to which requests will be forwarded,
* or null if there is none.
*
* @see #setMBeanServer
*/
public MBeanServer getMBeanServer();
/**
* Sets the MBeanServer object to which requests will be forwarded
* after treatment by this object.
*
* @param mbs the MBeanServer object to which requests will be forwarded.
*
* @exception IllegalArgumentException if this object is already
* forwarding to an MBeanServer object or if <code>mbs</code> is
* null or if <code>mbs</code> is identical to this object.
*
* @see #getMBeanServer
*/
public void setMBeanServer(MBeanServer mbs);
}

View File

@@ -0,0 +1,170 @@
/*
* 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
* 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 javax.management.remote;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
/**
* <p>Result of a query for buffered notifications. Notifications in
* a notification buffer have positive, monotonically increasing
* sequence numbers. The result of a notification query contains the
* following elements:</p>
*
* <ul>
*
* <li>The sequence number of the earliest notification still in
* the buffer.
*
* <li>The sequence number of the next notification available for
* querying. This will be the starting sequence number for the next
* notification query.
*
* <li>An array of (Notification,listenerID) pairs corresponding to
* the returned notifications and the listeners they correspond to.
*
* </ul>
*
* <p>It is possible for the <code>nextSequenceNumber</code> to be less
* than the <code>earliestSequenceNumber</code>. This signifies that
* notifications between the two might have been lost.</p>
*
* @since 1.5
*/
public class NotificationResult implements Serializable {
private static final long serialVersionUID = 1191800228721395279L;
/**
* <p>Constructs a notification query result.</p>
*
* @param earliestSequenceNumber the sequence number of the
* earliest notification still in the buffer.
* @param nextSequenceNumber the sequence number of the next
* notification available for querying.
* @param targetedNotifications the notifications resulting from
* the query, and the listeners they correspond to. This array
* can be empty.
*
* @exception IllegalArgumentException if
* <code>targetedNotifications</code> is null or if
* <code>earliestSequenceNumber</code> or
* <code>nextSequenceNumber</code> is negative.
*/
public NotificationResult(long earliestSequenceNumber,
long nextSequenceNumber,
TargetedNotification[] targetedNotifications) {
validate(targetedNotifications, earliestSequenceNumber, nextSequenceNumber);
this.earliestSequenceNumber = earliestSequenceNumber;
this.nextSequenceNumber = nextSequenceNumber;
this.targetedNotifications = (targetedNotifications.length == 0 ? targetedNotifications : targetedNotifications.clone());
}
/**
* Returns the sequence number of the earliest notification still
* in the buffer.
*
* @return the sequence number of the earliest notification still
* in the buffer.
*/
public long getEarliestSequenceNumber() {
return earliestSequenceNumber;
}
/**
* Returns the sequence number of the next notification available
* for querying.
*
* @return the sequence number of the next notification available
* for querying.
*/
public long getNextSequenceNumber() {
return nextSequenceNumber;
}
/**
* Returns the notifications resulting from the query, and the
* listeners they correspond to.
*
* @return the notifications resulting from the query, and the
* listeners they correspond to. This array can be empty.
*/
public TargetedNotification[] getTargetedNotifications() {
return targetedNotifications.length == 0 ? targetedNotifications : targetedNotifications.clone();
}
/**
* Returns a string representation of the object. The result
* should be a concise but informative representation that is easy
* for a person to read.
*
* @return a string representation of the object.
*/
public String toString() {
return "NotificationResult: earliest=" + getEarliestSequenceNumber() +
"; next=" + getNextSequenceNumber() + "; nnotifs=" +
getTargetedNotifications().length;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
try {
validate(
this.targetedNotifications,
this.earliestSequenceNumber,
this.nextSequenceNumber
);
this.targetedNotifications = this.targetedNotifications.length == 0 ?
this.targetedNotifications :
this.targetedNotifications.clone();
} catch (IllegalArgumentException e) {
throw new InvalidObjectException(e.getMessage());
}
}
private long earliestSequenceNumber;
private long nextSequenceNumber;
private TargetedNotification[] targetedNotifications;
private static void validate(TargetedNotification[] targetedNotifications,
long earliestSequenceNumber,
long nextSequenceNumber)
throws IllegalArgumentException {
if (targetedNotifications == null) {
final String msg = "Notifications null";
throw new IllegalArgumentException(msg);
}
if (earliestSequenceNumber < 0 || nextSequenceNumber < 0)
throw new IllegalArgumentException("Bad sequence numbers");
/* We used to check nextSequenceNumber >= earliestSequenceNumber
here. But in fact the opposite can legitimately be true if
notifications have been lost. */
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2003, 2007, 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 javax.management.remote;
import java.security.BasicPermission;
/**
* <p>Permission required by an authentication identity to perform
* operations on behalf of an authorization identity.</p>
*
* <p>A SubjectDelegationPermission contains a name (also referred
* to as a "target name") but no actions list; you either have the
* named permission or you don't.</p>
*
* <p>The target name is the name of the authorization principal
* classname followed by a period and the authorization principal
* name, that is
* <code>"<em>PrincipalClassName</em>.<em>PrincipalName</em>"</code>.</p>
*
* <p>An asterisk may appear by itself, or if immediately preceded
* by a "." may appear at the end of the target name, to signify a
* wildcard match.</p>
*
* <p>For example, "*", "javax.management.remote.JMXPrincipal.*" and
* "javax.management.remote.JMXPrincipal.delegate" are valid target
* names. The first one denotes any principal name from any principal
* class, the second one denotes any principal name of the concrete
* principal class <code>javax.management.remote.JMXPrincipal</code>
* and the third one denotes a concrete principal name
* <code>delegate</code> of the concrete principal class
* <code>javax.management.remote.JMXPrincipal</code>.</p>
*
* @since 1.5
*/
public final class SubjectDelegationPermission extends BasicPermission {
private static final long serialVersionUID = 1481618113008682343L;
/**
* Creates a new SubjectDelegationPermission with the specified name.
* The name is the symbolic name of the SubjectDelegationPermission.
*
* @param name the name of the SubjectDelegationPermission
*
* @throws NullPointerException if <code>name</code> is
* <code>null</code>.
* @throws IllegalArgumentException if <code>name</code> is empty.
*/
public SubjectDelegationPermission(String name) {
super(name);
}
/**
* Creates a new SubjectDelegationPermission object with the
* specified name. The name is the symbolic name of the
* SubjectDelegationPermission, and the actions String is
* currently unused and must be null.
*
* @param name the name of the SubjectDelegationPermission
* @param actions must be null.
*
* @throws NullPointerException if <code>name</code> is
* <code>null</code>.
* @throws IllegalArgumentException if <code>name</code> is empty
* or <code>actions</code> is not null.
*/
public SubjectDelegationPermission(String name, String actions) {
super(name, actions);
if (actions != null)
throw new IllegalArgumentException("Non-null actions");
}
}

View File

@@ -0,0 +1,151 @@
/*
* 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
* 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 javax.management.remote;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import javax.management.Notification;
/**
* <p>A (Notification, Listener ID) pair.</p>
* <p>This class is used to associate an emitted notification
* with the listener ID to which it is targeted.</p>
*
* @since 1.5
*/
public class TargetedNotification implements Serializable {
private static final long serialVersionUID = 7676132089779300926L;
// If we replace Integer with int...
// /**
// * <p>Constructs a <code>TargetedNotification</code> object. The
// * object contains a pair (Notification, Listener ID).
// * The Listener ID identifies the client listener to which that
// * notification is targeted. The client listener ID is one
// * previously returned by the connector server in response to an
// * <code>addNotificationListener</code> request.</p>
// * @param notification Notification emitted from the MBean server.
// * @param listenerID The ID of the listener to which this
// * notification is targeted.
// */
// public TargetedNotification(Notification notification,
// int listenerID) {
// this.notif = notification;
// this.id = listenerID;
// }
/**
* <p>Constructs a <code>TargetedNotification</code> object. The
* object contains a pair (Notification, Listener ID).
* The Listener ID identifies the client listener to which that
* notification is targeted. The client listener ID is one
* previously returned by the connector server in response to an
* <code>addNotificationListener</code> request.</p>
* @param notification Notification emitted from the MBean server.
* @param listenerID The ID of the listener to which this
* notification is targeted.
* @exception IllegalArgumentException if the <var>listenerID</var>
* or <var>notification</var> is null.
*/
public TargetedNotification(Notification notification,
Integer listenerID) {
validate(notification, listenerID);
// If we replace integer with int...
// this(notification,intValue(listenerID));
this.notif = notification;
this.id = listenerID;
}
/**
* <p>The emitted notification.</p>
*
* @return The notification.
*/
public Notification getNotification() {
return notif;
}
/**
* <p>The ID of the listener to which the notification is
* targeted.</p>
*
* @return The listener ID.
*/
public Integer getListenerID() {
return id;
}
/**
* Returns a textual representation of this Targeted Notification.
*
* @return a String representation of this Targeted Notification.
**/
public String toString() {
return "{" + notif + ", " + id + "}";
}
/**
* @serial A notification to transmit to the other side.
* @see #getNotification()
**/
private Notification notif;
/**
* @serial The ID of the listener to which the notification is
* targeted.
* @see #getListenerID()
**/
private Integer id;
//private final int id;
// Needed if we use int instead of Integer...
// private static int intValue(Integer id) {
// if (id == null) throw new
// IllegalArgumentException("Invalid listener ID: null");
// return id.intValue();
// }
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
try {
validate(this.notif, this.id);
} catch (IllegalArgumentException e) {
throw new InvalidObjectException(e.getMessage());
}
}
private static void validate(Notification notif, Integer id) throws IllegalArgumentException {
if (notif == null) {
throw new IllegalArgumentException("Invalid notification: null");
}
if (id == null) {
throw new IllegalArgumentException("Invalid listener ID: null");
}
}
}

View File

@@ -0,0 +1,297 @@
/*
* 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
* 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 javax.management.remote.rmi;
import java.security.ProtectionDomain;
/**
<p>A class loader that only knows how to define a limited number
of classes, and load a limited number of other classes through
delegation to another loader. It is used to get around a problem
with Serialization, in particular as used by RMI (including
RMI/IIOP). The JMX Remote API defines exactly what class loader
must be used to deserialize arguments on the server, and return
values on the client. We communicate this class loader to RMI by
setting it as the context class loader. RMI uses the context
class loader to load classes as it deserializes, which is what we
want. However, before consulting the context class loader, it
looks up the call stack for a class with a non-null class loader,
and uses that if it finds one. So, in the standalone version of
javax.management.remote, if the class you're looking for is known
to the loader of jmxremote.jar (typically the system class loader)
then that loader will load it. This contradicts the class-loading
semantics required.
<p>We get around the problem by ensuring that the search up the
call stack will find a non-null class loader that doesn't load any
classes of interest, namely this one. So even though this loader
is indeed consulted during deserialization, it never finds the
class being deserialized. RMI then proceeds to use the context
class loader, as we require.
<p>This loader is constructed with the name and byte-code of one
or more classes that it defines, and a class-loader to which it
will delegate certain other classes required by that byte-code.
We construct the byte-code somewhat painstakingly, by compiling
the Java code directly, converting into a string, copying that
string into the class that needs this loader, and using the
stringToBytes method to convert it into the byte array. We
compile with -g:none because there's not much point in having
line-number information and the like in these directly-encoded
classes.
<p>The referencedClassNames should contain the names of all
classes that are referenced by the classes defined by this loader.
It is not necessary to include standard J2SE classes, however.
Here, a class is referenced if it is the superclass or a
superinterface of a defined class, or if it is the type of a
field, parameter, or return value. A class is not referenced if
it only appears in the throws clause of a method or constructor.
Of course, referencedClassNames should not contain any classes
that the user might want to deserialize, because the whole point
of this loader is that it does not find such classes.
*/
class NoCallStackClassLoader extends ClassLoader {
/** Simplified constructor when this loader only defines one class. */
public NoCallStackClassLoader(String className,
byte[] byteCode,
String[] referencedClassNames,
ClassLoader referencedClassLoader,
ProtectionDomain protectionDomain) {
this(new String[] {className}, new byte[][] {byteCode},
referencedClassNames, referencedClassLoader, protectionDomain);
}
public NoCallStackClassLoader(String[] classNames,
byte[][] byteCodes,
String[] referencedClassNames,
ClassLoader referencedClassLoader,
ProtectionDomain protectionDomain) {
super(null);
/* Validation. */
if (classNames == null || classNames.length == 0
|| byteCodes == null || classNames.length != byteCodes.length
|| referencedClassNames == null || protectionDomain == null)
throw new IllegalArgumentException();
for (int i = 0; i < classNames.length; i++) {
if (classNames[i] == null || byteCodes[i] == null)
throw new IllegalArgumentException();
}
for (int i = 0; i < referencedClassNames.length; i++) {
if (referencedClassNames[i] == null)
throw new IllegalArgumentException();
}
this.classNames = classNames;
this.byteCodes = byteCodes;
this.referencedClassNames = referencedClassNames;
this.referencedClassLoader = referencedClassLoader;
this.protectionDomain = protectionDomain;
}
/* This method is called at most once per name. Define the name
* if it is one of the classes whose byte code we have, or
* delegate the load if it is one of the referenced classes.
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// Note: classNames is guaranteed by the constructor to be non-null.
for (int i = 0; i < classNames.length; i++) {
if (name.equals(classNames[i])) {
return defineClass(classNames[i], byteCodes[i], 0,
byteCodes[i].length, protectionDomain);
}
}
/* If the referencedClassLoader is null, it is the bootstrap
* class loader, and there's no point in delegating to it
* because it's already our parent class loader.
*/
if (referencedClassLoader != null) {
for (int i = 0; i < referencedClassNames.length; i++) {
if (name.equals(referencedClassNames[i]))
return referencedClassLoader.loadClass(name);
}
}
throw new ClassNotFoundException(name);
}
private final String[] classNames;
private final byte[][] byteCodes;
private final String[] referencedClassNames;
private final ClassLoader referencedClassLoader;
private final ProtectionDomain protectionDomain;
/**
* <p>Construct a <code>byte[]</code> using the characters of the
* given <code>String</code>. Only the low-order byte of each
* character is used. This method is useful to reduce the
* footprint of classes that include big byte arrays (e.g. the
* byte code of other classes), because a string takes up much
* less space in a class file than the byte code to initialize a
* <code>byte[]</code> with the same number of bytes.</p>
*
* <p>We use just one byte per character even though characters
* contain two bytes. The resultant output length is much the
* same: using one byte per character is shorter because it has
* more characters in the optimal 1-127 range but longer because
* it has more zero bytes (which are frequent, and are encoded as
* two bytes in classfile UTF-8). But one byte per character has
* two key advantages: (1) you can see the string constants, which
* is reassuring, (2) you don't need to know whether the class
* file length is odd.</p>
*
* <p>This method differs from {@link String#getBytes()} in that
* it does not use any encoding. So it is guaranteed that each
* byte of the result is numerically identical (mod 256) to the
* corresponding character of the input.
*/
public static byte[] stringToBytes(String s) {
final int slen = s.length();
byte[] bytes = new byte[slen];
for (int i = 0; i < slen; i++)
bytes[i] = (byte) s.charAt(i);
return bytes;
}
}
/*
You can use the following Emacs function to convert class files into
strings to be used by the stringToBytes method above. Select the
whole (defun...) with the mouse and type M-x eval-region, or save it
to a file and do M-x load-file. Then visit the *.class file and do
M-x class-string.
;; class-string.el
;; visit the *.class file with emacs, then invoke this function
(defun class-string ()
"Construct a Java string whose bytes are the same as the current
buffer. The resultant string is put in a buffer called *string*,
possibly with a numeric suffix like <2>. From there it can be
insert-buffer'd into a Java program."
(interactive)
(let* ((s (buffer-string))
(slen (length s))
(i 0)
(buf (generate-new-buffer "*string*")))
(set-buffer buf)
(insert "\"")
(while (< i slen)
(if (> (current-column) 61)
(insert "\"+\n\""))
(let ((c (aref s i)))
(insert (cond
((> c 126) (format "\\%o" c))
((= c ?\") "\\\"")
((= c ?\\) "\\\\")
((< c 33)
(let ((nextc (if (< (1+ i) slen)
(aref s (1+ i))
?\0)))
(cond
((and (<= nextc ?7) (>= nextc ?0))
(format "\\%03o" c))
(t
(format "\\%o" c)))))
(t c))))
(setq i (1+ i)))
(insert "\"")
(switch-to-buffer buf)))
Alternatively, the following class reads a class file and outputs a string
that can be used by the stringToBytes method above.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class BytesToString {
public static void main(String[] args) throws IOException {
File f = new File(args[0]);
int len = (int)f.length();
byte[] classBytes = new byte[len];
FileInputStream in = new FileInputStream(args[0]);
try {
int pos = 0;
for (;;) {
int n = in.read(classBytes, pos, (len-pos));
if (n < 0)
throw new RuntimeException("class file changed??");
pos += n;
if (pos >= n)
break;
}
} finally {
in.close();
}
int pos = 0;
boolean lastWasOctal = false;
for (int i=0; i<len; i++) {
int value = classBytes[i];
if (value < 0)
value += 256;
String s = null;
if (value == '\\')
s = "\\\\";
else if (value == '\"')
s = "\\\"";
else {
if ((value >= 32 && value < 127) && ((!lastWasOctal ||
(value < '0' || value > '7')))) {
s = Character.toString((char)value);
}
}
if (s == null) {
s = "\\" + Integer.toString(value, 8);
lastWasOctal = true;
} else {
lastWasOctal = false;
}
if (pos > 61) {
System.out.print("\"");
if (i<len)
System.out.print("+");
System.out.println();
pos = 0;
}
if (pos == 0)
System.out.print(" \"");
System.out.print(s);
pos += s.length();
}
System.out.println("\"");
}
}
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,604 @@
// Stub class generated by rmic, do not edit.
// Contents subject to change without notice.
package javax.management.remote.rmi;
public final class RMIConnectionImpl_Stub
extends java.rmi.server.RemoteStub
implements javax.management.remote.rmi.RMIConnection
{
private static final long serialVersionUID = 2;
private static java.lang.reflect.Method $method_addNotificationListener_0;
private static java.lang.reflect.Method $method_addNotificationListeners_1;
private static java.lang.reflect.Method $method_close_2;
private static java.lang.reflect.Method $method_createMBean_3;
private static java.lang.reflect.Method $method_createMBean_4;
private static java.lang.reflect.Method $method_createMBean_5;
private static java.lang.reflect.Method $method_createMBean_6;
private static java.lang.reflect.Method $method_fetchNotifications_7;
private static java.lang.reflect.Method $method_getAttribute_8;
private static java.lang.reflect.Method $method_getAttributes_9;
private static java.lang.reflect.Method $method_getConnectionId_10;
private static java.lang.reflect.Method $method_getDefaultDomain_11;
private static java.lang.reflect.Method $method_getDomains_12;
private static java.lang.reflect.Method $method_getMBeanCount_13;
private static java.lang.reflect.Method $method_getMBeanInfo_14;
private static java.lang.reflect.Method $method_getObjectInstance_15;
private static java.lang.reflect.Method $method_invoke_16;
private static java.lang.reflect.Method $method_isInstanceOf_17;
private static java.lang.reflect.Method $method_isRegistered_18;
private static java.lang.reflect.Method $method_queryMBeans_19;
private static java.lang.reflect.Method $method_queryNames_20;
private static java.lang.reflect.Method $method_removeNotificationListener_21;
private static java.lang.reflect.Method $method_removeNotificationListener_22;
private static java.lang.reflect.Method $method_removeNotificationListeners_23;
private static java.lang.reflect.Method $method_setAttribute_24;
private static java.lang.reflect.Method $method_setAttributes_25;
private static java.lang.reflect.Method $method_unregisterMBean_26;
static {
try {
$method_addNotificationListener_0 = javax.management.remote.rmi.RMIConnection.class.getMethod("addNotificationListener", new java.lang.Class[] {javax.management.ObjectName.class, javax.management.ObjectName.class, java.rmi.MarshalledObject.class, java.rmi.MarshalledObject.class, javax.security.auth.Subject.class});
$method_addNotificationListeners_1 = javax.management.remote.rmi.RMIConnection.class.getMethod("addNotificationListeners", new java.lang.Class[] {javax.management.ObjectName[].class, java.rmi.MarshalledObject[].class, javax.security.auth.Subject[].class});
$method_close_2 = java.lang.AutoCloseable.class.getMethod("close", new java.lang.Class[] {});
$method_createMBean_3 = javax.management.remote.rmi.RMIConnection.class.getMethod("createMBean", new java.lang.Class[] {java.lang.String.class, javax.management.ObjectName.class, java.rmi.MarshalledObject.class, java.lang.String[].class, javax.security.auth.Subject.class});
$method_createMBean_4 = javax.management.remote.rmi.RMIConnection.class.getMethod("createMBean", new java.lang.Class[] {java.lang.String.class, javax.management.ObjectName.class, javax.management.ObjectName.class, java.rmi.MarshalledObject.class, java.lang.String[].class, javax.security.auth.Subject.class});
$method_createMBean_5 = javax.management.remote.rmi.RMIConnection.class.getMethod("createMBean", new java.lang.Class[] {java.lang.String.class, javax.management.ObjectName.class, javax.management.ObjectName.class, javax.security.auth.Subject.class});
$method_createMBean_6 = javax.management.remote.rmi.RMIConnection.class.getMethod("createMBean", new java.lang.Class[] {java.lang.String.class, javax.management.ObjectName.class, javax.security.auth.Subject.class});
$method_fetchNotifications_7 = javax.management.remote.rmi.RMIConnection.class.getMethod("fetchNotifications", new java.lang.Class[] {long.class, int.class, long.class});
$method_getAttribute_8 = javax.management.remote.rmi.RMIConnection.class.getMethod("getAttribute", new java.lang.Class[] {javax.management.ObjectName.class, java.lang.String.class, javax.security.auth.Subject.class});
$method_getAttributes_9 = javax.management.remote.rmi.RMIConnection.class.getMethod("getAttributes", new java.lang.Class[] {javax.management.ObjectName.class, java.lang.String[].class, javax.security.auth.Subject.class});
$method_getConnectionId_10 = javax.management.remote.rmi.RMIConnection.class.getMethod("getConnectionId", new java.lang.Class[] {});
$method_getDefaultDomain_11 = javax.management.remote.rmi.RMIConnection.class.getMethod("getDefaultDomain", new java.lang.Class[] {javax.security.auth.Subject.class});
$method_getDomains_12 = javax.management.remote.rmi.RMIConnection.class.getMethod("getDomains", new java.lang.Class[] {javax.security.auth.Subject.class});
$method_getMBeanCount_13 = javax.management.remote.rmi.RMIConnection.class.getMethod("getMBeanCount", new java.lang.Class[] {javax.security.auth.Subject.class});
$method_getMBeanInfo_14 = javax.management.remote.rmi.RMIConnection.class.getMethod("getMBeanInfo", new java.lang.Class[] {javax.management.ObjectName.class, javax.security.auth.Subject.class});
$method_getObjectInstance_15 = javax.management.remote.rmi.RMIConnection.class.getMethod("getObjectInstance", new java.lang.Class[] {javax.management.ObjectName.class, javax.security.auth.Subject.class});
$method_invoke_16 = javax.management.remote.rmi.RMIConnection.class.getMethod("invoke", new java.lang.Class[] {javax.management.ObjectName.class, java.lang.String.class, java.rmi.MarshalledObject.class, java.lang.String[].class, javax.security.auth.Subject.class});
$method_isInstanceOf_17 = javax.management.remote.rmi.RMIConnection.class.getMethod("isInstanceOf", new java.lang.Class[] {javax.management.ObjectName.class, java.lang.String.class, javax.security.auth.Subject.class});
$method_isRegistered_18 = javax.management.remote.rmi.RMIConnection.class.getMethod("isRegistered", new java.lang.Class[] {javax.management.ObjectName.class, javax.security.auth.Subject.class});
$method_queryMBeans_19 = javax.management.remote.rmi.RMIConnection.class.getMethod("queryMBeans", new java.lang.Class[] {javax.management.ObjectName.class, java.rmi.MarshalledObject.class, javax.security.auth.Subject.class});
$method_queryNames_20 = javax.management.remote.rmi.RMIConnection.class.getMethod("queryNames", new java.lang.Class[] {javax.management.ObjectName.class, java.rmi.MarshalledObject.class, javax.security.auth.Subject.class});
$method_removeNotificationListener_21 = javax.management.remote.rmi.RMIConnection.class.getMethod("removeNotificationListener", new java.lang.Class[] {javax.management.ObjectName.class, javax.management.ObjectName.class, java.rmi.MarshalledObject.class, java.rmi.MarshalledObject.class, javax.security.auth.Subject.class});
$method_removeNotificationListener_22 = javax.management.remote.rmi.RMIConnection.class.getMethod("removeNotificationListener", new java.lang.Class[] {javax.management.ObjectName.class, javax.management.ObjectName.class, javax.security.auth.Subject.class});
$method_removeNotificationListeners_23 = javax.management.remote.rmi.RMIConnection.class.getMethod("removeNotificationListeners", new java.lang.Class[] {javax.management.ObjectName.class, java.lang.Integer[].class, javax.security.auth.Subject.class});
$method_setAttribute_24 = javax.management.remote.rmi.RMIConnection.class.getMethod("setAttribute", new java.lang.Class[] {javax.management.ObjectName.class, java.rmi.MarshalledObject.class, javax.security.auth.Subject.class});
$method_setAttributes_25 = javax.management.remote.rmi.RMIConnection.class.getMethod("setAttributes", new java.lang.Class[] {javax.management.ObjectName.class, java.rmi.MarshalledObject.class, javax.security.auth.Subject.class});
$method_unregisterMBean_26 = javax.management.remote.rmi.RMIConnection.class.getMethod("unregisterMBean", new java.lang.Class[] {javax.management.ObjectName.class, javax.security.auth.Subject.class});
} catch (java.lang.NoSuchMethodException e) {
throw new java.lang.NoSuchMethodError(
"stub class initialization failed");
}
}
// constructors
public RMIConnectionImpl_Stub(java.rmi.server.RemoteRef ref) {
super(ref);
}
// methods from remote interfaces
// implementation of addNotificationListener(ObjectName, ObjectName, MarshalledObject, MarshalledObject, Subject)
public void addNotificationListener(javax.management.ObjectName $param_ObjectName_1, javax.management.ObjectName $param_ObjectName_2, java.rmi.MarshalledObject $param_MarshalledObject_3, java.rmi.MarshalledObject $param_MarshalledObject_4, javax.security.auth.Subject $param_Subject_5)
throws java.io.IOException, javax.management.InstanceNotFoundException
{
try {
ref.invoke(this, $method_addNotificationListener_0, new java.lang.Object[] {$param_ObjectName_1, $param_ObjectName_2, $param_MarshalledObject_3, $param_MarshalledObject_4, $param_Subject_5}, -8578317696269497109L);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of addNotificationListeners(ObjectName[], MarshalledObject[], Subject[])
public java.lang.Integer[] addNotificationListeners(javax.management.ObjectName[] $param_arrayOf_ObjectName_1, java.rmi.MarshalledObject[] $param_arrayOf_MarshalledObject_2, javax.security.auth.Subject[] $param_arrayOf_Subject_3)
throws java.io.IOException, javax.management.InstanceNotFoundException
{
try {
Object $result = ref.invoke(this, $method_addNotificationListeners_1, new java.lang.Object[] {$param_arrayOf_ObjectName_1, $param_arrayOf_MarshalledObject_2, $param_arrayOf_Subject_3}, -5321691879380783377L);
return ((java.lang.Integer[]) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of close()
public void close()
throws java.io.IOException
{
try {
ref.invoke(this, $method_close_2, null, -4742752445160157748L);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of createMBean(String, ObjectName, MarshalledObject, String[], Subject)
public javax.management.ObjectInstance createMBean(java.lang.String $param_String_1, javax.management.ObjectName $param_ObjectName_2, java.rmi.MarshalledObject $param_MarshalledObject_3, java.lang.String[] $param_arrayOf_String_4, javax.security.auth.Subject $param_Subject_5)
throws java.io.IOException, javax.management.InstanceAlreadyExistsException, javax.management.MBeanException, javax.management.MBeanRegistrationException, javax.management.NotCompliantMBeanException, javax.management.ReflectionException
{
try {
Object $result = ref.invoke(this, $method_createMBean_3, new java.lang.Object[] {$param_String_1, $param_ObjectName_2, $param_MarshalledObject_3, $param_arrayOf_String_4, $param_Subject_5}, 4867822117947806114L);
return ((javax.management.ObjectInstance) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceAlreadyExistsException e) {
throw e;
} catch (javax.management.MBeanException e) {
throw e;
} catch (javax.management.NotCompliantMBeanException e) {
throw e;
} catch (javax.management.ReflectionException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of createMBean(String, ObjectName, ObjectName, MarshalledObject, String[], Subject)
public javax.management.ObjectInstance createMBean(java.lang.String $param_String_1, javax.management.ObjectName $param_ObjectName_2, javax.management.ObjectName $param_ObjectName_3, java.rmi.MarshalledObject $param_MarshalledObject_4, java.lang.String[] $param_arrayOf_String_5, javax.security.auth.Subject $param_Subject_6)
throws java.io.IOException, javax.management.InstanceAlreadyExistsException, javax.management.InstanceNotFoundException, javax.management.MBeanException, javax.management.MBeanRegistrationException, javax.management.NotCompliantMBeanException, javax.management.ReflectionException
{
try {
Object $result = ref.invoke(this, $method_createMBean_4, new java.lang.Object[] {$param_String_1, $param_ObjectName_2, $param_ObjectName_3, $param_MarshalledObject_4, $param_arrayOf_String_5, $param_Subject_6}, -6604955182088909937L);
return ((javax.management.ObjectInstance) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceAlreadyExistsException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.MBeanException e) {
throw e;
} catch (javax.management.NotCompliantMBeanException e) {
throw e;
} catch (javax.management.ReflectionException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of createMBean(String, ObjectName, ObjectName, Subject)
public javax.management.ObjectInstance createMBean(java.lang.String $param_String_1, javax.management.ObjectName $param_ObjectName_2, javax.management.ObjectName $param_ObjectName_3, javax.security.auth.Subject $param_Subject_4)
throws java.io.IOException, javax.management.InstanceAlreadyExistsException, javax.management.InstanceNotFoundException, javax.management.MBeanException, javax.management.MBeanRegistrationException, javax.management.NotCompliantMBeanException, javax.management.ReflectionException
{
try {
Object $result = ref.invoke(this, $method_createMBean_5, new java.lang.Object[] {$param_String_1, $param_ObjectName_2, $param_ObjectName_3, $param_Subject_4}, -8679469989872508324L);
return ((javax.management.ObjectInstance) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceAlreadyExistsException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.MBeanException e) {
throw e;
} catch (javax.management.NotCompliantMBeanException e) {
throw e;
} catch (javax.management.ReflectionException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of createMBean(String, ObjectName, Subject)
public javax.management.ObjectInstance createMBean(java.lang.String $param_String_1, javax.management.ObjectName $param_ObjectName_2, javax.security.auth.Subject $param_Subject_3)
throws java.io.IOException, javax.management.InstanceAlreadyExistsException, javax.management.MBeanException, javax.management.MBeanRegistrationException, javax.management.NotCompliantMBeanException, javax.management.ReflectionException
{
try {
Object $result = ref.invoke(this, $method_createMBean_6, new java.lang.Object[] {$param_String_1, $param_ObjectName_2, $param_Subject_3}, 2510753813974665446L);
return ((javax.management.ObjectInstance) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceAlreadyExistsException e) {
throw e;
} catch (javax.management.MBeanException e) {
throw e;
} catch (javax.management.NotCompliantMBeanException e) {
throw e;
} catch (javax.management.ReflectionException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of fetchNotifications(long, int, long)
public javax.management.remote.NotificationResult fetchNotifications(long $param_long_1, int $param_int_2, long $param_long_3)
throws java.io.IOException
{
try {
Object $result = ref.invoke(this, $method_fetchNotifications_7, new java.lang.Object[] {new java.lang.Long($param_long_1), new java.lang.Integer($param_int_2), new java.lang.Long($param_long_3)}, -5037523307973544478L);
return ((javax.management.remote.NotificationResult) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of getAttribute(ObjectName, String, Subject)
public java.lang.Object getAttribute(javax.management.ObjectName $param_ObjectName_1, java.lang.String $param_String_2, javax.security.auth.Subject $param_Subject_3)
throws java.io.IOException, javax.management.AttributeNotFoundException, javax.management.InstanceNotFoundException, javax.management.MBeanException, javax.management.ReflectionException
{
try {
Object $result = ref.invoke(this, $method_getAttribute_8, new java.lang.Object[] {$param_ObjectName_1, $param_String_2, $param_Subject_3}, -1089783104982388203L);
return ((java.lang.Object) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.AttributeNotFoundException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.MBeanException e) {
throw e;
} catch (javax.management.ReflectionException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of getAttributes(ObjectName, String[], Subject)
public javax.management.AttributeList getAttributes(javax.management.ObjectName $param_ObjectName_1, java.lang.String[] $param_arrayOf_String_2, javax.security.auth.Subject $param_Subject_3)
throws java.io.IOException, javax.management.InstanceNotFoundException, javax.management.ReflectionException
{
try {
Object $result = ref.invoke(this, $method_getAttributes_9, new java.lang.Object[] {$param_ObjectName_1, $param_arrayOf_String_2, $param_Subject_3}, 6285293806596348999L);
return ((javax.management.AttributeList) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.ReflectionException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of getConnectionId()
public java.lang.String getConnectionId()
throws java.io.IOException
{
try {
Object $result = ref.invoke(this, $method_getConnectionId_10, null, -67907180346059933L);
return ((java.lang.String) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of getDefaultDomain(Subject)
public java.lang.String getDefaultDomain(javax.security.auth.Subject $param_Subject_1)
throws java.io.IOException
{
try {
Object $result = ref.invoke(this, $method_getDefaultDomain_11, new java.lang.Object[] {$param_Subject_1}, 6047668923998658472L);
return ((java.lang.String) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of getDomains(Subject)
public java.lang.String[] getDomains(javax.security.auth.Subject $param_Subject_1)
throws java.io.IOException
{
try {
Object $result = ref.invoke(this, $method_getDomains_12, new java.lang.Object[] {$param_Subject_1}, -6662314179953625551L);
return ((java.lang.String[]) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of getMBeanCount(Subject)
public java.lang.Integer getMBeanCount(javax.security.auth.Subject $param_Subject_1)
throws java.io.IOException
{
try {
Object $result = ref.invoke(this, $method_getMBeanCount_13, new java.lang.Object[] {$param_Subject_1}, -2042362057335820635L);
return ((java.lang.Integer) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of getMBeanInfo(ObjectName, Subject)
public javax.management.MBeanInfo getMBeanInfo(javax.management.ObjectName $param_ObjectName_1, javax.security.auth.Subject $param_Subject_2)
throws java.io.IOException, javax.management.InstanceNotFoundException, javax.management.IntrospectionException, javax.management.ReflectionException
{
try {
Object $result = ref.invoke(this, $method_getMBeanInfo_14, new java.lang.Object[] {$param_ObjectName_1, $param_Subject_2}, -7404813916326233354L);
return ((javax.management.MBeanInfo) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.IntrospectionException e) {
throw e;
} catch (javax.management.ReflectionException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of getObjectInstance(ObjectName, Subject)
public javax.management.ObjectInstance getObjectInstance(javax.management.ObjectName $param_ObjectName_1, javax.security.auth.Subject $param_Subject_2)
throws java.io.IOException, javax.management.InstanceNotFoundException
{
try {
Object $result = ref.invoke(this, $method_getObjectInstance_15, new java.lang.Object[] {$param_ObjectName_1, $param_Subject_2}, 6950095694996159938L);
return ((javax.management.ObjectInstance) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of invoke(ObjectName, String, MarshalledObject, String[], Subject)
public java.lang.Object invoke(javax.management.ObjectName $param_ObjectName_1, java.lang.String $param_String_2, java.rmi.MarshalledObject $param_MarshalledObject_3, java.lang.String[] $param_arrayOf_String_4, javax.security.auth.Subject $param_Subject_5)
throws java.io.IOException, javax.management.InstanceNotFoundException, javax.management.MBeanException, javax.management.ReflectionException
{
try {
Object $result = ref.invoke(this, $method_invoke_16, new java.lang.Object[] {$param_ObjectName_1, $param_String_2, $param_MarshalledObject_3, $param_arrayOf_String_4, $param_Subject_5}, 1434350937885235744L);
return ((java.lang.Object) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.MBeanException e) {
throw e;
} catch (javax.management.ReflectionException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of isInstanceOf(ObjectName, String, Subject)
public boolean isInstanceOf(javax.management.ObjectName $param_ObjectName_1, java.lang.String $param_String_2, javax.security.auth.Subject $param_Subject_3)
throws java.io.IOException, javax.management.InstanceNotFoundException
{
try {
Object $result = ref.invoke(this, $method_isInstanceOf_17, new java.lang.Object[] {$param_ObjectName_1, $param_String_2, $param_Subject_3}, -2147516868461740814L);
return ((java.lang.Boolean) $result).booleanValue();
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of isRegistered(ObjectName, Subject)
public boolean isRegistered(javax.management.ObjectName $param_ObjectName_1, javax.security.auth.Subject $param_Subject_2)
throws java.io.IOException
{
try {
Object $result = ref.invoke(this, $method_isRegistered_18, new java.lang.Object[] {$param_ObjectName_1, $param_Subject_2}, 8325683335228268564L);
return ((java.lang.Boolean) $result).booleanValue();
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of queryMBeans(ObjectName, MarshalledObject, Subject)
public java.util.Set queryMBeans(javax.management.ObjectName $param_ObjectName_1, java.rmi.MarshalledObject $param_MarshalledObject_2, javax.security.auth.Subject $param_Subject_3)
throws java.io.IOException
{
try {
Object $result = ref.invoke(this, $method_queryMBeans_19, new java.lang.Object[] {$param_ObjectName_1, $param_MarshalledObject_2, $param_Subject_3}, 2915881009400597976L);
return ((java.util.Set) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of queryNames(ObjectName, MarshalledObject, Subject)
public java.util.Set queryNames(javax.management.ObjectName $param_ObjectName_1, java.rmi.MarshalledObject $param_MarshalledObject_2, javax.security.auth.Subject $param_Subject_3)
throws java.io.IOException
{
try {
Object $result = ref.invoke(this, $method_queryNames_20, new java.lang.Object[] {$param_ObjectName_1, $param_MarshalledObject_2, $param_Subject_3}, 9152567528369059802L);
return ((java.util.Set) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of removeNotificationListener(ObjectName, ObjectName, MarshalledObject, MarshalledObject, Subject)
public void removeNotificationListener(javax.management.ObjectName $param_ObjectName_1, javax.management.ObjectName $param_ObjectName_2, java.rmi.MarshalledObject $param_MarshalledObject_3, java.rmi.MarshalledObject $param_MarshalledObject_4, javax.security.auth.Subject $param_Subject_5)
throws java.io.IOException, javax.management.InstanceNotFoundException, javax.management.ListenerNotFoundException
{
try {
ref.invoke(this, $method_removeNotificationListener_21, new java.lang.Object[] {$param_ObjectName_1, $param_ObjectName_2, $param_MarshalledObject_3, $param_MarshalledObject_4, $param_Subject_5}, 2578029900065214857L);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.ListenerNotFoundException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of removeNotificationListener(ObjectName, ObjectName, Subject)
public void removeNotificationListener(javax.management.ObjectName $param_ObjectName_1, javax.management.ObjectName $param_ObjectName_2, javax.security.auth.Subject $param_Subject_3)
throws java.io.IOException, javax.management.InstanceNotFoundException, javax.management.ListenerNotFoundException
{
try {
ref.invoke(this, $method_removeNotificationListener_22, new java.lang.Object[] {$param_ObjectName_1, $param_ObjectName_2, $param_Subject_3}, 6604721169198089513L);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.ListenerNotFoundException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of removeNotificationListeners(ObjectName, Integer[], Subject)
public void removeNotificationListeners(javax.management.ObjectName $param_ObjectName_1, java.lang.Integer[] $param_arrayOf_Integer_2, javax.security.auth.Subject $param_Subject_3)
throws java.io.IOException, javax.management.InstanceNotFoundException, javax.management.ListenerNotFoundException
{
try {
ref.invoke(this, $method_removeNotificationListeners_23, new java.lang.Object[] {$param_ObjectName_1, $param_arrayOf_Integer_2, $param_Subject_3}, 2549120024456183446L);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.ListenerNotFoundException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of setAttribute(ObjectName, MarshalledObject, Subject)
public void setAttribute(javax.management.ObjectName $param_ObjectName_1, java.rmi.MarshalledObject $param_MarshalledObject_2, javax.security.auth.Subject $param_Subject_3)
throws java.io.IOException, javax.management.AttributeNotFoundException, javax.management.InstanceNotFoundException, javax.management.InvalidAttributeValueException, javax.management.MBeanException, javax.management.ReflectionException
{
try {
ref.invoke(this, $method_setAttribute_24, new java.lang.Object[] {$param_ObjectName_1, $param_MarshalledObject_2, $param_Subject_3}, 6738606893952597516L);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.AttributeNotFoundException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.InvalidAttributeValueException e) {
throw e;
} catch (javax.management.MBeanException e) {
throw e;
} catch (javax.management.ReflectionException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of setAttributes(ObjectName, MarshalledObject, Subject)
public javax.management.AttributeList setAttributes(javax.management.ObjectName $param_ObjectName_1, java.rmi.MarshalledObject $param_MarshalledObject_2, javax.security.auth.Subject $param_Subject_3)
throws java.io.IOException, javax.management.InstanceNotFoundException, javax.management.ReflectionException
{
try {
Object $result = ref.invoke(this, $method_setAttributes_25, new java.lang.Object[] {$param_ObjectName_1, $param_MarshalledObject_2, $param_Subject_3}, -230470228399681820L);
return ((javax.management.AttributeList) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.ReflectionException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of unregisterMBean(ObjectName, Subject)
public void unregisterMBean(javax.management.ObjectName $param_ObjectName_1, javax.security.auth.Subject $param_Subject_2)
throws java.io.IOException, javax.management.InstanceNotFoundException, javax.management.MBeanRegistrationException
{
try {
ref.invoke(this, $method_unregisterMBean_26, new java.lang.Object[] {$param_ObjectName_1, $param_Subject_2}, -159498580868721452L);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (javax.management.InstanceNotFoundException e) {
throw e;
} catch (javax.management.MBeanRegistrationException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,853 @@
/*
* 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
* 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 javax.management.remote.rmi;
import com.sun.jmx.remote.security.MBeanServerFileAccessController;
import com.sun.jmx.remote.internal.IIOPHelper;
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.remote.JMXConnectionNotification;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.MBeanServerForwarder;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* <p>A JMX API connector server that creates RMI-based connections
* from remote clients. Usually, such connector servers are made
* using {@link javax.management.remote.JMXConnectorServerFactory
* JMXConnectorServerFactory}. However, specialized applications can
* use this class directly, for example with an {@link RMIServerImpl}
* object.</p>
*
* @since 1.5
*/
public class RMIConnectorServer extends JMXConnectorServer {
/**
* <p>Name of the attribute that specifies whether the {@link
* RMIServer} stub that represents an RMI connector server should
* override an existing stub at the same address. The value
* associated with this attribute, if any, should be a string that
* is equal, ignoring case, to <code>"true"</code> or
* <code>"false"</code>. The default value is false.</p>
*/
public static final String JNDI_REBIND_ATTRIBUTE =
"jmx.remote.jndi.rebind";
/**
* <p>Name of the attribute that specifies the {@link
* RMIClientSocketFactory} for the RMI objects created in
* conjunction with this connector. The value associated with this
* attribute must be of type <code>RMIClientSocketFactory</code> and can
* only be specified in the <code>Map</code> argument supplied when
* creating a connector server.</p>
*/
public static final String RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE =
"jmx.remote.rmi.client.socket.factory";
/**
* <p>Name of the attribute that specifies the {@link
* RMIServerSocketFactory} for the RMI objects created in
* conjunction with this connector. The value associated with this
* attribute must be of type <code>RMIServerSocketFactory</code> and can
* only be specified in the <code>Map</code> argument supplied when
* creating a connector server.</p>
*/
public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE =
"jmx.remote.rmi.server.socket.factory";
/**
* <p>Makes an <code>RMIConnectorServer</code>.
* This is equivalent to calling {@link #RMIConnectorServer(
* JMXServiceURL,Map,RMIServerImpl,MBeanServer)
* RMIConnectorServer(directoryURL,environment,null,null)}</p>
*
* @param url the URL defining how to create the connector server.
* Cannot be null.
*
* @param environment attributes governing the creation and
* storing of the RMI object. Can be null, which is equivalent to
* an empty Map.
*
* @exception IllegalArgumentException if <code>url</code> is null.
*
* @exception MalformedURLException if <code>url</code> does not
* conform to the syntax for an RMI connector, or if its protocol
* is not recognized by this implementation. Only "rmi" and "iiop"
* are valid when this constructor is used.
*
* @exception IOException if the connector server cannot be created
* for some reason or if it is inevitable that its {@link #start()
* start} method will fail.
*/
public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment)
throws IOException {
this(url, environment, (MBeanServer) null);
}
/**
* <p>Makes an <code>RMIConnectorServer</code> for the given MBean
* server.
* This is equivalent to calling {@link #RMIConnectorServer(
* JMXServiceURL,Map,RMIServerImpl,MBeanServer)
* RMIConnectorServer(directoryURL,environment,null,mbeanServer)}</p>
*
* @param url the URL defining how to create the connector server.
* Cannot be null.
*
* @param environment attributes governing the creation and
* storing of the RMI object. Can be null, which is equivalent to
* an empty Map.
*
* @param mbeanServer the MBean server to which the new connector
* server is attached, or null if it will be attached by being
* registered as an MBean in the MBean server.
*
* @exception IllegalArgumentException if <code>url</code> is null.
*
* @exception MalformedURLException if <code>url</code> does not
* conform to the syntax for an RMI connector, or if its protocol
* is not recognized by this implementation. Only "rmi" and "iiop"
* are valid when this constructor is used.
*
* @exception IOException if the connector server cannot be created
* for some reason or if it is inevitable that its {@link #start()
* start} method will fail.
*/
public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
MBeanServer mbeanServer)
throws IOException {
this(url, environment, (RMIServerImpl) null, mbeanServer);
}
/**
* <p>Makes an <code>RMIConnectorServer</code> for the given MBean
* server.</p>
*
* @param url the URL defining how to create the connector server.
* Cannot be null.
*
* @param environment attributes governing the creation and
* storing of the RMI object. Can be null, which is equivalent to
* an empty Map.
*
* @param rmiServerImpl An implementation of the RMIServer interface,
* consistent with the protocol type specified in <var>url</var>.
* If this parameter is non null, the protocol type specified by
* <var>url</var> is not constrained, and is assumed to be valid.
* Otherwise, only "rmi" and "iiop" will be recognized.
*
* @param mbeanServer the MBean server to which the new connector
* server is attached, or null if it will be attached by being
* registered as an MBean in the MBean server.
*
* @exception IllegalArgumentException if <code>url</code> is null.
*
* @exception MalformedURLException if <code>url</code> does not
* conform to the syntax for an RMI connector, or if its protocol
* is not recognized by this implementation. Only "rmi" and "iiop"
* are recognized when <var>rmiServerImpl</var> is null.
*
* @exception IOException if the connector server cannot be created
* for some reason or if it is inevitable that its {@link #start()
* start} method will fail.
*
* @see #start
*/
public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
RMIServerImpl rmiServerImpl,
MBeanServer mbeanServer)
throws IOException {
super(mbeanServer);
if (url == null) throw new
IllegalArgumentException("Null JMXServiceURL");
if (rmiServerImpl == null) {
final String prt = url.getProtocol();
if (prt == null || !(prt.equals("rmi") || prt.equals("iiop"))) {
final String msg = "Invalid protocol type: " + prt;
throw new MalformedURLException(msg);
}
final String urlPath = url.getURLPath();
if (!urlPath.equals("")
&& !urlPath.equals("/")
&& !urlPath.startsWith("/jndi/")) {
final String msg = "URL path must be empty or start with " +
"/jndi/";
throw new MalformedURLException(msg);
}
}
if (environment == null)
this.attributes = Collections.emptyMap();
else {
EnvHelp.checkAttributes(environment);
this.attributes = Collections.unmodifiableMap(environment);
}
this.address = url;
this.rmiServerImpl = rmiServerImpl;
}
/**
* <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>
*
* @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 #isActive()}).
*
* @exception IOException if a communications problem means that a
* stub cannot be created.
**/
public JMXConnector toJMXConnector(Map<String,?> env) throws IOException {
// The serialized for of rmiServerImpl is automatically
// a RMI server stub.
if (!isActive()) throw new
IllegalStateException("Connector is not active");
// Merge maps
Map<String, Object> usemap = new HashMap<String, Object>(
(this.attributes==null)?Collections.<String, Object>emptyMap():
this.attributes);
if (env != null) {
EnvHelp.checkAttributes(env);
usemap.putAll(env);
}
usemap = EnvHelp.filterAttributes(usemap);
final RMIServer stub=(RMIServer)rmiServerImpl.toStub();
return new RMIConnector(stub, usemap);
}
/**
* <p>Activates the connector server, that is starts listening for
* client connections. Calling this method when the connector
* server is already active has no effect. Calling this method
* when the connector server has been stopped will generate an
* <code>IOException</code>.</p>
*
* <p>The behavior of this method when called for the first time
* depends on the parameters that were supplied at construction,
* as described below.</p>
*
* <p>First, an object of a subclass of {@link RMIServerImpl} is
* required, to export the connector server through RMI:</p>
*
* <ul>
*
* <li>If an <code>RMIServerImpl</code> was supplied to the
* constructor, it is used.
*
* <li>Otherwise, if the protocol part of the
* <code>JMXServiceURL</code> supplied to the constructor was
* <code>iiop</code>, an object of type {@link RMIIIOPServerImpl}
* is created.
*
* <li>Otherwise, if the <code>JMXServiceURL</code>
* was null, or its protocol part was <code>rmi</code>, an object
* of type {@link RMIJRMPServerImpl} is created.
*
* <li>Otherwise, the implementation can create an
* implementation-specific {@link RMIServerImpl} or it can throw
* {@link MalformedURLException}.
*
* </ul>
*
* <p>If the given address includes a JNDI directory URL as
* specified in the package documentation for {@link
* javax.management.remote.rmi}, then this
* <code>RMIConnectorServer</code> will bootstrap by binding the
* <code>RMIServerImpl</code> to the given address.</p>
*
* <p>If the URL path part of the <code>JMXServiceURL</code> was
* empty or a single slash (<code>/</code>), then the RMI object
* will not be bound to a directory. Instead, a reference to it
* will be encoded in the URL path of the RMIConnectorServer
* address (returned by {@link #getAddress()}). The encodings for
* <code>rmi</code> and <code>iiop</code> are described in the
* package documentation for {@link
* javax.management.remote.rmi}.</p>
*
* <p>The behavior when the URL path is neither empty nor a JNDI
* directory URL, or when the protocol is neither <code>rmi</code>
* nor <code>iiop</code>, is implementation defined, and may
* include throwing {@link MalformedURLException} when the
* connector server is created or when it is started.</p>
*
* @exception IllegalStateException if the connector server has
* not been attached to an MBean server.
* @exception IOException if the connector server cannot be
* started, or in the case of the {@code iiop} protocol, that
* RMI/IIOP is not supported.
*/
public synchronized void start() throws IOException {
final boolean tracing = logger.traceOn();
if (state == STARTED) {
if (tracing) logger.trace("start", "already started");
return;
} else if (state == STOPPED) {
if (tracing) logger.trace("start", "already stopped");
throw new IOException("The server has been stopped.");
}
if (getMBeanServer() == null)
throw new IllegalStateException("This connector server is not " +
"attached to an MBean server");
// Check the internal access file property to see
// if an MBeanServerForwarder is to be provided
//
if (attributes != null) {
// Check if access file property is specified
//
String accessFile =
(String) attributes.get("jmx.remote.x.access.file");
if (accessFile != null) {
// Access file property specified, create an instance
// of the MBeanServerFileAccessController class
//
MBeanServerForwarder mbsf;
try {
mbsf = new MBeanServerFileAccessController(accessFile);
} catch (IOException e) {
throw EnvHelp.initCause(
new IllegalArgumentException(e.getMessage()), e);
}
// Set the MBeanServerForwarder
//
setMBeanServerForwarder(mbsf);
}
}
try {
if (tracing) logger.trace("start", "setting default class loader");
defaultClassLoader = EnvHelp.resolveServerClassLoader(
attributes, getMBeanServer());
} catch (InstanceNotFoundException infc) {
IllegalArgumentException x = new
IllegalArgumentException("ClassLoader not found: "+infc);
throw EnvHelp.initCause(x,infc);
}
if (tracing) logger.trace("start", "setting RMIServer object");
final RMIServerImpl rmiServer;
if (rmiServerImpl != null)
rmiServer = rmiServerImpl;
else
rmiServer = newServer();
rmiServer.setMBeanServer(getMBeanServer());
rmiServer.setDefaultClassLoader(defaultClassLoader);
rmiServer.setRMIConnectorServer(this);
rmiServer.export();
try {
if (tracing) logger.trace("start", "getting RMIServer object to export");
final RMIServer objref = objectToBind(rmiServer, attributes);
if (address != null && address.getURLPath().startsWith("/jndi/")) {
final String jndiUrl = address.getURLPath().substring(6);
if (tracing)
logger.trace("start", "Using external directory: " + jndiUrl);
String stringBoolean = (String) attributes.get(JNDI_REBIND_ATTRIBUTE);
final boolean rebind = EnvHelp.computeBooleanFromString( stringBoolean );
if (tracing)
logger.trace("start", JNDI_REBIND_ATTRIBUTE + "=" + rebind);
try {
if (tracing) logger.trace("start", "binding to " + jndiUrl);
final Hashtable<?, ?> usemap = EnvHelp.mapToHashtable(attributes);
bind(jndiUrl, usemap, objref, rebind);
boundJndiUrl = jndiUrl;
} catch (NamingException e) {
// fit e in the nested exception if we are on 1.4
throw newIOException("Cannot bind to URL ["+jndiUrl+"]: "
+ e, e);
}
} else {
// if jndiURL is null, we must encode the stub into the URL.
if (tracing) logger.trace("start", "Encoding URL");
encodeStubInAddress(objref, attributes);
if (tracing) logger.trace("start", "Encoded URL: " + this.address);
}
} catch (Exception e) {
try {
rmiServer.close();
} catch (Exception x) {
// OK: we are already throwing another exception
}
if (e instanceof RuntimeException)
throw (RuntimeException) e;
else if (e instanceof IOException)
throw (IOException) e;
else
throw newIOException("Got unexpected exception while " +
"starting the connector server: "
+ e, e);
}
rmiServerImpl = rmiServer;
synchronized(openedServers) {
openedServers.add(this);
}
state = STARTED;
if (tracing) {
logger.trace("start", "Connector Server Address = " + address);
logger.trace("start", "started.");
}
}
/**
* <p>Deactivates the connector server, that is, stops listening for
* client connections. Calling this method will also close all
* client connections that were made by this server. After this
* method returns, whether normally or with an exception, the
* connector server will not create any new client
* connections.</p>
*
* <p>Once a connector server has been stopped, it cannot be started
* again.</p>
*
* <p>Calling this method when the connector server has already
* been stopped has no effect. Calling this method when the
* connector server has not yet been started will disable the
* connector server object permanently.</p>
*
* <p>If closing a client connection produces an exception, that
* exception is not thrown from this method. A {@link
* JMXConnectionNotification} is emitted from this MBean with the
* connection ID of the connection that could not be closed.</p>
*
* <p>Closing a connector server is a potentially slow operation.
* For example, if a client machine with an open connection has
* crashed, the close operation might have to wait for a network
* protocol timeout. Callers that do not want to block in a close
* operation should do it in a separate thread.</p>
*
* <p>This method calls the method {@link RMIServerImpl#close()
* close} on the connector server's <code>RMIServerImpl</code>
* object.</p>
*
* <p>If the <code>RMIServerImpl</code> was bound to a JNDI
* directory by the {@link #start() start} method, it is unbound
* from the directory by this method.</p>
*
* @exception IOException if the server cannot be closed cleanly,
* or if the <code>RMIServerImpl</code> cannot be unbound from the
* directory. When this exception is thrown, the server has
* already attempted to close all client connections, if
* appropriate; to call {@link RMIServerImpl#close()}; and to
* unbind the <code>RMIServerImpl</code> from its directory, if
* appropriate. All client connections are closed except possibly
* those that generated exceptions when the server attempted to
* close them.
*/
public void stop() throws IOException {
final boolean tracing = logger.traceOn();
synchronized (this) {
if (state == STOPPED) {
if (tracing) logger.trace("stop","already stopped.");
return;
} else if (state == CREATED) {
if (tracing) logger.trace("stop","not started yet.");
}
if (tracing) logger.trace("stop", "stopping.");
state = STOPPED;
}
synchronized(openedServers) {
openedServers.remove(this);
}
IOException exception = null;
// rmiServerImpl can be null if stop() called without start()
if (rmiServerImpl != null) {
try {
if (tracing) logger.trace("stop", "closing RMI server.");
rmiServerImpl.close();
} catch (IOException e) {
if (tracing) logger.trace("stop", "failed to close RMI server: " + e);
if (logger.debugOn()) logger.debug("stop",e);
exception = e;
}
}
if (boundJndiUrl != null) {
try {
if (tracing)
logger.trace("stop",
"unbind from external directory: " + boundJndiUrl);
final Hashtable<?, ?> usemap = EnvHelp.mapToHashtable(attributes);
InitialContext ctx =
new InitialContext(usemap);
ctx.unbind(boundJndiUrl);
ctx.close();
} catch (NamingException e) {
if (tracing) logger.trace("stop", "failed to unbind RMI server: "+e);
if (logger.debugOn()) logger.debug("stop",e);
// fit e in as the nested exception if we are on 1.4
if (exception == null)
exception = newIOException("Cannot bind to URL: " + e, e);
}
}
if (exception != null) throw exception;
if (tracing) logger.trace("stop", "stopped");
}
public synchronized boolean isActive() {
return (state == STARTED);
}
public JMXServiceURL getAddress() {
if (!isActive())
return null;
return address;
}
public Map<String,?> getAttributes() {
Map<String, ?> map = EnvHelp.filterAttributes(attributes);
return Collections.unmodifiableMap(map);
}
@Override
public synchronized
void setMBeanServerForwarder(MBeanServerForwarder mbsf) {
super.setMBeanServerForwarder(mbsf);
if (rmiServerImpl != null)
rmiServerImpl.setMBeanServer(getMBeanServer());
}
/* We repeat the definitions of connection{Opened,Closed,Failed}
here so that they are accessible to other classes in this package
even though they have protected access. */
@Override
protected void connectionOpened(String connectionId, String message,
Object userData) {
super.connectionOpened(connectionId, message, userData);
}
@Override
protected void connectionClosed(String connectionId, String message,
Object userData) {
super.connectionClosed(connectionId, message, userData);
}
@Override
protected void connectionFailed(String connectionId, String message,
Object userData) {
super.connectionFailed(connectionId, message, userData);
}
/**
* Bind a stub to a registry.
* @param jndiUrl URL of the stub in the registry, extracted
* from the <code>JMXServiceURL</code>.
* @param attributes A Hashtable containing environment parameters,
* built from the Map specified at this object creation.
* @param rmiServer The object to bind in the registry
* @param rebind true if the object must be rebound.
**/
void bind(String jndiUrl, Hashtable<?, ?> attributes,
RMIServer rmiServer, boolean rebind)
throws NamingException, MalformedURLException {
// if jndiURL is not null, we nust bind the stub to a
// directory.
InitialContext ctx =
new InitialContext(attributes);
if (rebind)
ctx.rebind(jndiUrl, rmiServer);
else
ctx.bind(jndiUrl, rmiServer);
ctx.close();
}
/**
* Creates a new RMIServerImpl.
**/
RMIServerImpl newServer() throws IOException {
final boolean iiop = isIiopURL(address,true);
final int port;
if (address == null)
port = 0;
else
port = address.getPort();
if (iiop)
return newIIOPServer(attributes);
else
return newJRMPServer(attributes, port);
}
/**
* Encode a stub into the JMXServiceURL.
* @param rmiServer The stub object to encode in the URL
* @param attributes A Map containing environment parameters,
* built from the Map specified at this object creation.
**/
private void encodeStubInAddress(
RMIServer rmiServer, Map<String, ?> attributes)
throws IOException {
final String protocol, host;
final int port;
if (address == null) {
if (IIOPHelper.isStub(rmiServer))
protocol = "iiop";
else
protocol = "rmi";
host = null; // will default to local host name
port = 0;
} else {
protocol = address.getProtocol();
host = (address.getHost().equals("")) ? null : address.getHost();
port = address.getPort();
}
final String urlPath = encodeStub(rmiServer, attributes);
address = new JMXServiceURL(protocol, host, port, urlPath);
}
static boolean isIiopURL(JMXServiceURL directoryURL, boolean strict)
throws MalformedURLException {
String protocol = directoryURL.getProtocol();
if (protocol.equals("rmi"))
return false;
else if (protocol.equals("iiop"))
return true;
else if (strict) {
throw new MalformedURLException("URL must have protocol " +
"\"rmi\" or \"iiop\": \"" +
protocol + "\"");
}
return false;
}
/**
* Returns the IOR of the given rmiServer.
**/
static String encodeStub(
RMIServer rmiServer, Map<String, ?> env) throws IOException {
if (IIOPHelper.isStub(rmiServer))
return "/ior/" + encodeIIOPStub(rmiServer, env);
else
return "/stub/" + encodeJRMPStub(rmiServer, env);
}
static String encodeJRMPStub(
RMIServer rmiServer, Map<String, ?> env)
throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oout = new ObjectOutputStream(bout);
oout.writeObject(rmiServer);
oout.close();
byte[] bytes = bout.toByteArray();
return byteArrayToBase64(bytes);
}
static String encodeIIOPStub(
RMIServer rmiServer, Map<String, ?> env)
throws IOException {
try {
Object orb = IIOPHelper.getOrb(rmiServer);
return IIOPHelper.objectToString(orb, rmiServer);
} catch (RuntimeException x) {
throw newIOException(x.getMessage(), x);
}
}
/**
* Object that we will bind to the registry.
* This object is a stub connected to our RMIServerImpl.
**/
private static RMIServer objectToBind(
RMIServerImpl rmiServer, Map<String, ?> env)
throws IOException {
return RMIConnector.
connectStub((RMIServer)rmiServer.toStub(),env);
}
private static RMIServerImpl newJRMPServer(Map<String, ?> env, int port)
throws IOException {
RMIClientSocketFactory csf = (RMIClientSocketFactory)
env.get(RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE);
RMIServerSocketFactory ssf = (RMIServerSocketFactory)
env.get(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE);
return new RMIJRMPServerImpl(port, csf, ssf, env);
}
private static RMIServerImpl newIIOPServer(Map<String, ?> env)
throws IOException {
return new RMIIIOPServerImpl(env);
}
private static String byteArrayToBase64(byte[] a) {
int aLen = a.length;
int numFullGroups = aLen/3;
int numBytesInPartialGroup = aLen - 3*numFullGroups;
int resultLen = 4*((aLen + 2)/3);
final StringBuilder result = new StringBuilder(resultLen);
// Translate all full groups from byte array elements to Base64
int inCursor = 0;
for (int i=0; i<numFullGroups; i++) {
int byte0 = a[inCursor++] & 0xff;
int byte1 = a[inCursor++] & 0xff;
int byte2 = a[inCursor++] & 0xff;
result.append(intToAlpha[byte0 >> 2]);
result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
result.append(intToAlpha[byte2 & 0x3f]);
}
// Translate partial group if present
if (numBytesInPartialGroup != 0) {
int byte0 = a[inCursor++] & 0xff;
result.append(intToAlpha[byte0 >> 2]);
if (numBytesInPartialGroup == 1) {
result.append(intToAlpha[(byte0 << 4) & 0x3f]);
result.append("==");
} else {
// assert numBytesInPartialGroup == 2;
int byte1 = a[inCursor++] & 0xff;
result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
result.append(intToAlpha[(byte1 << 2)&0x3f]);
result.append('=');
}
}
// assert inCursor == a.length;
// assert result.length() == resultLen;
return result.toString();
}
/**
* This array is a lookup table that translates 6-bit positive integer
* index values into their "Base64 Alphabet" equivalents as specified
* in Table 1 of RFC 2045.
*/
private static final char intToAlpha[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
/**
* Construct a new IOException with a nested exception.
* The nested exception is set only if JDK {@literal >= 1.4}
*/
private static IOException newIOException(String message,
Throwable cause) {
final IOException x = new IOException(message);
return EnvHelp.initCause(x,cause);
}
// Private variables
// -----------------
private static ClassLogger logger =
new ClassLogger("javax.management.remote.rmi", "RMIConnectorServer");
private JMXServiceURL address;
private RMIServerImpl rmiServerImpl;
private final Map<String, ?> attributes;
private ClassLoader defaultClassLoader = null;
private String boundJndiUrl;
// state
private static final int CREATED = 0;
private static final int STARTED = 1;
private static final int STOPPED = 2;
private int state = CREATED;
private final static Set<RMIConnectorServer> openedServers =
new HashSet<RMIConnectorServer>();
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright (c) 2003, 2007, 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 javax.management.remote.rmi;
import java.io.IOException;
import java.rmi.Remote;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Map;
import java.util.Collections;
import javax.security.auth.Subject;
import com.sun.jmx.remote.internal.IIOPHelper;
/**
* <p>An {@link RMIServerImpl} that is exported through IIOP and that
* creates client connections as RMI objects exported through IIOP.
* User code does not usually reference this class directly.</p>
*
* @see RMIServerImpl
*
* @since 1.5
*/
public class RMIIIOPServerImpl extends RMIServerImpl {
/**
* <p>Creates a new {@link RMIServerImpl}.</p>
*
* @param env the environment containing attributes for the new
* <code>RMIServerImpl</code>. Can be null, which is equivalent
* to an empty Map.
*
* @exception IOException if the RMI object cannot be created.
*/
public RMIIIOPServerImpl(Map<String,?> env)
throws IOException {
super(env);
this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;
callerACC = AccessController.getContext();
}
protected void export() throws IOException {
IIOPHelper.exportObject(this);
}
protected String getProtocol() {
return "iiop";
}
/**
* <p>Returns an IIOP stub.</p>
* The stub might not yet be connected to the ORB. The stub will
* be serializable only if it is connected to the ORB.
* @return an IIOP stub.
* @exception IOException if the stub cannot be created - e.g the
* RMIIIOPServerImpl has not been exported yet.
**/
public Remote toStub() throws IOException {
// javax.rmi.CORBA.Stub stub =
// (javax.rmi.CORBA.Stub) PortableRemoteObject.toStub(this);
final Remote stub = IIOPHelper.toStub(this);
// java.lang.System.out.println("NON CONNECTED STUB " + stub);
// org.omg.CORBA.ORB orb =
// org.omg.CORBA.ORB.init((String[])null, (Properties)null);
// stub.connect(orb);
// java.lang.System.out.println("CONNECTED STUB " + stub);
return stub;
}
/**
* <p>Creates a new client connection as an RMI object exported
* through IIOP.
*
* @param connectionId the ID of the new connection. Every
* connection opened by this connector server will have a
* different ID. The behavior is unspecified if this parameter is
* null.
*
* @param subject the authenticated subject. Can be null.
*
* @return the newly-created <code>RMIConnection</code>.
*
* @exception IOException if the new client object cannot be
* created or exported.
*/
protected RMIConnection makeClient(String connectionId, Subject subject)
throws IOException {
if (connectionId == null)
throw new NullPointerException("Null connectionId");
RMIConnection client =
new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
subject, env);
IIOPHelper.exportObject(client);
return client;
}
protected void closeClient(RMIConnection client) throws IOException {
IIOPHelper.unexportObject(client);
}
/**
* <p>Called by {@link #close()} to close the connector server by
* unexporting this object. After returning from this method, the
* connector server must not accept any new connections.</p>
*
* @exception IOException if the attempt to close the connector
* server failed.
*/
protected void closeServer() throws IOException {
IIOPHelper.unexportObject(this);
}
@Override
RMIConnection doNewClient(final Object credentials) throws IOException {
if (callerACC == null) {
throw new SecurityException("AccessControlContext cannot be null");
}
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<RMIConnection>() {
public RMIConnection run() throws IOException {
return superDoNewClient(credentials);
}
}, callerACC);
} catch (PrivilegedActionException pae) {
throw (IOException) pae.getCause();
}
}
RMIConnection superDoNewClient(Object credentials) throws IOException {
return super.doNewClient(credentials);
}
private final Map<String, ?> env;
private final AccessControlContext callerACC;
}

View File

@@ -0,0 +1,278 @@
/*
* Copyright (c) 2002, 2016, 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 javax.management.remote.rmi;
import java.io.IOException;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.RemoteObject;
import java.util.Map;
import java.util.Collections;
import javax.security.auth.Subject;
import com.sun.jmx.remote.internal.RMIExporter;
import com.sun.jmx.remote.util.EnvHelp;
import java.io.ObjectStreamClass;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import sun.reflect.misc.ReflectUtil;
import sun.rmi.server.DeserializationChecker;
import sun.rmi.server.UnicastServerRef;
import sun.rmi.server.UnicastServerRef2;
/**
* <p>An {@link RMIServer} object that is exported through JRMP and that
* creates client connections as RMI objects exported through JRMP.
* User code does not usually reference this class directly.</p>
*
* @see RMIServerImpl
*
* @since 1.5
*/
public class RMIJRMPServerImpl extends RMIServerImpl {
private final ExportedWrapper exportedWrapper;
/**
* <p>Creates a new {@link RMIServer} object that will be exported
* on the given port using the given socket factories.</p>
*
* @param port the port on which this object and the {@link
* RMIConnectionImpl} objects it creates will be exported. Can be
* zero, to indicate any available port.
*
* @param csf the client socket factory for the created RMI
* objects. Can be null.
*
* @param ssf the server socket factory for the created RMI
* objects. Can be null.
*
* @param env the environment map. Can be null.
*
* @exception IOException if the {@link RMIServer} object
* cannot be created.
*
* @exception IllegalArgumentException if <code>port</code> is
* negative.
*/
public RMIJRMPServerImpl(int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf,
Map<String,?> env)
throws IOException {
super(env);
if (port < 0)
throw new IllegalArgumentException("Negative port: " + port);
this.port = port;
this.csf = csf;
this.ssf = ssf;
this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;
String[] credentialsTypes
= (String[]) this.env.get(EnvHelp.CREDENTIAL_TYPES);
List<String> types = null;
if (credentialsTypes != null) {
types = new ArrayList<>();
for (String type : credentialsTypes) {
if (type == null) {
throw new IllegalArgumentException("A credential type is null.");
}
ReflectUtil.checkPackageAccess(type);
types.add(type);
}
}
exportedWrapper = types != null ?
new ExportedWrapper(this, types) :
null;
}
protected void export() throws IOException {
if (exportedWrapper != null) {
export(exportedWrapper);
} else {
export(this);
}
}
private void export(Remote obj) throws RemoteException {
final RMIExporter exporter =
(RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
final boolean daemon = EnvHelp.isServerDaemon(env);
if (daemon && exporter != null) {
throw new IllegalArgumentException("If "+EnvHelp.JMX_SERVER_DAEMON+
" is specified as true, "+RMIExporter.EXPORTER_ATTRIBUTE+
" cannot be used to specify an exporter!");
}
if (daemon) {
if (csf == null && ssf == null) {
new UnicastServerRef(port).exportObject(obj, null, true);
} else {
new UnicastServerRef2(port, csf, ssf).exportObject(obj, null, true);
}
} else if (exporter != null) {
exporter.exportObject(obj, port, csf, ssf);
} else {
UnicastRemoteObject.exportObject(obj, port, csf, ssf);
}
}
private void unexport(Remote obj, boolean force)
throws NoSuchObjectException {
RMIExporter exporter =
(RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
if (exporter == null)
UnicastRemoteObject.unexportObject(obj, force);
else
exporter.unexportObject(obj, force);
}
protected String getProtocol() {
return "rmi";
}
/**
* <p>Returns a serializable stub for this {@link RMIServer} object.</p>
*
* @return a serializable stub.
*
* @exception IOException if the stub cannot be obtained - e.g the
* RMIJRMPServerImpl has not been exported yet.
*/
public Remote toStub() throws IOException {
if (exportedWrapper != null) {
return RemoteObject.toStub(exportedWrapper);
} else {
return RemoteObject.toStub(this);
}
}
/**
* <p>Creates a new client connection as an RMI object exported
* through JRMP. The port and socket factories for the new
* {@link RMIConnection} object are the ones supplied
* to the <code>RMIJRMPServerImpl</code> constructor.</p>
*
* @param connectionId the ID of the new connection. Every
* connection opened by this connector server will have a
* different id. The behavior is unspecified if this parameter is
* null.
*
* @param subject the authenticated subject. Can be null.
*
* @return the newly-created <code>RMIConnection</code>.
*
* @exception IOException if the new {@link RMIConnection}
* object cannot be created or exported.
*/
protected RMIConnection makeClient(String connectionId, Subject subject)
throws IOException {
if (connectionId == null)
throw new NullPointerException("Null connectionId");
RMIConnection client =
new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
subject, env);
export(client);
return client;
}
protected void closeClient(RMIConnection client) throws IOException {
unexport(client, true);
}
/**
* <p>Called by {@link #close()} to close the connector server by
* unexporting this object. After returning from this method, the
* connector server must not accept any new connections.</p>
*
* @exception IOException if the attempt to close the connector
* server failed.
*/
protected void closeServer() throws IOException {
if (exportedWrapper != null) {
unexport(exportedWrapper, true);
} else {
unexport(this, true);
}
}
private final int port;
private final RMIClientSocketFactory csf;
private final RMIServerSocketFactory ssf;
private final Map<String, ?> env;
private static class ExportedWrapper implements RMIServer, DeserializationChecker {
private final RMIServer impl;
private final List<String> allowedTypes;
private ExportedWrapper(RMIServer impl, List<String> credentialsTypes) {
this.impl = impl;
allowedTypes = credentialsTypes;
}
@Override
public String getVersion() throws RemoteException {
return impl.getVersion();
}
@Override
public RMIConnection newClient(Object credentials) throws IOException {
return impl.newClient(credentials);
}
@Override
public void check(Method method, ObjectStreamClass descriptor,
int paramIndex, int callID) {
String type = descriptor.getName();
if (!allowedTypes.contains(type)) {
throw new ClassCastException("Unsupported type: " + type);
}
}
@Override
public void checkProxyClass(Method method, String[] ifaces,
int paramIndex, int callID) {
if (ifaces != null && ifaces.length > 0) {
for (String iface : ifaces) {
if (!allowedTypes.contains(iface)) {
throw new ClassCastException("Unsupported type: " + iface);
}
}
}
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2002, 2007, 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 javax.management.remote.rmi;
import java.io.IOException;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* <p>RMI object used to establish connections to an RMI connector.
* There is one Remote object implementing this interface for each RMI
* connector.</p>
*
* <p>User code does not usually refer to this interface. It is
* specified as part of the public API so that different
* implementations of that API will interoperate.</p>
*
* @since 1.5
*/
public interface RMIServer extends Remote {
/**
* <p>The version of the RMI Connector Protocol understood by this
* connector server. This is a string with the following format:</p>
*
* <pre>
* <em>protocol-version</em> <em>implementation-name</em>
* </pre>
*
* <p>The <code><em>protocol-version</em></code> is a series of
* two or more non-negative integers separated by periods
* (<code>.</code>). An implementation of the version described
* by this documentation must use the string <code>1.0</code>
* here.</p>
*
* <p>After the protocol version there must be a space, followed
* by the implementation name. The format of the implementation
* name is unspecified. It is recommended that it include an
* implementation version number. An implementation can use an
* empty string as its implementation name, for example for
* security reasons.</p>
*
* @return a string with the format described here.
*
* @exception RemoteException if there is a communication
* exception during the remote method call.
*/
public String getVersion() throws RemoteException;
/**
* <p>Makes a new connection through this RMI connector. Each
* remote client calls this method to obtain a new RMI object
* representing its connection.</p>
*
* @param credentials this object specifies the user-defined credentials
* to be passed in to the server in order to authenticate the user before
* creating the <code>RMIConnection</code>. Can be null.
*
* @return the newly-created connection object.
*
* @exception IOException if the new client object cannot be
* created or exported, or if there is a communication exception
* during the remote method call.
*
* @exception SecurityException if the given credentials do not
* allow the server to authenticate the caller successfully.
*/
public RMIConnection newClient(Object credentials) throws IOException;
}

View File

@@ -0,0 +1,551 @@
/*
* 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
* 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 javax.management.remote.rmi;
import com.sun.jmx.remote.internal.ArrayNotificationBuffer;
import com.sun.jmx.remote.internal.NotificationBuffer;
import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
import com.sun.jmx.remote.util.ClassLogger;
import java.io.Closeable;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.rmi.Remote;
import java.rmi.server.RemoteServer;
import java.rmi.server.ServerNotActiveException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.management.MBeanServer;
import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXConnectorServer;
import javax.security.auth.Subject;
/**
* <p>An RMI object representing a connector server. Remote clients
* can make connections using the {@link #newClient(Object)} method. This
* method returns an RMI object representing the connection.</p>
*
* <p>User code does not usually reference this class directly.
* RMI connection servers are usually created with the class {@link
* RMIConnectorServer}. Remote clients usually create connections
* either with {@link javax.management.remote.JMXConnectorFactory}
* or by instantiating {@link RMIConnector}.</p>
*
* <p>This is an abstract class. Concrete subclasses define the
* details of the client connection objects, such as whether they use
* JRMP or IIOP.</p>
*
* @since 1.5
*/
public abstract class RMIServerImpl implements Closeable, RMIServer {
/**
* <p>Constructs a new <code>RMIServerImpl</code>.</p>
*
* @param env the environment containing attributes for the new
* <code>RMIServerImpl</code>. Can be null, which is equivalent
* to an empty Map.
*/
public RMIServerImpl(Map<String,?> env) {
this.env = (env == null) ? Collections.<String,Object>emptyMap() : env;
}
void setRMIConnectorServer(RMIConnectorServer connServer)
throws IOException {
this.connServer = connServer;
}
/**
* <p>Exports this RMI object.</p>
*
* @exception IOException if this RMI object cannot be exported.
*/
protected abstract void export() throws IOException;
/**
* Returns a remotable stub for this server object.
* @return a remotable stub.
* @exception IOException if the stub cannot be obtained - e.g the
* RMIServerImpl has not been exported yet.
**/
public abstract Remote toStub() throws IOException;
/**
* <p>Sets the default <code>ClassLoader</code> for this connector
* server. New client connections will use this classloader.
* Existing client connections are unaffected.</p>
*
* @param cl the new <code>ClassLoader</code> to be used by this
* connector server.
*
* @see #getDefaultClassLoader
*/
public synchronized void setDefaultClassLoader(ClassLoader cl) {
this.cl = cl;
}
/**
* <p>Gets the default <code>ClassLoader</code> used by this connector
* server.</p>
*
* @return the default <code>ClassLoader</code> used by this
* connector server.
*
* @see #setDefaultClassLoader
*/
public synchronized ClassLoader getDefaultClassLoader() {
return cl;
}
/**
* <p>Sets the <code>MBeanServer</code> to which this connector
* server is attached. New client connections will interact
* with this <code>MBeanServer</code>. Existing client connections are
* unaffected.</p>
*
* @param mbs the new <code>MBeanServer</code>. Can be null, but
* new client connections will be refused as long as it is.
*
* @see #getMBeanServer
*/
public synchronized void setMBeanServer(MBeanServer mbs) {
this.mbeanServer = mbs;
}
/**
* <p>The <code>MBeanServer</code> to which this connector server
* is attached. This is the last value passed to {@link
* #setMBeanServer} on this object, or null if that method has
* never been called.</p>
*
* @return the <code>MBeanServer</code> to which this connector
* is attached.
*
* @see #setMBeanServer
*/
public synchronized MBeanServer getMBeanServer() {
return mbeanServer;
}
public String getVersion() {
// Expected format is: "protocol-version implementation-name"
try {
return "1.0 java_runtime_" +
System.getProperty("java.runtime.version");
} catch (SecurityException e) {
return "1.0 ";
}
}
/**
* <p>Creates a new client connection. This method calls {@link
* #makeClient makeClient} and adds the returned client connection
* object to an internal list. When this
* <code>RMIServerImpl</code> is shut down via its {@link
* #close()} method, the {@link RMIConnection#close() close()}
* method of each object remaining in the list is called.</p>
*
* <p>The fact that a client connection object is in this internal
* list does not prevent it from being garbage collected.</p>
*
* @param credentials this object specifies the user-defined
* credentials to be passed in to the server in order to
* authenticate the caller before creating the
* <code>RMIConnection</code>. Can be null.
*
* @return the newly-created <code>RMIConnection</code>. This is
* usually the object created by <code>makeClient</code>, though
* an implementation may choose to wrap that object in another
* object implementing <code>RMIConnection</code>.
*
* @exception IOException if the new client object cannot be
* created or exported.
*
* @exception SecurityException if the given credentials do not allow
* the server to authenticate the user successfully.
*
* @exception IllegalStateException if {@link #getMBeanServer()}
* is null.
*/
public RMIConnection newClient(Object credentials) throws IOException {
return doNewClient(credentials);
}
/**
* This method could be overridden by subclasses defined in this package
* to perform additional operations specific to the underlying transport
* before creating the new client connection.
*/
RMIConnection doNewClient(Object credentials) throws IOException {
final boolean tracing = logger.traceOn();
if (tracing) logger.trace("newClient","making new client");
if (getMBeanServer() == null)
throw new IllegalStateException("Not attached to an MBean server");
Subject subject = null;
JMXAuthenticator authenticator =
(JMXAuthenticator) env.get(JMXConnectorServer.AUTHENTICATOR);
if (authenticator == null) {
/*
* Create the JAAS-based authenticator only if authentication
* has been enabled
*/
if (env.get("jmx.remote.x.password.file") != null ||
env.get("jmx.remote.x.login.config") != null) {
authenticator = new JMXPluggableAuthenticator(env);
}
}
if (authenticator != null) {
if (tracing) logger.trace("newClient","got authenticator: " +
authenticator.getClass().getName());
try {
subject = authenticator.authenticate(credentials);
} catch (SecurityException e) {
logger.trace("newClient", "Authentication failed: " + e);
throw e;
}
}
if (tracing) {
if (subject != null)
logger.trace("newClient","subject is not null");
else logger.trace("newClient","no subject");
}
final String connectionId = makeConnectionId(getProtocol(), subject);
if (tracing)
logger.trace("newClient","making new connection: " + connectionId);
RMIConnection client = makeClient(connectionId, subject);
dropDeadReferences();
WeakReference<RMIConnection> wr = new WeakReference<RMIConnection>(client);
synchronized (clientList) {
clientList.add(wr);
}
connServer.connectionOpened(connectionId, "Connection opened", null);
synchronized (clientList) {
if (!clientList.contains(wr)) {
// can be removed only by a JMXConnectionNotification listener
throw new IOException("The connection is refused.");
}
}
if (tracing)
logger.trace("newClient","new connection done: " + connectionId );
return client;
}
/**
* <p>Creates a new client connection. This method is called by
* the public method {@link #newClient(Object)}.</p>
*
* @param connectionId the ID of the new connection. Every
* connection opened by this connector server will have a
* different ID. The behavior is unspecified if this parameter is
* null.
*
* @param subject the authenticated subject. Can be null.
*
* @return the newly-created <code>RMIConnection</code>.
*
* @exception IOException if the new client object cannot be
* created or exported.
*/
protected abstract RMIConnection makeClient(String connectionId,
Subject subject)
throws IOException;
/**
* <p>Closes a client connection made by {@link #makeClient makeClient}.
*
* @param client a connection previously returned by
* <code>makeClient</code> on which the <code>closeClient</code>
* method has not previously been called. The behavior is
* unspecified if these conditions are violated, including the
* case where <code>client</code> is null.
*
* @exception IOException if the client connection cannot be
* closed.
*/
protected abstract void closeClient(RMIConnection client)
throws IOException;
/**
* <p>Returns the protocol string for this object. The string is
* <code>rmi</code> for RMI/JRMP and <code>iiop</code> for RMI/IIOP.
*
* @return the protocol string for this object.
*/
protected abstract String getProtocol();
/**
* <p>Method called when a client connection created by {@link
* #makeClient makeClient} is closed. A subclass that defines
* <code>makeClient</code> must arrange for this method to be
* called when the resultant object's {@link RMIConnection#close()
* close} method is called. This enables it to be removed from
* the <code>RMIServerImpl</code>'s list of connections. It is
* not an error for <code>client</code> not to be in that
* list.</p>
*
* <p>After removing <code>client</code> from the list of
* connections, this method calls {@link #closeClient
* closeClient(client)}.</p>
*
* @param client the client connection that has been closed.
*
* @exception IOException if {@link #closeClient} throws this
* exception.
*
* @exception NullPointerException if <code>client</code> is null.
*/
protected void clientClosed(RMIConnection client) throws IOException {
final boolean debug = logger.debugOn();
if (debug) logger.trace("clientClosed","client="+client);
if (client == null)
throw new NullPointerException("Null client");
synchronized (clientList) {
dropDeadReferences();
for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
it.hasNext(); ) {
WeakReference<RMIConnection> wr = it.next();
if (wr.get() == client) {
it.remove();
break;
}
}
/* It is not a bug for this loop not to find the client. In
our close() method, we remove a client from the list before
calling its close() method. */
}
if (debug) logger.trace("clientClosed", "closing client.");
closeClient(client);
if (debug) logger.trace("clientClosed", "sending notif");
connServer.connectionClosed(client.getConnectionId(),
"Client connection closed", null);
if (debug) logger.trace("clientClosed","done");
}
/**
* <p>Closes this connection server. This method first calls the
* {@link #closeServer()} method so that no new client connections
* will be accepted. Then, for each remaining {@link
* RMIConnection} object returned by {@link #makeClient
* makeClient}, its {@link RMIConnection#close() close} method is
* called.</p>
*
* <p>The behavior when this method is called more than once is
* unspecified.</p>
*
* <p>If {@link #closeServer()} throws an
* <code>IOException</code>, the individual connections are
* nevertheless closed, and then the <code>IOException</code> is
* thrown from this method.</p>
*
* <p>If {@link #closeServer()} returns normally but one or more
* of the individual connections throws an
* <code>IOException</code>, then, after closing all the
* connections, one of those <code>IOException</code>s is thrown
* from this method. If more than one connection throws an
* <code>IOException</code>, it is unspecified which one is thrown
* from this method.</p>
*
* @exception IOException if {@link #closeServer()} or one of the
* {@link RMIConnection#close()} calls threw
* <code>IOException</code>.
*/
public synchronized void close() throws IOException {
final boolean tracing = logger.traceOn();
final boolean debug = logger.debugOn();
if (tracing) logger.trace("close","closing");
IOException ioException = null;
try {
if (debug) logger.debug("close","closing Server");
closeServer();
} catch (IOException e) {
if (tracing) logger.trace("close","Failed to close server: " + e);
if (debug) logger.debug("close",e);
ioException = e;
}
if (debug) logger.debug("close","closing Clients");
// Loop to close all clients
while (true) {
synchronized (clientList) {
if (debug) logger.debug("close","droping dead references");
dropDeadReferences();
if (debug) logger.debug("close","client count: "+clientList.size());
if (clientList.size() == 0)
break;
/* Loop until we find a non-null client. Because we called
dropDeadReferences(), this will usually be the first
element of the list, but a garbage collection could have
happened in between. */
for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
it.hasNext(); ) {
WeakReference<RMIConnection> wr = it.next();
RMIConnection client = wr.get();
it.remove();
if (client != null) {
try {
client.close();
} catch (IOException e) {
if (tracing)
logger.trace("close","Failed to close client: " + e);
if (debug) logger.debug("close",e);
if (ioException == null)
ioException = e;
}
break;
}
}
}
}
if(notifBuffer != null)
notifBuffer.dispose();
if (ioException != null) {
if (tracing) logger.trace("close","close failed.");
throw ioException;
}
if (tracing) logger.trace("close","closed.");
}
/**
* <p>Called by {@link #close()} to close the connector server.
* After returning from this method, the connector server must
* not accept any new connections.</p>
*
* @exception IOException if the attempt to close the connector
* server failed.
*/
protected abstract void closeServer() throws IOException;
private static synchronized String makeConnectionId(String protocol,
Subject subject) {
connectionIdNumber++;
String clientHost = "";
try {
clientHost = RemoteServer.getClientHost();
/*
* According to the rules specified in the javax.management.remote
* package description, a numeric IPv6 address (detected by the
* presence of otherwise forbidden ":" character) forming a part
* of the connection id must be enclosed in square brackets.
*/
if (clientHost.contains(":")) {
clientHost = "[" + clientHost + "]";
}
} catch (ServerNotActiveException e) {
logger.trace("makeConnectionId", "getClientHost", e);
}
final StringBuilder buf = new StringBuilder();
buf.append(protocol).append(":");
if (clientHost.length() > 0)
buf.append("//").append(clientHost);
buf.append(" ");
if (subject != null) {
Set<Principal> principals = subject.getPrincipals();
String sep = "";
for (Iterator<Principal> it = principals.iterator(); it.hasNext(); ) {
Principal p = it.next();
String name = p.getName().replace(' ', '_').replace(';', ':');
buf.append(sep).append(name);
sep = ";";
}
}
buf.append(" ").append(connectionIdNumber);
if (logger.traceOn())
logger.trace("newConnectionId","connectionId="+buf);
return buf.toString();
}
private void dropDeadReferences() {
synchronized (clientList) {
for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
it.hasNext(); ) {
WeakReference<RMIConnection> wr = it.next();
if (wr.get() == null)
it.remove();
}
}
}
synchronized NotificationBuffer getNotifBuffer() {
//Notification buffer is lazily created when the first client connects
if(notifBuffer == null)
notifBuffer =
ArrayNotificationBuffer.getNotificationBuffer(mbeanServer,
env);
return notifBuffer;
}
private static final ClassLogger logger =
new ClassLogger("javax.management.remote.rmi", "RMIServerImpl");
/** List of WeakReference values. Each one references an
RMIConnection created by this object, or null if the
RMIConnection has been garbage-collected. */
private final List<WeakReference<RMIConnection>> clientList =
new ArrayList<WeakReference<RMIConnection>>();
private ClassLoader cl;
private MBeanServer mbeanServer;
private final Map<String, ?> env;
private RMIConnectorServer connServer;
private static int connectionIdNumber;
private NotificationBuffer notifBuffer;
}

View File

@@ -0,0 +1,63 @@
// Stub class generated by rmic, do not edit.
// Contents subject to change without notice.
package javax.management.remote.rmi;
public final class RMIServerImpl_Stub
extends java.rmi.server.RemoteStub
implements javax.management.remote.rmi.RMIServer
{
private static final long serialVersionUID = 2;
private static java.lang.reflect.Method $method_getVersion_0;
private static java.lang.reflect.Method $method_newClient_1;
static {
try {
$method_getVersion_0 = javax.management.remote.rmi.RMIServer.class.getMethod("getVersion", new java.lang.Class[] {});
$method_newClient_1 = javax.management.remote.rmi.RMIServer.class.getMethod("newClient", new java.lang.Class[] {java.lang.Object.class});
} catch (java.lang.NoSuchMethodException e) {
throw new java.lang.NoSuchMethodError(
"stub class initialization failed");
}
}
// constructors
public RMIServerImpl_Stub(java.rmi.server.RemoteRef ref) {
super(ref);
}
// methods from remote interfaces
// implementation of getVersion()
public java.lang.String getVersion()
throws java.rmi.RemoteException
{
try {
Object $result = ref.invoke(this, $method_getVersion_0, null, -8081107751519807347L);
return ((java.lang.String) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.rmi.RemoteException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
// implementation of newClient(Object)
public javax.management.remote.rmi.RMIConnection newClient(java.lang.Object $param_Object_1)
throws java.io.IOException
{
try {
Object $result = ref.invoke(this, $method_newClient_1, new java.lang.Object[] {$param_Object_1}, -1089742558549201240L);
return ((javax.management.remote.rmi.RMIConnection) $result);
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.io.IOException e) {
throw e;
} catch (java.lang.Exception e) {
throw new java.rmi.UnexpectedException("undeclared checked exception", e);
}
}
}