001/*
002 * Copyright 2002-2017 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.Nullable;
024
025/**
026 * Abstract base class for JDBC {@link javax.sql.DataSource} implementations
027 * that operate on a JDBC {@link java.sql.Driver}.
028 *
029 * @author Juergen Hoeller
030 * @since 2.5.5
031 * @see SimpleDriverDataSource
032 * @see DriverManagerDataSource
033 */
034public abstract class AbstractDriverBasedDataSource extends AbstractDataSource {
035
036        @Nullable
037        private String url;
038
039        @Nullable
040        private String username;
041
042        @Nullable
043        private String password;
044
045        @Nullable
046        private String catalog;
047
048        @Nullable
049        private String schema;
050
051        @Nullable
052        private Properties connectionProperties;
053
054
055        /**
056         * Set the JDBC URL to use for connecting through the Driver.
057         * @see java.sql.Driver#connect(String, java.util.Properties)
058         */
059        public void setUrl(@Nullable String url) {
060                this.url = (url != null ? url.trim() : null);
061        }
062
063        /**
064         * Return the JDBC URL to use for connecting through the Driver.
065         */
066        @Nullable
067        public String getUrl() {
068                return this.url;
069        }
070
071        /**
072         * Set the JDBC username to use for connecting through the Driver.
073         * @see java.sql.Driver#connect(String, java.util.Properties)
074         */
075        public void setUsername(@Nullable String username) {
076                this.username = username;
077        }
078
079        /**
080         * Return the JDBC username to use for connecting through the Driver.
081         */
082        @Nullable
083        public String getUsername() {
084                return this.username;
085        }
086
087        /**
088         * Set the JDBC password to use for connecting through the Driver.
089         * @see java.sql.Driver#connect(String, java.util.Properties)
090         */
091        public void setPassword(@Nullable String password) {
092                this.password = password;
093        }
094
095        /**
096         * Return the JDBC password to use for connecting through the Driver.
097         */
098        @Nullable
099        public String getPassword() {
100                return this.password;
101        }
102
103        /**
104         * Specify a database catalog to be applied to each Connection.
105         * @since 4.3.2
106         * @see Connection#setCatalog
107         */
108        public void setCatalog(@Nullable String catalog) {
109                this.catalog = catalog;
110        }
111
112        /**
113         * Return the database catalog to be applied to each Connection, if any.
114         * @since 4.3.2
115         */
116        @Nullable
117        public String getCatalog() {
118                return this.catalog;
119        }
120
121        /**
122         * Specify a database schema to be applied to each Connection.
123         * @since 4.3.2
124         * @see Connection#setSchema
125         */
126        public void setSchema(@Nullable String schema) {
127                this.schema = schema;
128        }
129
130        /**
131         * Return the database schema to be applied to each Connection, if any.
132         * @since 4.3.2
133         */
134        @Nullable
135        public String getSchema() {
136                return this.schema;
137        }
138
139        /**
140         * Specify arbitrary connection properties as key/value pairs,
141         * to be passed to the Driver.
142         * <p>Can also contain "user" and "password" properties. However,
143         * any "username" and "password" bean properties specified on this
144         * DataSource will override the corresponding connection properties.
145         * @see java.sql.Driver#connect(String, java.util.Properties)
146         */
147        public void setConnectionProperties(@Nullable Properties connectionProperties) {
148                this.connectionProperties = connectionProperties;
149        }
150
151        /**
152         * Return the connection properties to be passed to the Driver, if any.
153         */
154        @Nullable
155        public Properties getConnectionProperties() {
156                return this.connectionProperties;
157        }
158
159
160        /**
161         * This implementation delegates to {@code getConnectionFromDriver},
162         * using the default username and password of this DataSource.
163         * @see #getConnectionFromDriver(String, String)
164         * @see #setUsername
165         * @see #setPassword
166         */
167        @Override
168        public Connection getConnection() throws SQLException {
169                return getConnectionFromDriver(getUsername(), getPassword());
170        }
171
172        /**
173         * This implementation delegates to {@code getConnectionFromDriver},
174         * using the given username and password.
175         * @see #getConnectionFromDriver(String, String)
176         */
177        @Override
178        public Connection getConnection(String username, String password) throws SQLException {
179                return getConnectionFromDriver(username, password);
180        }
181
182
183        /**
184         * Build properties for the Driver, including the given username and password (if any),
185         * and obtain a corresponding Connection.
186         * @param username the name of the user
187         * @param password the password to use
188         * @return the obtained Connection
189         * @throws SQLException in case of failure
190         * @see java.sql.Driver#connect(String, java.util.Properties)
191         */
192        protected Connection getConnectionFromDriver(@Nullable String username, @Nullable String password) throws SQLException {
193                Properties mergedProps = new Properties();
194                Properties connProps = getConnectionProperties();
195                if (connProps != null) {
196                        mergedProps.putAll(connProps);
197                }
198                if (username != null) {
199                        mergedProps.setProperty("user", username);
200                }
201                if (password != null) {
202                        mergedProps.setProperty("password", password);
203                }
204
205                Connection con = getConnectionFromDriver(mergedProps);
206                if (this.catalog != null) {
207                        con.setCatalog(this.catalog);
208                }
209                if (this.schema != null) {
210                        con.setSchema(this.schema);
211                }
212                return con;
213        }
214
215        /**
216         * Obtain a Connection using the given properties.
217         * <p>Template method to be implemented by subclasses.
218         * @param props the merged connection properties
219         * @return the obtained Connection
220         * @throws SQLException in case of failure
221         */
222        protected abstract Connection getConnectionFromDriver(Properties props) throws SQLException;
223
224}