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 [4/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/server/interceptor/DefaultMBeanServerInterceptor.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/interceptor/DefaultMBeanServerInterceptor.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/interceptor/DefaultMBeanServerInterceptor.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/DefaultMBeanServerInterceptor.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,157 @@
+/*
+ * 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.interceptor;
+
+import java.util.List;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ReflectionException;
+
+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.server.MBeanMetaData;
+
+/**
+ * Base class for MBeanServer --> MBean interceptors.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.2 $
+ */
+public abstract class DefaultMBeanServerInterceptor implements MBeanServerInterceptor, DefaultMBeanServerInterceptorMBean
+{
+ private boolean enabled = true;
+ private String logCategory;
+ private List chain;
+
+ protected DefaultMBeanServerInterceptor()
+ {
+ // It's amazing how setting up here this string dramatically reduces the times to get the Logger instance
+ logCategory = getClass().getName() + "." + getType();
+ }
+
+ /**
+ * Returns whether this interceptor is enabled
+ * @see #setEnabled
+ */
+ public boolean isEnabled()
+ {
+ return enabled;
+ }
+
+ /**
+ * Enables or disables this interceptor
+ * @see #isEnabled
+ */
+ public void setEnabled(boolean enabled)
+ {
+ this.enabled = enabled;
+ }
+
+ /**
+ * Returns the type of this interceptor
+ */
+ public abstract String getType();
+
+ protected synchronized MBeanServerInterceptor getNext()
+ {
+ int index = chain.indexOf(this);
+ MBeanServerInterceptor next = (MBeanServerInterceptor)chain.get(index + 1);
+ next.setChain(chain);
+ return next;
+ }
+
+ public synchronized void setChain(List chain)
+ {
+ this.chain = chain;
+ }
+
+ protected Logger getLogger()
+ {
+ return Log.getLogger(logCategory);
+ }
+
+ public void addNotificationListener(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback)
+ {
+ getNext().addNotificationListener(metadata, listener, filter, handback);
+ }
+
+ public void removeNotificationListener(MBeanMetaData metadata, NotificationListener listener) throws ListenerNotFoundException
+ {
+ getNext().removeNotificationListener(metadata, listener);
+ }
+
+ public void removeNotificationListener(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException
+ {
+ getNext().removeNotificationListener(metadata, listener, filter, handback);
+ }
+
+ public void instantiate(MBeanMetaData metadata, String className, String[] params, Object[] args) throws ReflectionException, MBeanException
+ {
+ getNext().instantiate(metadata, className, params, args);
+ }
+
+ public void registration(MBeanMetaData metadata, int operation) throws MBeanRegistrationException
+ {
+ getNext().registration(metadata, operation);
+ }
+
+ public MBeanInfo getMBeanInfo(MBeanMetaData metadata)
+ {
+ return getNext().getMBeanInfo(metadata);
+ }
+
+ public Object invoke(MBeanMetaData metadata, String method, String[] params, Object[] args) throws MBeanException, ReflectionException
+ {
+ return getNext().invoke(metadata, method, params, args);
+ }
+
+ public AttributeList getAttributes(MBeanMetaData metadata, String[] attributes)
+ {
+ return getNext().getAttributes(metadata, attributes);
+ }
+
+ public AttributeList setAttributes(MBeanMetaData metadata, AttributeList attributes)
+ {
+ return getNext().setAttributes(metadata, attributes);
+ }
+
+ public Object getAttribute(MBeanMetaData metadata, String attribute) throws MBeanException, AttributeNotFoundException, ReflectionException
+ {
+ return getNext().getAttribute(metadata, attribute);
+ }
+
+ public void setAttribute(MBeanMetaData metadata, Attribute attribute) throws MBeanException, AttributeNotFoundException, InvalidAttributeValueException, ReflectionException
+ {
+ getNext().setAttribute(metadata, attribute);
+ }
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/DefaultMBeanServerInterceptorMBean.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/interceptor/DefaultMBeanServerInterceptorMBean.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/interceptor/DefaultMBeanServerInterceptorMBean.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/DefaultMBeanServerInterceptorMBean.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,50 @@
+/*
+ * 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.interceptor;
+
+/**
+ * Management interface for the DefaultMBeanServerInterceptor MBean
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface DefaultMBeanServerInterceptorMBean
+{
+ /**
+ * Returns whether this interceptor is enabled
+ * @see #setEnabled
+ */
+ public boolean isEnabled();
+
+ /**
+ * Enables or disables this interceptor
+ * @see #isEnabled
+ */
+ public void setEnabled(boolean enabled);
+
+ /**
+ * Returns the type of this interceptor
+ */
+ public String getType();
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/InvokerMBeanServerInterceptor.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/interceptor/InvokerMBeanServerInterceptor.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/interceptor/InvokerMBeanServerInterceptor.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/InvokerMBeanServerInterceptor.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,399 @@
+/*
+ * 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.interceptor;
+
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.JMRuntimeException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.NotificationBroadcaster;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.RuntimeErrorException;
+import javax.management.RuntimeMBeanException;
+import javax.management.NotificationEmitter;
+
+import org.apache.felix.mosgi.jmx.agent.mx4j.ImplementationException;
+import org.apache.felix.mosgi.jmx.agent.mx4j.log.Logger;
+import org.apache.felix.mosgi.jmx.agent.mx4j.server.MBeanMetaData;
+import org.apache.felix.mosgi.jmx.agent.mx4j.util.Utils;
+
+/**
+ * The last MBeanServer --$gt; MBean interceptor in the chain.
+ * It calls the MBean instance; if the MBean is a dynamic MBean, the call is direct, otherwise the call is delegated
+ * to an {@link mx4j.server.MBeanInvoker MBeanInvoker}.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class InvokerMBeanServerInterceptor extends DefaultMBeanServerInterceptor implements InvokerMBeanServerInterceptorMBean
+{
+ private MBeanServer outerServer;
+
+ /**
+ * Instantiates a new interceptor instance.
+ * @param outerServer the {@link MBeanServer} instance that is passed to
+ * {@link MBeanRegistration#preRegister(MBeanServer, ObjectName)}.
+ */
+ public InvokerMBeanServerInterceptor(MBeanServer outerServer)
+ {
+ this.outerServer = outerServer;
+ }
+
+ /**
+ * Returns the type of this interceptor
+ */
+ public String getType()
+ {
+ return "invoker";
+ }
+
+ /**
+ * This interceptor is always enabled
+ */
+ public boolean isEnabled()
+ {
+ return true;
+ }
+
+ public void addNotificationListener(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback)
+ {
+ ((NotificationBroadcaster)metadata.mbean).addNotificationListener(listener, filter, handback);
+ }
+
+ public void removeNotificationListener(MBeanMetaData metadata, NotificationListener listener) throws ListenerNotFoundException
+ {
+ ((NotificationBroadcaster)metadata.mbean).removeNotificationListener(listener);
+ }
+
+ public void removeNotificationListener(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback)
+ throws ListenerNotFoundException
+ {
+ ((NotificationEmitter)metadata.mbean).removeNotificationListener(listener, filter, handback);
+ }
+
+ public void instantiate(MBeanMetaData metadata, String className, String[] params, Object[] args) throws ReflectionException, MBeanException
+ {
+ try
+ {
+ ClassLoader loader = metadata.classloader;
+ Class cls = null;
+ if (loader != null)
+ cls = loader.loadClass(className);
+ else
+ cls = Class.forName(className, false, null);
+
+ Class[] signature = Utils.loadClasses(loader, params);
+
+ Constructor ctor = cls.getConstructor(signature);
+
+ metadata.mbean = ctor.newInstance(args);
+ }
+ catch (ClassNotFoundException x)
+ {
+ throw new ReflectionException(x);
+ }
+ catch (NoSuchMethodException x)
+ {
+ throw new ReflectionException(x);
+ }
+ catch (InstantiationException x)
+ {
+ throw new ReflectionException(x);
+ }
+ catch (IllegalAccessException x)
+ {
+ throw new ReflectionException(x);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new ReflectionException(x);
+ }
+ catch (InvocationTargetException x)
+ {
+ Throwable t = x.getTargetException();
+ if (t instanceof Error)
+ {
+ throw new RuntimeErrorException((Error)t);
+ }
+ else if (t instanceof RuntimeException)
+ {
+ throw new RuntimeMBeanException((RuntimeException)t);
+ }
+ else
+ {
+ throw new MBeanException((Exception)t);
+ }
+ }
+ }
+
+ public void registration(MBeanMetaData metadata, int operation) throws MBeanRegistrationException
+ {
+ if (!(metadata.mbean instanceof MBeanRegistration)) return;
+
+ MBeanRegistration registrable = (MBeanRegistration)metadata.mbean;
+
+ try
+ {
+ switch (operation)
+ {
+ case PRE_REGISTER:
+ ObjectName objName = registrable.preRegister(outerServer, metadata.name);
+ metadata.name = objName;
+ break;
+ case POST_REGISTER_TRUE:
+ registrable.postRegister(Boolean.TRUE);
+ break;
+ case POST_REGISTER_FALSE:
+ registrable.postRegister(Boolean.FALSE);
+ break;
+ case PRE_DEREGISTER:
+ registrable.preDeregister();
+ break;
+ case POST_DEREGISTER:
+ registrable.postDeregister();
+ break;
+ default:
+ throw new ImplementationException();
+ }
+ }
+ catch (RuntimeException x) {
+ throw new RuntimeMBeanException(x);
+ }
+ catch (Exception x)
+ {
+ if (x instanceof MBeanRegistrationException)
+ {
+ throw (MBeanRegistrationException)x;
+ }
+ throw new MBeanRegistrationException(x);
+ }
+ }
+
+ public MBeanInfo getMBeanInfo(MBeanMetaData metadata)
+ {
+ if (metadata.dynamic)
+ {
+ // From JMX 1.1 the MBeanInfo may be dynamically changed at every time, let's refresh it
+ MBeanInfo info = null;
+ try {
+ info = ((DynamicMBean)metadata.mbean).getMBeanInfo();
+ } catch (RuntimeException x) {
+ throw new RuntimeMBeanException(x);
+ }
+ if (info == null) return null;
+ metadata.info = info;
+
+ // Refresh also ObjectInstance.getClassName(), if it's the case
+ String className = info.getClassName();
+ if (!metadata.instance.getClassName().equals(className))
+ {
+ metadata.instance = new ObjectInstance(metadata.name, className);
+ }
+ }
+
+ return (MBeanInfo)metadata.info.clone();
+ }
+
+ public Object invoke(MBeanMetaData metadata, String method, String[] params, Object[] args) throws MBeanException, ReflectionException
+ {
+ if (metadata.dynamic)
+ {
+ try
+ {
+ return ((DynamicMBean)metadata.mbean).invoke(method, args, params);
+ }
+ catch (JMRuntimeException x)
+ {
+ throw x;
+ }
+ catch (RuntimeException x)
+ {
+ throw new RuntimeMBeanException(x);
+ }
+ catch (Error x)
+ {
+ throw new RuntimeErrorException(x);
+ }
+ }
+ else
+ {
+ return metadata.invoker.invoke(metadata, method, params, args);
+ }
+ }
+
+ public Object getAttribute(MBeanMetaData metadata, String attribute) throws MBeanException, AttributeNotFoundException, ReflectionException
+ {
+ if (metadata.dynamic)
+ {
+ try
+ {
+ return ((DynamicMBean)metadata.mbean).getAttribute(attribute);
+ }
+ catch (JMRuntimeException x)
+ {
+ throw x;
+ }
+ catch (RuntimeException x)
+ {
+ throw new RuntimeMBeanException(x);
+ }
+ catch (Error x)
+ {
+ throw new RuntimeErrorException(x);
+ }
+ }
+ else
+ {
+ return metadata.invoker.getAttribute(metadata, attribute);
+ }
+ }
+
+ public void setAttribute(MBeanMetaData metadata, Attribute attribute) throws MBeanException, AttributeNotFoundException, InvalidAttributeValueException, ReflectionException
+ {
+ if (metadata.dynamic)
+ {
+ try
+ {
+ ((DynamicMBean)metadata.mbean).setAttribute(attribute);
+ }
+ catch (JMRuntimeException x)
+ {
+ throw x;
+ }
+ catch (RuntimeException x)
+ {
+ throw new RuntimeMBeanException(x);
+ }
+ catch (Error x)
+ {
+ throw new RuntimeErrorException(x);
+ }
+ }
+ else
+ {
+ metadata.invoker.setAttribute(metadata, attribute);
+ }
+ }
+
+ public AttributeList getAttributes(MBeanMetaData metadata, String[] attributes)
+ {
+ if (metadata.dynamic)
+ {
+ try
+ {
+ return ((DynamicMBean)metadata.mbean).getAttributes(attributes);
+ }
+ catch (JMRuntimeException x)
+ {
+ throw x;
+ }
+ catch (RuntimeException x)
+ {
+ throw new RuntimeMBeanException(x);
+ }
+ catch (Error x)
+ {
+ throw new RuntimeErrorException(x);
+ }
+ }
+ else
+ {
+ AttributeList list = new AttributeList();
+ for (int i = 0; i < attributes.length; ++i)
+ {
+ String name = attributes[i];
+ try
+ {
+ Object value = getAttribute(metadata, name);
+ Attribute attr = new Attribute(name, value);
+ list.add(attr);
+ }
+ catch (Exception ignored)
+ {
+ Logger logger = getLogger();
+ if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Exception caught from getAttributes(), ignoring attribute " + name);
+ }
+ }
+ return list;
+ }
+ }
+
+ public AttributeList setAttributes(MBeanMetaData metadata, AttributeList attributes)
+ {
+ if (metadata.dynamic)
+ {
+ try
+ {
+ return ((DynamicMBean)metadata.mbean).setAttributes(attributes);
+ }
+ catch (JMRuntimeException x)
+ {
+ throw x;
+ }
+ catch (RuntimeException x)
+ {
+ throw new RuntimeMBeanException(x);
+ }
+ catch (Error x)
+ {
+ throw new RuntimeErrorException(x);
+ }
+ }
+ else
+ {
+ AttributeList list = new AttributeList();
+ for (int i = 0; i < attributes.size(); ++i)
+ {
+ Attribute attr = (Attribute)attributes.get(i);
+ try
+ {
+ setAttribute(metadata, attr);
+ list.add(attr);
+ }
+ catch (Exception ignored)
+ {
+ Logger logger = getLogger();
+ if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Exception caught from setAttributes(), ignoring attribute " + attr, ignored);
+ }
+ }
+ return list;
+ }
+ }
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/InvokerMBeanServerInterceptorMBean.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/interceptor/InvokerMBeanServerInterceptorMBean.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/interceptor/InvokerMBeanServerInterceptorMBean.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/InvokerMBeanServerInterceptorMBean.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,43 @@
+/*
+ * 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.interceptor;
+
+/**
+ * Management interface for the InvokerMBeanServerInterceptor MBean
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface InvokerMBeanServerInterceptorMBean
+{
+ /**
+ * Returns the type of this interceptor
+ */
+ public String getType();
+
+ /**
+ * This interceptor is always enabled
+ */
+ public boolean isEnabled();
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/MBeanServerInterceptor.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/interceptor/MBeanServerInterceptor.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/interceptor/MBeanServerInterceptor.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/MBeanServerInterceptor.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,139 @@
+/*
+ * 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.interceptor;
+
+
+import java.util.List;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ReflectionException;
+
+import org.apache.felix.mosgi.jmx.agent.mx4j.server.MBeanMetaData;
+
+/**
+ * MBeanServer --> MBean interceptor.
+ * These interceptors are used internally to implement MBeanServer functionality prior to call
+ * MBeans, and can be used to customize MBeanServer implementation by users.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface MBeanServerInterceptor
+{
+ /**
+ * Constant used to specify the status of the MBean registration in {@link #registration}
+ */
+ public static final int PRE_REGISTER = 1;
+ /**
+ * Constant used to specify the status of the MBean registration in {@link #registration}
+ */
+ public static final int POST_REGISTER_TRUE = 2;
+ /**
+ * Constant used to specify the status of the MBean registration in {@link #registration}
+ */
+ public static final int POST_REGISTER_FALSE = 3;
+ /**
+ * Constant used to specify the status of the MBean registration in {@link #registration}
+ */
+ public static final int PRE_DEREGISTER = 4;
+ /**
+ * Constant used to specify the status of the MBean registration in {@link #registration}
+ */
+ public static final int POST_DEREGISTER = 5;
+
+ /**
+ * A concise string that tells the type of this interceptor
+ */
+ public String getType();
+
+ /**
+ * Sets the chain of interceptors on this interceptor. This interceptor will use this list to
+ * find the interceptor in the chain after itself
+ * @param interceptors The list of interceptors
+ */
+ public void setChain(List interceptors);
+
+ /**
+ * Adds the given notification listener to the MBean, along with the given filter and handback
+ */
+ public void addNotificationListener(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback);
+
+ /**
+ * Removes the given notification listener from the MBean.
+ */
+ public void removeNotificationListener(MBeanMetaData metadata, NotificationListener listener) throws ListenerNotFoundException;
+ /**
+ * Removes the given notification listener from the MBean, specified by the given filter and handback.
+ */
+ public void removeNotificationListener(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException;
+
+ /**
+ * Instantiate the given className passing the given arguments to the constructor with the given signature
+ */
+ public void instantiate(MBeanMetaData metadata, String className, String[] params, Object[] args) throws ReflectionException, MBeanException;
+
+ /**
+ * Calls the specified {@link javax.management.MBeanRegistration} method on the MBean instance.
+ */
+ public void registration(MBeanMetaData metadata, int operation) throws MBeanRegistrationException;
+
+ /**
+ * Calls getMBeanInfo on the MBean instance (only on DynamicMBeans).
+ */
+ public MBeanInfo getMBeanInfo(MBeanMetaData metadata);
+
+ /**
+ * Invokes the specified MBean operation on the MBean instance
+ */
+ public Object invoke(MBeanMetaData metadata, String method, String[] params, Object[] args) throws MBeanException, ReflectionException;
+
+ /**
+ * Gets the specified attributes values from the MBean instance.
+ */
+ public AttributeList getAttributes(MBeanMetaData metadata, String[] attributes);
+
+ /**
+ * Sets the specified attributes values on the MBean instance.
+ */
+ public AttributeList setAttributes(MBeanMetaData metadata, AttributeList attributes);
+
+ /**
+ * Gets the specified attribute value from the MBean instance.
+ */
+ public Object getAttribute(MBeanMetaData metadata, String attribute) throws MBeanException, AttributeNotFoundException, ReflectionException;
+
+ /**
+ * Sets the specified attribute value on the MBean instance.
+ */
+ 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/interceptor/MBeanServerInterceptorConfigurator.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/interceptor/MBeanServerInterceptorConfigurator.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/interceptor/MBeanServerInterceptorConfigurator.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/MBeanServerInterceptorConfigurator.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,197 @@
+/*
+ * 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.interceptor;
+
+import java.util.ArrayList;
+
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.felix.mosgi.jmx.agent.mx4j.ImplementationException;
+
+/**
+ * MBean that configures the MBeanServer --> MBean interceptor chain.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class MBeanServerInterceptorConfigurator implements MBeanServerInterceptorConfiguratorMBean
+{
+ public static final String OBJECT_NAME = "JMImplementation:type=MBeanServerInterceptorConfigurator";
+
+ private final MBeanServer server;
+ private final ArrayList preInterceptors = new ArrayList();
+ private final ArrayList postInterceptors = new ArrayList();
+ private final ArrayList clientInterceptors = new ArrayList();
+ private volatile boolean running;
+ private boolean chainModified;
+ private MBeanServerInterceptor head;
+
+ /**
+ * Creates an instance of this configurator, for the given MBeanServer
+ */
+ public MBeanServerInterceptorConfigurator(MBeanServer server)
+ {
+ this.server = server;
+ chainModified = true;
+ }
+
+ /**
+ * Appends the given interceptor, provided by the client, to the existing interceptor chain.
+ * @see #registerInterceptor
+ */
+ public void addInterceptor(MBeanServerInterceptor interceptor)
+ {
+ synchronized (clientInterceptors)
+ {
+ clientInterceptors.add(interceptor);
+ chainModified = true;
+ }
+ }
+
+ /**
+ * Appends the given interceptor, provided by the client, to the existing interceptor chain and registers it as MBean.
+ * @see #addInterceptor
+ */
+ public void registerInterceptor(MBeanServerInterceptor interceptor, ObjectName name) throws MBeanException
+ {
+ // First, try register this interceptor. The call will use the old interceptor chain
+ try
+ {
+ server.registerMBean(interceptor, name);
+ addInterceptor(interceptor);
+ }
+ catch (Exception x)
+ {
+ throw new MBeanException(x, "Could not register interceptor with name " + name);
+ }
+ }
+
+ /**
+ * Removes all the interceptors added via {@link #addInterceptor(MBeanServerInterceptor interceptor)}.
+ * @see #addInterceptor
+ */
+ public void clearInterceptors()
+ {
+ synchronized (clientInterceptors)
+ {
+ clientInterceptors.clear();
+ chainModified = true;
+ }
+ }
+
+ /**
+ * Adds the given interceptor at the beginning of the interceptor chain, before the custom interceptors that may be added
+ * via {@link #addInterceptor}.
+ * This method is called by the MBeanServer during initialization, to configure the interceptors needed to work properly.
+ */
+ public void addPreInterceptor(MBeanServerInterceptor interceptor)
+ {
+ if (isRunning()) throw new ImplementationException();
+ preInterceptors.add(interceptor);
+ }
+
+ /**
+ * Adds the given interceptor at the end of the interceptor chain, after the custom interceptors that may be added
+ * via {@link #addInterceptor}.
+ * This method is called by the MBeanServer during initialization, to configure the interceptors needed to work properly.
+ */
+ public void addPostInterceptor(MBeanServerInterceptor interceptor)
+ {
+ if (isRunning()) throw new ImplementationException();
+ postInterceptors.add(interceptor);
+ }
+
+ /**
+ * Returns the head interceptor of the interceptor chain.
+ * The head interceptor is always present.
+ */
+ public MBeanServerInterceptor getHeadInterceptor()
+ {
+ if (!isRunning()) return null;
+
+ if (chainModified) setupChain();
+
+ return head;
+ }
+
+ private void setupChain()
+ {
+ chainModified = false;
+
+ int size = clientInterceptors.size();
+ ArrayList chain = new ArrayList(preInterceptors.size() + size + postInterceptors.size());
+ chain.addAll(preInterceptors);
+ if (size > 0)
+ {
+ synchronized (clientInterceptors)
+ {
+ chain.addAll(clientInterceptors);
+ }
+ }
+ chain.addAll(postInterceptors);
+
+ // Set the chain on the first interceptor
+ MBeanServerInterceptor first = (MBeanServerInterceptor)chain.get(0);
+ first.setChain(chain);
+
+ head = first;
+ }
+
+ /**
+ * Starts this configurator, so that the MBeanServer is now able to accept incoming calls.
+ * @see #stop
+ * @see #isRunning
+ */
+ public void start()
+ {
+ if (!isRunning())
+ {
+ running = true;
+ }
+ }
+
+ /**
+ * Stops this configurator, so that the MBeanServer is not able to accept incoming calls.
+ * @see #start
+ */
+ public void stop()
+ {
+ if (isRunning())
+ {
+ running = false;
+ }
+ }
+
+ /**
+ * Returns whether this configurator is running and thus if the MBeanServer can accept incoming calls
+ * @see #start
+ */
+ public boolean isRunning()
+ {
+ return running;
+ }
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/MBeanServerInterceptorConfiguratorMBean.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/interceptor/MBeanServerInterceptorConfiguratorMBean.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/interceptor/MBeanServerInterceptorConfiguratorMBean.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/MBeanServerInterceptorConfiguratorMBean.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,73 @@
+/*
+ * 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.interceptor;
+
+
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+
+/**
+ * Management interface for the MBeanServerInterceptorConfigurator MBean.
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface MBeanServerInterceptorConfiguratorMBean
+{
+ /**
+ * Appends the given interceptor, provided by the client, to the existing interceptor chain.
+ * @see #registerInterceptor
+ */
+ public void addInterceptor(MBeanServerInterceptor interceptor);
+
+ /**
+ * Appends the given interceptor, provided by the client, to the existing interceptor chain and registers it as MBean.
+ * @see #addInterceptor
+ */
+ public void registerInterceptor(MBeanServerInterceptor interceptor, ObjectName name) throws MBeanException;
+
+ /**
+ * Removes all the interceptors added via {@link #addInterceptor(MBeanServerInterceptor interceptor)}.
+ * @see #addInterceptor
+ */
+ public void clearInterceptors();
+
+ /**
+ * Starts this configurator, so that the MBeanServer is now able to accept incoming calls.
+ * @see #stop
+ * @see #isRunning
+ */
+ public void start();
+
+ /**
+ * Stops this configurator, so that the MBeanServer is not able to accept incoming calls.
+ * @see #start
+ */
+ public void stop();
+
+ /**
+ * Returns whether this configurator is running and thus if the MBeanServer can accept incoming calls
+ * @see #start
+ */
+ public boolean isRunning();
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/NotificationListenerMBeanServerInterceptor.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/interceptor/NotificationListenerMBeanServerInterceptor.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/interceptor/NotificationListenerMBeanServerInterceptor.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/NotificationListenerMBeanServerInterceptor.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,150 @@
+/*
+ * 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.interceptor;
+
+import javax.management.ListenerNotFoundException;
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
+import org.apache.felix.mosgi.jmx.agent.mx4j.server.MBeanMetaData;
+
+/**
+ * Interceptor that takes care of replacing the source of Notifications to the
+ * ObjectName of the NotificationBroadcaster that emitted it.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class NotificationListenerMBeanServerInterceptor extends DefaultMBeanServerInterceptor
+{
+ private static class ListenerWrapper implements NotificationListener
+ {
+ private final NotificationListener listener;
+ private final ObjectName objectName;
+
+ private ListenerWrapper(NotificationListener listener, ObjectName name)
+ {
+ this.listener = listener;
+ this.objectName = name;
+ }
+
+ public void handleNotification(Notification notification, Object handback)
+ {
+ // The JMX spec does not specify how to change the source to be the ObjectName
+ // of the broadcaster. If we serialize the calls to the listeners, then it's
+ // possible to change the source and restore it back to the old value before
+ // calling the next listener; but if we want to support concurrent calls
+ // to the listeners, this is not possible. Here I chose to support concurrent
+ // calls so I change the value once and I never restore it.
+ Object src = notification.getSource();
+ if (!(src instanceof ObjectName))
+ {
+ // Change the source to be the ObjectName of the notification broadcaster
+ // if we are not already an ObjectName (compliant with RI behaviour)
+ notification.setSource(objectName);
+ }
+
+ // Notify the real listener
+ NotificationListener listener = getTargetListener();
+ listener.handleNotification(notification, handback);
+ }
+
+ private NotificationListener getTargetListener()
+ {
+ return listener;
+ }
+
+ public int hashCode()
+ {
+ return getTargetListener().hashCode();
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj == null) return false;
+ if (obj == this) return true;
+
+ try
+ {
+ ListenerWrapper other = (ListenerWrapper)obj;
+ return getTargetListener().equals(other.getTargetListener());
+ }
+ catch (ClassCastException ignored)
+ {
+ }
+ return false;
+ }
+
+ public String toString()
+ {
+ return getTargetListener().toString();
+ }
+ }
+
+ public String getType()
+ {
+ return "notificationlistener";
+ }
+
+ public void addNotificationListener(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback)
+ {
+ if (isEnabled())
+ {
+ ListenerWrapper wrapper = new ListenerWrapper(listener, metadata.name);
+ super.addNotificationListener(metadata, wrapper, filter, handback);
+ }
+ else
+ {
+ super.addNotificationListener(metadata, listener, filter, handback);
+ }
+ }
+
+ public void removeNotificationListener(MBeanMetaData metadata, NotificationListener listener) throws ListenerNotFoundException
+ {
+ if (isEnabled())
+ {
+ ListenerWrapper wrapper = new ListenerWrapper(listener, metadata.name);
+ super.removeNotificationListener(metadata, wrapper);
+ }
+ else
+ {
+ super.removeNotificationListener(metadata, listener);
+ }
+ }
+
+ public void removeNotificationListener(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException
+ {
+ if (isEnabled())
+ {
+ ListenerWrapper wrapper = new ListenerWrapper(listener, metadata.name);
+ super.removeNotificationListener(metadata, wrapper, filter, handback);
+ }
+ else
+ {
+ super.removeNotificationListener(metadata, listener, filter, handback);
+ }
+ }
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/SecurityMBeanServerInterceptor.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/interceptor/SecurityMBeanServerInterceptor.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/interceptor/SecurityMBeanServerInterceptor.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/SecurityMBeanServerInterceptor.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,209 @@
+/*
+ * 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.interceptor;
+
+
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.MBeanPermission;
+import javax.management.MBeanTrustPermission;
+
+import org.apache.felix.mosgi.jmx.agent.mx4j.server.MBeanMetaData;
+
+/**
+ * Interceptor that takes care of performing security checks (in case the SecurityManager is installed) for
+ * MBeanServer to MBean calls.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class SecurityMBeanServerInterceptor extends DefaultMBeanServerInterceptor implements SecurityMBeanServerInterceptorMBean
+{
+ public String getType()
+ {
+ return "security";
+ }
+
+ public boolean isEnabled()
+ {
+ return true;
+ }
+
+ public void addNotificationListener(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback)
+ {
+ checkPermission(metadata.info.getClassName(), null, metadata.name, "addNotificationListener");
+ super.addNotificationListener(metadata, listener, filter, handback);
+ }
+
+ public void removeNotificationListener(MBeanMetaData metadata, NotificationListener listener) throws ListenerNotFoundException
+ {
+ checkPermission(metadata.info.getClassName(), null, metadata.name, "removeNotificationListener");
+ super.removeNotificationListener(metadata, listener);
+ }
+
+ public void removeNotificationListener(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException
+ {
+ checkPermission(metadata.info.getClassName(), null, metadata.name, "removeNotificationListener");
+ super.removeNotificationListener(metadata, listener, filter, handback);
+ }
+
+ public void instantiate(MBeanMetaData metadata, String className, String[] params, Object[] args) throws ReflectionException, MBeanException
+ {
+ checkPermission(className, null, metadata.name, "instantiate");
+ super.instantiate(metadata, className, params, args);
+ }
+
+ public MBeanInfo getMBeanInfo(MBeanMetaData metadata)
+ {
+ checkPermission(metadata.info.getClassName(), null, metadata.name, "getMBeanInfo");
+ return super.getMBeanInfo(metadata);
+ }
+
+ public Object invoke(MBeanMetaData metadata, String method, String[] params, Object[] args) throws MBeanException, ReflectionException
+ {
+ checkPermission(metadata.info.getClassName(), method, metadata.name, "invoke");
+ return super.invoke(metadata, method, params, args);
+ }
+
+ public AttributeList getAttributes(MBeanMetaData metadata, String[] attributes)
+ {
+ Object[] secured = filterAttributes(metadata.info.getClassName(), metadata.name, attributes, true);
+ String[] array = new String[secured.length];
+ for (int i = 0; i < array.length; ++i) array[i] = (String)secured[i];
+ return super.getAttributes(metadata, array);
+ }
+
+ public AttributeList setAttributes(MBeanMetaData metadata, AttributeList attributes)
+ {
+ Object[] secured = filterAttributes(metadata.info.getClassName(), metadata.name, attributes.toArray(), false);
+ AttributeList list = new AttributeList();
+ for (int i = 0; i < secured.length; ++i) list.add(secured[i]);
+ return super.setAttributes(metadata, list);
+ }
+
+ public Object getAttribute(MBeanMetaData metadata, String attribute) throws MBeanException, AttributeNotFoundException, ReflectionException
+ {
+ checkPermission(metadata.info.getClassName(), attribute, metadata.name, "getAttribute");
+ return super.getAttribute(metadata, attribute);
+ }
+
+ public void setAttribute(MBeanMetaData metadata, Attribute attribute) throws MBeanException, AttributeNotFoundException, InvalidAttributeValueException, ReflectionException
+ {
+ checkPermission(metadata.info.getClassName(), attribute.getName(), metadata.name, "setAttribute");
+ super.setAttribute(metadata, attribute);
+ }
+
+ public void registration(MBeanMetaData metadata, int operation) throws MBeanRegistrationException
+ {
+ switch (operation)
+ {
+ case PRE_REGISTER:
+ checkPermission(metadata.info.getClassName(), null, metadata.name, "registerMBean");
+ checkTrustRegistration(metadata.mbean.getClass());
+ break;
+ case POST_REGISTER_TRUE:
+ // The MBean can implement MBeanRegistration and change the ObjectName
+ checkPermission(metadata.info.getClassName(), null, metadata.name, "registerMBean");
+ break;
+ case PRE_DEREGISTER:
+ checkPermission(metadata.info.getClassName(), null, metadata.name, "unregisterMBean");
+ break;
+ default:
+ break;
+ }
+ super.registration(metadata, operation);
+ }
+
+ private void checkPermission(String className, String methodName, ObjectName objectname, String action)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ sm.checkPermission(new MBeanPermission(className, methodName, objectname, action));
+ }
+ }
+
+ private void checkTrustRegistration(final Class cls)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ ProtectionDomain domain = (ProtectionDomain)AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return cls.getProtectionDomain();
+ }
+ });
+
+ MBeanTrustPermission permission = new MBeanTrustPermission("register");
+ if (!domain.implies(permission))
+ {
+ throw new AccessControlException("Access denied " + permission + ": MBean class " + cls.getName() + " is not trusted for registration");
+ }
+ }
+ }
+
+ private Object[] filterAttributes(String className, ObjectName objectName, Object[] attributes, boolean isGet)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) return attributes;
+
+ ArrayList list = new ArrayList();
+
+ for (int i = 0; i < attributes.length; ++i)
+ {
+ Object attribute = attributes[i];
+ String name = isGet ? (String)attribute : ((Attribute)attribute).getName();
+
+ try
+ {
+ checkPermission(className, name, objectName, isGet ? "getAttribute" : "setAttribute");
+ list.add(attribute);
+ }
+ catch (SecurityException ignore)
+ {
+ // This is ok. We just don't add this attribute to the list
+ }
+ }
+
+ return list.toArray();
+ }
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/SecurityMBeanServerInterceptorMBean.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/interceptor/SecurityMBeanServerInterceptorMBean.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/interceptor/SecurityMBeanServerInterceptorMBean.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/server/interceptor/SecurityMBeanServerInterceptorMBean.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,43 @@
+/*
+ * 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.interceptor;
+
+
+/**
+ * Management interface for the SecurityMBeanServerInterceptor MBean
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public interface SecurityMBeanServerInterceptorMBean
+{
+ /**
+ * Returns the type of this interceptor
+ */
+ public String getType();
+
+ /**
+ * This interceptor is always enabled
+ */
+ public boolean isEnabled();
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/util/Base64Codec.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/util/Base64Codec.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/util/Base64Codec.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/util/Base64Codec.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,402 @@
+/*
+ * 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.util;
+
+
+/**
+ * This class is copy/paste of Jakarta's Commons-Codec v1.1 <code>org.apache.commons.codec.binary.Base64</code>
+ * implementation.
+ * It is reproduced here because we don't want to require a new jar just to perform Base64 code/decoding.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class Base64Codec
+{
+ static final int CHUNK_SIZE = 76;
+ static final byte[] CHUNK_SEPARATOR = "\n".getBytes();
+
+ static final int BASELENGTH = 255;
+ static final int LOOKUPLENGTH = 64;
+ static final int TWENTYFOURBITGROUP = 24;
+ static final int EIGHTBIT = 8;
+ static final int SIXTEENBIT = 16;
+ static final int SIXBIT = 6;
+ static final int FOURBYTE = 4;
+ static final int SIGN = -128;
+ static final byte PAD = (byte)'=';
+
+ private static byte[] base64Alphabet = new byte[BASELENGTH];
+ private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
+
+ static
+ {
+ for (int i = 0; i < BASELENGTH; i++)
+ {
+ base64Alphabet[i] = (byte)-1;
+ }
+ for (int i = 'Z'; i >= 'A'; i--)
+ {
+ base64Alphabet[i] = (byte)(i - 'A');
+ }
+ for (int i = 'z'; i >= 'a'; i--)
+ {
+ base64Alphabet[i] = (byte)(i - 'a' + 26);
+ }
+ for (int i = '9'; i >= '0'; i--)
+ {
+ base64Alphabet[i] = (byte)(i - '0' + 52);
+ }
+
+ base64Alphabet['+'] = 62;
+ base64Alphabet['/'] = 63;
+
+ for (int i = 0; i <= 25; i++)
+ {
+ lookUpBase64Alphabet[i] = (byte)('A' + i);
+ }
+
+ for (int i = 26, j = 0; i <= 51; i++, j++)
+ {
+ lookUpBase64Alphabet[i] = (byte)('a' + j);
+ }
+
+ for (int i = 52, j = 0; i <= 61; i++, j++)
+ {
+ lookUpBase64Alphabet[i] = (byte)('0' + j);
+ }
+
+ lookUpBase64Alphabet[62] = (byte)'+';
+ lookUpBase64Alphabet[63] = (byte)'/';
+ }
+
+ private Base64Codec()
+ {
+ }
+
+ public static boolean isArrayByteBase64(byte[] arrayOctect)
+ {
+ arrayOctect = discardWhitespace(arrayOctect);
+
+ int length = arrayOctect.length;
+ if (length == 0)
+ {
+ return true;
+ }
+ for (int i = 0; i < length; i++)
+ {
+ if (!isBase64(arrayOctect[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static byte[] encodeBase64(byte[] binaryData)
+ {
+ return (encodeBase64(binaryData, false));
+ }
+
+ public static byte[] decodeBase64(byte[] base64Data)
+ {
+ // RFC 2045 suggests line wrapping at (no more than) 76
+ // characters -- we may have embedded whitespace.
+ base64Data = discardWhitespace(base64Data);
+
+ // handle the edge case, so we don't have to worry about it later
+ if (base64Data.length == 0)
+ {
+ return new byte[0];
+ }
+
+ int numberQuadruple = base64Data.length / FOURBYTE;
+ byte decodedData[] = null;
+ byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
+
+ // Throw away anything not in base64Data
+
+ int encodedIndex = 0;
+ int dataIndex = 0;
+ {
+ // this sizes the output array properly - rlw
+ int lastData = base64Data.length;
+ // ignore the '=' padding
+ while (base64Data[lastData - 1] == PAD)
+ {
+ if (--lastData == 0)
+ {
+ return new byte[0];
+ }
+ }
+ decodedData = new byte[lastData - numberQuadruple];
+ }
+
+ for (int i = 0; i < numberQuadruple; i++)
+ {
+ dataIndex = i * 4;
+ marker0 = base64Data[dataIndex + 2];
+ marker1 = base64Data[dataIndex + 3];
+
+ b1 = base64Alphabet[base64Data[dataIndex]];
+ b2 = base64Alphabet[base64Data[dataIndex + 1]];
+
+ if (marker0 != PAD && marker1 != PAD)
+ {
+ //No PAD e.g 3cQl
+ b3 = base64Alphabet[marker0];
+ b4 = base64Alphabet[marker1];
+
+ decodedData[encodedIndex] = (byte)(b1 << 2 | b2 >> 4);
+ decodedData[encodedIndex + 1] =
+ (byte)(((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+ decodedData[encodedIndex + 2] = (byte)(b3 << 6 | b4);
+ }
+ else if (marker0 == PAD)
+ {
+ //Two PAD e.g. 3c[Pad][Pad]
+ decodedData[encodedIndex] = (byte)(b1 << 2 | b2 >> 4);
+ }
+ else if (marker1 == PAD)
+ {
+ //One PAD e.g. 3cQ[Pad]
+ b3 = base64Alphabet[marker0];
+
+ decodedData[encodedIndex] = (byte)(b1 << 2 | b2 >> 4);
+ decodedData[encodedIndex + 1] =
+ (byte)(((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+ }
+ encodedIndex += 3;
+ }
+ return decodedData;
+ }
+
+ private static byte[] encodeBase64Chunked(byte[] binaryData)
+ {
+ return (encodeBase64(binaryData, true));
+ }
+
+ private static boolean isBase64(byte octect)
+ {
+ if (octect == PAD)
+ {
+ return true;
+ }
+ else if (base64Alphabet[octect] == -1)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ private static byte[] encodeBase64(byte[] binaryData, boolean isChunked)
+ {
+ int lengthDataBits = binaryData.length * EIGHTBIT;
+ int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
+ int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
+ byte encodedData[] = null;
+ int encodedDataLength = 0;
+ int nbrChunks = 0;
+
+ if (fewerThan24bits != 0)
+ {
+ //data not divisible by 24 bit
+ encodedDataLength = (numberTriplets + 1) * 4;
+ }
+ else
+ {
+ // 16 or 8 bit
+ encodedDataLength = numberTriplets * 4;
+ }
+
+ // If the output is to be "chunked" into 76 character sections,
+ // for compliance with RFC 2045 MIME, then it is important to
+ // allow for extra length to account for the separator(s)
+ if (isChunked)
+ {
+
+ nbrChunks =
+ (CHUNK_SEPARATOR.length == 0
+ ? 0
+ : (int)Math.ceil((float)encodedDataLength / CHUNK_SIZE));
+ encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length;
+ }
+
+ encodedData = new byte[encodedDataLength];
+
+ byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
+
+ int encodedIndex = 0;
+ int dataIndex = 0;
+ int i = 0;
+ int nextSeparatorIndex = CHUNK_SIZE;
+ int chunksSoFar = 0;
+
+ //log.debug("number of triplets = " + numberTriplets);
+ for (i = 0; i < numberTriplets; i++)
+ {
+ dataIndex = i * 3;
+ b1 = binaryData[dataIndex];
+ b2 = binaryData[dataIndex + 1];
+ b3 = binaryData[dataIndex + 2];
+
+ //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
+
+ l = (byte)(b2 & 0x0f);
+ k = (byte)(b1 & 0x03);
+
+ byte val1 =
+ ((b1 & SIGN) == 0)
+ ? (byte)(b1 >> 2)
+ : (byte)((b1) >> 2 ^ 0xc0);
+ byte val2 =
+ ((b2 & SIGN) == 0)
+ ? (byte)(b2 >> 4)
+ : (byte)((b2) >> 4 ^ 0xf0);
+ byte val3 =
+ ((b3 & SIGN) == 0)
+ ? (byte)(b3 >> 6)
+ : (byte)((b3) >> 6 ^ 0xfc);
+
+ encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
+ //log.debug( "val2 = " + val2 );
+ //log.debug( "k4 = " + (k<<4) );
+ //log.debug( "vak = " + (val2 | (k<<4)) );
+ encodedData[encodedIndex + 1] =
+ lookUpBase64Alphabet[val2 | (k << 4)];
+ encodedData[encodedIndex + 2] =
+ lookUpBase64Alphabet[(l << 2) | val3];
+ encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f];
+
+ encodedIndex += 4;
+
+ // If we are chunking, let's put a chunk separator down.
+ if (isChunked)
+ {
+ // this assumes that CHUNK_SIZE % 4 == 0
+ if (encodedIndex == nextSeparatorIndex)
+ {
+ System.arraycopy(
+ CHUNK_SEPARATOR,
+ 0,
+ encodedData,
+ encodedIndex,
+ CHUNK_SEPARATOR.length);
+ chunksSoFar++;
+ nextSeparatorIndex =
+ (CHUNK_SIZE * (chunksSoFar + 1))
+ + (chunksSoFar * CHUNK_SEPARATOR.length);
+ encodedIndex += CHUNK_SEPARATOR.length;
+ }
+ }
+ }
+
+ // form integral number of 6-bit groups
+ dataIndex = i * 3;
+
+ if (fewerThan24bits == EIGHTBIT)
+ {
+ b1 = binaryData[dataIndex];
+ k = (byte)(b1 & 0x03);
+ //log.debug("b1=" + b1);
+ //log.debug("b1<<2 = " + (b1>>2) );
+ byte val1 =
+ ((b1 & SIGN) == 0)
+ ? (byte)(b1 >> 2)
+ : (byte)((b1) >> 2 ^ 0xc0);
+ encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
+ encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4];
+ encodedData[encodedIndex + 2] = PAD;
+ encodedData[encodedIndex + 3] = PAD;
+ }
+ else if (fewerThan24bits == SIXTEENBIT)
+ {
+
+ b1 = binaryData[dataIndex];
+ b2 = binaryData[dataIndex + 1];
+ l = (byte)(b2 & 0x0f);
+ k = (byte)(b1 & 0x03);
+
+ byte val1 =
+ ((b1 & SIGN) == 0)
+ ? (byte)(b1 >> 2)
+ : (byte)((b1) >> 2 ^ 0xc0);
+ byte val2 =
+ ((b2 & SIGN) == 0)
+ ? (byte)(b2 >> 4)
+ : (byte)((b2) >> 4 ^ 0xf0);
+
+ encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
+ encodedData[encodedIndex + 1] =
+ lookUpBase64Alphabet[val2 | (k << 4)];
+ encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
+ encodedData[encodedIndex + 3] = PAD;
+ }
+
+ if (isChunked)
+ {
+ // we also add a separator to the end of the final chunk.
+ if (chunksSoFar < nbrChunks)
+ {
+ System.arraycopy(
+ CHUNK_SEPARATOR,
+ 0,
+ encodedData,
+ encodedDataLength - CHUNK_SEPARATOR.length,
+ CHUNK_SEPARATOR.length);
+ }
+ }
+
+ return encodedData;
+ }
+
+ private static byte[] discardWhitespace(byte[] data)
+ {
+ byte groomedData[] = new byte[data.length];
+ int bytesCopied = 0;
+
+ for (int i = 0; i < data.length; i++)
+ {
+ switch (data[i])
+ {
+ case (byte)' ':
+ case (byte)'\n':
+ case (byte)'\r':
+ case (byte)'\t':
+ break;
+ default:
+ groomedData[bytesCopied++] = data[i];
+ }
+ }
+
+ byte packedData[] = new byte[bytesCopied];
+
+ System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
+
+ return packedData;
+ }
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/util/MethodTernaryTree.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/util/MethodTernaryTree.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/util/MethodTernaryTree.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/util/MethodTernaryTree.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,199 @@
+/*
+ * 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.util;
+
+
+/**
+ * Specialized ternary tree for method metadata information. <p>
+ * In JMX methods are referred to with the method name and the String[] representing the signature.
+ * One can decide to cache method information using as key a concatenation of method name + signature,
+ * but the cost of concatenation is very high, while hashmap access is fast.
+ * Ternary trees avoid string concatenation, and result to be 10x faster than concatenation + hashmap.
+ * However, the signature of a standard TernaryTree would be <code>Object get(Object[] key)</code> and
+ * <code>void put(Object[] key, Object value)</code>. Unfortunately normalizing method name + signature
+ * into a single array is also very expensive. <br>
+ * This version leaves method name and signature separated to have the fastest access possible to
+ * method information.
+ * See <a href="http://www.ddj.com/documents/s=921/ddj9804a/9804a.htm">here</a> for further information
+ * on TernaryTrees.
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class MethodTernaryTree
+{
+ private Node m_root;
+
+ /**
+ * Returns the method information given the method name and its signature.
+ * @see #put
+ */
+ public Object get(String methodName, String[] signature)
+ {
+ if (signature == null) {throw new IllegalArgumentException();}
+ return search(methodName, signature);
+ }
+
+ /**
+ * Inserts in this TernaryTree the given method information, using as key the method name and its signature
+ * @see #get
+ */
+ public void put(String methodName, String[] signature, Object information)
+ {
+ if (signature == null) {throw new IllegalArgumentException();}
+ m_root = insert(m_root, methodName, signature, signature.length, information);
+ }
+
+ private Object search(String methodName, String[] signature)
+ {
+ Node node = m_root;
+ int index = 0;
+ while (node != null)
+ {
+ Object key = index == 0 ? methodName : signature[index - 1];
+ if (key == null) {throw new IllegalArgumentException();}
+
+ int split = splitFunction(key);
+ if (split < node.splitValue)
+ {
+ node = node.left;
+ }
+ else if (split == node.splitValue)
+ {
+ if (index == signature.length)
+ {
+ // Two objects may return the same split, because the splitFunction is not perfect
+ // (ie does not always yield different values for different objects, eg hash functions)
+ if (node.keys == null) {return null;}
+ for (int i = 0; i < node.keys.length; ++i)
+ {
+ if (node.keys[i].equals(key))
+ {
+ return node.values[i];
+ }
+ }
+ return null;
+ }
+ else
+ {
+ ++index;
+ node = node.middle;
+ }
+ }
+ else
+ {
+ node = node.right;
+ }
+ }
+ return null;
+ }
+
+ private Node insert(Node node, String methodName, String[] signature, int length, Object value)
+ {
+ Object key = methodName;
+ if (key == null) {throw new IllegalArgumentException();}
+
+ int split = splitFunction(key);
+ if (node == null)
+ {
+ node = new Node();
+ node.splitValue = split;
+ }
+
+ if (split < node.splitValue)
+ {
+ node.left = insert(node.left, methodName, signature, length, value);
+ }
+ else if (split == node.splitValue)
+ {
+ // Two objects may return the same split, because the splitFunction is not perfect
+ // (ie does not always yield different values for different objects, eg hash functions)
+ if (length == 0)
+ {
+ if (node.keys == null)
+ {
+ node.keys = new Object[1];
+ node.values = new Object[1];
+ node.keys[0] = key;
+ node.values[0] = value;
+ }
+ else
+ {
+ // Loop to see if the key already exists
+ boolean found = false;
+ for (int i = 0; i < node.keys.length; ++i)
+ {
+ if (node.keys[i].equals(key))
+ {
+ // Already present, replace the value
+ node.keys[i] = key;
+ node.values[i] = value;
+ found = true;
+ break;
+ }
+ }
+ // Not present, add it
+ if (!found)
+ {
+ int len = node.keys.length;
+ Object[] olds = node.keys;
+ node.keys = new Object[len + 1];
+ System.arraycopy(olds, 0, node.keys, 0, len);
+ node.keys[len] = key;
+
+ olds = node.values;
+ node.values = new Object[len + 1];
+ System.arraycopy(olds, 0, node.values, 0, len);
+ node.values[len] = value;
+ }
+ }
+ }
+ else
+ {
+ node.middle = insert(node.middle, signature[signature.length - length], signature, length - 1, value);
+ }
+ }
+ else
+ {
+ node.right = insert(node.right, methodName, signature, length, value);
+ }
+
+ return node;
+ }
+
+ protected int splitFunction(Object obj)
+ {
+ return obj.hashCode();
+ }
+
+ private class Node
+ {
+ private int splitValue;
+ private Node right;
+ private Node middle;
+ private Node left;
+ private Object[] keys;
+ private Object[] values;
+ }
+}
Added: incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/util/Utils.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/util/Utils.java?rev=422696&view=auto
==============================================================================
--- incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/util/Utils.java (added)
+++ incubator/felix/trunk/org.apache.felix.mosgi.jmx.agent/src/main/java/org/apache/felix/mosgi/jmx/agent/mx4j/util/Utils.java Mon Jul 17 05:14:31 2006
@@ -0,0 +1,287 @@
+/*
+ * 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.util;
+
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+
+/**
+ * Several utility functions for the JMX implementation
+ *
+ * @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
+ * @version $Revision: 1.1.1.1 $
+ */
+public class Utils
+{
+ /**
+ * This methods load a class given the classloader and the name of the class, and work for
+ * extended names of primitive types. <p>
+ * If you try to do ClassLoader.loadClass("boolean") it barfs it cannot find the class,
+ * so this method cope with this problem.
+ */
+ public static Class loadClass(ClassLoader loader, String name) throws ClassNotFoundException
+ {
+ if (name == null) throw new ClassNotFoundException("null");
+
+ name = name.trim();
+ if (name.equals("boolean")) return boolean.class;
+ else if (name.equals("byte")) return byte.class;
+ else if (name.equals("char")) return char.class;
+ else if (name.equals("short")) return short.class;
+ else if (name.equals("int")) return int.class;
+ else if (name.equals("long")) return long.class;
+ else if (name.equals("float")) return float.class;
+ else if (name.equals("double")) return double.class;
+ else if (name.equals("java.lang.String")) return String.class;
+ else if (name.equals("java.lang.Object")) return Object.class;
+ else if (name.startsWith("["))
+ {
+ // It's an array, figure out how many dimensions
+ int dimension = 0;
+ while (name.charAt(dimension) == '[')
+ {
+ ++dimension;
+ }
+ char type = name.charAt(dimension);
+ Class cls = null;
+ switch (type)
+ {
+ case 'Z':
+ cls = boolean.class;
+ break;
+ case 'B':
+ cls = byte.class;
+ break;
+ case 'C':
+ cls = char.class;
+ break;
+ case 'S':
+ cls = short.class;
+ break;
+ case 'I':
+ cls = int.class;
+ break;
+ case 'J':
+ cls = long.class;
+ break;
+ case 'F':
+ cls = float.class;
+ break;
+ case 'D':
+ cls = double.class;
+ break;
+ case 'L':
+ // Strip the semicolon at the end
+ String n = name.substring(dimension + 1, name.length() - 1);
+ cls = loadClass(loader, n);
+ break;
+ }
+
+ if (cls == null)
+ {
+ throw new ClassNotFoundException(name);
+ }
+ else
+ {
+ int[] dim = new int[dimension];
+ return Array.newInstance(cls, dim).getClass();
+ }
+ }
+ else
+ {
+ if (loader != null)
+ return loader.loadClass(name);
+ else
+ return Class.forName(name, false, null);
+ }
+ }
+
+ /**
+ * Returns the classes whose names are specified by the <code>names</code> argument, loaded with the
+ * specified classloader.
+ */
+ public static Class[] loadClasses(ClassLoader loader, String[] names) throws ClassNotFoundException
+ {
+ int n = names.length;
+ Class[] cls = new Class[n];
+ for (int i = 0; i < n; ++i)
+ {
+ String name = names[i];
+ cls[i] = loadClass(loader, name);
+ }
+ return cls;
+ }
+
+ /**
+ * Returns true is the given method is a JMX attribute getter method
+ */
+ public static boolean isAttributeGetter(Method m)
+ {
+ if (m == null) return false;
+
+ String name = m.getName();
+ Class retType = m.getReturnType();
+ Class[] params = m.getParameterTypes();
+ if (retType != Void.TYPE && params.length == 0)
+ {
+ if (name.startsWith("get") && name.length() > 3) return true;
+ else if (name.startsWith("is") && retType == Boolean.TYPE) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the method is a JMX attribute setter method
+ */
+ public static boolean isAttributeSetter(Method m)
+ {
+ if (m == null) return false;
+
+ String name = m.getName();
+ Class retType = m.getReturnType();
+ Class[] params = m.getParameterTypes();
+ if (retType == Void.TYPE && params.length == 1 && name.startsWith("set") && name.length() > 3)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean wildcardMatch(String pattern, String string)
+ {
+ int stringLength = string.length();
+ int stringIndex = 0;
+ for (int patternIndex = 0; patternIndex < pattern.length(); ++patternIndex)
+ {
+ char c = pattern.charAt(patternIndex);
+ if (c == '*')
+ {
+ // Recurse with the pattern without this '*' and the actual string, until
+ // match is found or we inspected the whole string
+ while (stringIndex < stringLength)
+ {
+ if (wildcardMatch(pattern.substring(patternIndex + 1), string.substring(stringIndex)))
+ {
+ return true;
+ }
+ // No match found, try a shorter string, since we are matching '*'
+ ++stringIndex;
+ }
+ }
+ else if (c == '?')
+ {
+ // Increment the string index, since '?' match a single char in the string
+ ++stringIndex;
+ if (stringIndex > stringLength)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // A normal character in the pattern, must match the one in the string
+ if (stringIndex >= stringLength || c != string.charAt(stringIndex))
+ {
+ return false;
+ }
+ ++stringIndex;
+ }
+ }
+
+ // I've inspected the whole pattern, but not the whole string
+ return stringIndex == stringLength;
+ }
+
+ public static boolean arrayEquals(Object[] arr1, Object[] arr2)
+ {
+ if (arr1 == null && arr2 == null) return true;
+ if (arr1 == null ^ arr2 == null) return false;
+ if (!arr1.getClass().equals(arr2.getClass())) return false;
+ if (arr1.length != arr2.length) return false;
+
+ for (int i = 0; i < arr1.length; ++i)
+ {
+ Object obj1 = arr1[i];
+ Object obj2 = arr2[i];
+ if (obj1 == null ^ obj2 == null) return false;
+ if (obj1 != null && !obj1.equals(obj2)) return false;
+ }
+ return true;
+ }
+
+ public static boolean arrayEquals(byte[] arr1, byte[] arr2)
+ {
+ if (arr1 == null && arr2 == null) return true;
+ if (arr1 == null ^ arr2 == null) return false;
+ if (!arr1.getClass().equals(arr2.getClass())) return false;
+ if (arr1.length != arr2.length) return false;
+
+ for (int i = 0; i < arr1.length; ++i)
+ {
+ byte b1 = arr1[i];
+ byte b2 = arr2[i];
+ if (b1 != b2) return false;
+ }
+ return true;
+ }
+
+ public static int arrayHashCode(Object[] arr)
+ {
+ int hash = 0;
+ if (arr != null)
+ {
+ // Avoid that 2 arrays of length 0 but different classes return same hash
+ hash ^= arr.getClass().hashCode();
+ for (int i = 0; i < arr.length; ++i)
+ {
+ hash ^= arr[i] == null ? 0 : arr[i].hashCode();
+ }
+ }
+ return hash;
+ }
+
+ public static int arrayHashCode(byte[] arr)
+ {
+ int hash = 0;
+ if (arr != null)
+ {
+ // Avoid that 2 arrays of length 0 but different classes return same hash
+ hash ^= arr.getClass().hashCode();
+ for (int i = 0; i < arr.length; ++i)
+ {
+ hash ^= arr[i];
+ }
+ }
+ return hash;
+ }
+
+ public static char[] arrayCopy(char[] chars)
+ {
+ if (chars == null) return null;
+ char[] copy = new char[chars.length];
+ System.arraycopy(chars, 0, copy, 0, chars.length);
+ return copy;
+ }
+}