KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > system > ServiceConfigurator


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.system;
23
24 import java.io.IOException JavaDoc;
25 import java.io.StringWriter JavaDoc;
26 import java.io.Writer JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32
33 import javax.management.Attribute JavaDoc;
34 import javax.management.InstanceNotFoundException JavaDoc;
35 import javax.management.MBeanAttributeInfo JavaDoc;
36 import javax.management.MBeanInfo JavaDoc;
37 import javax.management.MBeanServer JavaDoc;
38 import javax.management.ObjectName JavaDoc;
39 import javax.xml.parsers.DocumentBuilder JavaDoc;
40 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
41 import javax.xml.transform.Transformer JavaDoc;
42 import javax.xml.transform.TransformerException JavaDoc;
43 import javax.xml.transform.TransformerFactory JavaDoc;
44 import javax.xml.transform.dom.DOMSource JavaDoc;
45 import javax.xml.transform.stream.StreamResult JavaDoc;
46
47 import org.jboss.deployment.DeploymentException;
48 import org.jboss.logging.Logger;
49 import org.jboss.mx.util.JMXExceptionDecoder;
50 import org.jboss.system.metadata.ServiceAttributeMetaData;
51 import org.jboss.system.metadata.ServiceMetaData;
52 import org.jboss.system.metadata.ServiceMetaDataParser;
53 import org.jboss.system.metadata.ServiceValueContext;
54 import org.jboss.util.xml.DOMWriter;
55 import org.w3c.dom.Document JavaDoc;
56 import org.w3c.dom.Element JavaDoc;
57 import org.w3c.dom.Node JavaDoc;
58 import org.w3c.dom.NodeList JavaDoc;
59
60 /**
61  * Service configuration helper.
62  *
63  * @author <a HREF="mailto:marc@jboss.org">Marc Fleury</a>
64  * @author <a HREF="mailto:hiram@jboss.org">Hiram Chirino</a>
65  * @author <a HREF="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
66  * @author <a HREF="mailto:jason@planet57.com">Jason Dillon</a>
67  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
68  * @author <a HREF="adrian@jboss.com">Adrian Brock</a>
69  * @version <tt>$Revision: 57108 $</tt>
70  */

71 public class ServiceConfigurator
72 {
73    /** The MBean server which this service is registered in. */
74    private final MBeanServer JavaDoc server;
75    
76    /** The parent service controller */
77    private final ServiceController serviceController;
78    
79    /** The ServiceCreator */
80    private final ServiceCreator serviceCreator;
81    
82    /** The ServiceBinding plugin policy */
83    private ServiceBinding serviceBinding;
84
85    /** Instance logger. */
86    private static final Logger log = Logger.getLogger(ServiceConfigurator.class);
87
88    /**
89     * Configure an MBean
90     *
91     * @param server the server
92     * @param controller the service controller
93     * @param objectName the object name
94     * @param classLoaderName the classloader object name
95     * @param attrs the attributes
96     * @throws Exception for any error
97     */

98    public static void configure(MBeanServer JavaDoc server, ServiceController controller, ObjectName JavaDoc objectName, ObjectName JavaDoc classLoaderName, Collection JavaDoc<ServiceAttributeMetaData> attrs) throws Exception JavaDoc
99    {
100       server = checkMBeanServer(server, controller);
101       ClassLoader JavaDoc cl = server.getClassLoader(classLoaderName);
102       configure(server, controller, objectName, cl, attrs);
103    }
104    
105    /**
106     * Configure an MBean
107     *
108     * @param server the server
109     * @param controller the service controller
110     * @param objectName the object name
111     * @param cl the classloader
112     * @param attrs the attributes
113     * @throws Exception for any error
114     */

115    public static void configure(MBeanServer JavaDoc server, ServiceController controller, ObjectName JavaDoc objectName, ClassLoader JavaDoc cl, Collection JavaDoc<ServiceAttributeMetaData> attrs) throws Exception JavaDoc
116    {
117       ServiceValueContext valueContext = new ServiceValueContext(server, controller, cl);
118       server = checkMBeanServer(server, controller);
119       
120       HashMap JavaDoc<String JavaDoc, MBeanAttributeInfo JavaDoc> attributeMap = getAttributeMap(server, objectName);
121
122       for (ServiceAttributeMetaData attribute : attrs)
123       {
124          String JavaDoc attributeName = attribute.getName();
125          if (attributeName == null || attributeName.length() == 0)
126             throw new DeploymentException("No or empty attribute name for " + objectName);
127          MBeanAttributeInfo JavaDoc attributeInfo = attributeMap.get(attributeName);
128          if (attributeInfo == null)
129             throw new DeploymentException("No Attribute found with name: " + attributeName + " for " + objectName);
130
131          valueContext.setAttributeInfo(attributeInfo);
132          Object JavaDoc value = attribute.getValue(valueContext);
133          try
134          {
135             log.debug(attributeName + " set to " + value + " in " + objectName);
136             server.setAttribute(objectName, new Attribute JavaDoc(attributeName, value));
137          }
138          catch (Throwable JavaDoc t)
139          {
140             throw new DeploymentException("Exception setting attribute " + attributeName + " on mbean " + objectName, JMXExceptionDecoder.decode(t));
141          }
142       }
143    }
144
145    /**
146     * Check the server/controller parameters
147     *
148     * @param server the server
149     * @param controller the controller
150     * @return the server
151     */

152    private static MBeanServer JavaDoc checkMBeanServer(MBeanServer JavaDoc server, ServiceController controller)
153    {
154       if (server != null)
155          return server;
156       
157       if (controller != null)
158          return controller.getMBeanServer();
159       
160       throw new IllegalArgumentException JavaDoc("Either the server or controller must be passed");
161    }
162    
163    /**
164     * Apply any service binding overrides
165     *
166     * @review why isn't the MBeanServer part of this api?
167     * @param server the server
168     * @param objectName the object name
169     * @param serviceBinding the service binding
170     * @throws Exception for any error
171     */

172    public static void applyServiceConfig(MBeanServer JavaDoc server, ObjectName JavaDoc objectName, ServiceBinding serviceBinding) throws Exception JavaDoc
173    {
174       try
175       {
176          serviceBinding.applyServiceConfig(objectName);
177       }
178       catch (Throwable JavaDoc e)
179       {
180          // serviceBinding is most probably a dynamic mbean proxy
181
Throwable JavaDoc t = JMXExceptionDecoder.decode(e);
182          log.warn("Failed to apply service binding override for " + objectName, t);
183       }
184    }
185
186    /**
187     * Get an attribute map for the MBean
188     *
189     * @param server the server
190     * @param objectName the object name
191     * @return a map of attribute name to attribute info
192     * @throws Exception for any error
193     */

194    private static HashMap JavaDoc<String JavaDoc, MBeanAttributeInfo JavaDoc> getAttributeMap(MBeanServer JavaDoc server, ObjectName JavaDoc objectName) throws Exception JavaDoc
195    {
196       MBeanInfo JavaDoc info;
197       try
198       {
199          info = server.getMBeanInfo(objectName);
200       }
201       catch (InstanceNotFoundException JavaDoc e)
202       {
203          // The MBean is no longer available
204
throw new DeploymentException("Trying to configure nonexistent mbean: " + objectName);
205       }
206       catch (Exception JavaDoc e)
207       {
208          throw new DeploymentException("Could not get mbeanInfo", JMXExceptionDecoder.decode(e));
209       }
210       if (info == null)
211          throw new DeploymentException("MBeanInfo is null for mbean: " + objectName);
212       MBeanAttributeInfo JavaDoc[] attributes = info.getAttributes();
213       HashMap JavaDoc<String JavaDoc, MBeanAttributeInfo JavaDoc> attributeMap = new HashMap JavaDoc<String JavaDoc, MBeanAttributeInfo JavaDoc>();
214       for (int i = 0; i < attributes.length; i++)
215       {
216          MBeanAttributeInfo JavaDoc attr = attributes[i];
217          attributeMap.put(attr.getName(), attr);
218       }
219       
220       return attributeMap;
221    }
222    
223    /**
224     * Constructor
225     *
226     * @deprecated the service controller no longer uses the service configurator and vice-versa
227     * @param server the mbean server
228     * @param serviceController the servie controller
229     * @param serviceCreator the service creator
230     */

231    public ServiceConfigurator(MBeanServer JavaDoc server, ServiceController serviceController, ServiceCreator serviceCreator)
232    {
233       if (server == null)
234          throw new IllegalArgumentException JavaDoc("Null server");
235       if (serviceCreator == null)
236          throw new IllegalArgumentException JavaDoc("Null serverCreator");
237       
238       this.server = server;
239       this.serviceController = serviceController;
240       this.serviceCreator = serviceCreator;
241       if (serviceController != null)
242          this.serviceBinding = serviceController.getServiceBinding();
243    }
244    
245    /**
246     * Dynamically plug-in a ServiceBinding policy
247     * to possibly override the configuration of a service.
248     *
249     * @param serviceBinding policy
250     */

251    public void setServiceBinding(ServiceBinding serviceBinding)
252    {
253       this.serviceBinding = serviceBinding;
254    }
255    
256    /**
257     * The <code>install</code> method iterates through the mbean tags in the
258     * supplied xml configuration and creates and configures the mbeans shown.
259     * The mbean configuration can be nested.
260     *
261     * @deprecated the service controller no longer uses the service configurator and vice-versa
262     * @param config the xml <code>Element</code> containing the configuration of
263     * the mbeans to create and configure.
264     * @param loaderName the classloader's ObjectName
265     * @return a <code>List</code> of ObjectNames of created mbeans.
266     * @throws DeploymentException if an error occurs
267     */

268    public List JavaDoc<ObjectName JavaDoc> install(Element JavaDoc config, ObjectName JavaDoc loaderName) throws DeploymentException
269    {
270       // Parse the xml
271
ServiceMetaDataParser parser = new ServiceMetaDataParser(config);
272       List JavaDoc<ServiceMetaData> metaDatas = parser.parse();
273
274       // Track the registered object names
275
List JavaDoc<ObjectName JavaDoc> result = new ArrayList JavaDoc<ObjectName JavaDoc>(metaDatas.size());
276
277       // Go through each mbean in the passed xml
278
for (ServiceMetaData metaData : metaDatas)
279       {
280          ObjectName JavaDoc objectName = metaData.getObjectName();
281          Collection JavaDoc<ServiceAttributeMetaData> attrs = metaData.getAttributes();
282          // Install and configure the mbean
283
try
284          {
285             ServiceCreator.install(server, objectName, metaData, null);
286             result.add(objectName);
287             configure(server, null, objectName, loaderName, attrs);
288             if (serviceBinding != null)
289                applyServiceConfig(server, objectName, serviceBinding);
290          }
291          catch (Throwable JavaDoc t)
292          {
293             // Something went wrong
294
for (ObjectName JavaDoc name : result)
295             {
296                try
297                {
298                   serviceCreator.remove(name);
299                }
300                catch (Exception JavaDoc e)
301                {
302                   log.error("Error removing mbean after failed deployment: " + name, e);
303                }
304             }
305             DeploymentException.rethrowAsDeploymentException("Error during install", t);
306          }
307       }
308       return result;
309    }
310
311    /**
312     * Builds a string that consists of the configuration elements of the
313     * currently running MBeans registered in the server.
314     *
315     * @todo replace with more sophisticated mbean persistence mechanism.
316     * @param server the MBeanServer
317     * @param serviceController the service controller
318     * @param objectNames the object names to retrieve
319     * @return the xml string
320     * @throws Exception Failed to construct configuration.
321     */

322    public static String JavaDoc getConfiguration(MBeanServer JavaDoc server, ServiceController serviceController, ObjectName JavaDoc[] objectNames) throws Exception JavaDoc
323    {
324       Writer JavaDoc out = new StringWriter JavaDoc();
325
326       DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
327       DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
328       Document JavaDoc doc = builder.newDocument();
329
330       Element JavaDoc serverElement = doc.createElement("server");
331
332       // Store attributes as XML
333
for (int j = 0; j < objectNames.length; j++)
334       {
335          Element JavaDoc mbeanElement = internalGetConfiguration(doc, server, serviceController, objectNames[j]);
336          serverElement.appendChild(mbeanElement);
337       }
338
339       doc.appendChild(serverElement);
340
341       // Write configuration
342
new DOMWriter(out).setPrettyprint(true).print(doc);
343
344       out.close();
345
346       // Return configuration
347
return out.toString();
348    }
349
350    private static Element JavaDoc internalGetConfiguration(Document JavaDoc doc, MBeanServer JavaDoc server, ServiceController serviceController, ObjectName JavaDoc name) throws Exception JavaDoc
351    {
352       Element JavaDoc mbeanElement = doc.createElement("mbean");
353       mbeanElement.setAttribute("name", name.toString());
354
355       MBeanInfo JavaDoc info = server.getMBeanInfo(name);
356       mbeanElement.setAttribute("code", info.getClassName());
357       MBeanAttributeInfo JavaDoc[] attributes = info.getAttributes();
358       boolean trace = log.isTraceEnabled();
359       for (int i = 0; i < attributes.length; i++)
360       {
361          if (trace)
362             log.trace("considering attribute: " + attributes[i]);
363          if (attributes[i].isReadable() && attributes[i].isWritable())
364          {
365             Element JavaDoc attributeElement = null;
366             if (attributes[i].getType().equals("javax.management.ObjectName"))
367             {
368                attributeElement = doc.createElement("depends");
369                attributeElement.setAttribute("optional-attribute-name", attributes[i].getName());
370             }
371             else
372             {
373                attributeElement = doc.createElement("attribute");
374                attributeElement.setAttribute("name", attributes[i].getName());
375             }
376             Object JavaDoc value = server.getAttribute(name, attributes[i].getName());
377
378             if (value != null)
379             {
380                if (value instanceof Element JavaDoc)
381                {
382                   attributeElement.appendChild(doc.importNode((Element JavaDoc) value, true));
383                }
384                else
385                {
386                   attributeElement.appendChild(doc.createTextNode(value.toString()));
387                }
388             }
389             mbeanElement.appendChild(attributeElement);
390          }
391       }
392
393       ServiceContext sc = serviceController.getServiceContext(name);
394       for (Iterator JavaDoc i = sc.iDependOn.iterator(); i.hasNext();)
395       {
396          ServiceContext needs = (ServiceContext) i.next();
397          Element JavaDoc dependsElement = doc.createElement("depends");
398          dependsElement.appendChild(doc.createTextNode(needs.objectName.toString()));
399          mbeanElement.appendChild(dependsElement);
400       }
401
402       return mbeanElement;
403    }
404
405    /**
406     * Builds a string that consists of the configuration elements of the
407     * currently running MBeans registered in the server.
408     *
409     * TODO replace with more sophisticated mbean persistence mechanism.
410     * @param objectNames the object names
411     * @return the xml string
412     * @throws Exception Failed to construct configuration.
413     */

414    public String JavaDoc getConfiguration(ObjectName JavaDoc[] objectNames) throws Exception JavaDoc
415    {
416       return getConfiguration(server, serviceController, objectNames);
417    }
418
419    /**
420     * A utility method that transforms the contents of the argument element into
421     * a StringBuffer representation that can be reparsed.
422     *
423     * [FIXME] This is not a general DOMUtils method because of its funny contract. It does not
424     * support multiple child elements neither can it deal with text content.
425     *
426     * @param element - the parent dom element whose contents are to be extracted as an xml document string.
427     * @return the xml document string.
428     * @throws IOException for an error during IO
429     * @throws TransformerException for an erro during transformation
430     */

431    public static StringBuffer JavaDoc getElementContent(Element JavaDoc element) throws IOException JavaDoc, TransformerException JavaDoc
432    {
433       NodeList JavaDoc children = element.getChildNodes();
434       Element JavaDoc content = null;
435       for (int n = 0; n < children.getLength(); n++)
436       {
437          Node JavaDoc node = children.item(n);
438          if (node.getNodeType() == Node.ELEMENT_NODE)
439          {
440             content = (Element JavaDoc)node;
441             break;
442          }
443       }
444       if (content == null)
445          return null;
446
447       // Get a parsable representation of this elements content
448
DOMSource JavaDoc source = new DOMSource JavaDoc(content);
449       TransformerFactory JavaDoc tFactory = TransformerFactory.newInstance();
450       Transformer JavaDoc transformer = tFactory.newTransformer();
451       StringWriter JavaDoc sw = new StringWriter JavaDoc();
452       StreamResult JavaDoc result = new StreamResult JavaDoc(sw);
453       transformer.transform(source, result);
454       sw.close();
455       return sw.getBuffer();
456    }
457 }
Popular Tags