1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.germinus.easyconf.jmx;
17
18 import java.lang.reflect.Constructor;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26
27 import javax.management.Attribute;
28 import javax.management.AttributeList;
29 import javax.management.AttributeNotFoundException;
30 import javax.management.DynamicMBean;
31 import javax.management.InvalidAttributeValueException;
32 import javax.management.MBeanAttributeInfo;
33 import javax.management.MBeanConstructorInfo;
34 import javax.management.MBeanException;
35 import javax.management.MBeanInfo;
36 import javax.management.MBeanOperationInfo;
37 import javax.management.MBeanParameterInfo;
38 import javax.management.ReflectionException;
39
40 import com.germinus.easyconf.ComponentConfiguration;
41 import com.germinus.easyconf.ComponentProperties;
42 import com.germinus.easyconf.EasyConf;
43
44 /***
45 * MBean wrapper for a ComponentConfiguration. <a
46 * href="ComponentConfigurationDynamicMBean.java.html"> <b><i>View Source </i>
47 * </b> </a>
48 *
49 * @author Alvaro Gonz?lez
50 * @version $Revision: 1.4 $
51 *
52 */
53 public class ComponentConfigurationDynamicMBean implements DynamicMBean {
54 /***
55 * Name of the reloadConfiguration operation. Used when invoking
56 * <code>invoke</code> method.
57 */
58 public static final String RELOAD_OPERATION_NAME = "reloadConfiguration";
59
60 /***
61 * Name of the newProperty operations. Used when invoking
62 * <code>invoke</code> method.
63 */
64 public static final String NEW_PROPERTY_OPERATION_NAME = "newProperty";
65
66 /***
67 * Signature of the reloadConfiguration operation. Used when invoking
68 * <code>invoke</code> method.
69 */
70 public static final String[] RELOAD_OPERATION_SIGNATURE = new String[0];
71
72 /***
73 * Signature of the newProperty operation with one parameter.
74 * Used when invoking <code>invoke</code> method.
75 */
76 public static final String[] NEW_PROPERTY_OPERATION_SIGNATURE_1 =
77 new String[] { String.class.toString() };
78
79 /***
80 * Signature of the newProperty operation with two parameters.
81 * Used when invoking <code>invoke</code> method.
82 */
83 public static final String[] NEW_PROPERTY_OPERATION_SIGNATURE_2 =
84 new String[] {String.class.toString(), Object.class.toString() };
85
86 private static final String NEW_PROPERTY_OPERATION_DESCRIPTION_1 =
87 "Add new property to the Configuration Component. " +
88 "The Param is the property name. Must not" +
89 " exists another property with the same name.";
90
91 private static final String NEW_PROPERTY_OPERATION_DESCRIPTION_2 =
92 NEW_PROPERTY_OPERATION_DESCRIPTION_1 +
93 " The second param is the initial value of the new property";
94
95 private static final String RELOAD_OPERATION_DESCRIPTION =
96 "Reloads the configuration";
97
98 private static final String CONSTRUCTOR_DESCRIPTION_1 =
99 "Constructs new MBean with the configuration of the named Component";
100
101 private String componentName;
102
103 private ComponentConfiguration componentConfiguration;
104
105 private MBeanAttributeInfo[] attributesInfo;
106
107 private Map modifiedProperties;
108
109 private Map newPropeties;
110
111 private MBeanOperationInfo[] operationInfo;
112
113 private MBeanConstructorInfo[] constructorsInfo;
114
115 /***
116 * Create a MBean wraping some loaded ComponentConfiguration
117 * @param component
118 */
119 public ComponentConfigurationDynamicMBean
120 (ComponentConfiguration component) {
121 super();
122 this.componentName=component.getComponentName();
123 this.componentConfiguration=component;
124 init();
125 }
126
127 /***
128 * Loads and wraps a ComponentConfiguration
129 * @param componentName
130 */
131 public ComponentConfigurationDynamicMBean(String componentName) {
132 super();
133 this.componentName = componentName;
134 this.componentConfiguration = EasyConf.getConfiguration(componentName);
135 init();
136 }
137
138 /***
139 * Some initializations common to both constructors
140 */
141 private void init(){
142 this.modifiedProperties = new HashMap();
143 this.newPropeties = new HashMap();
144 }
145
146 /***
147 * Obtains the component attributes from the ComponentCongiguration
148 *
149 * @see javax.management.DynamicMBean#getAttribute(java.lang.String)
150 */
151 public Object getAttribute(String attributeName)
152 throws AttributeNotFoundException, MBeanException,
153 ReflectionException {
154 ComponentProperties prop = componentConfiguration.getProperties();
155 if (modifiedProperties.containsKey(attributeName))
156 return modifiedProperties.get(attributeName);
157 if (prop.containsKey(attributeName))
158 return prop.getProperty(attributeName);
159 else if (newPropeties.containsKey(attributeName))
160 return newPropeties.get(attributeName);
161 else
162 throw new AttributeNotFoundException(attributeName);
163 }
164
165 /***
166 * Sets an attribute
167 *
168 * @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute)
169 */
170 public void setAttribute(Attribute attribute)
171 throws AttributeNotFoundException, InvalidAttributeValueException,
172 MBeanException, ReflectionException {
173 if (componentConfiguration.getProperties().containsKey(
174 attribute.getName()))
175 modifiedProperties.put(attribute.getName(), attribute.getValue());
176 else if (newPropeties.containsKey(attribute.getName()))
177 newPropeties.put(attribute.getName(), attribute.getValue());
178 else
179 throw new AttributeNotFoundException(attribute.getName());
180 }
181
182 /***
183 * List named attributes
184 *
185 * @see javax.management.DynamicMBean#getAttributes(java.lang.String[])
186 */
187 public AttributeList getAttributes(String[] attributesNames) {
188 Set includedAttributeNames = new HashSet();
189 AttributeList attributeList = new AttributeList();
190 for (int i = 0; i < attributesNames.length; i++) {
191 String attributeName = attributesNames[i];
192 if (!includedAttributeNames.contains(attributeName)) {
193 includedAttributeNames.add(attributeName);
194 try {
195 Object value = getAttribute(attributeName);
196 Attribute attribute = new Attribute(attributeName, value);
197 attributeList.add(attribute);
198 } catch (AttributeNotFoundException e) {
199
200 } catch (MBeanException e) {
201 } catch (ReflectionException e) {
202 }
203 }
204 }
205 return attributeList;
206 }
207
208 /***
209 * Set named attributes
210 *
211 * @see javax.management.DynamicMBean#setAttributes(javax.management.AttributeList)
212 */
213 public AttributeList setAttributes(AttributeList attributes) {
214 AttributeList modifieds = new AttributeList();
215 Iterator it = attributes.iterator();
216 while (it.hasNext()) {
217 Attribute attribute = (Attribute) it.next();
218 try {
219 setAttribute(attribute);
220 modifieds.add(attribute);
221 } catch (AttributeNotFoundException e) {
222 } catch (InvalidAttributeValueException e) {
223 } catch (MBeanException e) {
224 } catch (ReflectionException e) {
225 }
226 }
227 return modifieds;
228 }
229
230 /***
231 * Invoke one of the operations exposed by the MBeanas.
232 * This Operations could be one of:
233 * <ul>
234 * <li><code>void newProperty(String propertyName)</code></li>
235 * <li>
236 * <code>void newProperty(String propertyName, String initialValue)
237 * </code>
238 * </li>
239 * <li><code>void reloadConfiguration()</code></li>
240 * </ul>
241 *
242 * @see javax.management.DynamicMBean#invoke(java.lang.String,
243 * java.lang.Object[], java.lang.String[])
244 */
245 public Object invoke(String operationName, Object[] params,
246 String[] signature) throws MBeanException, ReflectionException {
247 if (operationName.equals(RELOAD_OPERATION_NAME)) {
248 reloadConfiguration();
249 return null;
250 }
251 if (operationName.equals(NEW_PROPERTY_OPERATION_NAME)) {
252 if (signature.length == 1)
253 newProperty((String) params[0]);
254 else if (signature.length == 2)
255 newProperty((String) params[0], params[1]);
256 else
257 throw new MBeanException(new IllegalArgumentException(
258 "Operation not found in MBEan: " + operationName + "("
259 + signature + ")"));
260 return null;
261 }
262 throw new MBeanException(new IllegalArgumentException(
263 "Operation not found in MBEan: " + operationName + "("
264 + signature + ")"));
265 }
266
267
268
269 private void reloadConfiguration() {
270
271 EasyConf.refreshComponent(componentName);
272 this.componentConfiguration = EasyConf.getConfiguration(componentName);
273
274 }
275
276 private void newProperty(String propertyName) throws MBeanException {
277 newProperty(propertyName, null);
278 }
279
280 private void newProperty(String propertyName, Object value)
281 throws MBeanException {
282 ComponentProperties prop = componentConfiguration.getProperties();
283 if ((newPropeties.containsKey(propertyName))
284 || prop.containsKey(propertyName))
285 throw new MBeanException(new IllegalArgumentException(
286 "Cannot add new propert whith name: " + propertyName
287 + ". There is a property whith that name yet"));
288 newPropeties.put(propertyName, value);
289 }
290
291 /***
292 * Return the Information exposed by the MBean: Attributes, Operations,
293 * Constructors and Notifications.
294 *
295 * @see javax.management.DynamicMBean#getMBeanInfo()
296 */
297 public MBeanInfo getMBeanInfo() {
298 return new MBeanInfo(this.getClass().toString(), "Easyconf component: "
299 + this.componentName, getAttributeInfo(),
300 getConsturctorsInfo(), getOperationInfo(), null);
301 }
302
303 /***
304 * Constructs the info of the MBean's attributes.
305 *
306 * @return Array of MBeanAttributeInfo
307 */
308 protected MBeanAttributeInfo[] getAttributeInfo() {
309 if (attributesInfo == null) {
310 ComponentProperties properties = componentConfiguration
311 .getProperties();
312 List auxList = new ArrayList();
313 Iterator it = properties.getKeys();
314 while (it.hasNext()) {
315 String propertyName = (String) it.next();
316 Object value = properties.getProperty(propertyName);
317 String type = value.getClass().getName();
318 boolean isIs = value.getClass().equals(Boolean.class);
319 MBeanAttributeInfo attributeInfo = new MBeanAttributeInfo(
320 propertyName, type, "Easyconf " + componentName
321 + " component property: " + propertyName, true,
322 true, isIs);
323 auxList.add(attributeInfo);
324 this.attributesInfo = (MBeanAttributeInfo[]) auxList
325 .toArray(new MBeanAttributeInfo[auxList.size()]);
326 }
327 }
328 return this.attributesInfo;
329 }
330
331 /***
332 * Constructs the info of the MBean's operations.
333 *
334 * @return Array of MBeanOperationInfo
335 */
336 protected MBeanOperationInfo[] getOperationInfo() {
337 if (operationInfo == null) {
338 operationInfo = new MBeanOperationInfo[] {
339 new MBeanOperationInfo(NEW_PROPERTY_OPERATION_NAME,
340 NEW_PROPERTY_OPERATION_DESCRIPTION_1,
341
342 new MBeanParameterInfo[] { new MBeanParameterInfo(
343 "propertyName", String.class.getName(),
344 "Name of the new property") }, void.class
345 .getName(), MBeanOperationInfo.ACTION),
346 new MBeanOperationInfo(
347 NEW_PROPERTY_OPERATION_NAME,
348 NEW_PROPERTY_OPERATION_DESCRIPTION_2,
349
350 new MBeanParameterInfo[] {
351 new MBeanParameterInfo("propertyName",
352 String.class.getName(),
353 "Name of the new property"),
354 new MBeanParameterInfo("value",
355 Object.class.getName(),
356 "Initial value of the new property") },
357 void.class.getName(), MBeanOperationInfo.ACTION),
358 new MBeanOperationInfo(RELOAD_OPERATION_NAME,
359 RELOAD_OPERATION_DESCRIPTION,
360
361 new MBeanParameterInfo[] {}, void.class.getName(),
362 MBeanOperationInfo.ACTION) };
363
364 }
365 return operationInfo;
366 }
367
368 /***
369 * Constructs an array of the MBean's constructors.
370 *
371 * @return Array of MBeanConstructorInfo
372 */
373 protected MBeanConstructorInfo[] getConsturctorsInfo() {
374 if (constructorsInfo == null) {
375 Constructor constructor = null;
376 try {
377 constructor = this.getClass().getConstructor(
378 new Class[] { String.class });
379 } catch (Exception e) {
380 }
381 constructorsInfo = new MBeanConstructorInfo[] { new MBeanConstructorInfo(
382 CONSTRUCTOR_DESCRIPTION_1, constructor) };
383 }
384 return constructorsInfo;
385 }
386
387 /***
388 * Returns the ComponentConfiguration associated with this MBean.
389 *
390 * @return ComponentConfiguration.
391 */
392 protected ComponentConfiguration getComponentConfiguration() {
393 return componentConfiguration;
394 }
395
396 /***
397 * @param componentConfiguration
398 * The componentConfiguration to set.
399 */
400 protected void setComponentConfiguration(
401 ComponentConfiguration componentConfiguration) {
402 this.componentConfiguration = componentConfiguration;
403 }
404
405 private boolean propertyExists(String property) {
406 if (componentConfiguration.getProperties().containsKey(property))
407 return true;
408 if (newPropeties.containsKey(property))
409 return true;
410 return false;
411 }
412 }