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:
022: import java.lang.reflect.InvocationHandler;
023: import java.lang.reflect.Method;
024: import java.lang.reflect.Proxy;
025: import java.sql.SQLException;
026: import java.util.Collection;
027: import java.util.List;
028:
029: /**
030: * Class to lazily load results into objects
031: */
032: public class LazyResultLoader implements InvocationHandler {
033:
034: private static final Class[] LIST_INTERFACES = new Class[] { List.class };
035:
036: protected ExtendedSqlMapClient client;
037: protected String statementName;
038: protected Object parameterObject;
039: protected Class targetType;
040:
041: protected boolean loaded;
042: protected Object resultObject;
043:
044: /**
045: * Constructor for a lazy list loader
046: *
047: * @param client - the client that is creating the lazy list
048: * @param statementName - the statement to be used to build the list
049: * @param parameterObject - the parameter object to be used to build the list
050: * @param targetType - the type we are putting data into
051: */
052: public LazyResultLoader(ExtendedSqlMapClient client,
053: String statementName, Object parameterObject,
054: Class targetType) {
055: this .client = client;
056: this .statementName = statementName;
057: this .parameterObject = parameterObject;
058: this .targetType = targetType;
059: }
060:
061: /**
062: * Loads the result
063: *
064: * @return the results - a list or object
065: *
066: * @throws SQLException if there is a problem
067: */
068: public Object loadResult() throws SQLException {
069: if (Collection.class.isAssignableFrom(targetType)) {
070: InvocationHandler handler = new LazyResultLoader(client,
071: statementName, parameterObject, targetType);
072: ClassLoader cl = targetType.getClassLoader();
073: return Proxy.newProxyInstance(cl, LIST_INTERFACES, handler);
074: } else {
075: return ResultLoader.getResult(client, statementName,
076: parameterObject, targetType);
077: }
078: }
079:
080: public Object invoke(Object o, Method method, Object[] objects)
081: throws Throwable {
082: if ("finalize".hashCode() == method.getName().hashCode()
083: && "finalize".equals(method.getName())) {
084: return null;
085: } else {
086: loadObject();
087: if (resultObject != null) {
088: try {
089: return method.invoke(resultObject, objects);
090: } catch (Throwable t) {
091: throw ClassInfo.unwrapThrowable(t);
092: }
093: } else {
094: return null;
095: }
096: }
097: }
098:
099: private synchronized void loadObject() {
100: if (!loaded) {
101: try {
102: loaded = true;
103: resultObject = ResultLoader.getResult(client,
104: statementName, parameterObject, targetType);
105: } catch (SQLException e) {
106: throw new RuntimeException(
107: "Error lazy loading result. Cause: " + e, e);
108: }
109: }
110: }
111:
112: }
|