KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > conf > DriverDataSourceFactory


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. 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, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56 package org.objectstyle.cayenne.conf;
57
58 import java.io.InputStream JavaDoc;
59
60 import javax.sql.DataSource JavaDoc;
61
62 import org.apache.log4j.Level;
63 import org.apache.log4j.Logger;
64 import org.objectstyle.cayenne.ConfigurationException;
65 import org.objectstyle.cayenne.access.QueryLogger;
66 import org.objectstyle.cayenne.access.util.ConnectionEventLogger;
67 import org.objectstyle.cayenne.conn.DataSourceInfo;
68 import org.objectstyle.cayenne.conn.PoolManager;
69 import org.objectstyle.cayenne.util.AbstractHandler;
70 import org.objectstyle.cayenne.util.Util;
71 import org.xml.sax.Attributes JavaDoc;
72 import org.xml.sax.ContentHandler JavaDoc;
73 import org.xml.sax.InputSource JavaDoc;
74 import org.xml.sax.SAXException JavaDoc;
75 import org.xml.sax.XMLReader JavaDoc;
76 import org.xml.sax.helpers.DefaultHandler JavaDoc;
77
78 /**
79  * Creates DataSource objects from XML configuration files that describe a JDBC driver.
80  * Wraps JDBC driver in a generic DataSource implementation.
81  *
82  * @author Andrei Adamchik
83  */

84 // TODO: factory shouldn't contain any state specific to location ("driverInfo" ivar
85
// should go, and probably "parser" too)... Otherwise the API doesn't make sense -
86
// sequential invocations of getDataSource() will have side effects....
87
public class DriverDataSourceFactory implements DataSourceFactory {
88
89     private static Logger logObj = Logger.getLogger(DriverDataSourceFactory.class);
90
91     protected XMLReader JavaDoc parser;
92     protected DataSourceInfo driverInfo;
93     protected Level logLevel = Level.DEBUG;
94     protected Configuration parentConfiguration;
95
96     /**
97      * Creates new DriverDataSourceFactory.
98      */

99     public DriverDataSourceFactory() throws Exception JavaDoc {
100         this.parser = Util.createXmlReader();
101     }
102
103     /**
104      * Stores configuration object internally to use it later for resource loading.
105      */

106     public void initializeWithParentConfiguration(Configuration parentConfiguration) {
107         this.parentConfiguration = parentConfiguration;
108     }
109
110     public DataSource JavaDoc getDataSource(String JavaDoc location) throws Exception JavaDoc {
111         return this.getDataSource(location, Level.DEBUG);
112     }
113
114     public DataSource JavaDoc getDataSource(String JavaDoc location, Level logLevel) throws Exception JavaDoc {
115         this.logLevel = logLevel;
116         this.load(location);
117
118         ConnectionEventLogger logger = new ConnectionEventLogger(Level.INFO);
119
120         try {
121             return new PoolManager(driverInfo.getJdbcDriver(), driverInfo
122                     .getDataSourceUrl(), driverInfo.getMinConnections(), driverInfo
123                     .getMaxConnections(), driverInfo.getUserName(), driverInfo
124                     .getPassword(), logger);
125         }
126         catch (Exception JavaDoc ex) {
127             QueryLogger.logConnectFailure(logLevel, ex);
128             throw ex;
129         }
130     }
131
132     /**
133      * Returns DataSourceInfo property.
134      */

135     protected DataSourceInfo getDriverInfo() {
136         return this.driverInfo;
137     }
138
139     protected InputStream JavaDoc getInputStream(String JavaDoc location) {
140         if (this.parentConfiguration == null) {
141             throw new ConfigurationException(
142                     "No parent Configuration set - cannot continue.");
143         }
144
145         return this.parentConfiguration.getResourceLocator().findResourceStream(location);
146     }
147
148     /**
149      * Loads driver information from the file at <code>location</code>. Called
150      * internally from "getDataSource"
151      */

152     protected void load(String JavaDoc location) throws Exception JavaDoc {
153         logObj.log(logLevel, "loading driver information from '" + location + "'.");
154
155         InputStream JavaDoc in = this.getInputStream(location);
156         if (in == null) {
157             logObj.log(logLevel, "Error: location '" + location + "' not found.");
158             throw new ConfigurationException(
159                     "Can't find DataSource configuration file at " + location);
160         }
161
162         RootHandler handler = new RootHandler();
163         parser.setContentHandler(handler);
164         parser.setErrorHandler(handler);
165         parser.parse(new InputSource JavaDoc(in));
166     }
167
168     // SAX handlers start below
169

170     /** Handler for the root element. Its only child must be the "driver" element. */
171     private class RootHandler extends DefaultHandler JavaDoc {
172
173         /**
174          * Handles the start of a "driver" element. A driver handler is created and
175          * initialized with the element name and attributes.
176          *
177          * @exception SAXException if the tag given is not <code>"driver"</code>
178          */

179         public void startElement(
180                 String JavaDoc namespaceURI,
181                 String JavaDoc localName,
182                 String JavaDoc qName,
183                 Attributes JavaDoc atts) throws SAXException JavaDoc {
184             if (localName.equals("driver")) {
185                 new DriverHandler(parser, this).init(localName, atts);
186             }
187             else {
188                 logObj.log(logLevel, "<driver> must be the root element. <"
189                         + localName
190                         + "> is unexpected.");
191                 throw new SAXException JavaDoc("Config file is not of expected XML type. '"
192                         + localName
193                         + "' unexpected.");
194             }
195         }
196     }
197
198     /** Handler for the "driver" element. */
199     private class DriverHandler extends AbstractHandler {
200
201         public DriverHandler(XMLReader JavaDoc parser, ContentHandler JavaDoc parentHandler) {
202             super(parser, parentHandler);
203         }
204
205         public void init(String JavaDoc name, Attributes JavaDoc attrs) throws SAXException JavaDoc {
206             String JavaDoc className = attrs.getValue("", "class");
207             logObj.log(logLevel, "loading driver " + className);
208             driverInfo = new DataSourceInfo();
209             driverInfo.setJdbcDriver(className);
210         }
211
212         /**
213          * Handles the start of a driver child element. An appropriate handler is created
214          * and initialized with the element name and attributes.
215          *
216          * @exception SAXException if the tag given is not recognized.
217          */

218         public void startElement(
219                 String JavaDoc namespaceURI,
220                 String JavaDoc localName,
221                 String JavaDoc qName,
222                 Attributes JavaDoc atts) throws SAXException JavaDoc {
223             if (localName.equals("login")) {
224                 new LoginHandler(this.parser, this).init(localName, atts, driverInfo);
225             }
226             else if (localName.equals("url")) {
227                 new UrlHandler(this.parser, this).init(localName, atts, driverInfo);
228             }
229             else if (localName.equals("connectionPool")) {
230                 new ConnectionHandler(this.parser, this)
231                         .init(localName, atts, driverInfo);
232             }
233             else {
234                 logObj.log(logLevel, "<login, url, connectionPool> are valid. <"
235                         + localName
236                         + "> is unexpected.");
237                 throw new SAXException JavaDoc("Config file is not of expected XML type");
238             }
239         }
240
241     }
242
243     private class UrlHandler extends AbstractHandler {
244
245         /**
246          * Constructor which just delegates to the superconstructor.
247          *
248          * @param parentHandler The handler which should be restored to the parser at the
249          * end of the element. Must not be <code>null</code>.
250          */

251         public UrlHandler(XMLReader JavaDoc parser, ContentHandler JavaDoc parentHandler) {
252             super(parser, parentHandler);
253         }
254
255         public void init(String JavaDoc name, Attributes JavaDoc atts, DataSourceInfo driverInfo)
256                 throws SAXException JavaDoc {
257             driverInfo.setDataSourceUrl(atts.getValue("value"));
258             if (driverInfo.getDataSourceUrl() == null) {
259                 logObj.log(logLevel, "error: <url> has no 'value'.");
260                 throw new SAXException JavaDoc("'<url value=' attribute is required.");
261             }
262         }
263     }
264
265     private class LoginHandler extends AbstractHandler {
266
267         /**
268          * Constructor which just delegates to the superconstructor.
269          *
270          * @param parentHandler The handler which should be restored to the parser at the
271          * end of the element. Must not be <code>null</code>.
272          */

273         public LoginHandler(XMLReader JavaDoc parser, ContentHandler JavaDoc parentHandler) {
274             super(parser, parentHandler);
275         }
276
277         public void init(String JavaDoc name, Attributes JavaDoc atts, DataSourceInfo driverInfo)
278                 throws SAXException JavaDoc {
279             logObj.log(logLevel, "loading user name and password.");
280             driverInfo.setUserName(atts.getValue("userName"));
281             driverInfo.setPassword(atts.getValue("password"));
282         }
283     }
284
285     private class ConnectionHandler extends AbstractHandler {
286
287         /**
288          * Constructor which just delegates to the superconstructor.
289          *
290          * @param parentHandler The handler which should be restored to the parser at the
291          * end of the element. Must not be <code>null</code>.
292          */

293         public ConnectionHandler(XMLReader JavaDoc parser, ContentHandler JavaDoc parentHandler) {
294             super(parser, parentHandler);
295         }
296
297         public void init(String JavaDoc name, Attributes JavaDoc atts, DataSourceInfo driverInfo)
298                 throws SAXException JavaDoc {
299             try {
300                 String JavaDoc min = atts.getValue("min");
301                 if (min != null)
302                     driverInfo.setMinConnections(Integer.parseInt(min));
303
304                 String JavaDoc max = atts.getValue("max");
305                 if (max != null)
306                     driverInfo.setMaxConnections(Integer.parseInt(max));
307             }
308             catch (NumberFormatException JavaDoc nfex) {
309                 logObj.log(logLevel, "Error loading numeric attribute", nfex);
310                 throw new SAXException JavaDoc("Error reading numeric attribute.", nfex);
311             }
312         }
313     }
314 }
Popular Tags