blob: 25bd03d04b222c424e1d2198e3f3916acad23832 [file] [log] [blame]
/*
* 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.mina.integration.jmx;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.beans.PropertyEditor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import javax.management.Attribute;
import javax.management.AttributeChangeNotification;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.RuntimeOperationsException;
import javax.management.modelmbean.InvalidTargetObjectTypeException;
import javax.management.modelmbean.ModelMBean;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanConstructorInfo;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import javax.management.modelmbean.ModelMBeanNotificationInfo;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import ognl.ExpressionSyntaxException;
import ognl.InappropriateExpressionException;
import ognl.NoSuchPropertyException;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import ognl.OgnlRuntime;
import ognl.TypeConverter;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.filterchain.IoFilter;
import org.apache.mina.core.filterchain.IoFilterChain;
import org.apache.mina.core.filterchain.IoFilterChainBuilder;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.service.IoService;
import org.apache.mina.core.service.TransportMetadata;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.core.session.IoSessionDataStructureFactory;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.integration.beans.CollectionEditor;
import org.apache.mina.integration.beans.ListEditor;
import org.apache.mina.integration.beans.MapEditor;
import org.apache.mina.integration.beans.PropertyEditorFactory;
import org.apache.mina.integration.beans.SetEditor;
import org.apache.mina.integration.ognl.IoFilterPropertyAccessor;
import org.apache.mina.integration.ognl.IoServicePropertyAccessor;
import org.apache.mina.integration.ognl.IoSessionPropertyAccessor;
import org.apache.mina.integration.ognl.PropertyTypeConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A {@link ModelMBean} wrapper implementation for a POJO.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*
* @param <T> the type of the managed object
*/
public class ObjectMBean<T> implements ModelMBean, MBeanRegistration {
private static final Map<ObjectName, Object> sources = new ConcurrentHashMap<ObjectName, Object>();
/**
* Get the monitored object
*
* @param oname The object name
* @return The monitored object
*/
public static Object getSource(ObjectName oname) {
return sources.get(oname);
}
static {
OgnlRuntime.setPropertyAccessor(IoService.class, new IoServicePropertyAccessor());
OgnlRuntime.setPropertyAccessor(IoSession.class, new IoSessionPropertyAccessor());
OgnlRuntime.setPropertyAccessor(IoFilter.class, new IoFilterPropertyAccessor());
}
protected final static Logger LOGGER = LoggerFactory.getLogger(ObjectMBean.class);
private final T source;
private final TransportMetadata transportMetadata;
private final MBeanInfo info;
private final Map<String, PropertyDescriptor> propertyDescriptors = new HashMap<String, PropertyDescriptor>();
private final TypeConverter typeConverter = new OgnlTypeConverter();
private volatile MBeanServer server;
private volatile ObjectName name;
/**
* Creates a new instance with the specified POJO.
*
* @param source The original POJO
*/
public ObjectMBean(T source) {
if (source == null) {
throw new IllegalArgumentException("source");
}
this.source = source;
if (source instanceof IoService) {
transportMetadata = ((IoService) source).getTransportMetadata();
} else if (source instanceof IoSession) {
transportMetadata = ((IoSession) source).getTransportMetadata();
} else {
transportMetadata = null;
}
this.info = createModelMBeanInfo(source);
}
public final Object getAttribute(String fqan) throws AttributeNotFoundException, MBeanException,
ReflectionException {
try {
return convertValue(source.getClass(), fqan, getAttribute0(fqan), false);
} catch (AttributeNotFoundException e) {
// Do nothing
} catch (Exception e) {
throwMBeanException(e);
}
// Check if the attribute exist, if not throw an exception
PropertyDescriptor pdesc = propertyDescriptors.get(fqan);
if (pdesc == null) {
throwMBeanException(new IllegalArgumentException("Unknown attribute: " + fqan));
}
try {
Object parent = getParent(fqan);
boolean writable = isWritable(source.getClass(), pdesc);
return convertValue(parent.getClass(), getLeafAttributeName(fqan),
getAttribute(source, fqan, pdesc.getPropertyType()), writable);
} catch (Exception e) {
throwMBeanException(e);
}
throw new IllegalStateException();
}
public final void setAttribute(Attribute attribute) throws AttributeNotFoundException, MBeanException,
ReflectionException {
String aname = attribute.getName();
Object avalue = attribute.getValue();
try {
setAttribute0(aname, avalue);
} catch (AttributeNotFoundException e) {
// Do nothing
} catch (Exception e) {
throwMBeanException(e);
}
PropertyDescriptor pdesc = propertyDescriptors.get(aname);
if (pdesc == null) {
throwMBeanException(new IllegalArgumentException("Unknown attribute: " + aname));
}
try {
PropertyEditor e = getPropertyEditor(getParent(aname).getClass(), pdesc.getName(), pdesc.getPropertyType());
e.setAsText((String) avalue);
OgnlContext ctx = (OgnlContext) Ognl.createDefaultContext(source);
ctx.setTypeConverter(typeConverter);
Ognl.setValue(aname, ctx, source, e.getValue());
} catch (Exception e) {
throwMBeanException(e);
}
}
public final Object invoke(String name, Object params[], String signature[]) throws MBeanException,
ReflectionException {
// Handle synthetic operations first.
if (name.equals("unregisterMBean")) {
try {
server.unregisterMBean(this.name);
return null;
} catch (InstanceNotFoundException e) {
throwMBeanException(e);
}
}
try {
return convertValue(null, null, invoke0(name, params, signature), false);
} catch (NoSuchMethodException e) {
// Do nothing
} catch (Exception e) {
throwMBeanException(e);
}
// And then try reflection.
Class<?>[] paramTypes = new Class[signature.length];
for (int i = 0; i < paramTypes.length; i++) {
try {
paramTypes[i] = getAttributeClass(signature[i]);
} catch (ClassNotFoundException e) {
throwMBeanException(e);
}
PropertyEditor e = getPropertyEditor(source.getClass(), "p" + i, paramTypes[i]);
if (e == null) {
throwMBeanException(new RuntimeException("Conversion failure: " + params[i]));
}
e.setValue(params[i]);
params[i] = e.getAsText();
}
try {
// Find the right method.
for (Method m : source.getClass().getMethods()) {
if (!m.getName().equalsIgnoreCase(name)) {
continue;
}
Class<?>[] methodParamTypes = m.getParameterTypes();
if (methodParamTypes.length != params.length) {
continue;
}
Object[] convertedParams = new Object[params.length];
for (int i = 0; i < params.length; i++) {
if (Iterable.class.isAssignableFrom(methodParamTypes[i])) {
// Generics are not supported.
convertedParams = null;
break;
}
PropertyEditor e = getPropertyEditor(source.getClass(), "p" + i, methodParamTypes[i]);
if (e == null) {
convertedParams = null;
break;
}
e.setAsText((String) params[i]);
convertedParams[i] = e.getValue();
}
if (convertedParams == null) {
continue;
}
return convertValue(m.getReturnType(), "returnValue", m.invoke(source, convertedParams), false);
}
// No methods matched.
throw new IllegalArgumentException("Failed to find a matching operation: " + name);
} catch (Exception e) {
throwMBeanException(e);
}
throw new IllegalStateException();
}
/**
* @return The monitored object
*/
public final T getSource() {
return source;
}
/**
* @return The MBrean server
*/
public final MBeanServer getServer() {
return server;
}
/**
* @return The monitored object name
*/
public final ObjectName getName() {
return name;
}
public final MBeanInfo getMBeanInfo() {
return info;
}
public final AttributeList getAttributes(String names[]) {
AttributeList answer = new AttributeList();
for (int i = 0; i < names.length; i++) {
try {
answer.add(new Attribute(names[i], getAttribute(names[i])));
} catch (Exception e) {
// Ignore.
}
}
return answer;
}
public final AttributeList setAttributes(AttributeList attributes) {
// Prepare and return our response, eating all exceptions
String names[] = new String[attributes.size()];
int n = 0;
Iterator<Object> items = attributes.iterator();
while (items.hasNext()) {
Attribute item = (Attribute) items.next();
names[n++] = item.getName();
try {
setAttribute(item);
} catch (Exception e) {
// Ignore all exceptions
}
}
return getAttributes(names);
}
public final void setManagedResource(Object resource, String type) throws InstanceNotFoundException,
InvalidTargetObjectTypeException, MBeanException {
throw new RuntimeOperationsException(new UnsupportedOperationException());
}
public final void setModelMBeanInfo(ModelMBeanInfo info) throws MBeanException {
throw new RuntimeOperationsException(new UnsupportedOperationException());
}
@Override
public final String toString() {
return (source == null ? "" : source.toString());
}
public void addAttributeChangeNotificationListener(NotificationListener listener, String name, Object handback) {
// Do nothing
}
public void removeAttributeChangeNotificationListener(NotificationListener listener, String name)
throws ListenerNotFoundException {
// Do nothing
}
public void sendAttributeChangeNotification(AttributeChangeNotification notification) throws MBeanException {
throw new RuntimeOperationsException(new UnsupportedOperationException());
}
public void sendAttributeChangeNotification(Attribute oldValue, Attribute newValue) throws MBeanException {
throw new RuntimeOperationsException(new UnsupportedOperationException());
}
public void sendNotification(Notification notification) throws MBeanException {
throw new RuntimeOperationsException(new UnsupportedOperationException());
}
public void sendNotification(String message) throws MBeanException {
throw new RuntimeOperationsException(new UnsupportedOperationException());
}
public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback)
throws IllegalArgumentException {
// Do nothing
}
public MBeanNotificationInfo[] getNotificationInfo() {
return new MBeanNotificationInfo[0];
}
public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
// Do nothing
}
public void load() throws InstanceNotFoundException, MBeanException, RuntimeOperationsException {
throw new RuntimeOperationsException(new UnsupportedOperationException());
}
public void store() throws InstanceNotFoundException, MBeanException, RuntimeOperationsException {
throw new RuntimeOperationsException(new UnsupportedOperationException());
}
public final ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
this.server = server;
this.name = name;
return name;
}
public final void postRegister(Boolean registrationDone) {
if (registrationDone) {
sources.put(name, source);
}
}
public final void preDeregister() throws Exception {
// Do nothing
}
public final void postDeregister() {
sources.remove(name);
this.server = null;
this.name = null;
}
private MBeanInfo createModelMBeanInfo(T source) {
String className = source.getClass().getName();
String description = "";
ModelMBeanConstructorInfo[] constructors = new ModelMBeanConstructorInfo[0];
ModelMBeanNotificationInfo[] notifications = new ModelMBeanNotificationInfo[0];
List<ModelMBeanAttributeInfo> attributes = new ArrayList<ModelMBeanAttributeInfo>();
List<ModelMBeanOperationInfo> operations = new ArrayList<ModelMBeanOperationInfo>();
addAttributes(attributes, source);
addExtraAttributes(attributes);
addOperations(operations, source);
addExtraOperations(operations);
operations.add(new ModelMBeanOperationInfo("unregisterMBean", "unregisterMBean", new MBeanParameterInfo[0],
void.class.getName(), ModelMBeanOperationInfo.ACTION));
return new ModelMBeanInfoSupport(className, description,
attributes.toArray(new ModelMBeanAttributeInfo[attributes.size()]), constructors,
operations.toArray(new ModelMBeanOperationInfo[operations.size()]), notifications);
}
private void addAttributes(List<ModelMBeanAttributeInfo> attributes, Object object) {
addAttributes(attributes, object, object.getClass(), "");
}
private void addAttributes(List<ModelMBeanAttributeInfo> attributes, Object object, Class<?> type, String prefix) {
PropertyDescriptor[] pdescs;
try {
pdescs = Introspector.getBeanInfo(type).getPropertyDescriptors();
} catch (IntrospectionException e) {
return;
}
for (PropertyDescriptor pdesc : pdescs) {
// Ignore a write-only property.
if (pdesc.getReadMethod() == null) {
continue;
}
// Ignore unmanageable property.
String attrName = pdesc.getName();
Class<?> attrType = pdesc.getPropertyType();
if (attrName.equals("class")) {
continue;
}
if (!isReadable(type, attrName)) {
continue;
}
// Expand if possible.
if (isExpandable(type, attrName)) {
expandAttribute(attributes, object, prefix, pdesc);
continue;
}
// Ordinary property.
String fqan = prefix + attrName;
boolean writable = isWritable(type, pdesc);
attributes.add(new ModelMBeanAttributeInfo(fqan, convertType(object.getClass(), attrName, attrType,
writable).getName(), pdesc.getShortDescription(), true, writable, false));
propertyDescriptors.put(fqan, pdesc);
}
}
private boolean isWritable(Class<?> type, PropertyDescriptor pdesc) {
if (type == null) {
throw new IllegalArgumentException("type");
}
if (pdesc == null) {
return false;
}
String attrName = pdesc.getName();
Class<?> attrType = pdesc.getPropertyType();
boolean writable = (pdesc.getWriteMethod() != null) || isWritable(type, attrName);
if (getPropertyEditor(type, attrName, attrType) == null) {
writable = false;
}
return writable;
}
private void expandAttribute(List<ModelMBeanAttributeInfo> attributes, Object object, String prefix,
PropertyDescriptor pdesc) {
Object property;
String attrName = pdesc.getName();
try {
property = getAttribute(object, attrName, pdesc.getPropertyType());
} catch (Exception e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Unexpected exception.", e);
}
return;
}
if (property == null) {
return;
}
addAttributes(attributes, property, property.getClass(), prefix + attrName + '.');
}
private void addOperations(List<ModelMBeanOperationInfo> operations, Object object) {
for (Method m : object.getClass().getMethods()) {
String mname = m.getName();
// Ignore getters and setters.
if (mname.startsWith("is") || mname.startsWith("get") || mname.startsWith("set")) {
continue;
}
// Ignore Object methods.
if (mname.matches("(wait|notify|notifyAll|toString|equals|compareTo|hashCode|clone)")) {
continue;
}
// Ignore other user-defined non-operations.
if (!isOperation(mname, m.getParameterTypes())) {
continue;
}
List<MBeanParameterInfo> signature = new ArrayList<MBeanParameterInfo>();
int i = 1;
for (Class<?> paramType : m.getParameterTypes()) {
String paramName = "p" + (i++);
if (getPropertyEditor(source.getClass(), paramName, paramType) == null) {
continue;
}
signature.add(new MBeanParameterInfo(paramName, convertType(null, null, paramType, true).getName(),
paramName));
}
Class<?> returnType = convertType(null, null, m.getReturnType(), false);
operations.add(new ModelMBeanOperationInfo(m.getName(), m.getName(), signature
.toArray(new MBeanParameterInfo[signature.size()]), returnType.getName(),
ModelMBeanOperationInfo.ACTION));
}
}
private Object getParent(String fqan) throws OgnlException {
Object parent;
int dotIndex = fqan.lastIndexOf('.');
if (dotIndex < 0) {
parent = source;
} else {
parent = getAttribute(source, fqan.substring(0, dotIndex), null);
}
return parent;
}
private String getLeafAttributeName(String fqan) {
int dotIndex = fqan.lastIndexOf('.');
if (dotIndex < 0) {
return fqan;
}
return fqan.substring(dotIndex + 1);
}
private Class<?> getAttributeClass(String signature) throws ClassNotFoundException {
if (signature.equals(Boolean.TYPE.getName())) {
return Boolean.TYPE;
}
if (signature.equals(Byte.TYPE.getName())) {
return Byte.TYPE;
}
if (signature.equals(Character.TYPE.getName())) {
return Character.TYPE;
}
if (signature.equals(Double.TYPE.getName())) {
return Double.TYPE;
}
if (signature.equals(Float.TYPE.getName())) {
return Float.TYPE;
}
if (signature.equals(Integer.TYPE.getName())) {
return Integer.TYPE;
}
if (signature.equals(Long.TYPE.getName())) {
return Long.TYPE;
}
if (signature.equals(Short.TYPE.getName())) {
return Short.TYPE;
}
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl != null) {
return cl.loadClass(signature);
}
} catch (ClassNotFoundException e) {
// Do nothing
}
return Class.forName(signature);
}
private Object getAttribute(Object object, String fqan, Class<?> attrType) throws OgnlException {
Object property;
OgnlContext ctx = (OgnlContext) Ognl.createDefaultContext(object);
ctx.setTypeConverter(new OgnlTypeConverter());
if (attrType == null) {
property = Ognl.getValue(fqan, ctx, object);
} else {
property = Ognl.getValue(fqan, ctx, object, attrType);
}
return property;
}
private Class<?> convertType(Class<?> type, String attrName, Class<?> attrType, boolean writable) {
if ((attrName != null) && ((attrType == Long.class) || (attrType == long.class))) {
if (attrName.endsWith("Time") && (attrName.indexOf("Total") < 0) && (attrName.indexOf("Min") < 0)
&& (attrName.indexOf("Max") < 0) && (attrName.indexOf("Avg") < 0)
&& (attrName.indexOf("Average") < 0) && !propertyDescriptors.containsKey(attrName + "InMillis")) {
return Date.class;
}
}
if (IoFilterChain.class.isAssignableFrom(attrType)) {
return Map.class;
}
if (IoFilterChainBuilder.class.isAssignableFrom(attrType)) {
return Map.class;
}
if (!writable) {
if (Collection.class.isAssignableFrom(attrType) || Map.class.isAssignableFrom(attrType)) {
if (List.class.isAssignableFrom(attrType)) {
return List.class;
}
if (Set.class.isAssignableFrom(attrType)) {
return Set.class;
}
if (Map.class.isAssignableFrom(attrType)) {
return Map.class;
}
return Collection.class;
}
if (attrType.isPrimitive() || Date.class.isAssignableFrom(attrType)
|| Boolean.class.isAssignableFrom(attrType) || Character.class.isAssignableFrom(attrType)
|| Number.class.isAssignableFrom(attrType)) {
if ((attrName == null) || !attrName.endsWith("InMillis")
|| !propertyDescriptors.containsKey(attrName.substring(0, attrName.length() - 8))) {
return attrType;
}
}
}
return String.class;
}
private Object convertValue(Class<?> type, String attrName, Object v, boolean writable) {
if (v == null) {
return null;
}
if ((attrName != null) && (v instanceof Long)) {
if (attrName.endsWith("Time") && (attrName.indexOf("Total") < 0) && (attrName.indexOf("Min") < 0)
&& (attrName.indexOf("Max") < 0) && (attrName.indexOf("Avg") < 0)
&& (attrName.indexOf("Average") < 0) && !propertyDescriptors.containsKey(attrName + "InMillis")) {
long time = (Long) v;
if (time <= 0) {
return null;
}
return new Date((Long) v);
}
}
if ((v instanceof IoSessionDataStructureFactory) || (v instanceof IoHandler)) {
return v.getClass().getName();
}
if (v instanceof IoFilterChainBuilder) {
Map<String, String> filterMapping = new LinkedHashMap<String, String>();
if (v instanceof DefaultIoFilterChainBuilder) {
for (IoFilterChain.Entry e : ((DefaultIoFilterChainBuilder) v).getAll()) {
filterMapping.put(e.getName(), e.getFilter().getClass().getName());
}
} else {
filterMapping.put("Unknown builder type", v.getClass().getName());
}
return filterMapping;
}
if (v instanceof IoFilterChain) {
Map<String, String> filterMapping = new LinkedHashMap<String, String>();
for (IoFilterChain.Entry e : ((IoFilterChain) v).getAll()) {
filterMapping.put(e.getName(), e.getFilter().getClass().getName());
}
return filterMapping;
}
if (!writable) {
if ((v instanceof Collection) || (v instanceof Map)) {
if (v instanceof List) {
return convertCollection(v, new ArrayList<Object>());
}
if (v instanceof Set) {
return convertCollection(v, new LinkedHashSet<Object>());
}
if (v instanceof Map) {
return convertCollection(v, new LinkedHashMap<Object, Object>());
}
return convertCollection(v, new ArrayList<Object>());
}
if ((v instanceof Date) || (v instanceof Boolean) || (v instanceof Character) || (v instanceof Number)) {
if ((attrName == null) || !attrName.endsWith("InMillis")
|| !propertyDescriptors.containsKey(attrName.substring(0, attrName.length() - 8))) {
return v;
}
}
}
PropertyEditor editor = getPropertyEditor(type, attrName, v.getClass());
if (editor != null) {
editor.setValue(v);
return editor.getAsText();
}
return v.toString();
}
private Object convertCollection(Object src, Collection<Object> dst) {
Collection<?> srcCol = (Collection<?>) src;
for (Object e : srcCol) {
Object convertedValue = convertValue(dst.getClass(), "element", e, false);
if ((e != null) && (convertedValue == null)) {
convertedValue = e.toString();
}
dst.add(convertedValue);
}
return dst;
}
private Object convertCollection(Object src, Map<Object, Object> dst) {
Map<?, ?> srcCol = (Map<?, ?>) src;
for (Map.Entry<?, ?> e : srcCol.entrySet()) {
Object convertedKey = convertValue(dst.getClass(), "key", e.getKey(), false);
Object convertedValue = convertValue(dst.getClass(), "value", e.getValue(), false);
if ((e.getKey() != null) && (convertedKey == null)) {
convertedKey = e.getKey().toString();
}
if ((e.getValue() != null) && (convertedValue == null)) {
convertedKey = e.getValue().toString();
}
dst.put(convertedKey, convertedValue);
}
return dst;
}
private void throwMBeanException(Throwable e) throws MBeanException {
if (e instanceof OgnlException) {
OgnlException ognle = (OgnlException) e;
if (ognle.getReason() != null) {
throwMBeanException(ognle.getReason());
} else {
String message = ognle.getMessage();
if (e instanceof NoSuchPropertyException) {
message = "No such property: " + message;
} else if (e instanceof ExpressionSyntaxException) {
message = "Illegal expression syntax: " + message;
} else if (e instanceof InappropriateExpressionException) {
message = "Inappropriate expression: " + message;
}
e = new IllegalArgumentException(message);
e.setStackTrace(ognle.getStackTrace());
}
}
if (e instanceof InvocationTargetException) {
throwMBeanException(e.getCause());
}
LOGGER.warn("Unexpected exception.", e);
if (e.getClass().getPackage().getName().matches("javax?\\..+")) {
if (e instanceof Exception) {
throw new MBeanException((Exception) e, e.getMessage());
}
throw new MBeanException(new RuntimeException(e), e.getMessage());
}
throw new MBeanException(new RuntimeException(e.getClass().getName() + ": " + e.getMessage()), e.getMessage());
}
protected Object getAttribute0(String fqan) throws Exception {
throw new AttributeNotFoundException(fqan);
}
protected void setAttribute0(String attrName, Object attrValue) throws Exception {
throw new AttributeNotFoundException(attrName);
}
protected Object invoke0(String name, Object params[], String signature[]) throws Exception {
throw new NoSuchMethodException();
}
protected boolean isReadable(Class<?> type, String attrName) {
if (IoService.class.isAssignableFrom(type) && attrName.equals("filterChain")) {
return false;
}
if (IoService.class.isAssignableFrom(type) && attrName.equals("localAddress")) {
return false;
}
if (IoService.class.isAssignableFrom(type) && attrName.equals("defaultLocalAddress")) {
return false;
}
if (IoSession.class.isAssignableFrom(type) && attrName.equals("attachment")) {
return false;
}
if (IoSession.class.isAssignableFrom(type) && attrName.equals("attributeKeys")) {
return false;
}
if (IoSession.class.isAssignableFrom(type) && attrName.equals("closeFuture")) {
return false;
}
if (ThreadPoolExecutor.class.isAssignableFrom(type) && attrName.equals("queue")) {
return false;
}
return true;
}
protected boolean isWritable(Class<?> type, String attrName) {
if (IoService.class.isAssignableFrom(type) && attrName.startsWith("defaultLocalAddress")) {
return true;
}
return false;
}
protected Class<?> getElementType(Class<?> type, String attrName) {
if ((transportMetadata != null) && IoAcceptor.class.isAssignableFrom(type)
&& "defaultLocalAddresses".equals(attrName)) {
return transportMetadata.getAddressType();
}
return String.class;
}
protected Class<?> getMapKeyType(Class<?> type, String attrName) {
return String.class;
}
protected Class<?> getMapValueType(Class<?> type, String attrName) {
return String.class;
}
protected boolean isExpandable(Class<?> type, String attrName) {
if (IoService.class.isAssignableFrom(type)) {
if (attrName.equals("statistics") || attrName.equals("sessionConfig")
|| attrName.equals("transportMetadata") || attrName.equals("config")
|| attrName.equals("transportMetadata")) {
return true;
}
}
if (ExecutorFilter.class.isAssignableFrom(type) && attrName.equals("executor")) {
return true;
}
if (ThreadPoolExecutor.class.isAssignableFrom(type) && attrName.equals("queueHandler")) {
return true;
}
return false;
}
protected boolean isOperation(String methodName, Class<?>[] paramTypes) {
return true;
}
protected void addExtraAttributes(List<ModelMBeanAttributeInfo> attributes) {
// Do nothing
}
protected void addExtraOperations(List<ModelMBeanOperationInfo> operations) {
// Do nothing
}
protected PropertyEditor getPropertyEditor(Class<?> type, String attrName, Class<?> attrType) {
if (type == null) {
throw new IllegalArgumentException("type");
}
if (attrName == null) {
throw new IllegalArgumentException("attrName");
}
if ((transportMetadata != null) && (attrType == SocketAddress.class)) {
attrType = transportMetadata.getAddressType();
}
if (((attrType == Long.class) || (attrType == long.class))) {
if (attrName.endsWith("Time") && (attrName.indexOf("Total") < 0) && (attrName.indexOf("Min") < 0)
&& (attrName.indexOf("Max") < 0) && (attrName.indexOf("Avg") < 0)
&& (attrName.indexOf("Average") < 0) && !propertyDescriptors.containsKey(attrName + "InMillis")) {
return PropertyEditorFactory.getInstance(Date.class);
}
if (attrName.equals("id")) {
return PropertyEditorFactory.getInstance(String.class);
}
}
if (List.class.isAssignableFrom(attrType)) {
return new ListEditor(getElementType(type, attrName));
}
if (Set.class.isAssignableFrom(attrType)) {
return new SetEditor(getElementType(type, attrName));
}
if (Collection.class.isAssignableFrom(attrType)) {
return new CollectionEditor(getElementType(type, attrName));
}
if (Map.class.isAssignableFrom(attrType)) {
return new MapEditor(getMapKeyType(type, attrName), getMapValueType(type, attrName));
}
return PropertyEditorFactory.getInstance(attrType);
}
private class OgnlTypeConverter extends PropertyTypeConverter {
@Override
protected PropertyEditor getPropertyEditor(Class<?> type, String attrName, Class<?> attrType) {
return ObjectMBean.this.getPropertyEditor(type, attrName, attrType);
}
}
}