/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
*/
package org.opensolaris.os.rad.jmx;
import java.io.IOException;
import javax.management.*;
import org.opensolaris.os.adr.*;
import org.opensolaris.os.rad.Versions;
import org.opensolaris.os.rad.Version;
public class RadJMX {
//
// Static data
//
// Descriptor fields
static final String INTERFACE_NAME = "org.opensolaris.os.rad.interfaceName";
static final String API_NAME = "org.opensolaris.os.rad.apiName";
static final String PRIVATE_VER = "org.opensolaris.os.rad.privateVersion";
static final String UNCOMMITTED_VER =
"org.opensolaris.os.rad.uncommittedVersion";
static final String COMMITTED_VER =
"org.opensolaris.os.rad.commitedVersion";
static final String STABILITY = "org.opensolaris.os.rad.stability";
// Pointer to private API data - not for general consumption
static final String API_PRIVDATA = "org.opensolaris.os.rad.apiPrivate";
//
// RadJMXProxy methods
//
/**
* Creates an MXBean proxy after checking that the client and server
* versions of the specified interface are compatible, for the given
* stability.
*
* @param connection the MBean Server in which the MBean is registered.
* @param objectName the name of the MBean to forward to.
* @param interfaceClass the MBean interface that the proxy will implement.
* @param notificationBroadcaster whether to implement the
* {@code NotificationBroadcaster} interface in the proxy.
* @param stab the required stability of the MBean interface.
*
* @return a new proxy instance.
*
* @throws IOException if there is error while communicating with the
* MBean server.
* @throws InstanceNotFoundException if there is no MBean registered for
* the given object name.
* @throws IntrospectionException if there an error while introspecting
* the management interface.
* @throws ReflectionException if there is an error while invoking methods
* on the MBean using reflection.
* @throws IncompatibleVersionException if the client and server versions
* of the MBean interface are incompatible, for the specified stability.
*/
public static <T> T newMXBeanProxy(MBeanServerConnection connection,
ObjectName objectName, Class<T> interfaceClass,
boolean notificationBroadcaster, Stability stab) throws IOException,
InstanceNotFoundException, IntrospectionException, ReflectionException,
IncompatibleVersionException {
MBeanInfo mbInfo = connection.getMBeanInfo(objectName);
Versions versions = interfaceClass.getAnnotation(
org.opensolaris.os.rad.Versions.class);
Descriptor descriptor = mbInfo.getDescriptor();
assertCompatible(interfaceClass, stab, versions, descriptor);
return JMX.newMXBeanProxy(connection, objectName,
interfaceClass, notificationBroadcaster);
}
public static <T> T newMXBeanProxy(MBeanServerConnection connection,
ObjectName objectName, Class<T> interfaceClass, Stability stab)
throws IOException, InstanceNotFoundException, IntrospectionException,
ReflectionException, IncompatibleVersionException {
return newMXBeanProxy(connection, objectName, interfaceClass,
false, stab);
}
private static APIVersion getClientVersion(Stability s, Versions versInfo) {
if (versInfo != null) {
for (Version version : versInfo.versions()) {
if (version.stability() == s) {
return new APIVersion(version.stability(), version.major(),
version.minor());
}
}
}
return APIVersion.getNone(s);
}
private static void assertCompatible(Class<?> interfaceClass,
Stability stab, Versions vers, Descriptor desc)
throws IncompatibleVersionException {
APIVersion vc = getClientVersion(stab, vers);
APIVersion vs = APIVersion.getNone(stab);
if (vers != null && desc != null && vers.interfaceName() != null &&
vers.interfaceName().equals(desc.getFieldValue(INTERFACE_NAME))) {
String aname = vers.apiName();
API api = (API) desc.getFieldValue(API_PRIVDATA);
if (aname != null && api != null) {
if (aname.equals(desc.getFieldValue(API_NAME))) {
vs = api.getVersionByStability(stab);
} else {
for (API parent : api.getParents()) {
if (aname.equals(parent.getName())) {
vs = parent.getVersionByStability(stab);
break;
}
}
}
}
}
if (vs.getMajor() != vc.getMajor() || vs.getMinor() < vc.getMinor())
throw new IncompatibleVersionException(interfaceClass, vc, vs);
}
}