KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > cache > PropertyConfigurator


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.cache;
8
9 import org.jboss.logging.Logger;
10 import org.jboss.util.propertyeditor.ElementEditor;
11 import org.jboss.util.propertyeditor.PropertyEditors;
12 import org.w3c.dom.*;
13 import org.w3c.dom.Node JavaDoc;
14 import org.xml.sax.InputSource JavaDoc;
15 import org.xml.sax.SAXException JavaDoc;
16 import org.xml.sax.SAXParseException JavaDoc;
17
18 import javax.xml.parsers.DocumentBuilder JavaDoc;
19 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
20 import java.beans.PropertyEditor JavaDoc;
21 import java.beans.PropertyEditorManager JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.FileInputStream JavaDoc;
25 import java.io.FileNotFoundException JavaDoc;
26 import java.lang.reflect.Method JavaDoc;
27 import java.net.URL JavaDoc;
28
29 /**
30  * A generic object property configurator. It reads in a user-specified xml file from class path,
31  * parses it into xml format, and finally performs reflection to configure
32  * the object through setter methods.
33  * <p>Here is a typical usage:
34  * <pre>
35  * MyObject obj = new MyObject();
36  * PropertyConfigurator config = new PropertyConfigurator();
37  * config.configure(obj, "my.xml");
38  * </pre>
39  * that will configure MyObject automatically based on the input xml file.
40  * <p>Note that this class currently supports configuration parameter as primary types,
41  * e.g., int, float, String, long, etc. In addition, it also supports <code>org.w3c.dom.Element</code>
42  * type.</p>
43  * The tag of the xml file currently suports at the root level "mbean", "attribute" for each
44  * property, and, finally, if the attribute type is "Element", the sub-tag name is assumed to be
45  * "config".
46  * <p>See the tree cache xml file for example.</p>
47  *
48  * @author bwang
49  */

50 public class PropertyConfigurator {
51    private static Logger logger_=Logger.getLogger(PropertyConfigurator.class);
52    private Object JavaDoc objToConfigure_;
53    private static final String JavaDoc ROOT="mbean";
54    private static final String JavaDoc ATTR="attribute";
55    private static final String JavaDoc SUB_ATTR="config";
56    private static final String JavaDoc NAME="name";
57
58    public PropertyConfigurator() {
59       // register property editor for org.w3c.dom.Element
60
try {
61          Class JavaDoc clasz=Class.forName("org.w3c.dom.Element");
62          Class JavaDoc elementClasz=Class.forName("org.jboss.util.propertyeditor.ElementEditor");
63          try {
64             PropertyEditor JavaDoc editor = PropertyEditors.getEditor(clasz); // if null, will throw a rte. If not, we will use the existing ones.
65
logger_.info("Found existing property editor for org.w3c.dom.Element: " +editor);
66          } catch (RuntimeException JavaDoc ex) {
67             logger_.info("Property editor for org.w3c.dom.Element does not exist." +
68                  " Will register org.jboss.util.propertyeditor.ElementEditor");
69             PropertyEditors.registerEditor(clasz, elementClasz);
70          }
71       }
72       catch(ClassNotFoundException JavaDoc ex) {
73          logger_.error("Class not found for either org.w3c.dom.Element or " +
74                  "org.jboss.util.propertyeditor.ElementEditor");
75       }
76    }
77
78    protected Element loadDocument(String JavaDoc location) throws ConfigureException {
79       URL JavaDoc url=null;
80       try {
81          url=new URL JavaDoc("file", "", 80, location); // Use for Main
82

83          logger_.debug("URL location is " + url.toString());
84          return loadDocument(url.openStream());
85       }
86       catch(java.net.MalformedURLException JavaDoc mfx) {
87          logger_.error("Configurator error: " + mfx);
88          mfx.printStackTrace();
89       }
90       catch(java.io.IOException JavaDoc e) {
91          logger_.error("Configurator error: " + e);
92          e.printStackTrace();
93       }
94       return null;
95    }
96
97    protected Element loadDocument(InputStream JavaDoc is) throws ConfigureException {
98       Document doc=null;
99       try {
100          InputSource JavaDoc xmlInp=new InputSource JavaDoc(is);
101
102          DocumentBuilderFactory JavaDoc docBuilderFactory=DocumentBuilderFactory.newInstance();
103          DocumentBuilder JavaDoc parser=docBuilderFactory.newDocumentBuilder();
104          doc=parser.parse(xmlInp);
105          Element root=doc.getDocumentElement();
106          root.normalize();
107          return root;
108       }
109       catch(SAXParseException JavaDoc err) {
110          logger_.error("Configurator SAXParse error: " + err.getMessage());
111          err.printStackTrace();
112       }
113       catch(SAXException JavaDoc e) {
114          logger_.error("Configurator SAX error: " + e);
115          e.printStackTrace();
116       }
117       catch(Exception JavaDoc pce) {
118          logger_.error("Configurator general error: " + pce);
119          pce.printStackTrace();
120       }
121       return null;
122    }
123
124    protected Element getMBeanElement(Element root) throws ConfigureException {
125       // This is following JBoss convention.
126
NodeList list=root.getElementsByTagName(ROOT);
127       if(list == null)
128          throw new ConfigureException("Can't find " + ROOT + " tag");
129
130       if(list.getLength() > 1)
131          throw new ConfigureException("Has multiple " + ROOT + " tag");
132
133       Node node=list.item(0);
134       Element element=null;
135       if(node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
136          element=(Element)node;
137       }
138       else {
139          throw new ConfigureException("Can't find " + ROOT + " element");
140       }
141       return element;
142    }
143
144    /**
145     * Configure the object based on the config xml file.
146     *
147     * @param objToConfigure Object that needs configuration.
148     * @param configFile xml file name that exists in the class path.
149     * @throws ConfigureException when the configuration attempt fails.
150     */

151    public void configure(Object JavaDoc objToConfigure, String JavaDoc configFile) throws ConfigureException {
152       // step x. load document
153
ClassLoader JavaDoc cl=Thread.currentThread().getContextClassLoader();
154       InputStream JavaDoc is=cl.getResourceAsStream(configFile);
155       if(is == null) {
156          try {
157             is=new FileInputStream JavaDoc(configFile);
158          }
159          catch(FileNotFoundException JavaDoc e) {
160             e.printStackTrace();
161          }
162       }
163       if(is == null)
164          throw new ConfigureException("could not find resource " + configFile);
165       configure(objToConfigure, is);
166    }
167
168    /**
169     * Configure the object based on the config xml file.
170     *
171     * @param objToConfigure Object that needs configuration.
172     * @param is InputStream for the configuration xml file.
173     * @throws ConfigureException when the configuration attempt fails.
174     */

175    public void configure(Object JavaDoc objToConfigure, InputStream JavaDoc is) throws ConfigureException {
176       objToConfigure_=objToConfigure;
177
178       if(is == null)
179          throw new ConfigureException("configure(): input stream is null for property xml");
180
181       Element root=loadDocument(is);
182       Element mbeanElement=getMBeanElement(root);
183       NodeList list=mbeanElement.getElementsByTagName(ATTR);
184       logger_.info("configure(): attribute size: " + list.getLength());
185
186       Class JavaDoc objClass=objToConfigure_.getClass();
187       Method JavaDoc[] methods=objClass.getMethods();
188       Class JavaDoc[] string_sig=new Class JavaDoc[]{String JavaDoc.class};
189
190       // step x. loop through attributes
191
for(int loop=0; loop < list.getLength(); loop++) {
192          Node node=list.item(loop);
193          if(node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
194             continue;
195
196          Element element=(Element)node;
197          String JavaDoc name=element.getAttribute(NAME);
198          String JavaDoc valueStr=getElementContent(element, true);
199          Element valueObj=null;
200          if(valueStr.length() == 0) { // try out element object
201
valueObj=getSubElementObject(element);
202          }
203          String JavaDoc methodName="set" + name;
204          Object JavaDoc value=null;
205          Method JavaDoc method=null;
206          Object JavaDoc[] args;
207
208
209          // try whether we have a setter that takes a simple String first
210
try {
211             method=objClass.getMethod(methodName, string_sig);
212          }
213          catch(Exception JavaDoc e) {
214             ; /* we don't have a setter with a String arg, just continue */
215          }
216
217          if(method != null) {
218             try {
219                args=new Object JavaDoc[]{valueStr};
220                logger_.debug("setting attribute " + name + " to " + valueStr);
221                method.invoke(objToConfigure_, new Object JavaDoc[]{valueStr});
222                continue;
223             }
224             catch(Exception JavaDoc ex) {
225                ex.printStackTrace();
226                throw new ConfigureException("configure(): can't invoke " + methodName + " to configure " +
227                        "TreeCache properties. Exception: " + ex);
228             }
229          }
230
231
232          // step x. Do a reflection on the object class to see
233
// if there is a set"Attribute" method. If not, exception is thrown.
234
for(int i=0; i < methods.length; i++) {
235             // Exclude the possibility of overloading methods now.
236

237             if(methodName.equals(methods[i].getName())) {
238                method=methods[i];
239                Class JavaDoc[] clz=method.getParameterTypes(); // size should be 1
240
if(clz.length != 1)
241                   throw new ConfigureException("Parameter size of " + methodName +
242                           " is not 1 but " + clz.length);
243
244                Class JavaDoc classParam=clz[0];
245                // step x. Get the class type for the set"Attribute" argument and convert
246
// the attribute from String to the named class type.
247
PropertyEditor JavaDoc editor=PropertyEditorManager.findEditor(classParam);
248                if(editor == null) {
249                   String JavaDoc str="Could not find PropertyEditor for type class " +
250                           classParam;
251                   throw new ConfigureException(str);
252                }
253
254                if(valueObj != null) { // means there is a sub element
255
editor.setValue(valueObj);
256                }
257                else {
258                   editor.setAsText(valueStr);
259                }
260
261                value=editor.getValue();
262                logger_.debug("Invoking setter method: " + method +
263                        " with parameter \"" + value + "\" of type " + value.getClass());
264
265                // step x. invoke set"Attribute" from mthod.invoke(object, params)
266
try {
267                   method.invoke(objToConfigure_, new Object JavaDoc[]{value});
268                }
269                catch(Exception JavaDoc ex) {
270                   ex.printStackTrace();
271                   throw new ConfigureException("configure(): Can't invoke set method to configure " +
272                           "TreeCache properties. Method name: " + methodName + " exception: " + ex);
273                }
274             }
275          }
276       }
277    }
278
279    private Element getSubElementObject(Element element)
280            throws ConfigureException {
281
282 // NodeList nl = element.getElementsByTagName(SUB_ATTR); // somehoe this doesn't work.
283
NodeList nl=element.getChildNodes();
284       for(int i=0; i < nl.getLength(); i++) {
285          Node node=nl.item(i);
286          if(node.getNodeType() == Node.ELEMENT_NODE &&
287                  SUB_ATTR.equals( ((Element)node).getTagName() ) ) {
288             return (Element)node;
289          }
290       }
291
292       logger_.debug("getSubElementObject(): " +
293               "element object. Does not exist for " + SUB_ATTR);
294
295       return null;
296    }
297
298    private String JavaDoc getElementContent(Element element, boolean trim)
299            throws ConfigureException {
300       NodeList nl=element.getChildNodes();
301       String JavaDoc attributeText="";
302       for(int i=0; i < nl.getLength(); i++) {
303          Node n=nl.item(i);
304          if(n instanceof Text) {
305             attributeText+=((Text)n).getData();
306          }
307       } // end of for ()
308
if(trim)
309          attributeText=attributeText.trim();
310       return attributeText;
311    }
312
313    public static void main(String JavaDoc[] args) {
314       try {
315          TreeCache cache=new TreeCache();
316          PropertyConfigurator config=new PropertyConfigurator();
317          config.configure(cache, "tree-cache.xml");
318       }
319       catch(Exception JavaDoc ex) {
320          ex.printStackTrace();
321       }
322    }
323 }
324
Popular Tags