You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by sf...@apache.org on 2006/07/17 14:14:33 UTC

svn commit: r422696 [2/4] - in /incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/felix/ src/main/java/org/apache/felix/mosgi/ src/main/java/or...

Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/log/Log.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/log/Log.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/log/Log.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/log/Log.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) MX4J.
+ * All rights reserved.
+ *
+ * This software is distributed under the terms of the MX4J License version 1.0.
+ * See the terms of the MX4J License in the documentation provided with this software.
+ */
+/*
+ *   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.mosgi.jmx.agent.mx4j.log;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Map;
+import java.util.HashMap;
+
+import javax.management.RuntimeOperationsException;
+
+import org.apache.felix.mosgi.jmx.agent.mx4j.MX4JSystemKeys;
+
+/**
+ * Main class for the log service. <p>
+ * The system property 'mx4j.log.priority' controls the priority of the standard logging, and defaults to 'warn'.
+ * Possible values are, from least to greatest priority, the following (case insensitive):
+ * <ul>
+ * <li>trace
+ * <li>debug
+ * <li>info
+ * <li>warn
+ * <li>error
+ * <li>fatal
+ * </ul>
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class Log
+{
+	private static Logger m_prototype;
+	private static Map m_prototypeMap = new HashMap();
+	private static Map m_loggerCache = new HashMap();
+	private static int m_defaultPriority;
+
+	static
+	{
+		// Do not require callers up in the stack to have this permission
+		String priority = (String)AccessController.doPrivileged(new PrivilegedAction()
+		{
+			public Object run()
+			{
+				 return System.getProperty(MX4JSystemKeys.MX4J_LOG_PRIORITY);
+			}
+		});
+		if ("trace".equalsIgnoreCase(priority)) {m_defaultPriority = Logger.TRACE;}
+		else if ("debug".equalsIgnoreCase(priority)) {m_defaultPriority = Logger.DEBUG;}
+		else if ("info".equalsIgnoreCase(priority)) {m_defaultPriority = Logger.INFO;}
+		else if ("warn".equalsIgnoreCase(priority)) {m_defaultPriority = Logger.WARN;}
+		else if ("error".equalsIgnoreCase(priority)) {m_defaultPriority = Logger.ERROR;}
+		else if ("fatal".equalsIgnoreCase(priority)) {m_defaultPriority = Logger.FATAL;}
+		else {m_defaultPriority = Logger.INFO;}
+
+		String prototype = (String)AccessController.doPrivileged(new PrivilegedAction()
+		{
+			public Object run()
+			{
+				 return System.getProperty(MX4JSystemKeys.MX4J_LOG_PROTOTYPE);
+			}
+		});
+		if (prototype != null && prototype.trim().length() > 0)
+		{
+			try
+			{
+				ClassLoader cl = Thread.currentThread().getContextClassLoader();
+				Class cls = cl.loadClass(prototype);
+				redirectTo((Logger)cls.newInstance());
+			}
+			catch (Exception x)
+			{
+				x.printStackTrace();
+				// Do nothing else: the user will see the exception trace
+				// and understand that the property was wrong
+			}
+		}
+	}
+
+	private Log() {}
+
+	/**
+	 * Sets the default priority for all loggers.
+	 * @see #setDefaultPriority
+	 */
+	public static void setDefaultPriority(int priority)
+	{
+		switch (priority)
+		{
+			case Logger.TRACE: m_defaultPriority = Logger.TRACE; break;
+			case Logger.DEBUG: m_defaultPriority = Logger.DEBUG; break;
+			case Logger.INFO: m_defaultPriority = Logger.INFO; break;
+			case Logger.WARN: m_defaultPriority = Logger.WARN; break;
+			case Logger.ERROR: m_defaultPriority = Logger.ERROR; break;
+			case Logger.FATAL: m_defaultPriority = Logger.FATAL; break;
+			default: m_defaultPriority = Logger.WARN; break;
+		}
+	}
+
+	/**
+	 * Returns the default priority.
+	 * @see #setDefaultPriority
+	 */
+	public static int getDefaultPriority()
+	{
+		return m_defaultPriority;
+	}
+
+	/**
+	 * Returns a new instance of a Logger associated with the given <code>category</code>;
+	 * if {@link #redirectTo} has been called then a new instance of the prototype Logger, associated with the given
+	 * <code>category<code>, is returned. This requires the prototype Logger class to have a public parameterless
+	 * constructor.
+	 */
+	public static Logger getLogger(String category)
+	{
+		if (category == null) {throw new RuntimeOperationsException(new IllegalArgumentException("Category cannot be null"));}
+
+		synchronized (m_loggerCache)
+		{
+			Logger logger = (Logger)m_loggerCache.get(category);
+			if (logger == null)
+			{
+				// Try to see if a delegate for this category overrides other settings
+				Logger prototype = null;
+				synchronized (m_prototypeMap)
+				{
+					prototype = (Logger)m_prototypeMap.get(category);
+				}
+				if (prototype == null)
+				{
+					// Try to see if a prototype for all categories has been set
+					if (m_prototype != null)
+					{
+						logger = createLogger(m_prototype, category);
+					}
+					else
+					{
+						logger = createLogger(null, category);
+					}
+				}
+				else
+				{
+					logger = createLogger(prototype, category);
+				}
+
+				// cache it
+				m_loggerCache.put(category, logger);
+			}
+			return logger;
+		}
+	}
+
+	private static Logger createLogger(Logger prototype, String category)
+	{
+		Logger logger = null;
+		try
+		{
+			logger = prototype == null ? new Logger() : (Logger)prototype.getClass().newInstance();
+		}
+		catch (Exception x)
+		{
+			x.printStackTrace();
+			logger = new Logger();
+		}
+		logger.setCategory(category);
+		logger.setPriority(m_defaultPriority);
+		return logger;
+	}
+
+	/**
+	 * Tells to the log service to use the given <code>delegate</code> Logger to perform logging. <br>
+	 * Use a null delegate to remove redirection.
+	 * @see #getLogger
+	 */
+	public static void redirectTo(Logger prototype)
+	{
+		m_prototype = prototype;
+
+		// Clear the cache, as we want requests for new loggers to be generated again.
+		synchronized (m_loggerCache)
+		{
+			m_loggerCache.clear();
+		}
+	}
+
+	/**
+	 * Tells to the log service to use the given <code>delegate</code> Logger to perform logging for the given
+	 * category (that cannot be null). <br>
+	 * Settings made using this method overrides the ones made with {@link #redirectTo(Logger) redirectTo}, meaning
+	 * that it is possible to redirect all the log to a certain delegate but certain categories.
+	 * Use a null delegate to remove redirection for the specified category.
+	 * @see #getLogger
+	 */
+	public static void redirectTo(Logger prototype, String category)
+	{
+		if (category == null) {throw new RuntimeOperationsException(new IllegalArgumentException("Category cannot be null"));}
+
+		if (prototype == null)
+		{
+			// Remove the redirection
+			synchronized (m_prototypeMap)
+			{
+				m_prototypeMap.remove(category);
+			}
+
+			// Clear the cache for this category
+			synchronized (m_loggerCache)
+			{
+				m_loggerCache.remove(category);
+			}
+		}
+		else
+		{
+			// Put or replace
+			synchronized (m_prototypeMap)
+			{
+				m_prototypeMap.put(category, prototype);
+			}
+
+			// Clear the cache for this category
+			synchronized (m_loggerCache)
+			{
+				m_loggerCache.remove(category);
+			}
+		}
+	}
+}

Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/log/Logger.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/log/Logger.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/log/Logger.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/log/Logger.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) MX4J.
+ * All rights reserved.
+ *
+ * This software is distributed under the terms of the MX4J License version 1.0.
+ * See the terms of the MX4J License in the documentation provided with this software.
+ */
+
+/*
+ *   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.mosgi.jmx.agent.mx4j.log;
+
+/**
+ * Base class for logging objects.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class Logger
+{
+	public static final int TRACE = 0;
+	public static final int DEBUG = TRACE + 10;
+	public static final int INFO = DEBUG + 10;
+	public static final int WARN = INFO + 10;
+	public static final int ERROR = WARN + 10;
+	public static final int FATAL = ERROR + 10;
+
+	private int m_priority = WARN;
+	private String m_category;
+
+	protected Logger() {}
+
+	public void setPriority(int priority) {m_priority = priority;}
+	public int getPriority() {return m_priority;}
+
+	public String getCategory() {return m_category;}
+	protected void setCategory(String category) {m_category = category;}
+
+	public final boolean isEnabledFor(int priority)
+	{
+		return priority >= getPriority();
+	}
+
+	public final void fatal(Object message) {log(FATAL, message, null);}
+	public final void fatal(Object message, Throwable t) {log(FATAL, message, t);}
+	public final void error(Object message) {log(ERROR, message, null);}
+	public final void error(Object message, Throwable t) {log(ERROR, message, t);}
+	public final void warn(Object message) {log(WARN, message, null);}
+	public final void warn(Object message, Throwable t) {log(WARN, message, t);}
+	public final void info(Object message) {log(INFO, message, null);}
+	public final void info(Object message, Throwable t) {log(INFO, message, t);}
+	public final void debug(Object message) {log(DEBUG, message, null);}
+	public final void debug(Object message, Throwable t) {log(DEBUG, message, t);}
+	public final void trace(Object message) {log(TRACE, message, null);}
+	public final void trace(Object message, Throwable t) {log(TRACE, message, t);}
+
+	protected void log(int priority, Object message, Throwable t)
+	{
+		if (isEnabledFor(priority))
+		{
+			System.out.println(message);
+			if (t != null)
+			{
+				t.printStackTrace(System.out);
+			}
+		}
+	}
+}

Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/DefaultClassLoaderRepository.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/DefaultClassLoaderRepository.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/DefaultClassLoaderRepository.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/DefaultClassLoaderRepository.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) MX4J.
+ * All rights reserved.
+ *
+ * This software is distributed under the terms of the MX4J License version 1.0.
+ * See the terms of the MX4J License in the documentation provided with this software.
+ */
+/*
+ *   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.mosgi.jmx.agent.mx4j.server;
+
+import java.util.ArrayList;
+
+import javax.management.loading.MLet;
+
+/**
+ * Default implementation of a ClassLoaderRepository
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.2 $
+ */
+public class DefaultClassLoaderRepository extends ModifiableClassLoaderRepository implements java.io.Serializable
+{
+   private static final int WITHOUT = 1;
+   private static final int BEFORE = 2;
+
+   private ArrayList classLoaders = new ArrayList();
+
+   public Class loadClass(String className) throws ClassNotFoundException
+   {
+      return loadClassWithout(null, className);
+   }
+
+   public Class loadClassWithout(ClassLoader loader, String className) throws ClassNotFoundException
+   {
+       return loadClassFromRepository(loader, className, WITHOUT);
+   }
+
+   public Class loadClassBefore(ClassLoader loader, String className) throws ClassNotFoundException
+   {
+       return loadClassFromRepository(loader, className, BEFORE);
+   }
+
+   protected void addClassLoader(ClassLoader cl)
+   {
+      if (cl == null) return;
+
+      ArrayList loaders = getClassLoaders();
+      synchronized (loaders)
+      {
+         if (!loaders.contains(cl)) loaders.add(cl);
+      }
+   }
+
+   protected void removeClassLoader(ClassLoader cl)
+   {
+      if (cl == null) return;
+
+      ArrayList loaders = getClassLoaders();
+      synchronized (loaders)
+      {
+         loaders.remove(cl);
+      }
+   }
+
+   protected ArrayList cloneClassLoaders()
+   {
+      ArrayList loaders = getClassLoaders();
+      synchronized (loaders)
+      {
+         return (ArrayList)loaders.clone();
+      }
+   }
+
+   protected ArrayList getClassLoaders()
+   {
+       return classLoaders;
+   }
+
+   private Class loadClassFromRepository(ClassLoader loader, String className, int algorithm) throws ClassNotFoundException
+   {
+      ArrayList copy = cloneClassLoaders();
+      for (int i = 0; i < copy.size(); ++i)
+      {
+         try
+         {
+            ClassLoader cl = (ClassLoader)copy.get(i);
+            if (cl.equals(loader))
+            {
+               if (algorithm == BEFORE) break;
+               else continue;
+            }
+
+            return loadClass(cl, className);
+         }
+         catch (ClassNotFoundException ignored)
+         {
+         }
+      }
+      throw new ClassNotFoundException(className);
+   }
+
+   private Class loadClass(ClassLoader loader, String className) throws ClassNotFoundException
+   {
+      // This is an optimization: if the classloader is an MLet (and not a subclass)
+      // then the method MLet.loadClass(String, ClassLoaderRepository) is used.
+      if (loader.getClass() == MLet.class) return ((MLet)loader).loadClass(className, null);
+      return loader.loadClass(className);
+   }
+
+   private int getSize()
+   {
+      ArrayList loaders = getClassLoaders();
+      synchronized (loaders)
+      {
+         return loaders.size();
+      }
+   }
+}

Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/DefaultMBeanRepository.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/DefaultMBeanRepository.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/DefaultMBeanRepository.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/DefaultMBeanRepository.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) MX4J.
+ * All rights reserved.
+ *
+ * This software is distributed under the terms of the MX4J License version 1.0.
+ * See the terms of the MX4J License in the documentation provided with this software.
+ */
+/*
+ *   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.mosgi.jmx.agent.mx4j.server;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.management.ObjectName;
+
+/**
+ * Default implementation of the MBeanRepository interface.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+class DefaultMBeanRepository implements MBeanRepository
+{
+	private HashMap m_map = new HashMap();
+
+	public MBeanMetaData get(ObjectName name)
+	{
+		return (MBeanMetaData)m_map.get(name);
+	}
+
+	public void put(ObjectName name, MBeanMetaData metadata)
+	{
+		m_map.put(name, metadata);
+	}
+
+	public void remove(ObjectName name)
+	{
+		m_map.remove(name);
+	}
+
+	public int size()
+	{
+		return m_map.size();
+	}
+
+	public Iterator iterator()
+	{
+		return m_map.values().iterator();
+	}
+
+	public Object clone()
+	{
+		try
+		{
+			DefaultMBeanRepository repository = (DefaultMBeanRepository)super.clone();
+			repository.m_map = (HashMap)m_map.clone();
+			return repository;
+		}
+		catch (CloneNotSupportedException ignored)
+		{
+			return null;
+		}
+	}
+}

Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanIntrospector.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanIntrospector.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanIntrospector.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanIntrospector.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,607 @@
+/*
+ * Copyright (C) MX4J.
+ * All rights reserved.
+ *
+ * This software is distributed under the terms of the MX4J License version 1.0.
+ * See the terms of the MX4J License in the documentation provided with this software.
+ */
+/*
+ *   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.mosgi.jmx.agent.mx4j.server;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.management.DynamicMBean;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.NotificationBroadcaster;
+import javax.management.loading.MLet;
+
+import org.apache.felix.mosgi.jmx.agent.mx4j.MBeanDescription;
+import org.apache.felix.mosgi.jmx.agent.mx4j.MBeanDescriptionAdapter;
+import org.apache.felix.mosgi.jmx.agent.mx4j.MX4JSystemKeys;
+import org.apache.felix.mosgi.jmx.agent.mx4j.log.Log;
+import org.apache.felix.mosgi.jmx.agent.mx4j.log.Logger;
+import org.apache.felix.mosgi.jmx.agent.mx4j.util.Utils;
+
+/**
+ * Introspector for MBeans. <p>
+ * Main purposes of this class are:
+ * <ul>
+ * <li> Given an mbean, gather all information regarding it into a {@link MBeanMetaData} instance, see {@link #introspect}
+ * <li> Given an introspected MBeanMetaData, decide if the MBean is compliant or not.
+ * <li> Act as a factory for {@link MBeanInvoker}s
+ * </ul>
+ *
+ * The following system properties are used to control this class' behavior:
+ * <ul>
+ * <li> mx4j.strict.mbean.interface, if set to 'no' then are treated as standard MBeans also classes that implement
+ * management interfaces beloging to different packages or that are inner classes; otherwise are treated as MBeans
+ * only classes that implement interfaces whose name if the fully qualified name of the MBean class + "MBean"
+ * <li> mx4j.mbean.invoker, if set to the qualified name of an implementation of the {@link MBeanInvoker} interface,
+ * then an instance of the class will be used to invoke methods on standard MBeans. By default the generated-on-the-fly
+ * MBeanInvoker is used; to revert to the version that uses reflection, for example,
+ * use mx4j.mbean.invoker = {@link ReflectedMBeanInvoker mx4j.server.ReflectedMBeanInvoker}
+ * </ul>
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class MBeanIntrospector
+{
+   private static MBeanDescriptionAdapter DEFAULT_DESCRIPTION = new MBeanDescriptionAdapter();
+
+   private boolean m_useExtendedMBeanInterfaces = false;
+   private boolean m_bcelClassesAvailable = false;
+   private final String m_customMBeanInvoker;
+
+   public MBeanIntrospector()
+   {
+      String strict = (String)AccessController.doPrivileged(new PrivilegedAction()
+      {
+         public Object run()
+         {
+            return System.getProperty(MX4JSystemKeys.MX4J_STRICT_MBEAN_INTERFACE);
+         }
+      });
+      if (strict != null && !Boolean.valueOf(strict).booleanValue())
+      {
+         m_useExtendedMBeanInterfaces = true;
+      }
+
+      // Try to see if BCEL classes are present
+   /* SFR : removed BCEL management
+      try
+      {
+         getClass().getClassLoader().loadClass("org.apache.bcel.generic.Type");
+         m_bcelClassesAvailable = true;
+      }
+      catch (Throwable ignored)
+      {
+      }
+   */
+
+      // See if someone specified which MBean invoker to use
+      m_customMBeanInvoker = (String)AccessController.doPrivileged(new PrivilegedAction()
+      {
+         public Object run()
+         {
+            return System.getProperty(MX4JSystemKeys.MX4J_MBEAN_INVOKER);
+         }
+      });
+   }
+
+   /**
+    * Introspect the given mbean, storing the results in the given metadata.
+    * It expects that the mbean field and the classloader field are not null
+    * @see #isMBeanCompliant
+    */
+   public void introspect(MBeanMetaData metadata)
+   {
+      introspectType(metadata);
+      introspectMBeanInfo(metadata);
+   }
+
+   /**
+    * Returns whether the given already introspected metadata is compliant.
+    * Must be called after {@link #introspect}
+    */
+   public boolean isMBeanCompliant(MBeanMetaData metadata)
+   {
+      return isMBeanClassCompliant(metadata) && isMBeanTypeCompliant(metadata) && isMBeanInfoCompliant(metadata);
+   }
+
+   /**
+    * Used by the test cases, invoked via reflection, keep it private.
+    * Introspect the mbean and returns if it's compliant
+    */
+   private boolean testCompliance(MBeanMetaData metadata)
+   {
+      introspect(metadata);
+      return isMBeanCompliant(metadata);
+   }
+
+   private boolean isMBeanClassCompliant(MBeanMetaData metadata)
+   {
+      // From JMX 1.1: no requirements (can be abstract, non public and no accessible constructors)
+      return true;
+   }
+
+   private boolean isMBeanTypeCompliant(MBeanMetaData metadata)
+   {
+      Logger logger = getLogger();
+
+      if (metadata.standard && metadata.dynamic)
+      {
+         if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBean is both standard and dynamic");
+         return false;
+      }
+      if (!metadata.standard && !metadata.dynamic)
+      {
+         if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBean is not standard nor dynamic");
+         return false;
+      }
+
+      return true;
+   }
+
+   private boolean isMBeanInfoCompliant(MBeanMetaData metadata)
+   {
+      Logger logger = getLogger();
+
+      if (metadata.info == null)
+      {
+         if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBeanInfo is null");
+         return false;
+      }
+      return true;
+   }
+
+   private void introspectType(MBeanMetaData metadata)
+   {
+      // Some information is already provided (StandardMBean)
+      if (metadata.standard)
+      {
+         introspectStandardMBean(metadata);
+         return;
+      }
+
+      if (metadata.mbean instanceof DynamicMBean)
+      {
+         metadata.dynamic = true;
+         return;
+      }
+      else
+      {
+         metadata.dynamic = false;
+         // Continue and see if it's a plain standard MBean
+      }
+
+      // We have a plain standard MBean, introspect it
+      introspectStandardMBean(metadata);
+   }
+
+   private void introspectStandardMBean(MBeanMetaData metadata)
+   {
+      if (metadata.management != null)
+      {
+         // Be sure the MBean implements the management interface
+         if (metadata.management.isInstance(metadata.mbean))
+         {
+            if (metadata.invoker == null) metadata.invoker = createInvoker(metadata);
+            return;
+         }
+         else
+         {
+            // Not compliant, reset the values
+            metadata.standard = false;
+            metadata.management = null;
+            metadata.invoker = null;
+            return;
+         }
+      }
+      else
+      {
+         Class cls = metadata.mbean.getClass();
+         for (Class c = cls; c != null; c = c.getSuperclass())
+         {
+            Class[] intfs = c.getInterfaces();
+            for (int i = 0; i < intfs.length; ++i)
+            {
+               Class intf = intfs[i];
+
+               if (implementsMBean(c.getName(), intf.getName()))
+               {
+                  // OK, found the MBean interface for this class
+                  metadata.standard = true;
+                  metadata.management = intf;
+                  metadata.invoker = createInvoker(metadata);
+                  return;
+               }
+            }
+         }
+
+         // Management interface not found, it's not compliant, reset the values
+         metadata.standard = false;
+         metadata.management = null;
+         metadata.invoker = null;
+      }
+   }
+
+   private void introspectMBeanInfo(MBeanMetaData metadata)
+   {
+      if (metadata.dynamic)
+      {
+         metadata.info = getDynamicMBeanInfo(metadata);
+      }
+      else if (metadata.standard)
+      {
+         metadata.info = createStandardMBeanInfo(metadata);
+      }
+      else
+      {
+         // Not a valid MBean, reset the MBeanInfo: this will cause an exception later
+         metadata.info = null;
+      }
+   }
+
+   private MBeanInfo getDynamicMBeanInfo(MBeanMetaData metadata)
+   {
+      Logger logger = getLogger();
+
+      MBeanInfo info = null;
+      
+	  try {
+		 info = ((DynamicMBean) metadata.mbean).getMBeanInfo();
+	  } catch (Exception x) {
+	     if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("getMBeanInfo threw: " + x.toString());
+	  }
+	  
+      if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Dynamic MBeanInfo is: " + info);
+
+      if (info == null)
+      {
+         if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBeanInfo cannot be null");
+         return null;
+      }
+
+      return info;
+   }
+
+   private MBeanInfo createStandardMBeanInfo(MBeanMetaData metadata)
+   {
+      // This is a non-standard extension: description for standard MBeans
+      MBeanDescription description = createMBeanDescription(metadata);
+
+      MBeanConstructorInfo[] ctors = createMBeanConstructorInfo(metadata, description);
+      if (ctors == null) return null;
+      MBeanAttributeInfo[] attrs = createMBeanAttributeInfo(metadata, description);
+      if (attrs == null) return null;
+      MBeanOperationInfo[] opers = createMBeanOperationInfo(metadata, description);
+      if (opers == null) return null;
+      MBeanNotificationInfo[] notifs = createMBeanNotificationInfo(metadata);
+      if (notifs == null) return null;
+
+      return new MBeanInfo(metadata.mbean.getClass().getName(), description.getMBeanDescription(), attrs, ctors, opers, notifs);
+   }
+
+   private MBeanDescription createMBeanDescription(MBeanMetaData metadata)
+   {
+      // This is a non-standard extension
+
+      Logger logger = getLogger();
+      if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Looking for standard MBean description...");
+
+      Class mbeanClass = metadata.mbean.getClass();
+
+      for (Class cls = mbeanClass; cls != null; cls = cls.getSuperclass())
+      {
+         String clsName = cls.getName();
+         if (clsName.startsWith("java.")) break;
+
+         // Use full qualified name only
+         String descrClassName = clsName + "MBeanDescription";
+         // Try to load the class
+         try
+         {
+            Class descrClass = null;
+            ClassLoader loader = metadata.classloader;
+            if (loader != null)
+            {
+               // Optimize lookup of the description class in case of MLets: we lookup the description class
+               // only in the classloader of the mbean, not in the whole CLR (since MLets delegates to the CLR)
+               if (loader.getClass() == MLet.class)
+                  descrClass = ((MLet)loader).loadClass(descrClassName, null);
+               else
+                  descrClass = loader.loadClass(descrClassName);
+            }
+            else
+            {
+               descrClass = Class.forName(descrClassName, false, null);
+            }
+
+            Object descrInstance = descrClass.newInstance();
+            if (descrInstance instanceof MBeanDescription)
+            {
+               MBeanDescription description = (MBeanDescription)descrInstance;
+               if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Found provided standard MBean description: " + description);
+               return description;
+            }
+         }
+         catch (ClassNotFoundException ignored)
+         {
+         }
+         catch (InstantiationException ignored)
+         {
+         }
+         catch (IllegalAccessException ignored)
+         {
+         }
+      }
+
+      MBeanDescription description = DEFAULT_DESCRIPTION;
+      if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Cannot find standard MBean description, using default: " + description);
+      return description;
+   }
+
+   private MBeanOperationInfo[] createMBeanOperationInfo(MBeanMetaData metadata, MBeanDescription description)
+   {
+      ArrayList operations = new ArrayList();
+
+      Method[] methods = metadata.management.getMethods();
+      for (int j = 0; j < methods.length; ++j)
+      {
+         Method method = methods[j];
+         if (!Utils.isAttributeGetter(method) && !Utils.isAttributeSetter(method))
+         {
+            String descr = description == null ? null : description.getOperationDescription(method);
+            Class[] params = method.getParameterTypes();
+            MBeanParameterInfo[] paramsInfo = new MBeanParameterInfo[params.length];
+            for (int k = 0; k < params.length; ++k)
+            {
+               Class param = params[k];
+               String paramName = description == null ? null : description.getOperationParameterName(method, k);
+               String paramDescr = description == null ? null : description.getOperationParameterDescription(method, k);
+               paramsInfo[k] = new MBeanParameterInfo(paramName, param.getName(), paramDescr);
+            }
+            MBeanOperationInfo info = new MBeanOperationInfo(method.getName(), descr, paramsInfo, method.getReturnType().getName(), MBeanOperationInfo.UNKNOWN);
+            operations.add(info);
+         }
+      }
+
+      return (MBeanOperationInfo[])operations.toArray(new MBeanOperationInfo[operations.size()]);
+   }
+
+   private MBeanAttributeInfo[] createMBeanAttributeInfo(MBeanMetaData metadata, MBeanDescription description)
+   {
+      Logger logger = getLogger();
+
+      HashMap attributes = new HashMap();
+      HashMap getterNames = new HashMap();
+
+      Method[] methods = metadata.management.getMethods();
+      for (int j = 0; j < methods.length; ++j)
+      {
+         Method method = methods[j];
+         if (Utils.isAttributeGetter(method))
+         {
+            String name = method.getName();
+            boolean isIs = name.startsWith("is");
+
+            String attribute = null;
+            if (isIs)
+               attribute = name.substring(2);
+            else
+               attribute = name.substring(3);
+
+            String descr = description == null ? null : description.getAttributeDescription(attribute);
+
+            MBeanAttributeInfo info = (MBeanAttributeInfo)attributes.get(attribute);
+
+            if (info != null)
+            {
+               // JMX spec does not allow overloading attributes.
+               // If an attribute with the same name already exists the MBean is not compliant
+               if (!info.getType().equals(method.getReturnType().getName()))
+               {
+                  if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBean is not compliant: has overloaded attribute " + attribute);
+                  return null;
+               }
+               else
+               {
+                  // They return the same value, 
+                  if (getterNames.get(name) != null)
+                  {
+                  	// This is the case of an attribute being present in multiple interfaces
+                  	// Ignore all but the first, since they resolve to the same method anyways
+                 	continue;                  	 
+                  }
+                  
+				  // there is a chance that one is a get-getter and one is a is-getter
+				  // for a boolean attribute. In this case, the MBean is not compliant.
+                  if (info.isReadable())
+                  {
+                     if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBean is not compliant: has overloaded attribute " + attribute);
+                     return null;
+                  }
+
+                  // MBeanAttributeInfo is already present due to a setter method, just update its readability
+                  info = new MBeanAttributeInfo(attribute, info.getType(), info.getDescription(), true, info.isWritable(), isIs);
+               }
+            }
+            else
+            {
+               info = new MBeanAttributeInfo(attribute, method.getReturnType().getName(), descr, true, false, isIs);
+            }
+
+            // Replace if exists
+            attributes.put(attribute, info);
+			getterNames.put(name,method);
+         }
+         else if (Utils.isAttributeSetter(method))
+         {
+            String name = method.getName();
+            String attribute = name.substring(3);
+
+            String descr = description == null ? null : description.getAttributeDescription(attribute);
+
+            MBeanAttributeInfo info = (MBeanAttributeInfo)attributes.get(attribute);
+
+            if (info != null)
+            {
+               // JMX spec does not allow overloading attributes.
+               // If an attribute with the same name already exists the MBean is not compliant
+               if (!info.getType().equals(method.getParameterTypes()[0].getName()))
+               {
+                  if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("MBean is not compliant: has overloaded attribute " + attribute);
+                  return null;
+               }
+               else
+               {
+                  // MBeanAttributeInfo is already present due to a getter method, just update its writability
+                  info = new MBeanAttributeInfo(info.getName(), info.getType(), info.getDescription(), info.isReadable(), true, info.isIs());
+               }
+            }
+            else
+            {
+               info = new MBeanAttributeInfo(attribute, method.getParameterTypes()[0].getName(), descr, false, true, false);
+            }
+
+            // Replace if exists
+            attributes.put(attribute, info);
+         }
+      }
+
+      return (MBeanAttributeInfo[])attributes.values().toArray(new MBeanAttributeInfo[attributes.size()]);
+   }
+
+   private MBeanNotificationInfo[] createMBeanNotificationInfo(MBeanMetaData metadata)
+   {
+      MBeanNotificationInfo[] notifs = null;
+      if (metadata.mbean instanceof NotificationBroadcaster)
+      {
+         notifs = ((NotificationBroadcaster)metadata.mbean).getNotificationInfo();
+      }
+      if (notifs == null) notifs = new MBeanNotificationInfo[0];
+      return notifs;
+   }
+
+   private MBeanConstructorInfo[] createMBeanConstructorInfo(MBeanMetaData metadata, MBeanDescription descrs)
+   {
+      Class mbeanClass = metadata.mbean.getClass();
+
+      Constructor[] ctors = mbeanClass.getConstructors();
+      MBeanConstructorInfo[] constructors = new MBeanConstructorInfo[ctors.length];
+      for (int i = 0; i < ctors.length; ++i)
+      {
+         Constructor constructor = ctors[i];
+         String descr = descrs == null ? null : descrs.getConstructorDescription(constructor);
+         Class[] params = constructor.getParameterTypes();
+         MBeanParameterInfo[] paramsInfo = new MBeanParameterInfo[params.length];
+         for (int j = 0; j < params.length; ++j)
+         {
+            Class param = params[j];
+            String paramName = descrs == null ? null : descrs.getConstructorParameterName(constructor, j);
+            String paramDescr = descrs == null ? null : descrs.getConstructorParameterDescription(constructor, j);
+            paramsInfo[j] = new MBeanParameterInfo(paramName, param.getName(), paramDescr);
+         }
+
+         String ctorName = constructor.getName();
+         MBeanConstructorInfo info = new MBeanConstructorInfo(ctorName.substring(ctorName.lastIndexOf('.') + 1), descr, paramsInfo);
+         constructors[i] = info;
+      }
+      return constructors;
+   }
+
+   private boolean implementsMBean(String clsName, String intfName)
+   {
+      if (intfName.equals(clsName + "MBean")) return true;
+
+      if (m_useExtendedMBeanInterfaces)
+      {
+         // Check also that the may be in different packages and/or inner classes
+
+         // Trim packages
+         int clsDot = clsName.lastIndexOf('.');
+         if (clsDot > 0) clsName = clsName.substring(clsDot + 1);
+         int intfDot = intfName.lastIndexOf('.');
+         if (intfDot > 0) intfName = intfName.substring(intfDot + 1);
+         // Try again
+         if (intfName.equals(clsName + "MBean")) return true;
+
+         // Trim inner classes
+         int clsDollar = clsName.lastIndexOf('$');
+         if (clsDollar > 0) clsName = clsName.substring(clsDollar + 1);
+         int intfDollar = intfName.lastIndexOf('$');
+         if (intfDollar > 0) intfName = intfName.substring(intfDollar + 1);
+         // Try again
+         if (intfName.equals(clsName + "MBean")) return true;
+      }
+
+      // Give up
+      return false;
+   }
+
+   private MBeanInvoker createInvoker(MBeanMetaData metadata)
+   {
+      Logger logger = getLogger();
+
+      if (m_customMBeanInvoker != null)
+      {
+         if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Custom MBeanInvoker class is: " + m_customMBeanInvoker);
+         try
+         {
+            MBeanInvoker mbeanInvoker = (MBeanInvoker)Thread.currentThread().getContextClassLoader().loadClass(m_customMBeanInvoker).newInstance();
+            if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Using custom MBeanInvoker: " + mbeanInvoker);
+            return mbeanInvoker;
+         }
+         catch (Exception x)
+         {
+            if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Cannot instantiate custom MBeanInvoker, using default", x);
+         }
+      }
+
+/* SFR
+      if (m_bcelClassesAvailable)
+      {
+         MBeanInvoker mbeanInvoker = BCELMBeanInvoker.create(metadata);
+         if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Using default BCEL MBeanInvoker for MBean " + metadata.name + ", " + mbeanInvoker);
+         return mbeanInvoker;
+      }
+      else
+      {
+*/
+         MBeanInvoker mbeanInvoker = new ReflectedMBeanInvoker();
+         if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Using default Reflection MBeanInvoker for MBean " + metadata.name + ", " + mbeanInvoker);
+         return mbeanInvoker;
+/* SFR     } */
+   }
+
+   private Logger getLogger()
+   {
+      return Log.getLogger(getClass().getName());
+   }
+}

Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanInvoker.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanInvoker.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanInvoker.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanInvoker.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) MX4J.
+ * All rights reserved.
+ *
+ * This software is distributed under the terms of the MX4J License version 1.0.
+ * See the terms of the MX4J License in the documentation provided with this software.
+ */
+/*
+ *   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.mosgi.jmx.agent.mx4j.server;
+
+import javax.management.Attribute;
+import javax.management.AttributeNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanException;
+import javax.management.ReflectionException;
+
+/**
+ * Invokes methods on standard MBeans. <p>
+ * Actually two implementations are available: one that uses reflection and one that generates on-the-fly a customized
+ * MBeanInvoker per each particular MBean and that is implemented with direct calls. <br>
+ * The default is the direct call version, that uses the <a href="http://jakarta.apache.org/bcel">BCEL</a> to generate
+ * the required bytecode on-the-fly. <br>
+ * In the future may be the starting point for MBean interceptors.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface MBeanInvoker
+{
+	/**
+	 * Invokes the specified operation on the MBean instance
+	 */
+    public Object invoke(MBeanMetaData metadata, String method, String[] signature, Object[] args) throws MBeanException, ReflectionException;
+	/**
+	 * Returns the value of the specified attribute.
+	 */
+	public Object getAttribute(MBeanMetaData metadata, String attribute) throws MBeanException, AttributeNotFoundException, ReflectionException;
+	/**
+	 * Sets the value of the specified attribute.
+	 */
+	public void setAttribute(MBeanMetaData metadata, Attribute attribute) throws MBeanException, AttributeNotFoundException, InvalidAttributeValueException, ReflectionException;
+}

Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanMetaData.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanMetaData.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanMetaData.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanMetaData.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) MX4J.
+ * All rights reserved.
+ *
+ * This software is distributed under the terms of the MX4J License version 1.0.
+ * See the terms of the MX4J License in the documentation provided with this software.
+ */
+/*
+ *   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.mosgi.jmx.agent.mx4j.server;
+
+import javax.management.MBeanInfo;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+/**
+ * Objects of this class hold metadata information about MBeans.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class MBeanMetaData
+{
+	/**
+	 * The MBean instance.
+	 */
+	public Object mbean;
+
+	/**
+	 * The classloader of the MBean
+	 */
+	public ClassLoader classloader;
+
+	/**
+	 * The ObjectInstance of the MBean
+	 */
+	public ObjectInstance instance;
+
+	/**
+	 * The ObjectName of the MBean
+	 */
+	public ObjectName name;
+
+	/**
+	 * The MBeanInfo of the MBean
+	 */
+	public MBeanInfo info;
+
+	/**
+	 * True if the MBean is dynamic
+	 */
+	public boolean dynamic;
+
+	/**
+	 * True if the MBean is standard
+	 */
+	public boolean standard;
+
+	/**
+	 * The management interface of the MBean, if it is a standard MBean
+	 */
+	public Class management;
+
+	/**
+	 * The invoker for the MBean, if it is a standard MBean
+	 */
+	public MBeanInvoker invoker;
+}

Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanRepository.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanRepository.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanRepository.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/MBeanRepository.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) MX4J.
+ * All rights reserved.
+ *
+ * This software is distributed under the terms of the MX4J License version 1.0.
+ * See the terms of the MX4J License in the documentation provided with this software.
+ */
+/*
+ *   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.mosgi.jmx.agent.mx4j.server;
+
+import java.util.Iterator;
+import javax.management.ObjectName;
+
+/**
+ * The MBeanServer implementation delegates to implementations of this interface the storage of registered MBeans. <p>
+ * All necessary synchronization code is taken care by the MBeanServer, so implementations can be coded without caring
+ * of synchronization issues.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface MBeanRepository extends Cloneable
+{
+	/**
+	 * Returns the metadata information associated with the given object name.
+	 * @see #put
+	 */
+	public MBeanMetaData get(ObjectName name);
+
+	/**
+	 * Inserts the given metadata associated with the given object name into this repository.
+	 * @see #get
+	 */
+	public void put(ObjectName name, MBeanMetaData metadata);
+
+	/**
+	 * Removes the metadata associated with the given object name from this repository.
+	 */
+	public void remove(ObjectName name);
+
+	/**
+	 * Returns the size of this repository.
+	 */
+	public int size();
+
+	/**
+	 * Returns an iterator on the metadata stored in this repository.
+	 */
+	public Iterator iterator();
+
+	/**
+	 * Clones this MBean repository
+	 */
+	public Object clone();
+}