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.util.ArrayList;
21  import java.util.List;
22  
23  import javax.management.InstanceAlreadyExistsException;
24  import javax.management.MBeanRegistrationException;
25  import javax.management.MBeanServer;
26  import javax.management.MalformedObjectNameException;
27  import javax.management.NotCompliantMBeanException;
28  import javax.management.ObjectName;
29  
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  import org.springframework.beans.factory.BeanFactory;
33  import org.springframework.context.ApplicationContext;
34  
35  import ch.elca.el4j.core.context.ModuleApplicationContext;
36  import ch.elca.el4j.core.exceptions.BaseException;
37  import ch.elca.el4j.services.monitoring.notification.CoreNotificationHelper;
38  
39  import ch.elca.el4j.util.classpath.ClassloaderTools;
40  import ch.elca.el4j.util.codingsupport.Reject;
41  
42  /**
43   * The proxy class for an ApplicationContext.
44   *
45   * @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/ApplicationContextMB.java $
46   *
47   * @author Raphael Boog (RBO)
48   */
49  public class ApplicationContextMB implements ApplicationContextMBMBean {
50  
51  	/**
52  	 * The domain of the Application Context proxy as it will be registered at
53  	 * the MBean Server.
54  	 */
55  	public static final String APPLICATION_CONTEXT_DOMAIN
56  		= "ApplicationContext";
57  
58  	/**
59  	 * The message to be printed in case the used Application Context is not the
60  	 * ModuleApplicationContext.
61  	 */
62  	public static final String NOT_MODULE_APPLICATION_CONTEXT = "This context "
63  		+ "was not loaded via the "
64  		+ "'ch.elca.el4j.core.context.ModuleApplicationContext'. This is "
65  		+ "the reason why the configuration locations cannot be displayed.";
66  
67  	/**
68  	 * The counter on the number of Application Contexts.
69  	 */
70  	private static int s_counter = 1;
71  
72  	/**
73  	 * Private logger of this class.
74  	 */
75  	private static Logger s_logger = LoggerFactory.getLogger(ApplicationContextMB.class);
76  
77  	/**
78  	 * The reference to the real Application Context.
79  	 */
80  	protected ApplicationContext m_applicationContext;
81  
82  	/**
83  	 * The MBean Server to which this Application Context is registered.
84  	 */
85  	protected MBeanServer m_mBeanServer;
86  
87  	/**
88  	 * The Bean Factory belonging to this Application Context.
89  	 */
90  	protected BeanFactory m_beanFactory;
91  
92  	/**
93  	 * The instance counter of this object.
94  	 */
95  	private int m_instanceCounter;
96  
97  	/**
98  	 * An array of spring beans registered to this Application Context.
99  	 */
100 	private SpringBeanMB[] m_springBeanMB;
101 
102 	/**
103 	 * The object name of this Application Context.
104 	 */
105 	private ObjectName m_objectName;
106 
107 	/**
108 	 * The proxy JVM in which this Application Context is running.
109 	 */
110 	private JvmMB m_jvmmb;
111 
112 	/**
113 	 * Constructor.
114 	 *
115 	 * @param applicationContext
116 	 *            The Application Context to which this class is a proxy.
117 	 * @param beanFactory
118 	 *            The Bean Factory belonging to this Application Context.
119 	 * @param mBeanServer
120 	 *            The MBean Server to which this Application Context is
121 	 *            registered.
122 	 * @param jvmmb
123 	 *            The proxy JVM in which this Application Context is running.
124 	 */
125 	public ApplicationContextMB(ApplicationContext applicationContext,
126 		BeanFactory beanFactory, MBeanServer mBeanServer, JvmMB jvmmb) {
127 
128 		this.m_applicationContext = applicationContext;
129 		this.m_beanFactory = beanFactory;
130 		this.m_mBeanServer = mBeanServer;
131 		this.m_jvmmb = jvmmb;
132 
133 	}
134 
135 	/**
136 	 * Init method. Sets up this ApplicationContextMB.
137 	 *
138 	 * @throws BaseException
139 	 *             in case the initialization failed
140 	 */
141 	public void init() throws BaseException {
142 
143 		String[] beanDefinitionNames = m_applicationContext
144 			.getBeanDefinitionNames();
145 
146 		// Set the instanceCounter.
147 		setInstanceCounter();
148 
149 		// Set the object name of this object.
150 		setObjectName();
151 
152 		int cnt = m_applicationContext.getBeanDefinitionCount();
153 
154 		m_springBeanMB = new SpringBeanMB[cnt];
155 
156 		// Create and initialized a Log4jConfig object.
157 		Log4jConfig logConfig = new Log4jConfig("log4jConfig", this,
158 			m_applicationContext, m_beanFactory, m_mBeanServer);
159 		logConfig.init();
160 	 
161 		// Create the proxies of the SpringBeans loaded by this Application
162 		// Context.
163 		for (int i = 0; i < cnt; i++) {
164 			m_springBeanMB[i] = new SpringBeanMB(beanDefinitionNames[i], this,
165 				m_applicationContext, m_beanFactory, m_mBeanServer);
166 			m_springBeanMB[i].init();
167 		}
168 
169 		// Register the Application Context at the MBean Server.
170 		registerApplicationContext();
171 
172 		// Add this Application Context proxy to the JVM proxy.
173 		registerAtJvmMB();
174 
175 	}
176 
177 	/**
178 	 * Register this ApplicationContext at the MBean Server.
179 	 *
180 	 * @throws BaseException
181 	 *             in case the registration at the MBean Server failed
182 	 */
183 	protected void registerApplicationContext() throws BaseException {
184 
185 		Reject.ifNull(getObjectName(), "The object name of the "
186 				+ "ApplicationContextMB '" + this.toString()
187 				+ "' should not be null.");
188 
189 		try {
190 			m_mBeanServer.registerMBean(this, getObjectName());
191 		} catch (InstanceAlreadyExistsException e) {
192 			String message = "The MBean is already under the control"
193 				+ " of the MBean server.";
194 			s_logger.error(message);
195 			throw new BaseException(message, e);
196 		} catch (MBeanRegistrationException e) {
197 			String message = "The MBean will not be registered.";
198 			s_logger.error(message);
199 			throw new BaseException(message, e);
200 		} catch (NotCompliantMBeanException e) {
201 			String message = "This object is not a JMX compliant MBean.";
202 			s_logger.error(message);
203 			throw new BaseException(message, e);
204 		}
205 	}
206 
207 	/**
208 	 * Register this ApplicationContext at the JVM MBean.
209 	 *
210 	 */
211 	protected void registerAtJvmMB() {
212 		m_jvmmb.addApplicationContext(this);
213 	}
214 
215 	/**
216 	 * Set the objectName of this ApplicationContext.
217 	 *
218 	 */
219 	protected void setObjectName() {
220 
221 		// valid JMX key properties must not contain any of these chars
222 		// :",=*?  (JMX specs v1.2, p110)
223 		String dispName = getName().replaceAll("[:\\\",=*?]", " ");
224 		
225 		// Create the object name String.
226 		String name = APPLICATION_CONTEXT_DOMAIN + ":name="
227 			+ getInstanceCounter() + " - " + dispName;
228 
229 		try {
230 			m_objectName = new ObjectName(name);
231 		} catch (MalformedObjectNameException e) {
232 			CoreNotificationHelper.notifyMisconfiguration(
233 					"The string passed as a parameter does not have"
234 					+ " the right format.", e);
235 		}
236 	}
237 
238 	/**
239 	 * Returns the object name of the ApplicationContext.
240 	 *
241 	 * @return objectName The object name of this Application Context proxy.
242 	 */
243 	public ObjectName getObjectName() {
244 		return m_objectName;
245 	}
246 
247 	/**
248 	 * Save the class variable s_counter to an instance member and increment the
249 	 * class variable by 1.
250 	 *
251 	 */
252 	public void setInstanceCounter() {
253 
254 		synchronized (ApplicationContextMB.class) {
255 			m_instanceCounter = s_counter;
256 			s_counter++;
257 		}
258 
259 	}
260 
261 	/**
262 	 * The getter method for the instanceCounter member.
263 	 *
264 	 * @return The instanceCounter member
265 	 */
266 	public int getInstanceCounter() {
267 		return m_instanceCounter;
268 	}
269 
270 	/**
271 	 * {@inheritDoc}
272 	 */
273 	public String getName() {
274 		return m_applicationContext.getDisplayName();
275 	}
276 
277 	/**
278 	 * {@inheritDoc}
279 	 */
280 	public ObjectName[] getSpringBeansMB() {
281 
282 		List springBeansList = new ArrayList();
283 
284 		for (int i = 0; i < m_springBeanMB.length; i++) {
285 			if (m_mBeanServer.isRegistered(m_springBeanMB[i].getObjectName())) {
286 				springBeansList.add(m_springBeanMB[i].getObjectName());
287 			}
288 		}
289 
290 		return (ObjectName[]) springBeansList
291 			.toArray(new ObjectName[springBeansList.size()]);
292 	}
293 
294 	/**
295 	 * {@inheritDoc}
296 	 */
297 	public ObjectName getJvmMB() {
298 		return m_jvmmb.getObjectName();
299 	}
300 
301 	/**
302 	 * {@inheritDoc}
303 	 */
304 	public String[] getResolvedConfigLocations() {
305 		String[] result = null;
306 		if (m_applicationContext instanceof ModuleApplicationContext) {
307 			ModuleApplicationContext lac
308 				= (ModuleApplicationContext) m_applicationContext;
309 			result = lac.getConfigLocations();
310 		} else {
311 			result = new String[] {};
312 		}
313 		return result;
314 	}
315 
316 	/**
317 	 * {@inheritDoc}
318 	 */
319 	public String[] getInclusiveConfigLocations() {
320 		String[] result = null;
321 		if (m_applicationContext instanceof ModuleApplicationContext) {
322 			ModuleApplicationContext lac
323 				= (ModuleApplicationContext) m_applicationContext;
324 			result = lac.getInclusiveConfigLocations();
325 		} else {
326 			result = new String[] {NOT_MODULE_APPLICATION_CONTEXT};
327 		}
328 		return result;
329 	}
330 
331 	/**
332 	 * {@inheritDoc}
333 	 */
334 	public String[] getExclusiveConfigLocations() {
335 		String[] result = null;
336 		if (m_applicationContext instanceof ModuleApplicationContext) {
337 			ModuleApplicationContext lac
338 				= (ModuleApplicationContext) m_applicationContext;
339 			result = lac.getExclusiveConfigLocations();
340 		} else {
341 			result = new String[] {NOT_MODULE_APPLICATION_CONTEXT};
342 		}
343 		return result;
344 	}
345 	
346 	/** {@inheritDoc} */
347 	public String[] getURLClassPath() {
348 		Class<?> c = m_applicationContext.getClass();
349 		if (ClassloaderTools.isURLLoaded(c)) {
350 			return ClassloaderTools.getURLs(c);
351 		}
352 		return null;
353 	}
354 
355 	/**
356 	 * Setter for the springBeanMB member.
357 	 *
358 	 * @param springBeanMB
359 	 *            The value to set
360 	 */
361 	protected void setSpringBeanMB(SpringBeanMB[] springBeanMB) {
362 		this.m_springBeanMB = springBeanMB;
363 	}
364 
365 	/**
366 	 * Getter for the springBeanMB member.
367 	 *
368 	 * @return The value of the springBeanMB member
369 	 */
370 	public SpringBeanMB[] getSpringBeanMB() {
371 		return m_springBeanMB;
372 	}
373 }