1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.modeler.modules;
18
19 import java.io.FileNotFoundException;
20 import java.io.FileOutputStream;
21 import java.io.InputStream;
22 import java.net.URL;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26
27 import javax.management.Attribute;
28 import javax.management.MBeanServer;
29 import javax.management.ObjectName;
30 import javax.management.loading.MLet;
31 import javax.xml.transform.TransformerException;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.commons.modeler.AttributeInfo;
36 import org.apache.commons.modeler.BaseModelMBean;
37 import org.apache.commons.modeler.ManagedBean;
38 import org.apache.commons.modeler.Registry;
39 import org.apache.commons.modeler.util.DomUtil;
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Node;
42
43
44 /*** This will create mbeans based on a config file.
45 * The format is an extended version of MLET.
46 *
47 * Classloading. We don't support any explicit classloader tag.
48 * A ClassLoader is just an mbean ( it can be the standard MLetMBean or
49 * a custom one ).
50 *
51 * XXX add a special attribute to reference the loader mbean,
52 * XXX figure out how to deal with private loaders
53 */
54 public class MbeansSource extends ModelerSource implements MbeansSourceMBean
55 {
56 private static Log log = LogFactory.getLog(MbeansSource.class);
57 Registry registry;
58 String type;
59
60
61 boolean loading=true;
62 List mbeans=new ArrayList();
63 static boolean loaderLoaded=false;
64 private Document document;
65 private HashMap object2Node = new HashMap();
66
67 long lastUpdate;
68 long updateInterval=10000;
69
70 public void setRegistry(Registry reg) {
71 this.registry=reg;
72 }
73
74 public void setLocation( String loc ) {
75 this.location=loc;
76 }
77
78 /*** Used if a single component is loaded
79 *
80 * @param type
81 */
82 public void setType( String type ) {
83 this.type=type;
84 }
85
86 public void setSource( Object source ) {
87 this.source=source;
88 }
89
90 public Object getSource() {
91 return source;
92 }
93
94 public String getLocation() {
95 return location;
96 }
97
98 /*** Return the list of mbeans created by this source.
99 * It can be used to implement runtime services.
100 */
101 public List getMBeans() {
102 return mbeans;
103 }
104
105 public List loadDescriptors( Registry registry, String location,
106 String type, Object source)
107 throws Exception
108 {
109 setRegistry(registry);
110 setLocation(location);
111 setType(type);
112 setSource(source);
113 execute();
114 return mbeans;
115 }
116
117 public void start() throws Exception {
118 registry.invoke(mbeans, "start", false);
119 }
120
121 public void stop() throws Exception {
122 registry.invoke(mbeans, "stop", false);
123 }
124
125 public void init() throws Exception {
126 if( mbeans==null) execute();
127 if( registry==null ) registry=Registry.getRegistry();
128
129 registry.invoke(mbeans, "init", false);
130 }
131
132 public void destroy() throws Exception {
133 registry.invoke(mbeans, "destroy", false);
134 }
135
136 public void load() throws Exception {
137 execute();
138 }
139
140 public void execute() throws Exception {
141 if( registry==null ) registry=Registry.getRegistry();
142 try {
143 InputStream stream=getInputStream();
144 long t1=System.currentTimeMillis();
145 document = DomUtil.readXml(stream);
146
147
148 Node descriptorsN=document.getDocumentElement();
149
150 if( descriptorsN == null ) {
151 log.error("No descriptors found");
152 return;
153 }
154
155 Node firstMbeanN=DomUtil.getChild(descriptorsN, null);
156
157 if( firstMbeanN==null ) {
158
159 if( log.isDebugEnabled() )
160 log.debug("No child " + descriptorsN);
161 firstMbeanN=descriptorsN;
162 }
163
164 MBeanServer server=(MBeanServer)Registry.getServer();
165
166
167 if( ! loaderLoaded ) {
168
169 ObjectName defaultLoader= new ObjectName("modeler",
170 "loader", "modeler");
171 MLet mlet=new MLet( new URL[0], this.getClass().getClassLoader());
172 server.registerMBean(mlet, defaultLoader);
173 loaderLoaded=true;
174 }
175
176
177 for (Node mbeanN = firstMbeanN; mbeanN != null;
178 mbeanN= DomUtil.getNext(mbeanN, null, Node.ELEMENT_NODE))
179 {
180 String nodeName=mbeanN.getNodeName();
181
182
183 if( "mbean".equals(nodeName) || "MLET".equals(nodeName) )
184 {
185 String code=DomUtil.getAttribute( mbeanN, "code" );
186 String objectName=DomUtil.getAttribute( mbeanN, "objectName" );
187 if( objectName==null ) {
188 objectName=DomUtil.getAttribute( mbeanN, "name" );
189 }
190
191 if( log.isDebugEnabled())
192 log.debug( "Processing mbean objectName=" + objectName +
193 " code=" + code);
194
195
196 Node constructorN=DomUtil.getChild(mbeanN, "constructor");
197 if( constructorN == null ) constructorN=mbeanN;
198
199 ArgsInfo info = processArg(constructorN);
200
201 try {
202 ObjectName oname=new ObjectName(objectName);
203 if( ! server.isRegistered( oname )) {
204
205
206 String modelMBean=BaseModelMBean.class.getName();
207 if(info == null) {
208 server.createMBean(modelMBean, oname,
209 new Object[] { code, this},
210 new String[] { String.class.getName(),
211 ModelerSource.class.getName() }
212 );
213 } else {
214 server.createMBean(modelMBean, oname,
215 new Object[] { code, this,
216 info.getValues(),
217 info.getSigs()
218 },
219 new String[] { String.class.getName(),
220 ModelerSource.class.getName(),
221 Object[].class.getName(),
222 String[].class.getName()
223 }
224 );
225 }
226
227 mbeans.add(oname);
228 }
229 object2Node.put( oname, mbeanN );
230
231 } catch( Exception ex ) {
232 log.error( "Error creating mbean " + objectName, ex);
233 }
234
235 Node firstAttN=DomUtil.getChild(mbeanN, "attribute");
236 for (Node descN = firstAttN; descN != null;
237 descN = DomUtil.getNext( descN ))
238 {
239 processAttribute(server, descN, objectName);
240 }
241 } else if("jmx-operation".equals(nodeName) ) {
242 String name=DomUtil.getAttribute(mbeanN, "objectName");
243 if( name==null )
244 name=DomUtil.getAttribute(mbeanN, "name");
245
246 String operation=DomUtil.getAttribute(mbeanN, "operation");
247
248 if( log.isDebugEnabled())
249 log.debug( "Processing invoke objectName=" + name +
250 " code=" + operation);
251 try {
252 ObjectName oname=new ObjectName(name);
253
254 ArgsInfo info = processArg( mbeanN );
255 if(info == null) {
256 server.invoke( oname, operation, null, null);
257 } else {
258 server.invoke( oname, operation, info.getValues(), info.getSigs());
259 }
260 } catch (Exception e) {
261 log.error( "Error in invoke " + name + " " + operation);
262 }
263 }
264
265 ManagedBean managed=new ManagedBean();
266 DomUtil.setAttributes(managed, mbeanN);
267 Node firstN;
268
269
270 firstN=DomUtil.getChild( mbeanN, "attribute");
271 for (Node descN = firstN; descN != null;
272 descN = DomUtil.getNext( descN ))
273 {
274 AttributeInfo ci=new AttributeInfo();
275 DomUtil.setAttributes(ci, descN);
276 managed.addAttribute( ci );
277 }
278
279 }
280
281 long t2=System.currentTimeMillis();
282 log.info( "Reading mbeans " + (t2-t1));
283 loading=false;
284 } catch( Exception ex ) {
285 log.error( "Error reading mbeans ", ex);
286 }
287 }
288
289 public void updateField( ObjectName oname, String name,
290 Object value )
291 {
292 if( loading ) return;
293
294
295 Node n=(Node)object2Node.get( oname );
296 if( n == null ) {
297 log.info( "Node not found " + oname );
298 return;
299 }
300 Node attNode=DomUtil.findChildWithAtt(n, "attribute", "name", name);
301 if( attNode == null ) {
302
303 attNode=n.getOwnerDocument().createElement("attribute");
304 DomUtil.setAttribute(attNode, "name", name);
305 n.appendChild(attNode);
306 }
307 String oldValue=DomUtil.getAttribute(attNode, "value");
308 if( oldValue != null ) {
309
310 DomUtil.removeAttribute( attNode, "value");
311 }
312 DomUtil.setText(attNode, value.toString());
313
314
315 }
316
317 /*** Store the mbeans.
318 * XXX add a background thread to store it periodically
319 */
320 public void save() {
321
322
323
324 long time=System.currentTimeMillis();
325 if( location!=null &&
326 time - lastUpdate > updateInterval ) {
327 lastUpdate=time;
328 try {
329 FileOutputStream fos=new FileOutputStream(location);
330 DomUtil.writeXml(document, fos);
331 } catch (TransformerException e) {
332 log.error( "Error writing");
333 } catch (FileNotFoundException e) {
334 log.error( "Error writing" ,e );
335 }
336 }
337 }
338
339 private void processAttribute(MBeanServer server,
340 Node descN, String objectName ) {
341 String attName=DomUtil.getAttribute(descN, "name");
342 String value=DomUtil.getAttribute(descN, "value");
343 String type=null;
344 if( value==null ) {
345
346 value=DomUtil.getContent(descN);
347 }
348 try {
349 if( log.isDebugEnabled())
350 log.debug("Set attribute " + objectName + " " + attName +
351 " " + value);
352 ObjectName oname=new ObjectName(objectName);
353
354 if( type==null )
355 type=registry.getType( oname, attName );
356
357 if( type==null ) {
358 log.info("Can't find attribute " + objectName + " " + attName );
359
360 } else {
361 Object valueO=registry.convertValue( type, value);
362 server.setAttribute(oname, new Attribute(attName, valueO));
363 }
364 } catch( Exception ex) {
365 log.error("Error processing attribute " + objectName + " " +
366 attName + " " + value, ex);
367 }
368
369 }
370
371 private ArgsInfo processArg(Node mbeanN) {
372 Node firstArgN=DomUtil.getChild(mbeanN, "arg" );
373 if(firstArgN == null) {
374 return null;
375 }
376 ArgsInfo info = new ArgsInfo();
377
378 for (Node argN = firstArgN; argN != null;
379 argN = DomUtil.getNext( argN ))
380 {
381 String type=DomUtil.getAttribute(argN, "type");
382 String value=DomUtil.getAttribute(argN, "value");
383 if( value==null ) {
384
385 value=DomUtil.getContent(argN);
386 }
387 info.addArgPair(type, registry.convertValue(type,value));
388 }
389 return info;
390 }
391
392 private static class ArgsInfo {
393 private List sigs = new ArrayList();
394 private List values = new ArrayList();
395
396 ArgsInfo() {
397 }
398
399 public String [] getSigs() {
400 return (String [])sigs.toArray(new String[sigs.size()]);
401 }
402
403 public Object[] getValues () {
404 return values.toArray(new Object[values.size()]);
405 }
406
407 public void addArgPair(String name, Object val) {
408 sigs.add(name);
409 values.add(val);
410 }
411 }
412 }