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