001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.mx.capability;
023:
024: import org.jboss.mx.metadata.AttributeOperationResolver;
025: import org.jboss.mx.metadata.MethodMapper;
026:
027: import org.jboss.mx.server.ServerConstants;
028: import org.jboss.mx.util.PropertyAccess;
029:
030: import javax.management.DynamicMBean;
031: import javax.management.IntrospectionException;
032: import javax.management.MBeanAttributeInfo;
033: import javax.management.MBeanInfo;
034: import javax.management.MBeanOperationInfo;
035: import javax.management.Descriptor;
036: import javax.management.modelmbean.ModelMBeanAttributeInfo;
037: import java.lang.reflect.Method;
038:
039: /**
040: * Creates and binds a dispatcher
041: *
042: * @author <a href="mailto:trevor@protocool.com">Trevor Squires</a>.
043: * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>
044: */
045: public class DispatcherFactory implements ServerConstants {
046:
047: /**
048: * Creates a Dispatcher for an arbitrary resource. Useful for when you don't care
049: * about the AttributeOperationResolver.
050: */
051: public static DynamicMBean create(MBeanInfo info, Object resource)
052: throws IntrospectionException {
053: return create(info, resource, new AttributeOperationResolver(
054: info));
055: }
056:
057: /**
058: * Creates a dispatcher for an arbitrary resource using the named AttributeOperationResolver.
059: */
060: public static DynamicMBean create(MBeanInfo info, Object resource,
061: AttributeOperationResolver resolver)
062: throws IntrospectionException {
063: if (null == info) {
064: throw new IllegalArgumentException("info cannot be null");
065: }
066:
067: if (null == resolver) {
068: throw new IllegalArgumentException(
069: "resolver cannot be null");
070: }
071:
072: if (null == resource) {
073: throw new IllegalArgumentException(
074: "resource cannot be null");
075: }
076:
077: MethodMapper mmap = new MethodMapper(resource.getClass());
078: ReflectedMBeanDispatcher dispatcher = new ReflectedMBeanDispatcher(
079: info, resolver, resource);
080:
081: String flag = PropertyAccess.getProperty(
082: OPTIMIZE_REFLECTED_DISPATCHER, "false");
083: if (flag.equalsIgnoreCase("true")) {
084: // FIXME: subclassing for now so I can rely on the reflection based implementation for the parts
085: // that aren't implemented yet
086: dispatcher = OptimizedMBeanDispatcher
087: .create(info, resource /*, parent classloader */);
088: }
089:
090: MBeanAttributeInfo[] attributes = info.getAttributes();
091: for (int i = 0; i < attributes.length; i++) {
092: MBeanAttributeInfo attribute = attributes[i];
093: Method getter = null;
094: Method setter = null;
095:
096: if (attribute.isReadable()) {
097: if (attribute instanceof ModelMBeanAttributeInfo) {
098: ModelMBeanAttributeInfo mmbAttribute = (ModelMBeanAttributeInfo) attribute;
099: Descriptor desc = mmbAttribute.getDescriptor();
100: if (desc != null
101: && desc.getFieldValue("getMethod") != null) {
102: getter = mmap.lookupGetter(mmbAttribute);
103: if (getter == null) {
104: throw new IntrospectionException(
105: "no getter method found for attribute: "
106: + attribute.getName());
107: }
108: }
109: } else {
110: getter = mmap.lookupGetter(attribute);
111: if (getter == null) {
112: throw new IntrospectionException(
113: "no getter method found for attribute: "
114: + attribute.getName());
115: }
116: }
117: }
118:
119: if (attribute.isWritable()) {
120: if (attribute instanceof ModelMBeanAttributeInfo) {
121: ModelMBeanAttributeInfo mmbAttribute = (ModelMBeanAttributeInfo) attribute;
122: Descriptor desc = mmbAttribute.getDescriptor();
123: if (desc != null
124: && desc.getFieldValue("setMethod") != null) {
125: setter = mmap.lookupSetter(mmbAttribute);
126: if (setter == null) {
127: throw new IntrospectionException(
128: "no setter method found for attribute: "
129: + attribute.getName());
130: }
131: }
132: } else {
133: setter = mmap.lookupSetter(attribute);
134: if (setter == null) {
135: throw new IntrospectionException(
136: "no setter method found for attribute: "
137: + attribute.getName());
138: }
139: }
140: }
141:
142: dispatcher.bindAttributeAt(i, getter, setter);
143: }
144:
145: MBeanOperationInfo[] operations = info.getOperations();
146: for (int i = 0; i < operations.length; i++) {
147: MBeanOperationInfo operation = operations[i];
148: Method method = mmap.lookupOperation(operation);
149: if (method == null) {
150: throw new IntrospectionException(
151: "no method found for operation: "
152: + operation.getName()); // FIXME better error!
153: }
154:
155: dispatcher.bindOperationAt(i, method);
156: }
157:
158: return dispatcher;
159: }
160: }
|