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.io.PrintWriter;
020import java.sql.Connection;
021import java.sql.SQLException;
022import java.util.logging.Logger;
023
024import javax.sql.DataSource;
025
026import org.springframework.beans.factory.InitializingBean;
027import org.springframework.lang.Nullable;
028import org.springframework.util.Assert;
029
030/**
031 * JDBC {@link javax.sql.DataSource} implementation that delegates all calls
032 * to a given target {@link javax.sql.DataSource}.
033 *
034 * <p>This class is meant to be subclassed, with subclasses overriding only
035 * those methods (such as {@link #getConnection()}) that should not simply
036 * delegate to the target DataSource.
037 *
038 * @author Juergen Hoeller
039 * @since 1.1
040 * @see #getConnection
041 */
042public class DelegatingDataSource implements DataSource, InitializingBean {
043
044        @Nullable
045        private DataSource targetDataSource;
046
047
048        /**
049         * Create a new DelegatingDataSource.
050         * @see #setTargetDataSource
051         */
052        public DelegatingDataSource() {
053        }
054
055        /**
056         * Create a new DelegatingDataSource.
057         * @param targetDataSource the target DataSource
058         */
059        public DelegatingDataSource(DataSource targetDataSource) {
060                setTargetDataSource(targetDataSource);
061        }
062
063
064        /**
065         * Set the target DataSource that this DataSource should delegate to.
066         */
067        public void setTargetDataSource(@Nullable DataSource targetDataSource) {
068                this.targetDataSource = targetDataSource;
069        }
070
071        /**
072         * Return the target DataSource that this DataSource should delegate to.
073         */
074        @Nullable
075        public DataSource getTargetDataSource() {
076                return this.targetDataSource;
077        }
078
079        /**
080         * Obtain the target {@code DataSource} for actual use (never {@code null}).
081         * @since 5.0
082         */
083        protected DataSource obtainTargetDataSource() {
084                DataSource dataSource = getTargetDataSource();
085                Assert.state(dataSource != null, "No 'targetDataSource' set");
086                return dataSource;
087        }
088
089        @Override
090        public void afterPropertiesSet() {
091                if (getTargetDataSource() == null) {
092                        throw new IllegalArgumentException("Property 'targetDataSource' is required");
093                }
094        }
095
096
097        @Override
098        public Connection getConnection() throws SQLException {
099                return obtainTargetDataSource().getConnection();
100        }
101
102        @Override
103        public Connection getConnection(String username, String password) throws SQLException {
104                return obtainTargetDataSource().getConnection(username, password);
105        }
106
107        @Override
108        public PrintWriter getLogWriter() throws SQLException {
109                return obtainTargetDataSource().getLogWriter();
110        }
111
112        @Override
113        public void setLogWriter(PrintWriter out) throws SQLException {
114                obtainTargetDataSource().setLogWriter(out);
115        }
116
117        @Override
118        public int getLoginTimeout() throws SQLException {
119                return obtainTargetDataSource().getLoginTimeout();
120        }
121
122        @Override
123        public void setLoginTimeout(int seconds) throws SQLException {
124                obtainTargetDataSource().setLoginTimeout(seconds);
125        }
126
127
128        //---------------------------------------------------------------------
129        // Implementation of JDBC 4.0's Wrapper interface
130        //---------------------------------------------------------------------
131
132        @Override
133        @SuppressWarnings("unchecked")
134        public <T> T unwrap(Class<T> iface) throws SQLException {
135                if (iface.isInstance(this)) {
136                        return (T) this;
137                }
138                return obtainTargetDataSource().unwrap(iface);
139        }
140
141        @Override
142        public boolean isWrapperFor(Class<?> iface) throws SQLException {
143                return (iface.isInstance(this) || obtainTargetDataSource().isWrapperFor(iface));
144        }
145
146
147        //---------------------------------------------------------------------
148        // Implementation of JDBC 4.1's getParentLogger method
149        //---------------------------------------------------------------------
150
151        @Override
152        public Logger getParentLogger() {
153                return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
154        }
155
156}