diff options
author | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-11 23:26:33 +0000 |
---|---|---|
committer | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-11 23:26:33 +0000 |
commit | a40e527938d76ba71f211da7e327adb50384ba69 (patch) | |
tree | cb8f99f1727122b040a3f0fbb6649292b6a74302 /sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org | |
parent | 968721109881107520d7aefa91d7fcc0519d7739 (diff) |
Moving 1.x tags
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835157 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org')
10 files changed, 1092 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/JmxException.java b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/JmxException.java new file mode 100644 index 0000000000..5b50affdf2 --- /dev/null +++ b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/JmxException.java @@ -0,0 +1,39 @@ +/* + * 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; + +import org.apache.tuscany.api.TuscanyRuntimeException; + +/** + * Maps JMX exceptions to runtime exceptions. + * + * @version $Revision$ $Date$ + */ +@SuppressWarnings("serial") +public class JmxException extends TuscanyRuntimeException { + + /** + * Initializes the root cause. + * @param cause Initializes the root cause. + */ + public JmxException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/JmxManagementService.java b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/JmxManagementService.java new file mode 100644 index 0000000000..2905a50c54 --- /dev/null +++ b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/JmxManagementService.java @@ -0,0 +1,74 @@ +/* + * 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; + +import javax.management.JMException; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.apache.tuscany.service.management.jmx.instrument.InstrumentedComponent; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.services.management.TuscanyManagementService; + +/** + * JMX implementation of the management service. + * + * @version $Revision$ $Date$ + */ +public class JmxManagementService implements TuscanyManagementService { + + /** + * MBean server used by the JMX management service. + */ + private final MBeanServer mBeanServer; + + /** + * Management domain used by the runtime. + */ + private final String managementDomain; + + + /** + * Constructor that initializes the MBeanServer and domain to use for registering components. + * + * @param mBeanServer the MBeanServer components should be registered with + * @param managementDomain the JMX domain to use when generating ObjectNames + */ + public JmxManagementService(MBeanServer mBeanServer, String managementDomain) { + this.mBeanServer = mBeanServer; + this.managementDomain = managementDomain; + } + + /** + * @throws JmxException In case of an unexpected JMX exception. + * @see org.apache.tuscany.spi.services.management.TuscanyManagementService#registerComponent( + *java.lang.String,org.apache.tuscany.spi.component.Component) + */ + public final void registerComponent(String name, Component component) throws JmxException { + + try { + ObjectName on = new ObjectName(managementDomain + ":" + "type=component,name=" + name); + InstrumentedComponent mbean = new InstrumentedComponent(component); + mBeanServer.registerMBean(mbean, on); + } catch (JMException ex) { + throw new JmxException(ex); + } + + } +} diff --git a/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/AbstractAgent.java b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/AbstractAgent.java new file mode 100644 index 0000000000..0172b15d8c --- /dev/null +++ b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/AbstractAgent.java @@ -0,0 +1,154 @@ +/* + * 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.agent; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.ObjectName; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; + +/** + * Abstract super class for all the agents. + * @version $Revison$ $Date$ + * + */ +public abstract class AbstractAgent implements Agent { + + /** Root domain */ + private static final String DOMAIN = "tuscany"; + + /** MBean server to use. */ + private MBeanServer mBeanServer; + + /** Start flag. */ + private AtomicBoolean started = new AtomicBoolean(); + + /** RMI connector adaptor. */ + private JMXConnectorServer connectorServer; + + /** + * Initialies the server. + * @throws ManagementException If unable to start the agent. + */ + protected AbstractAgent() throws ManagementException { + mBeanServer = MBeanServerFactory.createMBeanServer(DOMAIN); + } + + /** + * @see org.apache.tuscany.service.management.jmx.agent.Agent#getMBeanServer() + */ + public MBeanServer getMBeanServer() { + return mBeanServer; + } + + /** + * @see org.apache.tuscany.service.management.jmx.agent.Agent#register(java.lang.Object, java.lang.String) + */ + public final void register(Object instance, String name) throws ManagementException { + + try { + mBeanServer.registerMBean(instance, new ObjectName(name)); + } catch (Exception ex) { + throw new ManagementException(ex); + } + + } + + /** + * @see org.apache.tuscany.service.management.jmx.agent.Agent#start() + */ + public final void start() throws ManagementException { + + try { + + if(started.get()) { + throw new IllegalArgumentException("Agent already started"); + } + + preStart(); + + JMXServiceURL url = getAdaptorUrl(); + connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mBeanServer); + + connectorServer.start(); + + started.set(true); + + } catch (MalformedURLException ex) { + throw new ManagementException(ex); + } catch (IOException ex) { + throw new ManagementException(ex); + } + + } + + /** + * @see org.apache.tuscany.service.management.jmx.agent.Agent#shutdown() + */ + public final void shutdown() throws ManagementException { + + try { + + if(!started.get()) { + throw new IllegalArgumentException("Agent not started"); + } + + connectorServer.stop(); + postStop(); + started.set(false); + + } catch (IOException ex) { + throw new ManagementException(ex); + } + + } + + /** + * Gets the underlying MBean server. + * @return A reference to the mbean server. + */ + protected MBeanServer getMbeanServer() { + return mBeanServer; + } + + /** + * Gets the adaptor URL. + * @return Adaptor URL. + */ + protected abstract JMXServiceURL getAdaptorUrl(); + + /** + * Any initialiation required for protocol specific agent. + * + */ + protected abstract void preStart(); + + /** + * Any initialiation required for protocol specific agent. + * + */ + protected abstract void postStop(); + +} diff --git a/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/Agent.java b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/Agent.java new file mode 100644 index 0000000000..30727e21bf --- /dev/null +++ b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/Agent.java @@ -0,0 +1,56 @@ +/* + * 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.agent; + +import javax.management.MBeanServer; + +/** + * Interface to a JMX agent. + * @version $Revision$ $Date$ + * + */ +public interface Agent { + + /** + * Registers a managed bean. + * @param instance Instance to be registered. + * @param name Object name of the instance. + * @throws ManagementException If unable to register the object. + */ + void register(Object instance, String name) throws ManagementException; + + /** + * Starts the JMX server. + * @throws ManagementException If unable to start the server. + */ + void start() throws ManagementException; + + /** + * Shuts down the JMX server. + * @throws ManagementException If unable to shutdown the server. + */ + void shutdown() throws ManagementException; + + /** + * Gets the MBean server used by the agent. + * @return MBean server used by the agent. + */ + MBeanServer getMBeanServer(); + +} diff --git a/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/ManagementException.java b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/ManagementException.java new file mode 100644 index 0000000000..6ff8c14ac6 --- /dev/null +++ b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/ManagementException.java @@ -0,0 +1,37 @@ +/* + * 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.agent; + +import org.apache.tuscany.api.TuscanyRuntimeException; + +/** + * @version $Revision$ $Date$ + * + */ +@SuppressWarnings("serial") +public class ManagementException extends TuscanyRuntimeException { + + /** + * Initializes the root cause. + * @param th Root cause. + */ + public ManagementException(Throwable th) { + super(th); + } +} diff --git a/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/RmiAgent.java b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/RmiAgent.java new file mode 100644 index 0000000000..593f6fec90 --- /dev/null +++ b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/agent/RmiAgent.java @@ -0,0 +1,114 @@ +/* + * 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.agent; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.UnicastRemoteObject; + +import javax.management.remote.JMXServiceURL; + +/** + * Utility for starting the JMX server with an RMI agent. + * + * @version $Revsion$ $Date$ + * + */ +public class RmiAgent extends AbstractAgent { + + /** Administration port system property. */ + private static final String ADMIN_PORT_PROPERTY = "tuscany.adminPort"; + + /** Default admin port. */ + private static final int DEFAULT_ADMIN_PORT = 1099; + + /** Instance */ + private static final Agent INSTANCE = new RmiAgent(); + + /** RMI registry. */ + private Registry registry; + + /** Listen port */ + private int port = DEFAULT_ADMIN_PORT; + + /** + * Gets the adaptor URL. + * @return Adaptor URL used by the agent. + * @throws ManagementException If unable to start the agent. + */ + protected JMXServiceURL getAdaptorUrl() throws ManagementException { + + try { + + String portValue = System.getProperty(ADMIN_PORT_PROPERTY); + if(portValue != null) { + port = Integer.parseInt(portValue); + } + + // service:jmx:rmi:///jndi/rmi://localhost:1099/server + return new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + port + "/server"); + + + } catch (MalformedURLException ex) { + throw new ManagementException(ex); + } + + } + + /** + * Returns the singleton agent instance. + * @return Agent instance. + * @throws ManagementException If unable to start the agent. + */ + public static Agent getInstance() throws ManagementException { + return INSTANCE; + } + + /** + * @see org.apache.tuscany.service.management.jmx.agent.AbstractAgent#preStart() + */ + @Override + public void preStart() throws ManagementException { + + try { + registry = LocateRegistry.createRegistry(port); + } catch (RemoteException ex) { + throw new ManagementException(ex); + } + + } + + /** + * @see org.apache.tuscany.service.management.jmx.agent.AbstractAgent#postStop() + */ + @Override + public void postStop() throws ManagementException { + + try { + UnicastRemoteObject.unexportObject(registry, true); + } catch (IOException ex) { + throw new ManagementException(ex); + } + + } + +} diff --git a/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/AnnotationDrivenDynamicMBean.java b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/AnnotationDrivenDynamicMBean.java new file mode 100644 index 0000000000..3d16ff6a2a --- /dev/null +++ b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/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/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentationException.java b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentationException.java new file mode 100644 index 0000000000..a8ad1666d5 --- /dev/null +++ b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/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/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentedComponent.java b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentedComponent.java new file mode 100644 index 0000000000..2fccdc00f0 --- /dev/null +++ b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/InstrumentedComponent.java @@ -0,0 +1,135 @@ +/* + * 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; + + final MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[properties.size()]; + + 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/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/ReflectedDynamicMBean.java b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/jmx/src/main/java/org/apache/tuscany/service/management/jmx/instrument/ReflectedDynamicMBean.java new file mode 100644 index 0000000000..b07787208c --- /dev/null +++ b/sca-java-1.x/tags/runtime/2.0-alpha-incubating/services/management/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); + } + + } + } + +} |