KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > protomatter > syslog > xml > SyslogXML


1 package com.protomatter.syslog.xml;
2
3 /**
4  * {{{ The Protomatter Software License, Version 1.0
5  * derived from The Apache Software License, Version 1.1
6  *
7  * Copyright (c) 1998-2002 Nate Sammons. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed for the
24  * Protomatter Software Project
25  * (http://protomatter.sourceforge.net/)."
26  * Alternately, this acknowledgment may appear in the software itself,
27  * if and wherever such third-party acknowledgments normally appear.
28  *
29  * 4. The names "Protomatter" and "Protomatter Software Project" must
30  * not be used to endorse or promote products derived from this
31  * software without prior written permission. For written
32  * permission, please contact support@protomatter.com.
33  *
34  * 5. Products derived from this software may not be called "Protomatter",
35  * nor may "Protomatter" appear in their name, without prior written
36  * permission of the Protomatter Software Project
37  * (support@protomatter.com).
38  *
39  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42  * DISCLAIMED. IN NO EVENT SHALL THE PROTOMATTER SOFTWARE PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE. }}}
51  */

52
53 import java.io.*;
54 import java.net.*;
55 import java.util.*;
56 import java.text.*;
57 import com.protomatter.syslog.*;
58 import com.protomatter.util.Debug;
59 import com.protomatter.xml.*;
60 import org.jdom.*;
61 import org.jdom.output.*;
62 import org.jdom.input.*;
63
64 /**
65  * A utility class for configuring Syslog from an XML file.
66  */

67 public class SyslogXML
68 {
69   // We need local copies of these since we can't reference
70
// the Syslog.WARNING_PROPERTY constant without loading
71
// the Syslog class, which would show the warning ;-)
72
private static String JavaDoc CLASSLOADER_WARNING_PROPERTY = "Syslog.classloader.warning";
73   private static String JavaDoc WARNING_OFF = "off";
74
75   // By default, we show the classloader warning
76
private static boolean WARNING_DEFAULT = true;
77
78   /**
79    * The system property used to set the XML parser class.
80    */

81   public static String JavaDoc XML_PARSER_PROPERTY = "Syslog.xml.parser";
82
83   /**
84    * Default constructor.
85    */

86   private SyslogXML()
87   {
88     super();
89   }
90
91   /**
92    * Get an XML representation of the current configuration state of
93    * Syslog including all loggers, etc and write it to the given
94    * output stream.
95    */

96   public static void writeConfiguration(OutputStream out)
97   throws IOException
98   {
99     Document d = getConfiguration();
100     XMLOutputter output = new XMLOutputter();
101     //output.setIndent(true);
102
//output.setIndentSize(2);
103
output.setIndent(" ");
104     output.setNewlines(true);
105     //output.setSuppressDeclaration(true);
106
output.output(d, out);
107   }
108
109   /**
110    * Get an XML representation of the current configuration state of
111    * Syslog including all loggers, etc.
112    */

113   public static Document getConfiguration()
114   {
115     Element e = new Element("Syslog");
116     Document d = new Document(e);
117     e.setAttribute("defaultMask", Syslog.getLogMaskAsString());
118
119     long sleepInterval = Syslog.getFlushThreadInterval();
120     if (sleepInterval != 0)
121       e.setAttribute("flushThreadInterval", String.valueOf(sleepInterval));
122
123     if (Syslog.getLocalHostName() != null)
124     {
125       InetAddress addr = Syslog.getLocalHostName();
126       String JavaDoc name = addr.getHostName();
127       if (name == null)
128         name = addr.getHostAddress();
129       e.setAttribute("hostname", name);
130     }
131
132     e.setAttribute("computeCaller", String.valueOf(Syslog.getComputeCaller()));
133     e.setAttribute("alwaysComputeCaller", String.valueOf(Syslog.getAlwaysComputeCaller()));
134
135     Element debug = new Element("Debug");
136     debug.setAttribute("enabled", String.valueOf(Debug.isEnabled()));
137     debug.setAttribute("scan", String.valueOf(Debug.getScan()));
138     Iterator list = Debug.getTraceNames();
139     while (list.hasNext())
140     {
141       Element config = new Element("name");
142       config.setText((String JavaDoc)list.next());
143       config.setAttribute("level", "trace");
144       debug.getChildren().add(config);
145     }
146     list = Debug.getDebugNames();
147     while (list.hasNext())
148     {
149       Element config = new Element("name");
150       config.setText((String JavaDoc)list.next());
151       config.setAttribute("level", "debug");
152       debug.getChildren().add(config);
153     }
154     list = Debug.getInfoNames();
155     while (list.hasNext())
156     {
157       Element config = new Element("name");
158       config.setText((String JavaDoc)list.next());
159       config.setAttribute("level", "info");
160       debug.getChildren().add(config);
161     }
162     e.getChildren().add(debug);
163
164     list = Syslog.getLoggers();
165     while (list.hasNext())
166     {
167       Syslogger logger = (Syslogger)list.next();
168       XMLConfigHelper helper = null;
169       try
170       {
171         helper = XMLConfigUtil.getConfigHelper(logger);
172       }
173       catch (Exception JavaDoc x)
174       {
175         x.printStackTrace();
176       }
177       Element config = helper.getConfiguration(logger, null);
178       e.getChildren().add(config);
179     }
180
181     return d;
182   }
183
184   /**
185    * Configure syslog from the given XML file. The root
186    * element of the file must either be a <TT>&lt;Syslog&gt;</TT>
187    * tag, or it must contain a child that is a <TT>&lt;Syslog&gt;</TT>
188    * tag.<P>
189    *
190    * By default, this method will use the default SAX parser
191    * to parse the configuration file using JDom. If you wish
192    * to change the parser, you can specify the
193    * "<TT>Syslog.xml.parser</TT>" system property. That property
194    * should be set to the fully qualified class name of a SAX
195    * parser, such as "<TT>org.apache.xerces.parsers.SAXParser</TT>".
196    *
197    * @see #configure(Element element)
198    */

199   public static void configure(File xmlFile)
200   throws SyslogInitException
201   {
202     configure(xmlFile, System.getProperty(XML_PARSER_PROPERTY), WARNING_DEFAULT);
203   }
204
205   /**
206    * Configure syslog from the given XML file. The root
207    * element of the file must either be a <TT>&lt;Syslog&gt;</TT>
208    * tag, or it must contain a child that is a <TT>&lt;Syslog&gt;</TT>
209    * tag.<P>
210    *
211    * By default, this method will use the default SAX parser
212    * to parse the configuration file using JDom. If you wish
213    * to change the parser, you can specify the
214    * "<TT>Syslog.xml.parser</TT>" system property. That property
215    * should be set to the fully qualified class name of a SAX
216    * parser, such as "<TT>org.apache.xerces.parsers.SAXParser</TT>".
217    *
218    * @see #configure(Element element)
219    */

220   public static void configure(InputStream input)
221   throws SyslogInitException
222   {
223     configure(input, System.getProperty(XML_PARSER_PROPERTY), WARNING_DEFAULT);
224   }
225
226   /**
227    * Configure syslog from the given XML file using the
228    * given JDom SAX driver class as a parser. The driver
229    * class is given as a parameter to the constructor for a
230    * <TT>org.jdom.input.SAXBuilder</TT> object. For instance,
231    * to use the Apache Xerces parser, pass in
232    * "<TT>org.apache.xerces.parsers.SAXParser</TT>" as the
233    * driver.
234    *
235    * @param xmlFile Configuration file
236    * @param saxDriverClass XML parser class name
237    * @param showClassloaderWarning Should the classloader warning be shown?
238    * @see #configure(Element element)
239    */

240   public static void configure(File xmlFile, String JavaDoc saxDriverClass, boolean showClassloaderWarning)
241   throws SyslogInitException
242   {
243     if (!xmlFile.exists())
244     {
245       throw new SyslogInitException(Syslog.getResourceString(MessageConstants.CANNOT_CONFIGURE_MESSAGE),
246         new FileNotFoundException(
247           MessageFormat.format(Syslog.getResourceString(MessageConstants.FILE_NOT_FOUND_MESSAGE),
248           new Object JavaDoc[] { xmlFile })
249           ));
250     }
251
252     // Ditch the classloader warning
253
if (!showClassloaderWarning)
254         System.setProperty(CLASSLOADER_WARNING_PROPERTY, WARNING_OFF);
255
256     try
257     {
258       String JavaDoc rootName = "Syslog";
259       SAXBuilder builder = null;
260       if (saxDriverClass == null)
261         builder = new SAXBuilder();
262       else
263         builder = new SAXBuilder(saxDriverClass);
264       Document document = builder.build(xmlFile);
265       Element c = document.getRootElement();
266       if (c == null)
267         throw new SyslogInitException(MessageFormat.format(
268           Syslog.getResourceString(MessageConstants.XML_NO_SYSLOG_ELEMENT_MESSAGE),
269           new Object JavaDoc[] { "Syslog" }));
270       if (!c.getName().equals(rootName))
271       {
272         c = c.getChild(rootName, c.getNamespace());
273         if ((c == null) || (!rootName.equals(c.getName())))
274           throw new SyslogInitException(MessageFormat.format(
275             Syslog.getResourceString(MessageConstants.XML_NO_SYSLOG_ELEMENT_MESSAGE),
276             new Object JavaDoc[] { "Syslog" }));
277       }
278       configure(c);
279     }
280     catch (Exception JavaDoc x)
281     {
282       if (x instanceof SyslogInitException)
283         throw (SyslogInitException)x;
284       throw new SyslogInitException(Syslog.getResourceString(MessageConstants.CANNOT_CONFIGURE_MESSAGE), x);
285     }
286   }
287
288   /**
289    * Configure syslog from the given XML file using the
290    * given JDom SAX driver class as a parser. The driver
291    * class is given as a parameter to the constructor for a
292    * <TT>org.jdom.input.SAXBuilder</TT> object. For instance,
293    * to use the Apache Xerces parser, pass in
294    * "<TT>org.apache.xerces.parsers.SAXParser</TT>" as the
295    * driver.
296    *
297    * @param input InputStream carrying the XML configuration data
298    * @param saxDriverClass XML parser class name
299    * @param showClassloaderWarning Should the classloader warning be shown?
300    * @see #configure(Element element)
301    */

302   public static void configure(InputStream input, String JavaDoc saxDriverClass, boolean showClassloaderWarning)
303   throws SyslogInitException
304   {
305     try
306     {
307       // Ditch the classloader warning
308
if (!showClassloaderWarning)
309           System.setProperty(CLASSLOADER_WARNING_PROPERTY, WARNING_OFF);
310       String JavaDoc rootName = "Syslog";
311       SAXBuilder builder = null;
312       if (saxDriverClass == null)
313         builder = new SAXBuilder();
314       else
315         builder = new SAXBuilder(saxDriverClass);
316       Document document = builder.build(input);
317       Element c = document.getRootElement();
318       if (c == null)
319         throw new SyslogInitException(MessageFormat.format(
320           Syslog.getResourceString(MessageConstants.XML_NO_SYSLOG_ELEMENT_MESSAGE),
321           new Object JavaDoc[] { "Syslog" }));
322       if (!c.getName().equals(rootName))
323       {
324         c = c.getChild(rootName, c.getNamespace());
325         if ((c == null) || (!c.getName().equals(rootName)))
326           throw new SyslogInitException(MessageFormat.format(
327             Syslog.getResourceString(MessageConstants.XML_NO_SYSLOG_ELEMENT_MESSAGE),
328             new Object JavaDoc[] { "Syslog" }));
329       }
330       configure(c);
331     }
332     catch (Exception JavaDoc x)
333     {
334       x.printStackTrace();
335       if (x instanceof SyslogInitException)
336         throw (SyslogInitException)x;
337       throw new SyslogInitException(Syslog.getResourceString(MessageConstants.CANNOT_CONFIGURE_MESSAGE), x);
338     }
339   }
340
341   /**
342    * Configure syslog from the given XML document.
343    * The document should look like this:<P>
344    *
345    * <TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0 WIDTH="90%">
346    * <TR><TD>
347    * <PRE><B>
348    *
349    * &lt;Syslog
350    * defaultMask="<i>DefaultSyslogLogMask</i>"
351    * hostname="<i>LocalHostName</i>"
352    * computeCaller="<i>true|false</i>"
353    * alwaysComputeCaller="<i>true|false</i>"
354    * flushThreadInterval="<i>milliseconds</i>"
355    * &gt;
356    *
357    * &lt;Debug enabled="<i>true|false</i>" scan="<i>true|false</i>"&gt;
358    * &lt;name level="<i>trace|debug|info</i>"&gt;<i>name1</i>&lt;/name&gt;
359    * &lt;name level="<i>trace|debug|info</i>"&gt;<i>pattern1</i>&lt;/name&gt;
360    * &lt;name level="<i>trace|debug|info</i>"&gt;<i>name2</i>&lt;/name&gt;
361    * &lt;name level="<i>trace|debug|info</i>"&gt;<i>pattern2</i>&lt;/name&gt;
362    * &lt;/Debug&gt;
363    *
364    * &lt;Logger
365    * name="<i>LoggerName</i>"
366    * class="<i>LoggerClassName</i>"
367    * &gt;
368    * <font color="#888888">&lt;!-- Logger directives --&gt;</font>
369    * &lt;/Logger&gt;
370    *
371    * <font color="#888888">&lt;!-- More loggers here --&gt;</font>
372    *
373    * &lt;/Syslog&gt;
374    * </B></PRE>
375    * </TD></TR></TABLE><P>
376    *
377    * Each logger is loaded and configured with it's <tt>Logger</tt>
378    * XML element. See the Javadoc for individual loggers for more
379    * information.<P>
380    *
381    * The default, system-wide log mask is set to be "at or above"
382    * the value of the <tt>defaultMask</tt> attribute (if present).
383    * The hostname that Syslog thinks is "local" is set to the value
384    * of the <tt>hostname</tt> attribute (if present).<P>
385    *
386    * If the <TT>flushThreadInterval</TT> attribute is set,
387    * it is interpreted as the number of milliseconds for a
388    * background thread to sleep between attempts to flush
389    * all the loggers.<P>
390    *
391    * The <tt>computeCaller</tt> and <tt>alwaysComputeCaller</tt>
392    * attributes correspond to the
393    * <tt><a HREF="../Syslog.html#setComputeCaller(boolean)">Syslog.setComputeCaller()</a></tt>
394    * and
395    * <tt><a HREF="../Syslog.html#setAlwaysComputeCaller(boolean)">Syslog.setAlwaysComputeCaller()</a></tt>
396    * methods.<P>
397    *
398    * The optional <tt>&lt;Debug&gt;</tt> element contains a list of
399    * <tt>&lt;name&gt;</tt> elements, which are passed to the
400    * <tt>addXXXName()</tt> method of the
401    * <tt><a HREF="../../util/Debug.html">com.protomatter.util.Debug</a></tt> class.<P>
402    *
403    * @see BasicLogger
404    */

405   public static boolean configure(Element syslogConfig)
406   throws SyslogInitException
407   {
408     // setup syslog
409
try
410     {
411       Syslog.removeAllLoggers();
412       Debug.clear();
413
414       String JavaDoc syslogLevel = syslogConfig.getAttributeValue("defaultMask");
415       if (syslogLevel != null)
416         Syslog.setLogMask(syslogLevel);
417
418       String JavaDoc interval = syslogConfig.getAttributeValue("flushThreadInterval");
419       if (interval != null)
420         Syslog.setFlushThreadInterval(Long.parseLong(interval));
421
422       String JavaDoc name = syslogConfig.getAttributeValue("hostname");
423       if (name != null)
424       {
425         Syslog.setLocalHostName(InetAddress.getByName(name));
426       }
427
428       String JavaDoc computeCaller = syslogConfig.getAttributeValue("computeCaller");
429       if (computeCaller != null)
430       {
431         Syslog.setComputeCaller("true".equalsIgnoreCase(computeCaller));
432       }
433
434       computeCaller = syslogConfig.getAttributeValue("alwaysComputeCaller");
435       if (computeCaller != null)
436       {
437         Syslog.setAlwaysComputeCaller("true".equalsIgnoreCase(computeCaller));
438       }
439
440       // setup debug
441
Iterator list = syslogConfig.getChildren("Debug", syslogConfig.getNamespace()).iterator();
442       if (list.hasNext())
443       {
444         Element element = (Element)list.next();
445
446         String JavaDoc enabled = element.getAttributeValue("enabled");
447         if ("true".equalsIgnoreCase(enabled))
448             Debug.enable();
449         else
450             Debug.disable();
451
452         String JavaDoc scan = element.getAttributeValue("scan");
453         if (scan != null)
454           Debug.setScan("true".equalsIgnoreCase(scan));
455
456         Iterator children = element.getChildren("name", element.getNamespace()).iterator();
457         while (children.hasNext())
458         {
459           Element child = (Element)children.next();
460           String JavaDoc severity = child.getAttributeValue("level");
461           if ("trace".equals(severity))
462             Debug.addInfoName(child.getText());
463           else if ("debug".equals(severity))
464             Debug.addDebugName(child.getText());
465           else if ("info".equals(severity))
466             Debug.addInfoName(child.getText());
467         }
468       }
469
470       list = syslogConfig.getChildren("Logger",
471         syslogConfig.getNamespace()).iterator();
472       while (list.hasNext())
473       {
474         Element element = (Element)list.next();
475         String JavaDoc lClass = element.getAttributeValue("class");
476         String JavaDoc lName = element.getAttributeValue("name");
477         try
478         {
479           Syslogger logger = (Syslogger)Class.forName(lClass).newInstance();
480           XMLConfigHelper helper = XMLConfigUtil.getConfigHelper(logger);
481           helper.configure(logger, element);
482           logger.setName(lName);
483           Syslog.addLogger(logger);
484         }
485         catch (Exception JavaDoc x)
486         {
487           throw new SyslogInitException(
488             MessageFormat.format(Syslog.getResourceString(MessageConstants.CANNOT_REGISTER_LOGGER_MESSAGE),
489               new Object JavaDoc[] { lName }), x);
490         }
491       }
492     }
493     catch (Exception JavaDoc x)
494     {
495       if (x instanceof SyslogInitException)
496         throw (SyslogInitException)x;
497       throw new SyslogInitException(Syslog.getResourceString(MessageConstants.CANNOT_CONFIGURE_MESSAGE), x);
498     }
499
500     return true;
501   }
502
503   /**
504    * Write an example XML configuration file to
505    * standard out. The optional first command line
506    * argument is a filename to load as a configuration
507    * and then print to standard out. This can be
508    * useful, as all the default values are populated
509    * (which may not have been present in the input
510    * file).
511    *
512    * @see #configure(Element element)
513    */

514   public static final void main(String JavaDoc args[])
515   {
516     ResourceBundle bundle = null;
517     try
518     {
519       String JavaDoc bundleName = "com.protomatter.syslog.Syslog";
520       bundle = ResourceBundle.getBundle(bundleName);
521       if (bundle == null)
522       {
523         System.err.println("ERROR: Cannot load resource bundle \"" + bundleName + "\"");
524         System.exit(0);
525       }
526       if (args.length == 1)
527       {
528         File file = new File(args[0]);
529         System.out.println(MessageFormat.format(bundle.getString(MessageConstants.XML_LOADING_CONFIG_FILE),
530           new Object JavaDoc[] { file } ));
531         long time = System.currentTimeMillis();
532         SyslogXML.configure(file);
533         time = System.currentTimeMillis() - time;
534         System.out.println(MessageFormat.format(bundle.getString(MessageConstants.XML_LOADED_CONFIG_IN),
535           new Object JavaDoc[] { String.valueOf(time) } ));
536       }
537       System.out.println(bundle.getString(MessageConstants.XML_DUMPING_CONFIG));
538       System.out.println("----------------------------------------------------------------------");
539       SyslogXML.writeConfiguration(System.out);
540       System.out.println("----------------------------------------------------------------------");
541       System.out.println(bundle.getString(MessageConstants.XML_CONFIG_OK));
542     }
543     catch (Exception JavaDoc x)
544     {
545       System.out.println(bundle.getString(MessageConstants.XML_CONFIG_EXCEPTION));
546       x.printStackTrace();
547     }
548   }
549 }
550
Popular Tags