KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > varia > deployment > BeanShellScript


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.varia.deployment;
23
24 import java.io.InputStream JavaDoc;
25 import java.lang.reflect.InvocationTargetException JavaDoc;
26 import java.lang.reflect.Method JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.Iterator JavaDoc;
31
32 import javax.management.Attribute JavaDoc;
33 import javax.management.AttributeNotFoundException JavaDoc;
34 import javax.management.IntrospectionException JavaDoc;
35 import javax.management.InvalidAttributeValueException JavaDoc;
36 import javax.management.MBeanAttributeInfo JavaDoc;
37 import javax.management.MBeanException JavaDoc;
38 import javax.management.MBeanInfo JavaDoc;
39 import javax.management.MBeanOperationInfo JavaDoc;
40 import javax.management.ObjectName JavaDoc;
41 import javax.management.ReflectionException JavaDoc;
42
43 import org.jboss.deployment.DeploymentException;
44 import org.jboss.deployment.DeploymentInfo;
45 import org.jboss.system.ServiceDynamicMBeanSupport;
46 import org.jboss.util.Classes;
47
48 import bsh.EvalError;
49 import bsh.Interpreter;
50
51 /**
52  * A wrapper service that exposes a BeanShell script as a JBoss service
53  * MBean.
54  *
55  * @see BeanShellSubDeployer
56  *
57  * @author <a HREF="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>.
58  * @version $Revision: 42148 $
59  */

60 public class BeanShellScript extends ServiceDynamicMBeanSupport
61 {
62
63    protected DeploymentInfo deploymentInfo = null;
64    protected String JavaDoc name = null;
65
66    protected ScriptService scriptService = null;
67
68    protected ObjectName JavaDoc preferedObjectName = null;
69    protected ObjectName JavaDoc[] dependsServices = null;
70    protected HashMap JavaDoc supportedInterfaces = new HashMap JavaDoc ();
71
72    protected MBeanInfo JavaDoc mbeanInfo = null;
73
74    // Static --------------------------------------------------------
75

76    // Constructors --------------------------------------------------
77

78    public BeanShellScript(final DeploymentInfo di)
79       throws DeploymentException
80    {
81       try
82       {
83          this.deploymentInfo = di;
84          String JavaDoc name = deploymentInfo.url.toString();
85          if (name.endsWith("/"))
86          {
87             name = name.substring(0, name.length() - 1);
88          }
89          this.name = name;
90
91          loadScript (di.url);
92       }
93       catch (Exception JavaDoc e)
94       {
95          throw new DeploymentException (e);
96       }
97    }
98
99    // Public --------------------------------------------------------
100

101    // Z implementation ----------------------------------------------
102

103    // ServiceDynamicMBeanSupport overrides --------------------------
104

105    protected Object JavaDoc getInternalAttribute(String JavaDoc attribute)
106       throws AttributeNotFoundException JavaDoc, MBeanException JavaDoc, ReflectionException JavaDoc
107    {
108       try
109       {
110          String JavaDoc action = "get" + attribute.substring(0, 1).toUpperCase() + attribute.substring(1);
111
112          InvocationCouple invoc = retrieveCompatibleInvocation
113             (action, new Class JavaDoc[0]);
114          if (invoc == null)
115             throw new AttributeNotFoundException JavaDoc (attribute + " getter not implemented on target script");
116
117          return invoc.method.invoke(invoc.proxy, null);
118
119       }
120       catch (ClassNotFoundException JavaDoc cnfe)
121       {
122          throw new javax.management.ReflectionException JavaDoc (cnfe, "A signature class couldn't be loaded");
123       }
124       catch (IllegalAccessException JavaDoc iae)
125       {
126          throw new javax.management.ReflectionException JavaDoc (iae, "Problem while invoking gettter for field " + attribute);
127       }
128       catch (InvocationTargetException JavaDoc ite)
129       {
130          throw new MBeanException JavaDoc (ite, "Problem while invoking gettter for field " + attribute);
131       }
132   }
133
134    protected void setInternalAttribute(Attribute JavaDoc attribute)
135       throws
136          AttributeNotFoundException JavaDoc,
137          InvalidAttributeValueException JavaDoc,
138          MBeanException JavaDoc,
139          ReflectionException JavaDoc
140    {
141       String JavaDoc field = attribute.getName();
142       try
143       {
144          String JavaDoc action = "set" + field.substring(0, 1).toUpperCase() + field.substring(1);
145          Object JavaDoc value = attribute.getValue();
146          Class JavaDoc clazz = value.getClass();
147          Class JavaDoc tmp = Classes.getPrimitive(clazz);
148          if (tmp != null)
149             clazz = tmp;
150
151          InvocationCouple invoc = retrieveCompatibleInvocation
152             (action, new Class JavaDoc[] {clazz});
153          if (invoc == null)
154             throw new AttributeNotFoundException JavaDoc (field + " setter not implemented on target script");
155
156          invoc.method.invoke(invoc.proxy, new Object JavaDoc[] {value});
157
158       }
159       catch (ClassNotFoundException JavaDoc cnfe)
160       {
161          throw new javax.management.ReflectionException JavaDoc (cnfe, "A signature class couldn't be loaded");
162       }
163       catch (IllegalAccessException JavaDoc iae)
164       {
165          throw new javax.management.ReflectionException JavaDoc (iae, "Problem while invoking setter for field " + field);
166       }
167       catch (InvocationTargetException JavaDoc ite)
168       {
169          throw new MBeanException JavaDoc (ite, "Problem while invoking setter for field " + field);
170       }
171    }
172
173    protected Object JavaDoc internalInvoke(String JavaDoc actionName, Object JavaDoc[] params, String JavaDoc[] signature)
174       throws MBeanException JavaDoc, ReflectionException JavaDoc
175    {
176       try
177       {
178          InvocationCouple invoc = retrieveCompatibleInvocation (actionName, signature);
179          if (invoc == null)
180             throw new javax.management.ReflectionException JavaDoc (new Exception JavaDoc(), actionName + " not implemented on target script");
181
182          Object JavaDoc value = invoc.method.invoke(invoc.proxy, params);
183          return value;
184
185       }
186       catch (ClassNotFoundException JavaDoc cnfe)
187       {
188          throw new javax.management.ReflectionException JavaDoc (cnfe, "A signature class couldn't be loaded");
189       }
190       catch (IllegalAccessException JavaDoc iae)
191       {
192          throw new javax.management.ReflectionException JavaDoc (iae, "Problem while invoking " + actionName);
193       }
194       catch (InvocationTargetException JavaDoc ite)
195       {
196          throw new MBeanException JavaDoc (ite, "Problem while invoking " + actionName);
197       }
198    }
199
200    public MBeanInfo JavaDoc getMBeanInfo()
201    {
202       return this.mbeanInfo;
203    }
204
205    // ServiceMBeanSupport overrides ---------------------------------------------------
206

207    protected void createService() throws Exception JavaDoc
208    {
209       try
210       {
211          this.scriptService.setCtx(this);
212       }
213       catch (Exception JavaDoc e)
214       {
215          log.trace("setCtx", e);
216       }
217
218       try
219       {
220          this.scriptService.create();
221       }
222       catch (EvalError e)
223       {
224          log.trace("start", e);
225       }
226    }
227
228    protected void startService() throws Exception JavaDoc
229    {
230       try
231       {
232          this.scriptService.start();
233       }
234       catch (EvalError e)
235       {
236          log.trace("start", e);
237       }
238    }
239
240    protected void stopService() throws Exception JavaDoc
241    {
242       try
243       {
244          this.scriptService.stop();
245       }
246       catch (Exception JavaDoc e)
247       {
248          log.trace("stop", e);
249       }
250    }
251
252    protected void destroyService() throws Exception JavaDoc
253    {
254       try
255       {
256          this.scriptService.destroy();
257       }
258       catch (Exception JavaDoc e)
259       {
260          log.trace("destroy", e);
261       }
262    }
263
264    // Package protected ---------------------------------------------
265

266    // Protected -----------------------------------------------------
267

268    protected InvocationCouple retrieveCompatibleInvocation
269       (String JavaDoc name, String JavaDoc[] signature)
270       throws ClassNotFoundException JavaDoc
271    {
272       ClassLoader JavaDoc ucl = Thread.currentThread().getContextClassLoader();
273       // first transform signature
274
//
275
Class JavaDoc[] realSignature = null;
276       if (signature != null)
277       {
278          realSignature = new Class JavaDoc[signature.length];
279          for (int i=0; i<signature.length;i++)
280             realSignature[i] = ucl.loadClass(signature[i]);
281       }
282
283       return retrieveCompatibleInvocation (name, realSignature);
284    }
285
286    protected InvocationCouple retrieveCompatibleInvocation
287       (String JavaDoc name, Class JavaDoc[] signature)
288       throws ClassNotFoundException JavaDoc
289    {
290       Iterator JavaDoc keys = supportedInterfaces.keySet().iterator();
291       while (keys.hasNext())
292       {
293          Class JavaDoc key = (Class JavaDoc)keys.next();
294          try
295          {
296             Method JavaDoc method = key.getMethod(name, signature);
297
298             Object JavaDoc targetProxy = supportedInterfaces.get(key);
299             return new InvocationCouple (targetProxy, method);
300          }
301          catch (NoSuchMethodException JavaDoc ok) {}
302       }
303
304       // if we arrive here it means that this operation does not exist!
305
//
306
return null;
307
308
309    }
310
311    protected void loadScript (java.net.URL JavaDoc url) throws Exception JavaDoc
312    {
313       Interpreter interpreter = new Interpreter ();
314       interpreter.setClassLoader(Thread.currentThread().getContextClassLoader());
315       InputStream JavaDoc stream = url.openStream();
316       try
317       {
318          interpreter.eval (new java.io.InputStreamReader JavaDoc (stream));
319       }
320       finally
321       {
322          try
323          {
324             stream.close();
325          }
326          catch (Exception JavaDoc strange) { log.info(strange); }
327       }
328
329       scriptService = (ScriptService)interpreter.getInterface(ScriptService.class);
330
331       // We now load the script preferences
332
//
333
String JavaDoc[] depends = null;
334       try
335       {
336          depends = scriptService.dependsOn();
337       }
338       catch (Exception JavaDoc e)
339       {
340          log.trace("dependsOn", e);
341       }
342       if (depends != null)
343       {
344          dependsServices = new ObjectName JavaDoc[depends.length];
345          for (int i=0; i<depends.length; i++)
346             dependsServices[i] = new ObjectName JavaDoc (depends[i]);
347       }
348
349       String JavaDoc myName = null;
350       try
351       {
352          myName = scriptService.objectName ();
353       }
354       catch (Exception JavaDoc e)
355       {
356          log.trace("objectName", e);
357       }
358       if (myName != null)
359          this.preferedObjectName = new ObjectName JavaDoc (myName);
360
361       Class JavaDoc[] intfs = null;
362       try
363       {
364          intfs = scriptService.getInterfaces ();
365          if (intfs != null)
366             log.debug("getInterfaces=" + Arrays.asList(intfs));
367       }
368       catch (Exception JavaDoc e)
369       {
370          log.trace("getInterfaces", e);
371       }
372       if (intfs != null)
373       {
374          for (int i=0; i<intfs.length; i++)
375          {
376             Object JavaDoc iface = interpreter.getInterface(intfs[i]);
377             supportedInterfaces.put (intfs[i], iface);
378          }
379       }
380
381       this.mbeanInfo = generateMBeanInfo (intfs);
382       log.debug("mbeanInfo=" + mbeanInfo);
383
384    }
385
386    protected MBeanInfo JavaDoc generateMBeanInfo (Class JavaDoc[] intfs)
387       throws IntrospectionException JavaDoc
388    {
389       MBeanInfo JavaDoc result = super.getMBeanInfo();
390
391       if (intfs != null && intfs.length > 0)
392       {
393          ArrayList JavaDoc attrs = new ArrayList JavaDoc (Arrays.asList(result.getAttributes()));
394          ArrayList JavaDoc ops = new ArrayList JavaDoc (Arrays.asList(result.getOperations()));
395
396          HashMap JavaDoc readAttr = new HashMap JavaDoc ();
397          HashMap JavaDoc writeAttr = new HashMap JavaDoc ();
398
399          // we now populate the MBeanInfo with information from our script
400
//
401
for (int i=0; i<intfs.length; i++)
402          {
403             Class JavaDoc clazz = intfs[i];
404             Method JavaDoc[] methods = clazz.getMethods();
405             for (int m=0; m<methods.length; m++)
406             {
407                Method JavaDoc meth = methods[m];
408                String JavaDoc name = meth.getName();
409                Class JavaDoc[] params = meth.getParameterTypes();
410
411                if (name.startsWith("get") && params.length == 0)
412                {
413                   readAttr.put (name, meth);
414                }
415                else if (name.startsWith("set") && params.length == 1)
416                {
417                   writeAttr.put (name, meth);
418                }
419                else
420                {
421                   ops.add(new MBeanOperationInfo JavaDoc
422                      (
423                      "Method " + name + " from class/interface " + clazz.getName(), meth
424                      )
425                   );
426
427                }
428             }
429          }
430
431          // we now combine the getters and setters in single RW attributes
432
//
433
Iterator JavaDoc readKeys = readAttr.keySet().iterator();
434          while (readKeys.hasNext())
435          {
436             String JavaDoc getter = (String JavaDoc)readKeys.next();
437             Method JavaDoc getterMethod = (Method JavaDoc)readAttr.get( getter );
438
439             String JavaDoc attribute = getter.substring(3);
440             String JavaDoc setter = "set" + attribute;
441
442             Method JavaDoc setterMethod = (Method JavaDoc)writeAttr.remove(setter);
443             attrs.add (new MBeanAttributeInfo JavaDoc (attribute, "", getterMethod, setterMethod));
444          }
445
446          // we add the remaining WO attributes
447
//
448
Iterator JavaDoc writeKeys = writeAttr.keySet().iterator();
449          while (writeKeys.hasNext())
450          {
451             String JavaDoc setter = (String JavaDoc)writeKeys.next();
452             Method JavaDoc setterMethod = (Method JavaDoc)writeAttr.get( setter );
453             String JavaDoc attribute = setter.substring(3);
454
455             attrs.add (new MBeanAttributeInfo JavaDoc (attribute, "", null, setterMethod));
456          }
457
458
459          result = new MBeanInfo JavaDoc(this.name,
460                            "Dynamic MBean Service around BSH script " + this.name,
461                            (MBeanAttributeInfo JavaDoc[])attrs.toArray(new MBeanAttributeInfo JavaDoc[attrs.size()]),
462                            result.getConstructors(),
463                            (MBeanOperationInfo JavaDoc[])ops.toArray(new MBeanOperationInfo JavaDoc[ops.size()]),
464                            result.getNotifications());
465       }
466
467       return result;
468    }
469
470    public ObjectName JavaDoc getPreferedObjectName ()
471    {
472       return this.preferedObjectName;
473    }
474
475    public ObjectName JavaDoc[] getDependsServices ()
476    {
477       return this.dependsServices;
478    }
479
480    // Private -------------------------------------------------------
481

482    // Inner classes -------------------------------------------------
483

484    public class InvocationCouple
485    {
486       public Object JavaDoc proxy = null;
487       public Method JavaDoc method = null;
488
489       public InvocationCouple (Object JavaDoc proxy, Method JavaDoc m)
490       {
491          this.proxy = proxy;
492          this.method = m;
493       }
494
495    }
496 }
497
Popular Tags