KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > proxool > configuration > XMLConfigurator


1 /*
2  * This software is released under a licence similar to the Apache Software Licence.
3  * See org.logicalcobwebs.proxool.package.html for details.
4  * The latest version is available at http://proxool.sourceforge.net
5  */

6 package org.logicalcobwebs.proxool.configuration;
7
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10 import org.logicalcobwebs.proxool.ProxoolConstants;
11 import org.logicalcobwebs.proxool.ProxoolException;
12 import org.logicalcobwebs.proxool.ProxoolFacade;
13 import org.xml.sax.Attributes JavaDoc;
14 import org.xml.sax.SAXException JavaDoc;
15 import org.xml.sax.SAXParseException JavaDoc;
16 import org.xml.sax.helpers.DefaultHandler JavaDoc;
17
18 import java.util.Properties JavaDoc;
19
20 /**
21  * <p>A SAX 2 ContentHandler that can configure Proxool from an XML source.</p>
22  *
23  * <p>This is just a <a
24  * HREF="http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html" target="_new"
25  * >ContentHandler</a>, so you must associate it with a SAX parser for it to actually do anything.
26  * If you have JAXP available {@link JAXPConfigurator} will do this for you.</p>
27  *
28  * <p>Properties that you pass on to the delegate driver have to be treated specially. They
29  * must be contained within a &lt;driver-properties&gt; element.</p>
30  *
31  * <p>See the <a HREF="The latest version is available at http://proxool.sourceforge.net/properties.html" target="_new">Proxool properties</a> for documentation
32  * on the available configuration properties.</p>
33  *
34  * Example configuration:
35  * <pre>
36  * &lt;proxool&gt;
37  * &lt;alias&gt;apple&lt;/alias&gt;
38  * &lt;driver-url&gt;jdbc:hsqldb:.&lt;/driver-url&gt;
39  * &lt;driver-class&gt;org.hsqldb.jdbcDriver&lt;/driver-class&gt;
40  * &lt;driver-properties&gt;
41  * &lt;property name="user" value="abc" /&gt;
42  * &lt;property name="password" value="def" /&gt;
43  * &lt;/driver-properties&gt;
44  * &lt;house-keeping-sleep-time&gt;40000&lt;/house-keeping-sleep-time&gt;
45  * &lt;house-keeping-test-sql&gt;select CURRENT_DATE&lt;/house-keeping-test-sql&gt;
46  * &lt;maximum-connection-count&gt;10&lt;/maximum-connection-count&gt;
47  * &lt;minimum-connection-count&gt;3&lt;/minimum-connection-count&gt;
48  * &lt;maximum-connection-lifetime&gt;18000000&lt;/maximum-connection-lifetime&gt; &lt;!-- 5 hours --&gt;
49  * &lt;simultaneous-build-throttle&gt;5&lt;/simultaneous-build-throttle&gt;
50  * &lt;recently-started-threshold&gt;40000&lt;/recently-started-threshold&gt;
51  * &lt;overload-without-refusal-lifetime&gt;50000&lt;/overload-without-refusal-lifetime&gt;
52  * &lt;maximum-active-time&gt;60000&lt;/maximum-active-time&gt;
53  * &lt;verbose&gt;true&lt;/verbose&gt;
54  * &lt;trace&gt;true&lt;/trace&gt;
55  * &lt;fatal-sql-exception&gt;ORA-1234&lt;/fatal-sql-exception&gt;
56  * &lt;prototype-count&gt;2&lt;/prototype-count&gt;
57  * &lt;/proxool&gt;
58  * </pre>
59  *
60  * When the parser reaches the end of the &lt;proxool&gt; element the pool
61  * is automatically registered. You can contain the &lt;proxool&gt; element
62  * in any other elements as you wish. And the &lt;proxool&gt; element can
63  * occur as many times as you wish. This allows you to use an XML file that
64  * configures your whole application as the source. This configurator will
65  * ignore everything apart from the elements contained within the &lt;proxool&gt;
66  * element.
67  *<p><a name="#validation">
68  * <b>Validation</b><br>
69  * A couple of additional steps are required if you want your SAX parser to validate your Proxool xml confguration:
70  * <ul>
71  * <li>
72  * Put your proxool configuration elements inside a root <code>proxool-config</code> element.
73  * The document must adhere to the <a HREF="proxool.dtd">Proxool dtd</a>.
74  * </li>
75  * <li>
76  * Add a <code>DOCTYPE</code> entry to your xml with a system id containing the <i>absolute url</i> to the Proxool
77  * dtd. The Proxool jar contains a copy of the Proxool dtd in the confguration package. You can reference that with
78  * a jar url like this:<br>
79  * <code><nobr>&lt;!DOCTYPE proxool-config SYSTEM "jar:file:///C:/Proxool/lib/proxool.jar!/org/logicalcobwebs/proxool/configuration/proxool.dtd"&gt;</nobr></code></li>
80  * <li>
81  * Configure your parser to be validating. In the {@link JAXPConfigurator} this is done by passing <code>true</code> as
82  * the second arghument to any of the <code>configure</code> methods.
83  * </li>
84  * </ul>
85  * </p>
86  *<p>This class is not thread safe.</p>
87  *
88  * @version $Revision: 1.18 $, $Date: 2006/01/18 14:39:58 $
89  * @author billhorsman
90  * @author $Author: billhorsman $ (current maintainer)
91  */

92 public class XMLConfigurator extends DefaultHandler JavaDoc {
93     private static final Log LOG = LogFactory.getLog(XMLConfigurator.class);
94
95     private StringBuffer JavaDoc content = new StringBuffer JavaDoc();
96
97     private String JavaDoc poolName;
98
99     private String JavaDoc driverClass;
100
101     private String JavaDoc driverUrl;
102
103     private Properties JavaDoc properties = new Properties JavaDoc();
104
105     private static final String JavaDoc PROXOOL = "proxool";
106
107     private static final String JavaDoc DRIVER_PROPERTIES = "driver-properties";
108
109     private static final String JavaDoc PROPERTY = "property";
110
111     private static final String JavaDoc NAME = "name";
112
113     private static final String JavaDoc VALUE = "value";
114
115     private boolean insideDelegateProperties;
116
117     private boolean insideProxool;
118
119     /**
120      * @see org.xml.sax.ContentHandler#startElement
121      */

122     public void startElement(String JavaDoc uri, String JavaDoc lname, String JavaDoc qname, Attributes JavaDoc attributes) throws SAXException JavaDoc {
123         content.setLength(0);
124
125         if (!namespaceOk(uri)) {
126             return;
127         }
128
129         final String JavaDoc elementName = getElementName(uri, lname, qname);
130
131         if (elementName.equals(PROXOOL)) {
132             if (insideProxool) {
133                 throw new SAXException JavaDoc("A <" + PROXOOL + "> element can't contain another <" + PROXOOL + "> element.");
134             }
135             insideProxool = true;
136             properties.clear();
137             driverClass = null;
138             driverUrl = null;
139         }
140
141         if (insideProxool) {
142             if (elementName.equals(DRIVER_PROPERTIES)) {
143                 insideDelegateProperties = true;
144             } else if (insideDelegateProperties) {
145                 if (elementName.equals(PROPERTY)) {
146                     setDriverProperty(attributes);
147                 }
148             }
149         }
150     }
151
152     /**
153      * @see org.xml.sax.ContentHandler#characters
154      */

155     public void characters(char[] chars, int start, int length) throws SAXException JavaDoc {
156         if (insideProxool) {
157             content.append(chars, start, length);
158         }
159     }
160
161     /**
162      * @see org.xml.sax.ContentHandler#endElement
163      */

164     public void endElement(String JavaDoc uri, String JavaDoc lname, String JavaDoc qname) throws SAXException JavaDoc {
165         if (!namespaceOk(uri)) {
166             return;
167         }
168
169         final String JavaDoc elementName = getElementName(uri, lname, qname);
170
171         // Are we ending a proxool configuration section?
172
if (elementName.equals(PROXOOL)) {
173
174             // Check that we have defined the minimum information
175
if (driverClass == null || driverUrl == null) {
176                 throw new SAXException JavaDoc("You must define the " + ProxoolConstants.DRIVER_CLASS + " and the " + ProxoolConstants.DRIVER_URL + ".");
177             }
178
179             // Build the URL; optinally defining a name
180
StringBuffer JavaDoc url = new StringBuffer JavaDoc();
181             url.append("proxool");
182             if (poolName != null) {
183                 url.append(ProxoolConstants.ALIAS_DELIMITER);
184                 url.append(poolName);
185             }
186             url.append(ProxoolConstants.URL_DELIMITER);
187             url.append(driverClass);
188             url.append(ProxoolConstants.URL_DELIMITER);
189             url.append(driverUrl);
190             if (LOG.isDebugEnabled()) {
191                 LOG.debug("Created url: " + url);
192             }
193
194             // Register the pool
195
try {
196                 ProxoolFacade.registerConnectionPool(url.toString(), properties);
197             } catch (ProxoolException e) {
198                 throw new SAXException JavaDoc(e);
199             }
200
201             // This ensures we ignore remaining XML until we come across another
202
// <proxool> element.
203
insideProxool = false;
204         }
205
206         if (insideProxool && !elementName.equals(PROXOOL)) {
207             if (elementName.equals(DRIVER_PROPERTIES)) {
208                 insideDelegateProperties = false;
209             } else if (!insideDelegateProperties) {
210                 setProxoolProperty(elementName, content.toString().trim());
211             }
212         }
213     }
214
215     private void setProxoolProperty(String JavaDoc localName, String JavaDoc value) {
216         if (localName.equals(ProxoolConstants.ALIAS)) {
217             poolName = value;
218         } else if (localName.equals(ProxoolConstants.DRIVER_CLASS)) {
219             driverClass = value;
220         } else if (localName.equals(ProxoolConstants.DRIVER_URL)) {
221             driverUrl = value;
222         } else {
223             if (LOG.isDebugEnabled()) {
224                 LOG.debug("Setting property '" + ProxoolConstants.PROPERTY_PREFIX + localName + "' to value '" + value + "'.");
225             }
226             properties.put(ProxoolConstants.PROPERTY_PREFIX + localName, value);
227         }
228     }
229
230     private void setDriverProperty(Attributes JavaDoc attributes) throws SAXException JavaDoc {
231         final String JavaDoc name = attributes.getValue(NAME);
232         final String JavaDoc value = attributes.getValue(VALUE);
233         if (name == null || name.length() < 1 || value == null) {
234             throw new SAXException JavaDoc("Name or value attribute missing from property element."
235                 + "Name: '" + name + "' Value: '" + value + "'.");
236         }
237         if (LOG.isDebugEnabled()) {
238             if (name.toLowerCase().indexOf("password") > -1) {
239                 LOG.debug("Adding driver property: " + name + "=" + "*******");
240             } else {
241                 LOG.debug("Adding driver property: " + name + "=" + value);
242             }
243         }
244         properties.put(name, value);
245     }
246
247     /**
248      * @see org.xml.sax.ErrorHandler#warning(SAXParseException)
249      */

250     public void warning(SAXParseException JavaDoc e) throws SAXException JavaDoc {
251         // Just debug-log the warning. We'll probably survive.
252
LOG.debug("The saxparser reported a warning.", e);
253     }
254
255     /**
256      * @see org.xml.sax.ErrorHandler#error(SAXParseException)
257      */

258     public void error(SAXParseException JavaDoc e) throws SAXException JavaDoc {
259         // On error we rethrow the exception.
260
// This should cause the parser stop and an exeption be thrown back to the client.
261
throw e;
262     }
263
264     /**
265      * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException)
266      */

267     public void fatalError(SAXParseException JavaDoc e) throws SAXException JavaDoc {
268         // On fatal error we rethrow the exception.
269
// This should cause the parser stop and an exeption be thrown back to the client.
270
throw e;
271     }
272
273     // If no namespace use qname, else use lname.
274
private String JavaDoc getElementName(String JavaDoc uri, String JavaDoc lname, String JavaDoc qname) {
275         if (uri == null || "".equals(uri)) {
276             return qname;
277         } else {
278             return lname;
279         }
280     }
281
282     private boolean namespaceOk(String JavaDoc uri) {
283         return uri == null || uri.length() == 0 || uri.equals(ProxoolConstants.PROXOOL_XML_NAMESPACE_URI);
284     }
285 }
286
Popular Tags