1 /* Copyright (c) 2001-2016, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 
32 package org.hsqldb.jdbc;
33 
34 import java.io.Serializable;
35 import java.sql.Connection;
36 import java.sql.SQLException;
37 
38 //#ifdef JAVA6
39 import java.sql.Wrapper;
40 
41 //#endif JAVA6
42 import java.util.Properties;
43 
44 import javax.naming.NamingException;
45 import javax.naming.Reference;
46 import javax.naming.Referenceable;
47 import javax.naming.StringRefAddr;
48 import javax.sql.DataSource;
49 
50 /**
51  * <p>A factory for connections to the physical data source that this
52  * <code>DataSource</code> object represents.  An alternative to the
53  * <code>DriverManager</code> facility, a <code>DataSource</code> object
54  * is the preferred means of getting a connection. An object that implements
55  * the <code>DataSource</code> interface will typically be
56  * registered with a naming service based on the
57  * Java<sup><font size=-2>TM</font></sup> Naming and Directory (JNDI) API.
58  * <P>
59  * The <code>DataSource</code> interface is implemented by a driver vendor.
60  * There are three types of implementations:
61  * <OL>
62  *   <LI>Basic implementation -- produces a standard <code>Connection</code>
63  *       object
64  *   <LI>Connection pooling implementation -- produces a <code>Connection</code>
65  *       object that will automatically participate in connection pooling.  This
66  *       implementation works with a middle-tier connection pooling manager.
67  *   <LI>Distributed transaction implementation -- produces a
68  *       <code>Connection</code> object that may be used for distributed
69  *       transactions and almost always participates in connection pooling.
70  *       This implementation works with a middle-tier
71  *       transaction manager and almost always with a connection
72  *       pooling manager.
73  * </OL>
74  * <P>
75  * A <code>DataSource</code> object has properties that can be modified
76  * when necessary.  For example, if the data source is moved to a different
77  * server, the property for the server can be changed.  The benefit is that
78  * because the data source's properties can be changed, any code accessing
79  * that data source does not need to be changed.
80  * <P>
81  * A driver that is accessed via a <code>DataSource</code> object does not
82  * register itself with the <code>DriverManager</code>.  Rather, a
83  * <code>DataSource</code> object is retrieved though a lookup operation
84  * and then used to create a <code>Connection</code> object.  With a basic
85  * implementation, the connection obtained through a <code>DataSource</code>
86  * object is identical to a connection obtained through the
87  * <code>DriverManager</code> facility.
88  *
89  * <!-- start Release-specific documentation -->
90  * <div class="ReleaseSpecificDocumentation">
91  * <h3>HSQLDB-Specific Information:</h3> <p>
92  *
93  * This implementation of data source is a basic implementation and does not
94  * perform connection pooling.<p>
95  *
96  * The getter and setter methods of the parent class, {@link JDBCCommonDataSource},
97  * can be used.<p>
98  * </div>
99  * <!-- end Release-specific documentation -->
100  * @since JDK 1.4
101  * @author Campbell Burnet (boucherb@users dot sourceforge.net)
102  * @author Fred Toussi (fredt@users dot sourceforge.net)
103  * @version 2.3.2
104  * @since 1.7.2
105  */
106 
107 //#ifdef JAVA6
108 @SuppressWarnings("serial")
109 
110 //#endif JAVA6
111 public class JDBCDataSource extends JDBCCommonDataSource implements DataSource,
112         Serializable, Referenceable
113 
114 //#ifdef JAVA6
115 , Wrapper
116 
117 //#endif JAVA6
118 {
119 
120     /**
121      * Retrieves a new connection using the properties that have already been
122      * set.
123      *
124      * @return  a connection to the data source
125      * @exception SQLException if a database access error occurs
126      */
getConnection()127     public Connection getConnection() throws SQLException {
128 
129         if (url == null) {
130             throw JDBCUtil.nullArgument("url");
131         }
132 
133         if (connectionProps == null) {
134             if (user == null) {
135                 throw JDBCUtil.invalidArgument("user");
136             }
137 
138             if (password == null) {
139                 throw JDBCUtil.invalidArgument("password");
140             }
141 
142             return getConnection(user, password);
143         }
144 
145         return getConnection(url, connectionProps);
146     }
147 
148     /**
149      * Retrieves a new connection using the given username and password,
150      * and the database url that has been set. No other properties are
151      * used for the connection
152      *
153      * @param username the database user on whose behalf the connection is
154      *  being made
155      * @param password the user's password
156      * @return  a connection to the data source
157      * @exception SQLException if a database access error occurs
158      */
getConnection(String username, String password)159     public Connection getConnection(String username,
160                                     String password) throws SQLException {
161 
162         if (username == null) {
163             throw JDBCUtil.invalidArgument("user");
164         }
165 
166         if (password == null) {
167             throw JDBCUtil.invalidArgument("password");
168         }
169 
170         Properties props = new Properties();
171 
172         props.setProperty("user", username);
173         props.setProperty("password", password);
174         props.setProperty("loginTimeout", Integer.toString(loginTimeout));
175 
176         return getConnection(url, props);
177     }
178 
getConnection(String url, Properties props)179     private Connection getConnection(String url,
180                                      Properties props) throws SQLException {
181 
182         if (!url.startsWith("jdbc:hsqldb:")) {
183             url = "jdbc:hsqldb:" + url;
184         }
185 
186         return JDBCDriver.getConnection(url, props);
187     }
188 
189     //------------------------- JDBC 4.0 -----------------------------------
190     // ------------------- java.sql.Wrapper implementation ---------------------
191 
192     /**
193      * Returns an object that implements the given interface to allow access to
194      * non-standard methods, or standard methods not exposed by the proxy.
195      *
196      * If the receiver implements the interface then the result is the receiver
197      * or a proxy for the receiver. If the receiver is a wrapper
198      * and the wrapped object implements the interface then the result is the
199      * wrapped object or a proxy for the wrapped object. Otherwise return the
200      * the result of calling <code>unwrap</code> recursively on the wrapped object
201      * or a proxy for that result. If the receiver is not a
202      * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
203      *
204      * @param iface A Class defining an interface that the result must implement.
205      * @return an object that implements the interface. May be a proxy for the actual implementing object.
206      * @throws java.sql.SQLException If no object found that implements the interface
207      * @since JDK 1.6, HSQLDB 2.0
208      */
209 //#ifdef JAVA6
210     @SuppressWarnings("unchecked")
unwrap(java.lang.Class<T> iface)211     public <T>T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
212 
213         if (isWrapperFor(iface)) {
214             return (T) this;
215         }
216 
217         throw JDBCUtil.invalidArgument("iface: " + iface);
218     }
219 
220 //#endif JAVA6
221 
222     /**
223      * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
224      * for an object that does. Returns false otherwise. If this implements the interface then return true,
225      * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
226      * object. If this does not implement the interface and is not a wrapper, return false.
227      * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
228      * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
229      * returns true then calling <code>unwrap</code> with the same argument should succeed.
230      *
231      * @param iface a Class defining an interface.
232      * @return true if this implements the interface or directly or indirectly wraps an object that does.
233      * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
234      * for an object with the given interface.
235      * @since JDK 1.6, HSQLDB 2.0
236      */
237 //#ifdef JAVA6
isWrapperFor( java.lang.Class<?> iface)238     public boolean isWrapperFor(
239             java.lang.Class<?> iface) throws java.sql.SQLException {
240         return (iface != null && iface.isAssignableFrom(this.getClass()));
241     }
242 
243 //#endif JAVA6
244 
245     /**
246      * Retrieves the Reference of this object.
247      *
248      * @return The non-null Reference of this object.
249      * @exception NamingException If a naming exception was encountered
250      *          while retrieving the reference.
251      */
getReference()252     public Reference getReference() throws NamingException {
253 
254         String    cname = "org.hsqldb.jdbc.JDBCDataSourceFactory";
255         Reference ref   = new Reference(getClass().getName(), cname, null);
256 
257         ref.add(new StringRefAddr("database", getDatabase()));
258         ref.add(new StringRefAddr("user", getUser()));
259         ref.add(new StringRefAddr("password", password));
260         ref.add(new StringRefAddr("loginTimeout",
261                                   Integer.toString(loginTimeout)));
262 
263         return ref;
264     }
265 
266     // ------------------------ custom public methods ------------------------
JDBCDataSource()267     public JDBCDataSource() {
268     }
269 }
270