EMMA Coverage Report (generated Tue Apr 17 08:51:20 BST 2007)
[all classes][org.jtoolkit.essence.app.impl]

COVERAGE SUMMARY FOR SOURCE FILE [DynamicMBeanWrapper.java]

nameclass, %method, %block, %line, %
DynamicMBeanWrapper.java100% (1/1)47%  (8/17)61%  (496/819)58%  (78.8/137)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DynamicMBeanWrapper100% (1/1)47%  (8/17)61%  (496/819)58%  (78.8/137)
getAttribute (String): Object 0%   (0/1)0%   (0/62)0%   (0/13)
getAttributeOrError (String): Attribute 0%   (0/1)0%   (0/28)0%   (0/6)
getAttributeSetError (Attribute): String 0%   (0/1)0%   (0/17)0%   (0/1)
getAttributes (String []): AttributeList 0%   (0/1)0%   (0/27)0%   (0/4)
getThreadName (): String 0%   (0/1)0%   (0/3)0%   (0/1)
handleAccessException (IllegalAccessException, String): Object 0%   (0/1)0%   (0/13)0%   (0/1)
invoke (String, Object [], String []): Object 0%   (0/1)0%   (0/74)0%   (0/13)
setAttribute (Attribute): void 0%   (0/1)0%   (0/57)0%   (0/9)
setAttributes (AttributeList): AttributeList 0%   (0/1)0%   (0/41)0%   (0/10)
getDeclaredMethods (Class): List 100% (1/1)99%  (92/93)99%  (15.8/16)
<static initializer> 100% (1/1)100% (10/10)100% (3/3)
DynamicMBeanWrapper (Object, String): void 100% (1/1)100% (226/226)100% (35/35)
getDeclaredFields (Class): List 100% (1/1)100% (52/52)100% (9/9)
getMBeanInfo (): MBeanInfo 100% (1/1)100% (22/22)100% (1/1)
getSetters (Class): List 100% (1/1)100% (46/46)100% (9/9)
isGetter (Method): boolean 100% (1/1)100% (21/21)100% (3/3)
isSetter (Method): boolean 100% (1/1)100% (27/27)100% (3/3)

1package org.jtoolkit.essence.app.impl;
2 
3import org.apache.commons.logging.Log;
4import static org.apache.commons.logging.LogFactory.getLog;
5import org.jetbrains.annotations.Nullable;
6import static org.jtoolkit.essence.app.pojo.impl.DataValueClass.*;
7import org.jtoolkit.essence.utils.Named;
8 
9import javax.management.*;
10import java.lang.reflect.Field;
11import java.lang.reflect.InvocationTargetException;
12import java.lang.reflect.Method;
13import java.lang.reflect.Modifier;
14import java.util.ArrayList;
15import static java.util.Arrays.asList;
16import java.util.LinkedHashMap;
17import java.util.List;
18import java.util.Map;
19 
20/*
21   Copyright 2006 Peter Lawrey
22 
23   Licensed under the Apache License, Version 2.0 (the "License");
24   you may not use this file except in compliance with the License.
25   You may obtain a copy of the License at
26 
27       http://www.apache.org/licenses/LICENSE-2.0
28 
29   Unless required by applicable law or agreed to in writing, software
30   distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
31   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32   See the License for the specific language governing permissions and
33   limitations under the License.
34*/
35/**
36 * @author Peter Lawrey
37 */
38public class DynamicMBeanWrapper<T> implements DynamicMBean {
39    private static final Log LOG = getLog(DynamicMBeanWrapper.class);
40    private static final MBeanConstructorInfo[] CONSTRUCTORS = {};
41//    private static final int MAX_FIELDS_LENGTH = 1000;
42//    private static final int MAX_FIELD_WIDTH = 64;
43//    private static final int MAX_VALUE_WIDTH = 128;
44 
45    private final T comp;
46    private final MBeanInfo mBeanInfo;
47    private final Map<String, Method> settersMap = new LinkedHashMap<String, Method>();
48    private final Map<String, Method> methodMap = new LinkedHashMap<String, Method>();
49    private final Map<String, Field> fieldMap = new LinkedHashMap<String, Field>();
50    private static final MBeanNotificationInfo[] NO_M_BEAN_NOTIFICATION_INFO = new MBeanNotificationInfo[0];
51 
52    public DynamicMBeanWrapper(T comp, String description) {
53        this.comp = comp;
54        Class<? extends Object> type = comp.getClass();
55        List<Field> fields = getDeclaredFields(type);
56        List<Method> setters = getSetters(type);
57        for (Method m : setters) {
58            String name = m.getName();
59            name = Character.toLowerCase(name.charAt(3)) + name.substring(4);
60            settersMap.put(name, m);
61        }
62        MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[fields.size()];
63        for (int i = 0; i < fields.size(); i++) {
64            Field field = fields.get(i);
65            String name = field.getName();
66            fieldMap.put(name, field);
67            attributes[i] = new MBeanAttributeInfo(name, field.getType().getName(), name, true, settersMap.get(name) != null, false);
68        }
69        List<Method> methods = getDeclaredMethods(type);
70        MBeanOperationInfo[] operations = new MBeanOperationInfo[methods.size()];
71        for (int i = 0; i < methods.size(); i++) {
72            Method method = methods.get(i);
73            Class<?>[] parameterTypes = method.getParameterTypes();
74            MBeanParameterInfo[] signature = new MBeanParameterInfo[parameterTypes.length];
75            String[] signatureArr = new String[parameterTypes.length];
76            for (int j = 0; j < parameterTypes.length; j++) {
77                String sigName = parameterTypes[j].getName();
78                signatureArr[j] = sigName;
79                signature[j] = new MBeanParameterInfo("p" + j, sigName, "p" + j);
80            }
81            operations[i] = new MBeanOperationInfo(method.getName(), method.getName(), signature, method.getReturnType().getName(), MBeanOperationInfo.UNKNOWN);
82            methodMap.put(method.getName() + asList(signatureArr), method);
83        }
84        MBeanNotificationInfo[] notifications = NO_M_BEAN_NOTIFICATION_INFO;
85        mBeanInfo = new MBeanInfo(type.getName(), description, attributes, CONSTRUCTORS, operations, notifications);
86    }
87 
88    private static List<Method> getDeclaredMethods(Class<? extends Object> type) {
89        List<Method> methods = new ArrayList<Method>();
90        Class<?> parent = type.getSuperclass();
91        if (parent != null && parent != Object.class)
92            methods.addAll(getDeclaredMethods(parent));
93        LOOP:
94        for (Method method : type.getDeclaredMethods()) {
95            if ((method.getModifiers() & Modifier.STATIC) != 0) continue;
96            // is it an accessor method.
97            if (method.getName().startsWith("access$")) continue;
98            /// is it a setter?
99            if (isSetter(method) || isGetter(method)) continue;
100            for (Class type2 : method.getParameterTypes())
101                if (!isBaseType(type2))
102                    continue LOOP;
103            Class<?> returnType = method.getReturnType();
104            if (!isBaseType(returnType) && returnType != void.class) continue;
105            method.setAccessible(true);
106            methods.add(method);
107        }
108        return methods;
109    }
110 
111    private static boolean isSetter(Method method) {
112        String name = method.getName();
113        Class<?>[] classes = method.getParameterTypes();
114        return name.startsWith("set") && name.length() > 3 && classes.length == 1 && isBaseType(classes[0]);
115    }
116 
117    private static boolean isGetter(Method method) {
118        String name = method.getName();
119        Class<?>[] classes = method.getParameterTypes();
120        return name.startsWith("get") && name.length() > 3 && classes.length == 0;
121    }
122 
123    private static List<Method> getSetters(Class type) {
124        List<Method> ret = new ArrayList<Method>();
125        Class<?> parent = type.getSuperclass();
126        if (parent != null && parent != Object.class)
127            ret.addAll(getSetters(parent));
128        for (Method m : type.getDeclaredMethods()) {
129            if (isSetter(m)) {
130                m.setAccessible(true);
131                ret.add(m);
132            }
133        }
134        return ret;
135    }
136 
137    private static List<Field> getDeclaredFields(Class<? extends Object> type) {
138        List<Field> fields = new ArrayList<Field>();
139        Class<?> parent = type.getSuperclass();
140        if (parent != null && parent != Object.class)
141            fields.addAll(getDeclaredFields(parent));
142        for (Field field : type.getDeclaredFields())
143            if (isBaseType(field.getType()) || isAssignableFrom(Named.class, field.getType())) {
144                field.setAccessible(true);
145                fields.add(field);
146            }
147        return fields;
148    }
149 
150    @Nullable public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
151        try {
152            Field field = fieldMap.get(attribute);
153            if (field == null)
154                throw new AttributeNotFoundException(attribute);
155            Object obj = field.get(comp);
156            if (obj == null) return null;
157            if (isPrimative(obj.getClass())) return obj;
158            if (obj.getClass().getPackage().getName().startsWith("java")) return obj;
159            if (obj instanceof Named)
160                obj = "Reference => " + ((Named) obj).getName();
161            else
162                obj = obj.toString();
163            return obj;
164        } catch (IllegalAccessException e) {
165            return handleAccessException(e, attribute);
166        }
167    }
168 
169    private static Object handleAccessException(IllegalAccessException e, String attribute) throws MBeanException {
170        throw new MBeanException(e, "Unable to access " + attribute);
171    }
172 
173    public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
174        try {
175            Method method = settersMap.get(attribute.getName());
176            if (method == null) throw new AttributeNotFoundException(attribute.getName());
177            method.invoke(comp, cast(method.getParameterTypes()[0], attribute.getValue()));
178        } catch (IllegalAccessException e) {
179            handleAccessException(e, attribute.getName());
180        } catch (InvocationTargetException e) {
181            throw new MBeanException(e.getCause() instanceof Exception ? (Exception) e.getCause() : e, getAttributeSetError(attribute));
182        }
183    }
184 
185    private static String getAttributeSetError(Attribute attribute) {
186        return getThreadName() + ": Unable to set " + attribute.getName() + " to " + attribute.getValue();
187    }
188 
189    public AttributeList getAttributes(String[] attributes) {
190        AttributeList ret = new AttributeList();
191        for (String attribute : attributes) {
192            ret.add(getAttributeOrError(attribute));
193        }
194        return ret;
195    }
196 
197    private Attribute getAttributeOrError(String attribute) {
198        Object value;
199        try {
200            value = getAttribute(attribute);
201        } catch (Exception e) {
202            LOG.warn(getThreadName() + ": Unable to get " + attribute, e);
203            value = e.toString();
204        }
205        return new Attribute(attribute, value);
206    }
207 
208    public AttributeList setAttributes(AttributeList attributes) {
209        AttributeList ret = new AttributeList();
210        //noinspection unchecked,CastToIncompatibleInterface
211        for (Attribute attribute : (Iterable<Attribute>) attributes.iterator()) {
212            String attrName = attribute.getName();
213            try {
214                setAttribute(attribute);
215            } catch (Exception e) {
216                LOG.warn(getAttributeSetError(attribute), e);
217            }
218            ret.add(new Attribute(attrName, getAttributeOrError(attrName)));
219        }
220        return ret;
221    }
222 
223    private static String getThreadName() {
224        return Thread.currentThread().getName();
225    }
226 
227    public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
228        String name = actionName + asList(signature);
229        Method m = methodMap.get(name);
230        if (m == null)
231            throw new MBeanException(null, "Unable to find " + name);
232        try {
233            Object[] toInvoke = new Object[params.length];
234            Class<?>[] parameterTypes = m.getParameterTypes();
235            for (int i = 0; i < params.length; i++)
236                toInvoke[i] = cast(parameterTypes[i], params[i]);
237            return m.invoke(comp, toInvoke);
238        } catch (IllegalAccessException e) {
239            throw new ReflectionException(e);
240        } catch (InvocationTargetException e) {
241            throw new ReflectionException(e);
242        }
243    }
244 
245    public MBeanInfo getMBeanInfo() {
246/*
247        try {
248            Method asMap = comp.getClass().getMethod("asMap");
249            Map map2 = (Map) asMap.invoke(comp);
250            List<String> fields = new ArrayList<String>();
251            List<Object> values = new ArrayList<Object>();
252            try {
253                map2 = new TreeMap(map2);
254            } catch (RuntimeException ignored) {
255                // ignored.
256            }
257            fields.add("{size}");
258            values.add(map2.size());
259            for (Map.Entry entry : (Set<Map.Entry>) map2.entrySet()) {
260                fields.add(trim(entry.getKey(), MAX_FIELD_WIDTH));
261                values.add(trim(entry.getValue(), MAX_VALUE_WIDTH));
262                if (fields.size() > MAX_FIELDS_LENGTH)
263                    break;
264            }
265*/
266 
267        //Descriptor descriptor = new ImmutableDescriptor(fields.toArray(new String[fields.size()]), values.toArray());
268        return new MBeanInfo(mBeanInfo.getClassName(), mBeanInfo.getDescription(), mBeanInfo.getAttributes(), mBeanInfo.getConstructors(), mBeanInfo.getOperations(), mBeanInfo.getNotifications()); //, descriptor);
269/*
270        } catch (IllegalAccessException e) {
271            throw new IllegalStateException(e);
272        } catch (InvocationTargetException e) {
273            throw new IllegalStateException(e);
274        } catch (NoSuchMethodException ignored) {
275            // ignored.
276        }
277        return mBeanInfo;
278*/
279    }
280}

[all classes][org.jtoolkit.essence.app.impl]
EMMA 2.0.5312 (C) Vladimir Roubtsov