001: /*
002: * Copyright 2004 Clinton Begin
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: * http://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: package com.ibatis.sqlmap.engine.mapping.result.loader;
017:
018: import com.ibatis.common.beans.ClassInfo;
019:
020: import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;
021: import com.ibatis.sqlmap.engine.type.DomTypeMarker;
022: import net.sf.cglib.proxy.Enhancer;
023: import net.sf.cglib.proxy.InvocationHandler;
024:
025: import java.lang.reflect.Method;
026: import java.sql.SQLException;
027: import java.util.Collection;
028: import java.util.List;
029:
030: /**
031: * Class to lazily load results into objects (uses CGLib to improve performance)
032: */
033: public class EnhancedLazyResultLoader {
034:
035: private static final Class[] INTERFACES = new Class[] { List.class };
036: private Object loader;
037:
038: /**
039: * Constructor for an enhanced lazy list loader
040: *
041: * @param client - the client that is creating the lazy list
042: * @param statementName - the statement to be used to build the list
043: * @param parameterObject - the parameter object to be used to build the list
044: * @param targetType - the type we are putting data into
045: */
046: public EnhancedLazyResultLoader(ExtendedSqlMapClient client,
047: String statementName, Object parameterObject,
048: Class targetType) {
049: loader = new EnhancedLazyResultLoaderImpl(client,
050: statementName, parameterObject, targetType);
051: }
052:
053: /**
054: * Loads the result
055: *
056: * @return the results - a list or object
057: *
058: * @throws SQLException if there is a problem
059: */
060: public Object loadResult() throws SQLException {
061: return ((EnhancedLazyResultLoaderImpl) loader).loadResult();
062: }
063:
064: private static class EnhancedLazyResultLoaderImpl implements
065: InvocationHandler {
066:
067: protected ExtendedSqlMapClient client;
068: protected String statementName;
069: protected Object parameterObject;
070: protected Class targetType;
071:
072: protected boolean loaded;
073: protected Object resultObject;
074:
075: /**
076: * Constructor for an enhanced lazy list loader implementation
077: *
078: * @param client - the client that is creating the lazy list
079: * @param statementName - the statement to be used to build the list
080: * @param parameterObject - the parameter object to be used to build the list
081: * @param targetType - the type we are putting data into
082: */
083: public EnhancedLazyResultLoaderImpl(
084: ExtendedSqlMapClient client, String statementName,
085: Object parameterObject, Class targetType) {
086: this .client = client;
087: this .statementName = statementName;
088: this .parameterObject = parameterObject;
089: this .targetType = targetType;
090: }
091:
092: /**
093: * Loads the result
094: *
095: * @return the results - a list or object
096: *
097: * @throws SQLException if there is a problem
098: */
099: public Object loadResult() throws SQLException {
100: if (DomTypeMarker.class.isAssignableFrom(targetType)) {
101: return ResultLoader.getResult(client, statementName,
102: parameterObject, targetType);
103: } else if (Collection.class.isAssignableFrom(targetType)) {
104: return Enhancer.create(Object.class, INTERFACES, this );
105: } else if (targetType.isArray()
106: || ClassInfo.isKnownType(targetType)) {
107: return ResultLoader.getResult(client, statementName,
108: parameterObject, targetType);
109: } else {
110: return Enhancer.create(targetType, this );
111: }
112: }
113:
114: public Object invoke(Object o, Method method, Object[] objects)
115: throws Throwable {
116: if ("finalize".hashCode() == method.getName().hashCode()
117: && "finalize".equals(method.getName())) {
118: return null;
119: } else {
120: loadObject();
121: if (resultObject != null) {
122: try {
123: return method.invoke(resultObject, objects);
124: } catch (Throwable t) {
125: throw ClassInfo.unwrapThrowable(t);
126: }
127: } else {
128: return null;
129: }
130: }
131: }
132:
133: private synchronized void loadObject() {
134: if (!loaded) {
135: try {
136: loaded = true;
137: resultObject = ResultLoader.getResult(client,
138: statementName, parameterObject, targetType);
139: } catch (SQLException e) {
140: throw new RuntimeException(
141: "Error lazy loading result. Cause: " + e, e);
142: }
143: }
144: }
145: }
146:
147: }
|