View Javadoc

1   /*
2    * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3    * the spring framework, http://el4j.sf.net
4    * Copyright (C) 2005 by ELCA Informatique SA, Av. de la Harpe 22-24,
5    * 1000 Lausanne, Switzerland, http://www.elca.ch
6    *
7    * EL4J is published under the GNU Lesser General Public License (LGPL)
8    * Version 2.1. See http://www.gnu.org/licenses/
9    *
10   * This program 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
13   * GNU Lesser General Public License for more details.
14   *
15   * For alternative licensing, please contact info@elca.ch
16   */
17  
18  package ch.elca.el4j.services.monitoring.jmx;
19  
20  import java.net.URL;
21  import java.net.URLClassLoader;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Properties;
26  import java.util.Set;
27  
28  import javax.management.MalformedObjectNameException;
29  import javax.management.ObjectName;
30  
31  import ch.elca.el4j.services.monitoring.notification.CoreNotificationHelper;
32  import ch.elca.el4j.util.classpath.DuplicateClassFinder;
33  
34  /**
35   * The proxy class for the JVM. Each MBean Server contains exactly one JVM
36   * MBean.
37   *
38   * @svnLink $Revision: 4010 $;$Date: 2009-12-01 10:59:54 +0100 (Di, 01. Dez 2009) $;$Author: jonasha $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/jmx/src/main/java/ch/elca/el4j/services/monitoring/jmx/JvmMB.java $
39   *
40   * @author Raphael Boog (RBO)
41   * @author Rashid Waraich (RWA)
42   */
43  public class JvmMB implements JvmMBMBean {
44  
45  	/**
46  	 * The domain of the JVM proxy as it will be registered at the MBean Server.
47  	 */
48  	public static final String JVM_DOMAIN = "JVM";
49  
50  	/**
51  	 * The counter on the number of JVMs.
52  	 */
53  	private static int s_counter = 1;
54  
55  	/**
56  	 * A list of Application Context proxies which are running in this JVM
57  	 * proxy.
58  	 */
59  	protected List m_applicationContextMB = new ArrayList();
60  
61  	/**
62  	 * The object name of this object.
63  	 */
64  	private ObjectName m_objectName;
65  
66  	/**
67  	 * The instance counter of this object.
68  	 */
69  	private int m_instanceCounter;
70  
71  	/**
72  	 * Constructor which calls the setObjectName() method.
73  	 *
74  	 */
75  	public JvmMB() {
76  
77  		// Set the instanceCounter.
78  		setInstanceCounter();
79  
80  		// Set the object name of this object.
81  		setObjectName();
82  
83  	}
84  
85  	/**
86  	 * {@inheritDoc}
87  	 */
88  	public String[] getSystemProperties() {
89  		Properties systemProperties = System.getProperties();
90  
91  		Set keySet = systemProperties.keySet();
92  		String[] result = new String[keySet.size()];
93  		Iterator iter = keySet.iterator();
94  		int j = 0;
95  
96  		while (iter.hasNext()) {
97  			Object key = iter.next();
98  			result[j] = (String) key + " = " + systemProperties.get(key);
99  			j++;
100 		}
101 
102 		return result;
103 
104 	}
105 
106 	/** {@inheritDoc} */
107 	public String[] getClassPath() {
108 		String[] cp;
109 		ClassLoader myLoader = JvmMB.class.getClassLoader();
110 		if (myLoader instanceof URLClassLoader) {
111 			// This is an URLClassLoader, so get the urls.
112 			URL[] urls = ((URLClassLoader) myLoader).getURLs();
113 			cp = new String[urls.length];
114 			for (int i = 0; i < urls.length; i++) {
115 				cp[i] = urls[i].toExternalForm();
116 			}
117 			return cp;
118 		} else {
119 			// Not an URLClassLoader. Try returning the System cp.
120 			return System.getProperty("java.class.path")
121 				.split(System.getProperty("path.separator"));
122 		}
123 	}
124 	
125 	/** {@inheritDoc} */
126 	public String findDuplicateClasses() {
127 		DuplicateClassFinder finder = new DuplicateClassFinder();
128 		finder.addClass(JvmMB.class);
129 		finder.search();
130 		String report;
131 		if (finder.duplicatesFound()) {
132 			report = "Duplicate classes found: \n";
133 			Set<String> duplicates = finder.getAllDuplicates();
134 			for (String current : duplicates) {
135 				report += "Class: " + current + "\n";
136 				for (String loc : finder.getLocations(current)) {
137 					report += "  " + loc + "\n";
138 				}
139 				report += "\n";
140 			}
141 		} else {
142 			report = "No duplicate classes were found.";
143 		}
144 		return report;
145 	}
146 	
147 	/**
148 	 * {@inheritDoc}
149 	 */
150 	public ObjectName[] getApplicationContexts() {
151 
152 		ObjectName[] result = new ObjectName[m_applicationContextMB.size()];
153 
154 		for (int i = 0; i < result.length; i++) {
155 			ApplicationContextMB acLocal
156 				= (ApplicationContextMB) m_applicationContextMB.get(i);
157 			result[i] = acLocal.getObjectName();
158 
159 		}
160 		return result;
161 	}
162 
163 	/**
164 	 * Add an Application Context proxy to the list of Application Context
165 	 * proxies in this JVM proxy.
166 	 *
167 	 * @param appCont
168 	 *            The Application Context proxy to add
169 	 */
170 	@SuppressWarnings("unchecked")
171 	public void addApplicationContext(ApplicationContextMB appCont) {
172 		this.m_applicationContextMB.add(appCont);
173 	}
174 
175 	/**
176 	 * Sets the object name of this JVM proxy.
177 	 *
178 	 */
179 	public void setObjectName() {
180 
181 		String name
182 			= JVM_DOMAIN + ":name=jvmRootMonitor " + getInstanceCounter();
183 
184 		try {
185 			m_objectName = new ObjectName(name);
186 		} catch (MalformedObjectNameException e) {
187 			CoreNotificationHelper.notifyMisconfiguration(
188 					"The string passed as a parameter does not have"
189 					+ " the right format.", e);
190 		}
191 	}
192 
193 	/**
194 	 * The getter method for the object name of this JVM proxy.
195 	 *
196 	 * @return The object name of this JVM proxy
197 	 */
198 	public ObjectName getObjectName() {
199 		return m_objectName;
200 	}
201 
202 	/**
203 	 * The getter method for the instanceCounter member.
204 	 *
205 	 * @return The instanceCounter member
206 	 */
207 	public int getInstanceCounter() {
208 		return m_instanceCounter;
209 	}
210 
211 	/**
212 	 * Save the class variable s_counter to an instance member and increment the
213 	 * class variable by 1.
214 	 *
215 	 */
216 	public void setInstanceCounter() {
217 
218 		synchronized (JvmMB.class) {
219 			m_instanceCounter = s_counter;
220 			s_counter++;
221 		}
222 
223 	}
224 	
225 	/**
226 	 * {@inheritDoc}
227 	 */
228 	public String showThreadTable() {
229 		// Checkstyle: MagicNumber off
230 		Thread[] threads = getAllThreads();
231 		String[][] cells = new String[threads.length + 1][7];
232 		
233 		cells[0][0] = "Thread Id";
234 		cells[0][1] = "Name";
235 		cells[0][2] = "isDeamon";
236 		cells[0][3] = "State";
237 		cells[0][4] = "Thread Group";
238 		cells[0][5] = "Priority";
239 		cells[0][6] = "Stack Trace";
240 		
241 		for (int i = 0; i < threads.length; i++) {
242 			cells[i + 1][0] = Long.toString(threads[i].getId());
243 			cells[i + 1][1] = threads[i].getName();
244 			cells[i + 1][2] = Boolean.toString(threads[i].isDaemon());
245 			cells[i + 1][3] = threads[i].getState().toString();
246 			cells[i + 1][4] = threads[i].getThreadGroup().getName();
247 			cells[i + 1][5] = Integer.toString(threads[i].getPriority());
248 			cells[i + 1][6]
249 				= stackTraceElementsToString(threads[i].getStackTrace());
250 		}
251 		// Checkstyle: MagicNumber on
252 		return JmxHtmlFormatter.getHtmlTable(cells);
253 	}
254 	
255 	
256 	/**
257 	 * Converts an array of stacktrace elements to a string.
258 	 * @param trace The stacktrace array to convert
259 	 * @return The resulting string
260 	 */
261 	private String stackTraceElementsToString(StackTraceElement[] trace) {
262 		String result = "";
263 		
264 		for (int i = 0; i < trace.length; i++) {
265 			result = result.concat(trace[i].toString());
266 		}
267 		
268 		return result;
269 	}
270 	
271 	
272 	/**
273 	 * @return An array of all current threads.
274 	 */
275 	private Thread[] getAllThreads() {
276 		return Thread.getAllStackTraces().keySet().toArray(new Thread[1]);
277 	}
278 	
279 	
280 	
281 	
282 }