jmx introspector is a small bundle that creates dynamic proxies for remote mbeans. See README.txt for details
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@441807 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/jmxintrospector/README.txt b/jmxintrospector/README.txt
new file mode 100644
index 0000000..979b5b3
--- /dev/null
+++ b/jmxintrospector/README.txt
@@ -0,0 +1,27 @@
+JMX introspector is a small library bundle that
+uses the Javassist library, the reflection API and
+the metadata provided by JMX on the managed objects
+to dynamically proxy remote MBeans, without having
+the classes in your classpath.
+It can be used to create management consoles that do not
+need to have the remote mbeans classes in its classpath to
+use dynamic proxies.
+
+It is used by the org.apache.felix.mishell project to create management clients
+for felix jmood, but it can be used to manage any JMX agent.
+
+It currently uses Javassist version 3.3 for the generation
+of the interface classes, which is part of JBoss and
+can be downloaded from http://www.jboss.org
+or directly from https://sourceforge.net/project/showfiles.php?group_id=22866&package_id=80766
+Javassist is licensed under the Mozilla Public License and the LGPL.
+IMPORTANT:
+You need to install Javassist manually to your local maven repository
+in order to build this bundle, as it is not available at the repositories yet:
+
+mvn install:install-file -Dfile=<path-to-file> -DgroupId=javassist \
+ -DartifactId=javassist -Dversion=3.3 -Dpackaging=jar
+
+//TODO
+
+
diff --git a/jmxintrospector/pom.xml b/jmxintrospector/pom.xml
new file mode 100644
index 0000000..4da175a
--- /dev/null
+++ b/jmxintrospector/pom.xml
@@ -0,0 +1,62 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>felix</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <name>JMXIntrospector</name>
+ <packaging>osgi-bundle</packaging>
+ <artifactId>${groupId}.jmxintrospector</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>3.3</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix.plugins</groupId>
+ <artifactId>maven-osgi-plugin</artifactId>
+ <version>${pom.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <inlinedArtifacts>
+ <inlinedArtifact>javassist</inlinedArtifact>
+ </inlinedArtifacts>
+ <osgiManifest>
+ <bundleName>${name}</bundleName>
+ <bundleSymbolicName>${artifactId}</bundleSymbolicName>
+ <exportPackage>
+ org.apache.felix.jmxintrospector
+ </exportPackage>
+ </osgiManifest>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source><!--should fail if not java6-->
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/MBean.java b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/MBean.java
new file mode 100644
index 0000000..f983408
--- /dev/null
+++ b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/MBean.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.jmxintrospector;
+
+import javax.management.MBeanInfo;
+import javax.management.MBeanServerConnection;
+
+/**
+ * Proxies returned implement this interface, to ease handling of mbeans (filtering and so on)
+ *
+ */
+public interface MBean {
+ public String getObjectName();
+ public MBeanServerConnection getMBeanServer();
+ public MBeanInfo getMBeanInfo();
+}
diff --git a/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/MBeanProxyFactory.java b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/MBeanProxyFactory.java
new file mode 100644
index 0000000..753e6e9
--- /dev/null
+++ b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/MBeanProxyFactory.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.jmxintrospector;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.List;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.NotificationEmitter;
+import javax.management.ObjectName;
+
+import org.apache.felix.jmxintrospector.classbean.TypeGetterMBean;
+
+public class MBeanProxyFactory {
+ private MBeanServerConnection mbeanServer;
+
+ public MBeanProxyFactory(){
+ }
+
+ public MBeanProxyFactory(MBeanServerConnection mbeanServer) {
+ super();
+ this.mbeanServer = mbeanServer;
+
+ }
+
+ private Class getInterface(String oname)throws Exception{
+ ObjectName objectName=ObjectName.getInstance(oname);
+
+ String ifaceName=mbeanServer.getObjectInstance(objectName).getClassName().replace('.', '_');
+ CtClass ctIface=null;
+ try{
+ ctIface=javassist.ClassPool.getDefault().get(ifaceName);
+ return this.getClass().getClassLoader().loadClass(ifaceName);
+ }catch (Exception e) {
+ ctIface=javassist.ClassPool.getDefault().makeInterface(ifaceName);
+ for (CtMethod m : addMethods(ctIface, objectName)) {
+ ctIface.addMethod(m);
+ }
+ try {
+ return ctIface.toClass(this.getClass().getClassLoader(), this.getClass().getProtectionDomain());
+ } catch (CannotCompileException cce) {
+ System.out.println(cce.getCause());
+ throw cce;
+ }
+ }
+
+ }
+ private List<CtMethod> addMethods(CtClass ctIface, ObjectName objectName)throws Exception{
+ ClassPool pool=javassist.ClassPool.getDefault();
+ List<CtMethod> methods=new ArrayList<CtMethod>();
+ MBeanInfo minfo =mbeanServer.getMBeanInfo(objectName);
+ CtMethod m=null;
+
+ for (MBeanAttributeInfo info : minfo.getAttributes()) {
+ String name=info.getName().substring(0, 1).toUpperCase()+info.getName().substring(1);
+ if(info.isReadable()){
+ if(info.isIs()){
+ m=new CtMethod(CtClass.booleanType, "is"+ name,null, ctIface);
+ methods.add(m);
+ }
+ else{
+// try {
+ m=new CtMethod(pool.get(info.getType()), "get"+ name,null, ctIface);
+// }catch (NotFoundException nfe) {
+// String n=nfe.getMessage();
+// String notFoundName=n.startsWith("[")?n.substring(1, n.length()):n;
+// Class notFound=(Class)mbeanServer.invoke(ObjectName.getInstance(TypeGetterMBean.MBEAN_NAME), "getType", new Object[] {notFoundName}, new String[] {String.class.getName()});
+//
+// m=new CtMethod(pool.get(info.getType()), "get"+ name,null, ctIface);
+// }
+ methods.add(m);
+ }
+
+ }
+
+ if(info.isWritable()){
+ m=new CtMethod(CtClass.voidType, "set"+ name,new CtClass[]{pool.get(info.getType())} , ctIface);
+ methods.add(m);
+ }
+ }
+ for (MBeanOperationInfo info : minfo.getOperations()) {
+ CtClass[] params=new CtClass[info.getSignature().length];
+ for (int i = 0; i < params.length; i++) {
+ params[i]=pool.get(info.getSignature()[i].getType());
+ }
+ m=new CtMethod(pool.get(info.getReturnType()), info.getName(),params, ctIface);
+ methods.add(m);
+
+ }
+ return methods;
+ }
+ /**
+ * Returns a proxy object for the MBean specified by the object name oname in the
+ * mbean server associated with this factory. This proxy object implements
+ * @param oname
+ * @return
+ * @throws Exception
+ */
+ public Object newProxyInstance(String oname)throws Exception{
+ ObjectName objectName=ObjectName.getInstance(oname);
+ Class iface=getInterface(oname);
+ MBeanInfo info=mbeanServer.getMBeanInfo(objectName);
+ boolean isBroadcaster=false;
+ MBeanNotificationInfo[] notifs=info.getNotifications();
+ if (notifs!=null && notifs.length!=0) isBroadcaster=true;
+ Object proxy=MBeanServerInvocationHandler.newProxyInstance(mbeanServer, objectName, iface, isBroadcaster);
+ InvocationHandler h=Proxy.getInvocationHandler(proxy);
+ InvocationHandler wrapper=new JMXInvocationHandler(oname,mbeanServer, mbeanServer.getMBeanInfo(objectName), h);
+ Class[] ifaces;
+ if (isBroadcaster) {
+ ifaces=new Class[]{iface, NotificationEmitter.class, MBean.class};
+ }else ifaces=new Class[]{iface, MBean.class};
+ Object mbeanProxy=Proxy.newProxyInstance(proxy.getClass().getClassLoader(), ifaces, wrapper);
+ return mbeanProxy;
+ }
+ private class JMXInvocationHandler implements InvocationHandler, MBean{
+ private String objectName;
+ private MBeanServerConnection mBeanServer;
+ private InvocationHandler mbeanHandler;
+ private MBeanInfo mbeanInfo;
+
+ public JMXInvocationHandler(String objectName, MBeanServerConnection mbeanServer, MBeanInfo mBeanInfo, InvocationHandler mbeanHandler) {
+ super();
+ this.objectName = objectName;
+ this.mBeanServer = mbeanServer;
+ this.mbeanHandler = mbeanHandler;
+ this.mbeanInfo =mBeanInfo;
+
+ }
+
+ //FIXME: hashCode() and equals do not work if not exposed in management interface
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if(method.getDeclaringClass().equals(MBean.class)){
+ return this.getClass().getMethod(method.getName(), null).invoke(this, args);
+ }
+ else return mbeanHandler.invoke(proxy, method, args);
+ }
+
+ public MBeanServerConnection getMBeanServer() {
+ return mBeanServer;
+ }
+
+ public String getObjectName() {
+ return objectName;
+ }
+
+ public MBeanInfo getMBeanInfo() {
+ return mbeanInfo;
+ }
+
+
+
+ }
+
+ public MBeanServerConnection getMbeanServer() {
+ return mbeanServer;
+ }
+
+ public void setMbeanServer(MBeanServerConnection mbs) {
+ this.mbeanServer = mbs;
+ }
+
+}
diff --git a/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/MBeanProxyManager.java b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/MBeanProxyManager.java
new file mode 100644
index 0000000..1d935f3
--- /dev/null
+++ b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/MBeanProxyManager.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.jmxintrospector;
+
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+public class MBeanProxyManager {
+ //FIXME: mixing up Server and MBeanServerConnections is dirty and error-prone
+ private List<Server> servers = new ArrayList<Server>();
+
+ private List<Object> objects = new ArrayList<Object>();
+
+ private Logger logger = Logger.getLogger(this.getClass().getName());
+
+ public void addRMIServer(String host, String path) throws Exception {
+ addRMIServer(host, path, 1099);
+ }
+
+ public void addRMIServer(String host, String path, int port)
+ throws Exception {
+ addRemoteServer("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + path);
+ }
+
+ public void addRemoteServer(String url) throws Exception {
+ JMXServiceURL u = new JMXServiceURL(url);
+ MBeanServerConnection s = JMXConnectorFactory.connect(u)
+ .getMBeanServerConnection();
+ add(url, s);
+ }
+
+ public void addLocalServer() throws Exception {
+ MBeanServerConnection s=ManagementFactory.getPlatformMBeanServer();
+ add(s.getDefaultDomain(), s);
+ }
+
+ private void add(String id, MBeanServerConnection s) throws Exception {
+ Server server=new Server(s,id);
+ servers.add(server);
+ Set<ObjectName> onames = s.queryNames(ObjectName.WILDCARD, null);
+ MBeanProxyFactory introspector = new MBeanProxyFactory(server);
+ for (ObjectName name : onames) {
+ try {
+ objects.add(introspector.newProxyInstance(name
+ .toString()));
+ } catch (javassist.NotFoundException nfe) {
+
+ logger.warning("ERROR"+nfe);
+ continue;
+ }
+ }
+ }
+
+ public void removeServer(Server server) {
+ servers.remove(server);
+ for (Object o : objects) {
+ if (((MBean)o).getMBeanServer().equals(server)) objects.remove(o);
+ }
+ }
+ ///////////
+ //Finders//
+ ///////////
+ public List<Object> getObjects() {
+ return objects;
+ }
+ public Object findFirst(String substring){
+ return findFirst(substring, null);
+ }
+ public Object findFirst(String substring, Server server){
+ for (Object o :objects){
+ MBean bean=(MBean)o;
+ if (isTheServer(bean, server)&&bean.getObjectName().contains(substring)){
+ return o;
+ }
+ }
+ return null;
+ }
+ private boolean isTheServer(MBean bean, MBeanServerConnection server){
+ return server==null?true:bean.getMBeanServer().equals(server);
+ }
+ public List<Object> findAll(String substring){
+ return findAll(substring, null);
+ }
+
+ public List<Object> findAll(String substring, MBeanServerConnection server){
+ List<Object> matches=new ArrayList<Object>();
+ for (Object o :objects){
+ MBean bean=(MBean)o;
+ if (isTheServer(bean, server)&&bean.getObjectName().contains(substring)){
+ matches.add(o);
+ }
+ }
+ return matches;
+ }
+
+ public List<Object> findMatches(String regex){
+ List<Object> matches=new ArrayList<Object>();
+ for (Object o :objects){
+ if (((MBean)o).getObjectName().matches(regex)){
+ matches.add(o);
+ }
+ }
+ return matches;
+ }
+
+ public List<Server> getServers() {
+ return servers;
+ }
+}
diff --git a/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/Server.java b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/Server.java
new file mode 100644
index 0000000..1d6beb1
--- /dev/null
+++ b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/Server.java
@@ -0,0 +1,110 @@
+package org.apache.felix.jmxintrospector;
+
+import java.io.IOException;
+import java.util.Set;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServerConnection;
+import javax.management.NotCompliantMBeanException;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.QueryExp;
+import javax.management.ReflectionException;
+
+public class Server implements MBeanServerConnection {
+ private MBeanServerConnection server;
+ private String id;
+ public Server(MBeanServerConnection server, String id){
+ this.server=server;
+ this.id=id;
+ }
+
+ //Delegates
+ public void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, IOException {
+ server.addNotificationListener(name, listener, filter, handback);
+ }
+ public void addNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, IOException {
+ server.addNotificationListener(name, listener, filter, handback);
+ }
+ public ObjectInstance createMBean(String className, ObjectName name, Object[] params, String[] signature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, IOException {
+ return server.createMBean(className, name, params, signature);
+ }
+ public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object[] params, String[] signature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException, IOException {
+ return server.createMBean(className, name, loaderName, params, signature);
+ }
+ public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException, IOException {
+ return server.createMBean(className, name, loaderName);
+ }
+ public ObjectInstance createMBean(String className, ObjectName name) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, IOException {
+ return server.createMBean(className, name);
+ }
+ public Object getAttribute(ObjectName name, String attribute) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException {
+ return server.getAttribute(name, attribute);
+ }
+ public AttributeList getAttributes(ObjectName name, String[] attributes) throws InstanceNotFoundException, ReflectionException, IOException {
+ return server.getAttributes(name, attributes);
+ }
+ public String getDefaultDomain() throws IOException {
+ return server.getDefaultDomain();
+ }
+ public String[] getDomains() throws IOException {
+ return server.getDomains();
+ }
+ public Integer getMBeanCount() throws IOException {
+ return server.getMBeanCount();
+ }
+ public MBeanInfo getMBeanInfo(ObjectName name) throws InstanceNotFoundException, IntrospectionException, ReflectionException, IOException {
+ return server.getMBeanInfo(name);
+ }
+ public ObjectInstance getObjectInstance(ObjectName name) throws InstanceNotFoundException, IOException {
+ return server.getObjectInstance(name);
+ }
+ public Object invoke(ObjectName name, String operationName, Object[] params, String[] signature) throws InstanceNotFoundException, MBeanException, ReflectionException, IOException {
+ return server.invoke(name, operationName, params, signature);
+ }
+ public boolean isInstanceOf(ObjectName name, String className) throws InstanceNotFoundException, IOException {
+ return server.isInstanceOf(name, className);
+ }
+ public boolean isRegistered(ObjectName name) throws IOException {
+ return server.isRegistered(name);
+ }
+ public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) throws IOException {
+ return server.queryMBeans(name, query);
+ }
+ public Set<ObjectName> queryNames(ObjectName name, QueryExp query) throws IOException {
+ return server.queryNames(name, query);
+ }
+ public void removeNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException, IOException {
+ server.removeNotificationListener(name, listener, filter, handback);
+ }
+ public void removeNotificationListener(ObjectName name, NotificationListener listener) throws InstanceNotFoundException, ListenerNotFoundException, IOException {
+ server.removeNotificationListener(name, listener);
+ }
+ public void removeNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException, IOException {
+ server.removeNotificationListener(name, listener, filter, handback);
+ }
+ public void removeNotificationListener(ObjectName name, ObjectName listener) throws InstanceNotFoundException, ListenerNotFoundException, IOException {
+ server.removeNotificationListener(name, listener);
+ }
+ public void setAttribute(ObjectName name, Attribute attribute) throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException, IOException {
+ server.setAttribute(name, attribute);
+ }
+ public AttributeList setAttributes(ObjectName name, AttributeList attributes) throws InstanceNotFoundException, ReflectionException, IOException {
+ return server.setAttributes(name, attributes);
+ }
+ public void unregisterMBean(ObjectName name) throws InstanceNotFoundException, MBeanRegistrationException, IOException {
+ server.unregisterMBean(name);
+ }
+}
\ No newline at end of file
diff --git a/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/classbean/TypeGetter.java b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/classbean/TypeGetter.java
new file mode 100644
index 0000000..e52277d
--- /dev/null
+++ b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/classbean/TypeGetter.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.jmxintrospector.classbean;
+
+import java.util.Collection;
+
+import sun.security.krb5.internal.tools.Klist;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+
+public class TypeGetter implements TypeGetterMBean {
+
+ public Class getType(String name) throws Exception{
+ CtClass cl=ClassPool.getDefault().get(name);
+ Collection classes=cl.getRefClasses();
+ CtClass[] all=ClassPool.getDefault().get((String[])classes.toArray(new String[classes.size()]));
+ for (CtClass klazz : all) {
+ klazz.toBytecode();
+
+ }
+ ClassLoader loader=this.getClass().getClassLoader();
+ try {
+ return loader.loadClass(name);
+ } catch (ClassNotFoundException e) {
+ return null; //FIXME: should we implement an searching mechanism?
+ }
+ }
+
+}
diff --git a/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/classbean/TypeGetterMBean.java b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/classbean/TypeGetterMBean.java
new file mode 100644
index 0000000..9722e89
--- /dev/null
+++ b/jmxintrospector/src/main/java/org/apache/felix/jmxintrospector/classbean/TypeGetterMBean.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.jmxintrospector.classbean;
+
+public interface TypeGetterMBean {
+ public static final String MBEAN_NAME="org.apache.felix:class=TypeGetterMBean";
+ public Class getType (String name) throws Exception;
+}
diff --git a/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/IntrospectorTestHarness.java b/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/IntrospectorTestHarness.java
new file mode 100644
index 0000000..888a360
--- /dev/null
+++ b/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/IntrospectorTestHarness.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.jmxintrospector;
+
+import java.lang.management.ManagementFactory;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+
+
+import junit.framework.TestCase;
+
+public class IntrospectorTestHarness extends TestCase {
+ Logger logger=Logger.getLogger(this.getClass().getName());
+ MBeanServerConnection mbs;
+ MBeanProxyManager proxyManager;
+ JMXConnectorServer jmxServer;
+ Registry registry;
+ ObjectName testName;
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mbs = ManagementFactory.getPlatformMBeanServer();
+ JMXServiceURL u=new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/server");
+ registry=LocateRegistry.createRegistry(1099);
+ jmxServer=JMXConnectorServerFactory.newJMXConnectorServer(u, null, (MBeanServer)mbs);
+ testName=ObjectName.getInstance("test:name="+this.getClass().getName());
+ ((MBeanServer)mbs).registerMBean(jmxServer, testName);
+ jmxServer.start();
+ proxyManager=new MBeanProxyManager();
+ proxyManager.addRemoteServer(u.toString());
+
+ }
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ jmxServer.stop();
+ ((MBeanServer)mbs).unregisterMBean(testName);
+ UnicastRemoteObject.unexportObject(registry, true);
+ }
+}
diff --git a/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/MBeanProxyFactoryTestCase.java b/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/MBeanProxyFactoryTestCase.java
new file mode 100644
index 0000000..8bde9fb
--- /dev/null
+++ b/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/MBeanProxyFactoryTestCase.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.jmxintrospector;
+
+import java.lang.management.ManagementFactory;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+
+import junit.framework.TestCase;
+
+public class MBeanProxyFactoryTestCase extends IntrospectorTestHarness {
+
+ MBeanProxyFactory factory;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ factory = new MBeanProxyFactory(mbs);
+ }
+
+ public void testNewProxyInstance() throws Exception{
+ Set<ObjectName> onames = mbs.queryNames(ObjectName.WILDCARD, null);
+ for (ObjectName name : onames) {
+ Object mbean=factory.newProxyInstance(name.toString());
+ assertTrue(mbean instanceof MBean);
+ logger.info(((MBean)mbean).getObjectName());
+ }
+ }
+}
diff --git a/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/OutOfProcessTestHarness.java b/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/OutOfProcessTestHarness.java
new file mode 100644
index 0000000..14cc269
--- /dev/null
+++ b/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/OutOfProcessTestHarness.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.jmxintrospector;
+
+import java.lang.management.ManagementFactory;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import junit.framework.TestCase;
+
+public class OutOfProcessTestHarness extends TestCase {
+ Logger logger=Logger.getLogger(this.getClass().getName());
+ MBeanServerConnection mbs;
+ MBeanProxyManager proxyManager;
+ ObjectName testName;
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ JMXServiceURL u=new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1199/server");
+ mbs=JMXConnectorFactory.connect(u).getMBeanServerConnection();
+ proxyManager=new MBeanProxyManager();
+ proxyManager.addRemoteServer(u.toString());
+
+ }
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/RemoteMBeanProxyFactoryTestCase.java b/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/RemoteMBeanProxyFactoryTestCase.java
new file mode 100644
index 0000000..c1fb215
--- /dev/null
+++ b/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/RemoteMBeanProxyFactoryTestCase.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.felix.jmxintrospector;
+
+/**
+ * @author mili
+ *
+ */
+public class RemoteMBeanProxyFactoryTestCase extends MBeanProxyFactoryTestCase{
+
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmxintrospector.MBeanProxyFactoryTestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ OutOfProcessTestHarness t=new OutOfProcessTestHarness();
+ t.setUp();
+ mbs=t.mbs;
+ factory=new MBeanProxyFactory(mbs);
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmxintrospector.IntrospectorTestHarness#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ }
+
+
+}
diff --git a/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/ScriptTestCase.java b/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/ScriptTestCase.java
new file mode 100644
index 0000000..a88ab79
--- /dev/null
+++ b/jmxintrospector/src/test/java/org/apache/felix/jmxintrospector/ScriptTestCase.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.jmxintrospector;
+
+import java.lang.management.ManagementFactory;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServerConnection;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+import junit.framework.TestCase;
+
+public class ScriptTestCase extends IntrospectorTestHarness {
+ Logger logger=Logger.getLogger(this.getClass().getName());
+ ScriptEngineManager engineManager;
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ engineManager=new ScriptEngineManager();
+ engineManager.put("manager", proxyManager);
+ }
+ public void testRuby() throws Exception{
+ fail("Not implemented");
+ }
+ public void testJavascript() throws Exception{
+ ScriptEngine js=engineManager.getEngineByName("javascript");
+ //results are the same, but may have different hash
+ List<Object> objectsInJava=proxyManager.getObjects();
+ List<Object> objectsInJS=(List<Object>) js.eval("manager.getObjects()");
+ for (Object objectJS : objectsInJS) {
+ Object javaPeer=null;
+ for (Object objectJava : objectsInJava) {
+ if (((MBean)objectJava).getObjectName().equals(((MBean)objectJS).getObjectName()))
+ javaPeer=objectJava;
+ }
+ assertNotNull(javaPeer);
+ System.out.println(javaPeer+";"+ objectJS);
+ assertEquals(javaPeer.getClass(), objectJS.getClass());
+ assertEquals(javaPeer, objectJS);//BUG in MBeanProxyFactory$JMXInvocationHandler
+
+ }
+
+
+ }
+
+}