001/*
002 * Copyright 2002-2016 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.jdbc.datasource;
018
019import java.sql.Connection;
020import java.sql.SQLException;
021import java.util.Properties;
022
023import org.springframework.lang.UsesJava7;
024import org.springframework.util.Assert;
025
026/**
027 * Abstract base class for JDBC {@link javax.sql.DataSource} implementations
028 * that operate on a JDBC {@link java.sql.Driver}.
029 *
030 * @author Juergen Hoeller
031 * @since 2.5.5
032 * @see SimpleDriverDataSource
033 * @see DriverManagerDataSource
034 */
035public abstract class AbstractDriverBasedDataSource extends AbstractDataSource {
036
037        private String url;
038
039        private String username;
040
041        private String password;
042
043        private String catalog;
044
045        private String schema;
046
047        private Properties connectionProperties;
048
049
050        /**
051         * Set the JDBC URL to use for connecting through the Driver.
052         * @see java.sql.Driver#connect(String, java.util.Properties)
053         */
054        public void setUrl(String url) {
055                Assert.hasText(url, "Property 'url' must not be empty");
056                this.url = url.trim();
057        }
058
059        /**
060         * Return the JDBC URL to use for connecting through the Driver.
061         */
062        public String getUrl() {
063                return this.url;
064        }
065
066        /**
067         * Set the JDBC username to use for connecting through the Driver.
068         * @see java.sql.Driver#connect(String, java.util.Properties)
069         */
070        public void setUsername(String username) {
071                this.username = username;
072        }
073
074        /**
075         * Return the JDBC username to use for connecting through the Driver.
076         */
077        public String getUsername() {
078                return this.username;
079        }
080
081        /**
082         * Set the JDBC password to use for connecting through the Driver.
083         * @see java.sql.Driver#connect(String, java.util.Properties)
084         */
085        public void setPassword(String password) {
086                this.password = password;
087        }
088
089        /**
090         * Return the JDBC password to use for connecting through the Driver.
091         */
092        public String getPassword() {
093                return this.password;
094        }
095
096        /**
097         * Specify a database catalog to be applied to each Connection.
098         * @since 4.3.2
099         * @see Connection#setCatalog
100         */
101        public void setCatalog(String catalog) {
102                this.catalog = catalog;
103        }
104
105        /**
106         * Return the database catalog to be applied to each Connection, if any.
107         * @since 4.3.2
108         */
109        public String getCatalog() {
110                return this.catalog;
111        }
112
113        /**
114         * Specify a database schema to be applied to each Connection.
115         * @since 4.3.2
116         * @see Connection#setSchema
117         */
118        public void setSchema(String schema) {
119                this.schema = schema;
120        }
121
122        /**
123         * Return the database schema to be applied to each Connection, if any.
124         * @since 4.3.2
125         */
126        public String getSchema() {
127                return this.schema;
128        }
129
130        /**
131         * Specify arbitrary connection properties as key/value pairs,
132         * to be passed to the Driver.
133         * <p>Can also contain "user" and "password" properties. However,
134         * any "username" and "password" bean properties specified on this
135         * DataSource will override the corresponding connection properties.
136         * @see java.sql.Driver#connect(String, java.util.Properties)
137         */
138        public void setConnectionProperties(Properties connectionProperties) {
139                this.connectionProperties = connectionProperties;
140        }
141
142        /**
143         * Return the connection properties to be passed to the Driver, if any.
144         */
145        public Properties getConnectionProperties() {
146                return this.connectionProperties;
147        }
148
149
150        /**
151         * This implementation delegates to {@code getConnectionFromDriver},
152         * using the default username and password of this DataSource.
153         * @see #getConnectionFromDriver(String, String)
154         * @see #setUsername
155         * @see #setPassword
156         */
157        @Override
158        public Connection getConnection() throws SQLException {
159                return getConnectionFromDriver(getUsername(), getPassword());
160        }
161
162        /**
163         * This implementation delegates to {@code getConnectionFromDriver},
164         * using the given username and password.
165         * @see #getConnectionFromDriver(String, String)
166         */
167        @Override
168        public Connection getConnection(String username, String password) throws SQLException {
169                return getConnectionFromDriver(username, password);
170        }
171
172
173        /**
174         * Build properties for the Driver, including the given username and password (if any),
175         * and obtain a corresponding Connection.
176         * @param username the name of the user
177         * @param password the password to use
178         * @return the obtained Connection
179         * @throws SQLException in case of failure
180         * @see java.sql.Driver#connect(String, java.util.Properties)
181         */
182        @UsesJava7
183        protected Connection getConnectionFromDriver(String username, String password) throws SQLException {
184                Properties mergedProps = new Properties();
185                Properties connProps = getConnectionProperties();
186                if (connProps != null) {
187                        mergedProps.putAll(connProps);
188                }
189                if (username != null) {
190                        mergedProps.setProperty("user", username);
191                }
192                if (password != null) {
193                        mergedProps.setProperty("password", password);
194                }
195
196                Connection con = getConnectionFromDriver(mergedProps);
197                if (this.catalog != null) {
198                        con.setCatalog(this.catalog);
199                }
200                if (this.schema != null) {
201                        con.setSchema(this.schema);
202                }
203                return con;
204        }
205
206        /**
207         * Obtain a Connection using the given properties.
208         * <p>Template method to be implemented by subclasses.
209         * @param props the merged connection properties
210         * @return the obtained Connection
211         * @throws SQLException in case of failure
212         */
213        protected abstract Connection getConnectionFromDriver(Properties props) throws SQLException;
214
215}