1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.jdbc.datasource.lookup;
18
19 import java.sql.Connection;
20 import java.sql.SQLException;
21 import java.util.HashMap;
22 import java.util.Map;
23 import javax.sql.DataSource;
24
25 import org.springframework.beans.factory.InitializingBean;
26 import org.springframework.jdbc.datasource.AbstractDataSource;
27 import org.springframework.util.Assert;
28
29
30
31
32
33
34
35
36
37
38
39
40 public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
41
42 private Map<Object, Object> targetDataSources;
43
44 private Object defaultTargetDataSource;
45
46 private boolean lenientFallback = true;
47
48 private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
49
50 private Map<Object, DataSource> resolvedDataSources;
51
52 private DataSource resolvedDefaultDataSource;
53
54
55
56
57
58
59
60
61
62
63
64
65 public void setTargetDataSources(Map<Object, Object> targetDataSources) {
66 this.targetDataSources = targetDataSources;
67 }
68
69
70
71
72
73
74
75
76
77
78 public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
79 this.defaultTargetDataSource = defaultTargetDataSource;
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 public void setLenientFallback(boolean lenientFallback) {
96 this.lenientFallback = lenientFallback;
97 }
98
99
100
101
102
103
104
105 public void setDataSourceLookup(DataSourceLookup dataSourceLookup) {
106 this.dataSourceLookup = (dataSourceLookup != null ? dataSourceLookup : new JndiDataSourceLookup());
107 }
108
109
110 @Override
111 public void afterPropertiesSet() {
112 if (this.targetDataSources == null) {
113 throw new IllegalArgumentException("Property 'targetDataSources' is required");
114 }
115 this.resolvedDataSources = new HashMap<Object, DataSource>(this.targetDataSources.size());
116 for (Map.Entry<Object, Object> entry : this.targetDataSources.entrySet()) {
117 Object lookupKey = resolveSpecifiedLookupKey(entry.getKey());
118 DataSource dataSource = resolveSpecifiedDataSource(entry.getValue());
119 this.resolvedDataSources.put(lookupKey, dataSource);
120 }
121 if (this.defaultTargetDataSource != null) {
122 this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);
123 }
124 }
125
126
127
128
129
130
131
132
133
134
135 protected Object resolveSpecifiedLookupKey(Object lookupKey) {
136 return lookupKey;
137 }
138
139
140
141
142
143
144
145
146
147
148 protected DataSource resolveSpecifiedDataSource(Object dataSource) throws IllegalArgumentException {
149 if (dataSource instanceof DataSource) {
150 return (DataSource) dataSource;
151 }
152 else if (dataSource instanceof String) {
153 return this.dataSourceLookup.getDataSource((String) dataSource);
154 }
155 else {
156 throw new IllegalArgumentException(
157 "Illegal data source value - only [javax.sql.DataSource] and String supported: " + dataSource);
158 }
159 }
160
161
162 @Override
163 public Connection getConnection() throws SQLException {
164 return determineTargetDataSource().getConnection();
165 }
166
167 @Override
168 public Connection getConnection(String username, String password) throws SQLException {
169 return determineTargetDataSource().getConnection(username, password);
170 }
171
172 @Override
173 @SuppressWarnings("unchecked")
174 public <T> T unwrap(Class<T> iface) throws SQLException {
175 if (iface.isInstance(this)) {
176 return (T) this;
177 }
178 return determineTargetDataSource().unwrap(iface);
179 }
180
181 @Override
182 public boolean isWrapperFor(Class<?> iface) throws SQLException {
183 return (iface.isInstance(this) || determineTargetDataSource().isWrapperFor(iface));
184 }
185
186
187
188
189
190
191
192
193
194 protected DataSource determineTargetDataSource() {
195 Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
196 Object lookupKey = determineCurrentLookupKey();
197 DataSource dataSource = this.resolvedDataSources.get(lookupKey);
198 if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
199 dataSource = this.resolvedDefaultDataSource;
200 }
201 if (dataSource == null) {
202 throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
203 }
204 return dataSource;
205 }
206
207
208
209
210
211
212
213
214 protected abstract Object determineCurrentLookupKey();
215
216 }