diff options
Diffstat (limited to 'sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument')
4 files changed, 621 insertions, 0 deletions
diff --git a/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/AnnotationDrivenDynamicMBean.java b/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/AnnotationDrivenDynamicMBean.java new file mode 100644 index 0000000000..3d16ff6a2a --- /dev/null +++ b/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/AnnotationDrivenDynamicMBean.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.tuscany.service.management.jmx.instrument; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.DynamicMBean; +import javax.management.InvalidAttributeValueException; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.ReflectionException; + +/** + * Dynamic MBean based on management annotations. + * + * @version $Revision$ $Date$ + */ +public class AnnotationDrivenDynamicMBean implements DynamicMBean { + + /** + * @see javax.management.DynamicMBean#getAttribute(java.lang.String) + */ + public Object getAttribute(String attribute) + throws AttributeNotFoundException, MBeanException, ReflectionException { + throw new UnsupportedOperationException(); + } + + /** + * @see javax.management.DynamicMBean#getAttributes(java.lang.String[]) + */ + public AttributeList getAttributes(String[] attributes) { + throw new UnsupportedOperationException(); + } + + /** + * @see javax.management.DynamicMBean#getMBeanInfo() + */ + public MBeanInfo getMBeanInfo() { + throw new UnsupportedOperationException(); + } + + /** + * @see javax.management.DynamicMBean#invoke(java.lang.String,java.lang.Object[],java.lang.String[]) + */ + public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, + ReflectionException { + throw new UnsupportedOperationException(); + } + + /** + * @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute) + */ + public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, + MBeanException, ReflectionException { + throw new UnsupportedOperationException(); + } + + /** + * @see javax.management.DynamicMBean#setAttributes(javax.management.AttributeList) + */ + public AttributeList setAttributes(AttributeList attributes) { + throw new UnsupportedOperationException(); + } + +} diff --git a/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentationException.java b/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentationException.java new file mode 100644 index 0000000000..a8ad1666d5 --- /dev/null +++ b/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentationException.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.tuscany.service.management.jmx.instrument; + +import org.apache.tuscany.api.TuscanyRuntimeException; + +/** + * Excpetion thrown when there is an instrumentation error. + * + * @version $Revison$ $Date$ + * + */ +@SuppressWarnings("serial") +public class InstrumentationException extends TuscanyRuntimeException { + + /** + * Initializes the root cause. + * @param cause Initializes the root cause. + */ + public InstrumentationException(Throwable cause) { + super(cause); + } + + /** + * Initializes the message. + * @param message Initializes the message. + */ + public InstrumentationException(String message) { + super(message); + } + +} diff --git a/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentedComponent.java b/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentedComponent.java new file mode 100644 index 0000000000..9e0f06ec13 --- /dev/null +++ b/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentedComponent.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.tuscany.service.management.jmx.instrument; + +import java.util.Map; +import java.net.URI; +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +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 org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.model.PropertyValue; + +/** + * This is Ruscany component exposed as a dynamic MBean. Currently it only supports a read-only vew of all the + * properties on the component. + * + * @version $Revision$ $Date$ + */ +public class InstrumentedComponent implements DynamicMBean { + + /** + * Properties available on the component. + */ + private final Map<String, PropertyValue<?>> properties; + + /** + * Name of the component. + */ + private URI componentId; + + /** + * Initializes the property values. + * + * @param component Component that is being managed. + */ + @SuppressWarnings("unchecked") + public InstrumentedComponent(final Component component) { + this.properties = component.getDefaultPropertyValues(); + this.componentId = component.getUri(); + } + + /** + * @see javax.management.DynamicMBean#getAttribute(java.lang.String) + */ + public final Object getAttribute(final String attribute) throws AttributeNotFoundException { + PropertyValue<?> propertyValue = properties.get(attribute); + if (propertyValue != null) { + return propertyValue.getValueFactory().getInstance(); + } + throw new AttributeNotFoundException(attribute + " not found."); + } + + /** + * @see javax.management.DynamicMBean#getAttributes(java.lang.String[]) + */ + public final AttributeList getAttributes(final String[] attributes) { + + AttributeList list = new AttributeList(); + for (String attribute : attributes) { + try { + list.add(new Attribute(attribute, getAttribute(attribute))); + } catch (AttributeNotFoundException ex) { + throw new InstrumentationException(ex); + } + } + return list; + + } + + /** + * @see javax.management.DynamicMBean#getMBeanInfo() + */ + public final MBeanInfo getMBeanInfo() { + + final MBeanConstructorInfo[] constructors = null; + final MBeanOperationInfo[] operations = null; + final MBeanNotificationInfo[] notifications = null; + + int size = properties != null ? properties.size() : 0; + final MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[size]; + + if(properties != null) { + int i = 0; + for (PropertyValue<?> propertyValue : properties.values()) { + attributes[i++] = + new MBeanAttributeInfo(propertyValue.getName(), String.class.getName(), null, true, false, false); + } + } + + return new MBeanInfo(componentId.toString(), null, attributes, constructors, operations, notifications); + + } + + /** + * @see javax.management.DynamicMBean#invoke(java.lang.String,java.lang.Object[],java.lang.String[]) + */ + public final Object invoke(final String actionName, final Object[] params, final String[] signature) { + throw new UnsupportedOperationException("Managed ops not supported"); + } + + /** + * @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute) + */ + public final void setAttribute(final Attribute attribute) { + throw new UnsupportedOperationException("Mutable props not supported"); + } + + /** + * @see javax.management.DynamicMBean#setAttributes(javax.management.AttributeList) + */ + public final AttributeList setAttributes(final AttributeList attributes) { + throw new UnsupportedOperationException("Mutable props not supported"); + } + +} diff --git a/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/ReflectedDynamicMBean.java b/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/ReflectedDynamicMBean.java new file mode 100644 index 0000000000..b07787208c --- /dev/null +++ b/sandbox/old/contrib/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/ReflectedDynamicMBean.java @@ -0,0 +1,353 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.tuscany.service.management.jmx.instrument; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.MethodDescriptor; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.DynamicMBean; +import javax.management.InvalidAttributeValueException; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.ReflectionException; + +/** + * Uses JMX dynamic MBean to expose management information of a delegate instance using reflection. Currently + * constructor and notification metadata are not supported. Any attribute or operation that needs to be excluded from + * the management information can be specified optionally in the factory method. + * <p/> + * All the methods and properties on <code>java.lang.Object</code> are excluded by default. Also only public and + * non-static members are made available for management. + * <p/> + * TODO Find a homw other than server.start for this class. TODO Tidy up, unit tests + * + * @version $Revsion$ $Date$ + */ +public class ReflectedDynamicMBean implements DynamicMBean { + + /** + * Excluded methods. + */ + private static final List<String> DEFAULT_EXCLUDED_METHODS = + Arrays.asList(new String[]{"wait", "toString", "hashCode", "notify", "equals", "notifyAll", "getClass"}); + + /** + * Excluded properties. + */ + private static final List<String> DEFAULT_EXCLUDED_PROPERTIES = Arrays.asList(new String[]{"class"}); + + /** + * Proxied object that is managed. + */ + private Object delegate; + + /** + * Runtime type of the managed object. + */ + private Class delegateClass; + + /** + * Delegate class name. + */ + private String delegateClassName; + + /** + * Cache of property write methods. + */ + private Map<String, Method> propertyWriteMethods = new HashMap<String, Method>(); + + /** + * Cache of property read methods. + */ + private Map<String, Method> propertyReadMethods = new HashMap<String, Method>(); + + /** + * Managed operation cache. + */ + private Map<String, Method> methods = new HashMap<String, Method>(); + + /** + * Property descriptor cache. + */ + private Map<String, PropertyDescriptor> properties = new HashMap<String, PropertyDescriptor>(); + + /** + * Excluded methods. + */ + private final List<String> excludedMethods = new ArrayList<String>(); + + /** + * Excluded properties. + */ + private final List<String> excludedProperties = new ArrayList<String>(); + + /** + * Introspects the bean and populate meta information. + * + * @param delegate Proxied managed instance. + */ + private ReflectedDynamicMBean(Object delegate) { + this(delegate, new ArrayList<String>(), new ArrayList<String>()); + } + + /** + * Introspects the bean and populate meta information. + * + * @param delegate Proxied managed instance. + * @param excludedMethods Operations excluded from managed view. + * @param excludedProperties Properties excluded from managed view. + */ + private ReflectedDynamicMBean(Object delegate, List<String> excludedMethods, List<String> excludedProperties) { + + this.delegate = delegate; + this.delegateClass = delegate.getClass(); + this.delegateClassName = delegateClass.getName(); + + this.excludedMethods.addAll(excludedMethods); + this.excludedMethods.addAll(DEFAULT_EXCLUDED_METHODS); + this.excludedProperties.addAll(excludedProperties); + this.excludedProperties.addAll(DEFAULT_EXCLUDED_PROPERTIES); + + BeanInfo beanInfo; + try { + beanInfo = Introspector.getBeanInfo(delegateClass); + } catch (IntrospectionException ex) { + throw new InstrumentationException(ex); + } + + cacheProperties(beanInfo); + + cacheMethods(beanInfo); + } + + /** + * Factory method for creating the management view. + * + * @param delegate Proxied managed instance. + * @param excludedMethods Operations excluded from managed view. + * @param excludedProperties Properties excluded from managed view. + * @return Proxy for the managed instance. + */ + public static ReflectedDynamicMBean newInstance(Object delegate, List<String> excludedMethods, + List<String> excludedProperties) { + return new ReflectedDynamicMBean(delegate, excludedMethods, excludedProperties); + } + + /** + * Factory method for creating the management view. + * + * @param delegate Proxied managed instance. + * @return Proxy for the managed instance. + */ + public static ReflectedDynamicMBean newInstance(Object delegate) { + return new ReflectedDynamicMBean(delegate); + } + + /** + * @see javax.management.DynamicMBean#getAttribute(java.lang.String) + */ + public Object getAttribute(String attribute) + throws AttributeNotFoundException, MBeanException, ReflectionException { + + Method readMethod = propertyReadMethods.get(attribute); + if (readMethod == null) { + throw new AttributeNotFoundException(attribute + " not found"); + } + try { + return readMethod.invoke(delegate); + } catch (IllegalAccessException ex) { + throw new ReflectionException(ex); + } catch (InvocationTargetException ex) { + throw new ReflectionException(ex); + } + + } + + /** + * @see javax.management.DynamicMBean#getAttributes(java.lang.String[]) + */ + public AttributeList getAttributes(String[] attributes) { + + AttributeList list = new AttributeList(); + for (String attribute : attributes) { + try { + list.add(new Attribute(attribute, getAttribute(attribute))); + } catch (AttributeNotFoundException ex) { + throw new InstrumentationException(ex); + } catch (MBeanException ex) { + throw new InstrumentationException(ex); + } catch (ReflectionException ex) { + throw new InstrumentationException(ex); + } + } + return list; + + } + + /** + * @see javax.management.DynamicMBean#getMBeanInfo() + */ + public MBeanInfo getMBeanInfo() { + + try { + + MBeanAttributeInfo[] attrs = new MBeanAttributeInfo[properties.keySet().size()]; + int count = 0; + for (String property : properties.keySet()) { + Method readMethod = propertyReadMethods.get(property); + Method writeMethod = propertyWriteMethods.get(property); + attrs[count++] = new MBeanAttributeInfo(property, "", readMethod, writeMethod); + } + + MBeanOperationInfo[] ops = new MBeanOperationInfo[methods.keySet().size()]; + count = 0; + for (Method method : methods.values()) { + ops[count++] = new MBeanOperationInfo("", method); + } + + MBeanInfo mBeanInfo = new MBeanInfo(delegateClassName, "", attrs, null, ops, null); + return mBeanInfo; + + } catch (javax.management.IntrospectionException ex) { + throw new InstrumentationException(ex); + } + + } + + /** + * @see javax.management.DynamicMBean#invoke(java.lang.String,java.lang.Object[],java.lang.String[]) + */ + public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, + ReflectionException { + + Method method = methods.get(actionName); + if (method == null) { + throw new InstrumentationException("Operation not found: " + actionName); + } + try { + return method.invoke(delegate, params); + } catch (IllegalAccessException ex) { + throw new ReflectionException(ex); + } catch (InvocationTargetException ex) { + throw new ReflectionException(ex); + } + + } + + /** + * @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute) + */ + public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, + MBeanException, ReflectionException { + + Method writeMethod = propertyWriteMethods.get(attribute.getName()); + if (writeMethod == null) { + throw new AttributeNotFoundException(attribute + " not found"); + } + try { + writeMethod.invoke(delegate, attribute.getValue()); + } catch (IllegalAccessException ex) { + throw new ReflectionException(ex); + } catch (InvocationTargetException ex) { + throw new ReflectionException(ex); + } + + } + + /** + * @see javax.management.DynamicMBean#setAttributes(javax.management.AttributeList) + */ + public AttributeList setAttributes(AttributeList attributes) { + throw new UnsupportedOperationException(); + } + + /** + * Caches managed operations. + * + * @param beanInfo Bean info for the managed instance. + */ + private void cacheMethods(BeanInfo beanInfo) { + + for (MethodDescriptor methodDescriptor : beanInfo.getMethodDescriptors()) { + + Method method = methodDescriptor.getMethod(); + String name = method.getName(); + + if (excludedMethods.contains(name)) { + continue; + } + int modifiers = method.getModifiers(); + if (!Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers)) { + continue; + } + if (propertyReadMethods.values().contains(method) || propertyWriteMethods.values().contains(method)) { + continue; + } + + // TODO Add support for overloaded methods + methods.put(name, method); + + } + + } + + /** + * Caches managed properties. + * + * @param beanInfo Bean info for the managed instance. + */ + private void cacheProperties(BeanInfo beanInfo) { + for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) { + + String name = propertyDescriptor.getName(); + + if (excludedProperties.contains(name)) { + continue; + } + properties.put(name, propertyDescriptor); + + Method readMethod = propertyDescriptor.getReadMethod(); + if (readMethod != null && Modifier.isPublic(readMethod.getModifiers())) { + propertyReadMethods.put(name, readMethod); + } + + Method writeMethod = propertyDescriptor.getWriteMethod(); + if (writeMethod != null && Modifier.isPublic(writeMethod.getModifiers())) { + propertyWriteMethods.put(name, writeMethod); + } + + } + } + +} |