1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.ibatis.sqlmap.engine.config;
17
18 import com.ibatis.common.beans.ClassInfo;
19 import com.ibatis.common.beans.Probe;
20 import com.ibatis.common.beans.ProbeFactory;
21 import com.ibatis.common.resources.Resources;
22 import com.ibatis.sqlmap.client.SqlMapException;
23 import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;
24 import com.ibatis.sqlmap.engine.accessplan.AccessPlanFactory;
25 import com.ibatis.sqlmap.engine.cache.CacheController;
26 import com.ibatis.sqlmap.engine.cache.CacheModel;
27 import com.ibatis.sqlmap.engine.cache.fifo.FifoCacheController;
28 import com.ibatis.sqlmap.engine.cache.lru.LruCacheController;
29 import com.ibatis.sqlmap.engine.cache.memory.MemoryCacheController;
30 import com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory;
31 import com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory;
32 import com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory;
33 import com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;
34 import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
35 import com.ibatis.sqlmap.engine.mapping.result.Discriminator;
36 import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
37 import com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactory;
38 import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
39 import com.ibatis.sqlmap.engine.scope.ErrorContext;
40 import com.ibatis.sqlmap.engine.transaction.TransactionManager;
41 import com.ibatis.sqlmap.engine.transaction.external.ExternalTransactionConfig;
42 import com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig;
43 import com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig;
44 import com.ibatis.sqlmap.engine.type.*;
45
46 import java.util.Iterator;
47 import java.util.Map;
48
49
50
51
52 public class SqlMapConfiguration {
53
54
55 private static final Probe PROBE = ProbeFactory.getProbe();
56
57
58 private ErrorContext errorContext;
59
60
61 private SqlMapExecutorDelegate delegate;
62
63
64 private TypeHandlerFactory typeHandlerFactory;
65
66
67 private SqlMapClientImpl client;
68
69
70 private Integer defaultStatementTimeout;
71
72
73
74
75 public SqlMapConfiguration() {
76 errorContext = new ErrorContext();
77 delegate = new SqlMapExecutorDelegate();
78 typeHandlerFactory = delegate.getTypeHandlerFactory();
79 client = new SqlMapClientImpl(delegate);
80 registerDefaultTypeAliases();
81 }
82
83
84
85
86
87
88 public TypeHandlerFactory getTypeHandlerFactory() {
89 return typeHandlerFactory;
90 }
91
92
93
94
95
96
97 public ErrorContext getErrorContext() {
98 return errorContext;
99 }
100
101
102
103
104
105
106 public SqlMapClientImpl getClient() {
107 return client;
108 }
109
110
111
112
113
114
115 public SqlMapExecutorDelegate getDelegate() {
116 return delegate;
117 }
118
119
120
121
122
123
124
125 public void setClassInfoCacheEnabled(boolean classInfoCacheEnabled) {
126 errorContext.setActivity("setting class info cache enabled/disabled");
127 ClassInfo.setCacheEnabled(classInfoCacheEnabled);
128 }
129
130
131
132
133
134
135
136 public void setLazyLoadingEnabled(boolean lazyLoadingEnabled) {
137 errorContext.setActivity("setting lazy loading enabled/disabled");
138 client.getDelegate().setLazyLoadingEnabled(lazyLoadingEnabled);
139 }
140
141
142
143
144
145
146
147 public void setStatementCachingEnabled(boolean statementCachingEnabled) {
148 errorContext.setActivity("setting statement caching enabled/disabled");
149 client.getDelegate().setStatementCacheEnabled(statementCachingEnabled);
150 }
151
152
153
154
155
156
157
158 public void setCacheModelsEnabled(boolean cacheModelsEnabled) {
159 errorContext.setActivity("setting cache models enabled/disabled");
160 client.getDelegate().setCacheModelsEnabled(cacheModelsEnabled);
161 }
162
163
164
165
166
167
168
169 public void setEnhancementEnabled(boolean enhancementEnabled) {
170 errorContext.setActivity("setting enhancement enabled/disabled");
171 try {
172 enhancementEnabled = enhancementEnabled && Resources.classForName("net.sf.cglib.proxy.InvocationHandler") != null;
173 } catch (ClassNotFoundException e) {
174 enhancementEnabled = false;
175 }
176 client.getDelegate().setEnhancementEnabled(enhancementEnabled);
177 AccessPlanFactory.setBytecodeEnhancementEnabled(enhancementEnabled);
178 }
179
180
181
182
183
184
185
186 public void setUseColumnLabel(boolean useColumnLabel) {
187 client.getDelegate().setUseColumnLabel(useColumnLabel);
188 }
189
190
191
192
193
194
195
196 public void setForceMultipleResultSetSupport(boolean forceMultipleResultSetSupport) {
197 client.getDelegate().setForceMultipleResultSetSupport(forceMultipleResultSetSupport);
198 }
199
200
201
202
203
204
205
206 public void setDefaultStatementTimeout(Integer defaultTimeout) {
207 errorContext.setActivity("setting default timeout");
208 if (defaultTimeout != null) {
209 try {
210 defaultStatementTimeout = defaultTimeout;
211 } catch (NumberFormatException e) {
212 throw new SqlMapException("Specified defaultStatementTimeout is not a valid integer");
213 }
214 }
215 }
216
217
218
219
220
221
222
223 public void setTransactionManager(TransactionManager txManager) {
224 delegate.setTxManager(txManager);
225 }
226
227
228
229
230
231
232
233 public void setResultObjectFactory(ResultObjectFactory rof) {
234 delegate.setResultObjectFactory(rof);
235 }
236
237
238
239
240
241
242
243
244
245
246
247 public void newTypeHandler(Class javaType, String jdbcType, Object callback) {
248 try {
249 errorContext.setActivity("building a building custom type handler");
250 TypeHandlerFactory typeHandlerFactory = client.getDelegate().getTypeHandlerFactory();
251 TypeHandler typeHandler;
252 if (callback instanceof TypeHandlerCallback) {
253 typeHandler = new CustomTypeHandler((TypeHandlerCallback) callback);
254 } else if (callback instanceof TypeHandler) {
255 typeHandler = (TypeHandler) callback;
256 } else {
257 throw new RuntimeException(
258 "The object '" + callback + "' is not a valid implementation of TypeHandler or TypeHandlerCallback");
259 }
260 errorContext.setMoreInfo("Check the javaType attribute '" + javaType + "' (must be a classname) or the jdbcType '"
261 + jdbcType + "' (must be a JDBC type name).");
262 if (jdbcType != null && jdbcType.length() > 0) {
263 typeHandlerFactory.register(javaType, jdbcType, typeHandler);
264 } else {
265 typeHandlerFactory.register(javaType, typeHandler);
266 }
267 } catch (Exception e) {
268 throw new SqlMapException("Error registering occurred. Cause: " + e, e);
269 }
270 errorContext.setMoreInfo(null);
271 errorContext.setObjectId(null);
272 }
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288 public CacheModelConfig newCacheModelConfig(String id, CacheController controller, boolean readOnly,
289 boolean serialize) {
290 return new CacheModelConfig(this, id, controller, readOnly, serialize);
291 }
292
293
294
295
296
297
298
299
300
301
302
303 public ParameterMapConfig newParameterMapConfig(String id, Class parameterClass) {
304 return new ParameterMapConfig(this, id, parameterClass);
305 }
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323 public ResultMapConfig newResultMapConfig(String id, Class resultClass, String groupBy, String extended,
324 String xmlName) {
325 return new ResultMapConfig(this, id, resultClass, groupBy, extended, xmlName);
326 }
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364 public MappedStatementConfig newMappedStatementConfig(String id, MappedStatement statement, SqlSource processor,
365 String parameterMapName, Class parameterClass, String resultMapName, String[] additionalResultMapNames,
366 Class resultClass, Class[] additionalResultClasses, String resultSetType, Integer fetchSize,
367 boolean allowRemapping, Integer timeout, String cacheModelName, String xmlResultName) {
368 return new MappedStatementConfig(this, id, statement, processor, parameterMapName, parameterClass, resultMapName,
369 additionalResultMapNames, resultClass, additionalResultClasses, cacheModelName, resultSetType, fetchSize,
370 allowRemapping, timeout, defaultStatementTimeout, xmlResultName);
371 }
372
373
374
375
376 public void finalizeSqlMapConfig() {
377 wireUpCacheModels();
378 bindResultMapDiscriminators();
379 }
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397 TypeHandler resolveTypeHandler(TypeHandlerFactory typeHandlerFactory, Class clazz, String propertyName,
398 Class javaType, String jdbcType) {
399 return resolveTypeHandler(typeHandlerFactory, clazz, propertyName, javaType, jdbcType, false);
400 }
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420 TypeHandler resolveTypeHandler(TypeHandlerFactory typeHandlerFactory, Class clazz, String propertyName,
421 Class javaType, String jdbcType, boolean useSetterToResolve) {
422 TypeHandler handler;
423 if (clazz == null) {
424
425 handler = typeHandlerFactory.getUnkownTypeHandler();
426 } else if (DomTypeMarker.class.isAssignableFrom(clazz)) {
427
428 handler = typeHandlerFactory.getTypeHandler(String.class, jdbcType);
429 } else if (java.util.Map.class.isAssignableFrom(clazz)) {
430
431 if (javaType == null) {
432 handler = typeHandlerFactory.getUnkownTypeHandler();
433
434
435 } else {
436 handler = typeHandlerFactory.getTypeHandler(javaType, jdbcType);
437 }
438 } else if (typeHandlerFactory.getTypeHandler(clazz, jdbcType) != null) {
439
440 handler = typeHandlerFactory.getTypeHandler(clazz, jdbcType);
441 } else {
442
443 if (javaType == null) {
444 if (useSetterToResolve) {
445 Class type = PROBE.getPropertyTypeForSetter(clazz, propertyName);
446 handler = typeHandlerFactory.getTypeHandler(type, jdbcType);
447 } else {
448 Class type = PROBE.getPropertyTypeForGetter(clazz, propertyName);
449 handler = typeHandlerFactory.getTypeHandler(type, jdbcType);
450 }
451 } else {
452 handler = typeHandlerFactory.getTypeHandler(javaType, jdbcType);
453 }
454 }
455 return handler;
456 }
457
458
459
460
461 private void registerDefaultTypeAliases() {
462
463 typeHandlerFactory.putTypeAlias("JDBC", JdbcTransactionConfig.class.getName());
464 typeHandlerFactory.putTypeAlias("JTA", JtaTransactionConfig.class.getName());
465 typeHandlerFactory.putTypeAlias("EXTERNAL", ExternalTransactionConfig.class.getName());
466
467
468 typeHandlerFactory.putTypeAlias("SIMPLE", SimpleDataSourceFactory.class.getName());
469 typeHandlerFactory.putTypeAlias("DBCP", DbcpDataSourceFactory.class.getName());
470 typeHandlerFactory.putTypeAlias("JNDI", JndiDataSourceFactory.class.getName());
471
472
473 typeHandlerFactory.putTypeAlias("FIFO", FifoCacheController.class.getName());
474 typeHandlerFactory.putTypeAlias("LRU", LruCacheController.class.getName());
475 typeHandlerFactory.putTypeAlias("MEMORY", MemoryCacheController.class.getName());
476
477
478 typeHandlerFactory.putTypeAlias("dom", DomTypeMarker.class.getName());
479 typeHandlerFactory.putTypeAlias("domCollection", DomCollectionTypeMarker.class.getName());
480 typeHandlerFactory.putTypeAlias("xml", XmlTypeMarker.class.getName());
481 typeHandlerFactory.putTypeAlias("xmlCollection", XmlCollectionTypeMarker.class.getName());
482 }
483
484
485
486
487 private void wireUpCacheModels() {
488
489 Iterator cacheNames = client.getDelegate().getCacheModelNames();
490 while (cacheNames.hasNext()) {
491 String cacheName = (String) cacheNames.next();
492 CacheModel cacheModel = client.getDelegate().getCacheModel(cacheName);
493 Iterator statementNames = cacheModel.getFlushTriggerStatementNames();
494 while (statementNames.hasNext()) {
495 String statementName = (String) statementNames.next();
496 MappedStatement statement = client.getDelegate().getMappedStatement(statementName);
497 if (statement != null) {
498 statement.addExecuteListener(cacheModel);
499 } else {
500 throw new RuntimeException("Could not find statement named '" + statementName
501 + "' for use as a flush trigger for the cache model named '" + cacheName + "'.");
502 }
503 }
504 }
505 }
506
507
508
509
510 private void bindResultMapDiscriminators() {
511
512 Iterator names = delegate.getResultMapNames();
513 while (names.hasNext()) {
514 String name = (String) names.next();
515 ResultMap rm = delegate.getResultMap(name);
516 Discriminator disc = rm.getDiscriminator();
517 if (disc != null) {
518 disc.bindSubMaps();
519 }
520 }
521 }
522
523 }