1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.velocity.internal.jmx

File JMXVelocityEngine.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

2
39
4
1
160
81
6
0.15
9.75
4
1.5

Classes

Class Line # Actions
JMXVelocityEngine 46 39 0% 6 1
0.977777897.8%
 

Contributing tests

This file is covered by 19 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.velocity.internal.jmx;
21   
22    import java.lang.reflect.Field;
23    import java.util.HashMap;
24    import java.util.Map;
25   
26    import javax.management.openmbean.ArrayType;
27    import javax.management.openmbean.CompositeData;
28    import javax.management.openmbean.CompositeDataSupport;
29    import javax.management.openmbean.CompositeType;
30    import javax.management.openmbean.OpenType;
31    import javax.management.openmbean.SimpleType;
32    import javax.management.openmbean.TabularData;
33    import javax.management.openmbean.TabularDataSupport;
34    import javax.management.openmbean.TabularType;
35   
36    import org.xwiki.velocity.VelocityEngine;
37   
38    /**
39    * Uses non-stable (ie might need to be modified when we upgrade the Velocity JAR) introspection to access private
40    * fields of Velocity. This is needed since Velocity doesn't offer a way to access information about the template
41    * namespaces and the macros within them.
42    *
43    * @version $Id: 2004e35d46cae1f32e5c76b8d261226954e2d46d $
44    * @since 2.4M2
45    */
 
46    public class JMXVelocityEngine implements JMXVelocityEngineMBean
47    {
48    /**
49    * The Velocity Engine for which to return management data.
50    */
51    private VelocityEngine engine;
52   
53    /**
54    * @param engine the Velocity Engine for which to return management data
55    */
 
56  52 toggle public JMXVelocityEngine(VelocityEngine engine)
57    {
58  52 this.engine = engine;
59    }
60   
 
61  4 toggle @Override
62    public TabularData getTemplates()
63    {
64  4 TabularData data;
65   
66  4 try {
67  4 Map<String, String[]> result = getInternalTemplates();
68   
69    // Note: JDK 1.6 has the notion of MXBean which support returning a Map type but since we must use
70    // JDK 1.5 for now we have to output a TabularData value.
71   
72    // Represents the list of macro names
73  4 ArrayType macroNameType = new ArrayType(1, SimpleType.STRING);
74   
75    // Represents one row (template name, macro names) in the returned table data
76  4 String[] columnNames = new String[] { "templateName", "macroNames" };
77  4 String[] descriptions = new String[] { "The Template Name (namespace)", "The names of registered Macros" };
78  4 CompositeType rowType = new CompositeType("template",
79    "Template management data (namespaces, macros) for a row", columnNames, descriptions,
80    new OpenType[] { SimpleType.STRING, macroNameType });
81   
82  4 TabularType type = new TabularType("templates", "Template management data (namespaces, macros)", rowType,
83    columnNames);
84  4 data = new TabularDataSupport(type);
85   
86  4 for (Map.Entry<String, String[]> entry : result.entrySet()) {
87   
88  5 String templateName = entry.getKey();
89  5 String[] macroNames = entry.getValue();
90   
91  5 CompositeData rowData = new CompositeDataSupport(rowType, columnNames, new Object[] {
92    templateName, macroNames });
93  5 data.put(rowData);
94    }
95   
96    } catch (Exception e) {
97  0 throw new RuntimeException("Failed to gather information on Velocity Templates/Macros", e);
98    }
99   
100  4 return data;
101    }
102   
103    /**
104    * @return the data using standard Java classes, {@link #getTemplates()} wraps it in generic Open types to make the
105    * returned data portable and accessible remotely from a JMX management console
106    * @throws NoSuchFieldException in case of an exception in getting the data
107    * @throws IllegalAccessException in case of an exception in getting the data
108    * @see #getTemplates()
109    */
 
110  4 toggle private Map<String, String[]> getInternalTemplates() throws NoSuchFieldException, IllegalAccessException
111    {
112    // Get the internal Velocity Engine (not the XWiki wrapping one)
113  4 Object velocityEngine = getField(this.engine, "engine");
114   
115  4 Object runtimeInstance = getField(velocityEngine, "ri");
116  4 Object vmFactory = getField(runtimeInstance, "vmFactory");
117  4 Object vmManager = getField(vmFactory, "vmManager");
118   
119  4 Map<String, Map<String, ?>> namespaceHash =
120    (Map<String, Map<String, ?>>) getField(vmManager, "namespaceHash");
121   
122  4 Map<String, ?> globalNamespace = (Map<String, ?>) getField(vmManager, "globalNamespace");
123   
124  4 Map<String, String[]> result = new HashMap<String, String[]>();
125   
126  4 for (Map.Entry<String, Map<String, ?>> entry : namespaceHash.entrySet()) {
127  5 String nameSpaceName = entry.getKey();
128  5 Map<String, ?> namespace = entry.getValue();
129  5 if (globalNamespace.equals(namespace)) {
130  4 nameSpaceName = "<global>";
131    }
132  5 String[] macroNames = new String[namespace.size()];
133  5 int i = 0;
134  5 for (String macroName : namespace.keySet()) {
135  1 macroNames[i] = macroName;
136  1 i++;
137    }
138   
139  5 result.put(nameSpaceName, macroNames);
140    }
141   
142  4 return result;
143    }
144   
145    /**
146    * Helper method to access a private field.
147    *
148    * @param instance the instance containing the field to access
149    * @param fieldName the name of the field to access
150    * @return the field object
151    * @throws NoSuchFieldException in case of an error when accessing the private field
152    * @throws IllegalAccessException in case of an error when accessing the private field
153    */
 
154  24 toggle private Object getField(Object instance, String fieldName) throws NoSuchFieldException, IllegalAccessException
155    {
156  24 Field field = instance.getClass().getDeclaredField(fieldName);
157  24 field.setAccessible(true);
158  24 return field.get(instance);
159    }
160    }