001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: Xml2Datasources.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.database;
009:
010: import com.uwyn.rife.config.Config;
011: import com.uwyn.rife.xml.Xml2Data;
012: import com.uwyn.rife.xml.exceptions.XmlErrorException;
013: import java.util.HashMap;
014: import javax.naming.Context;
015: import javax.naming.InitialContext;
016: import javax.naming.NamingException;
017: import javax.sql.DataSource;
018: import org.xml.sax.Attributes;
019:
020: /**
021: * This class parses an XML file to create a set of {@link Datasource}
022: * objects.
023: * <p>An example of the parsable datasource file:
024: * <pre><datasources>
025: * <datasource name="postgres">
026: * <driver>org.postgresql.Driver</driver>
027: * <url>jdbc:postgres://localhost/database</url>
028: * <user>username</user>
029: * <password>password</user>
030: * <poolsize>5</poolsize>
031: * </datasource>
032: *</datasources></pre>
033: * <p>An explaination of terms:
034: * <ul>
035: * <li>datasource name: used to uniquely identify the datasource
036: * <li>driver: the classname of the driver to use to connect
037: * <li>url: the connection url used to connect
038: * <li>user: the username needed for authentication
039: * <li>password: the password needed for authentication
040: * <li>poolsize: the number of connections to always keep connected
041: * </ul>
042: * Multiple datasource definitions are supported and can be used at anytime.
043: *
044: * @author JR Boyens (jboyens[remove] at uwyn dot com)
045: * @author Geert Bevin (gbevin[remove] at uwyn dot com)
046: * @version $Revision: 3634 $
047: * @since 1.0
048: */
049: public class Xml2Datasources extends Xml2Data {
050: private Datasource mDatasource = null;
051: private HashMap<String, Datasource> mDatasources = null;
052: private String mNameAttribute = null;
053: private StringBuilder mCharacterData = null;
054:
055: /**
056: * Return the created datasources.
057: *
058: * @return the datasources created after parsing
059: * @since 1.0
060: */
061: public HashMap<String, Datasource> getDatasources() {
062: return mDatasources;
063: }
064:
065: /**
066: * Clears the information in this datasource.
067: *
068: * @since 1.0
069: */
070: protected void clear() {
071: mDatasource = null;
072: mDatasources = new HashMap<String, Datasource>();
073: mNameAttribute = null;
074: mCharacterData = null;
075: }
076:
077: /**
078: * Called when the beginng of the document to be parsed is found
079: *
080: * @since 1.0
081: */
082: public void startDocument() {
083: clear();
084: }
085:
086: /**
087: * Called when the start tag of an XML element is encountered
088: *
089: * @param namespaceURI the URI of the namespace of the start tag
090: * @param localName the local name of the starting element
091: * @param qName the qualified name of the starting element
092: * @param atts the attributes of the starting element
093: * @since 1.0
094: */
095: public void startElement(String namespaceURI, String localName,
096: String qName, Attributes atts) {
097: if (qName.equals("datasource")) {
098: mNameAttribute = atts.getValue("name");
099:
100: mDatasource = new Datasource();
101: } else if (qName.equals("driver") || qName.equals("url")
102: || qName.equals("user") || qName.equals("password")
103: || qName.equals("poolsize") || qName.equals("jndi")) {
104: mCharacterData = new StringBuilder();
105: } else if (qName.equals("config")) {
106: if (mCharacterData != null && Config.hasRepInstance()) {
107: mCharacterData.append(Config.getRepInstance()
108: .getString(atts.getValue("param"), ""));
109: }
110: } else if (qName.equals("datasources")) {
111: // do nothing
112: } else {
113: throw new XmlErrorException("Unsupport element name '"
114: + qName + "'.");
115: }
116: }
117:
118: /**
119: * Called when the end tag of an XML element is encountered
120: *
121: * @param namespaceURI the URI of the namespace of the ending element
122: * @param localName the local name of the ending element
123: * @param qName the qualified name of the ending element
124: * @since 1.0
125: */
126: public void endElement(String namespaceURI, String localName,
127: String qName) {
128: if (qName.equals("datasource")) {
129: mDatasources.put(mNameAttribute, mDatasource);
130: } else if (qName.equals("driver")) {
131: mDatasource.setDriver(mCharacterData.toString());
132: } else if (qName.equals("url")) {
133: mDatasource.setUrl(mCharacterData.toString());
134: } else if (qName.equals("user")) {
135: mDatasource.setUser(mCharacterData.toString());
136: } else if (qName.equals("password")) {
137: mDatasource.setPassword(mCharacterData.toString());
138: } else if (qName.equals("jndi")) {
139: Context ctx;
140: try {
141: ctx = new InitialContext();
142:
143: Object ds = ctx.lookup(mCharacterData.toString());
144: if (null == ds) {
145: throw new XmlErrorException("The '"
146: + mCharacterData.toString()
147: + "' JNDI entry returned 'null'.");
148: }
149: if (!(ds instanceof DataSource)) {
150: throw new XmlErrorException("The '"
151: + mCharacterData.toString()
152: + "' JNDI entry isn't a DataSource.");
153: }
154:
155: mDatasource.setDataSource((DataSource) ds);
156: } catch (NamingException e) {
157: throw new XmlErrorException(
158: "Unexpected error while looking up the '"
159: + mCharacterData.toString()
160: + "' JNDI entry.", e);
161: }
162:
163: } else if (qName.equals("poolsize")) {
164: try {
165: mDatasource.setPoolsize(Integer.parseInt(mCharacterData
166: .toString()));
167: } catch (NumberFormatException e) {
168: throw new XmlErrorException(
169: "The value of the poolsize isn't an integer.",
170: e);
171: }
172: }
173: }
174:
175: /**
176: * Called when text data is encountered, usually between tags.
177: *
178: * @param ch a character array of the encountered text content
179: * @param start the index in the array at which the content starts
180: * @param length the length of the data stored in the character array
181: * @since 1.0
182: */
183: public void characters(char[] ch, int start, int length) {
184: if (length > 0) {
185: mCharacterData
186: .append(String.copyValueOf(ch, start, length));
187: }
188: }
189: }
|