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.statement;
017:
018: import com.ibatis.common.jdbc.exception.NestedSQLException;
019: import com.ibatis.common.io.ReaderInputStream;
020:
021: import com.ibatis.sqlmap.client.event.RowHandler;
022: import com.ibatis.sqlmap.engine.execution.SqlExecutor;
023: import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
024: import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
025: import com.ibatis.sqlmap.engine.mapping.sql.Sql;
026: import com.ibatis.sqlmap.engine.scope.ErrorContext;
027: import com.ibatis.sqlmap.engine.scope.RequestScope;
028: import com.ibatis.sqlmap.engine.transaction.Transaction;
029: import com.ibatis.sqlmap.engine.transaction.TransactionException;
030: import com.ibatis.sqlmap.engine.type.*;
031: import org.w3c.dom.Document;
032:
033: import javax.xml.parsers.*;
034: import java.sql.Connection;
035: import java.sql.SQLException;
036: import java.util.List;
037: import java.io.*;
038:
039: public class GeneralStatement extends BaseStatement {
040:
041: public StatementType getStatementType() {
042: return StatementType.UNKNOWN;
043: }
044:
045: public int executeUpdate(RequestScope request, Transaction trans,
046: Object parameterObject) throws SQLException {
047: ErrorContext errorContext = request.getErrorContext();
048: errorContext
049: .setActivity("preparing the mapped statement for execution");
050: errorContext.setObjectId(this .getId());
051: errorContext.setResource(this .getResource());
052:
053: request.getSession().setCommitRequired(true);
054:
055: try {
056: parameterObject = validateParameter(parameterObject);
057:
058: Sql sql = getSql();
059:
060: errorContext.setMoreInfo("Check the parameter map.");
061: ParameterMap parameterMap = sql.getParameterMap(request,
062: parameterObject);
063:
064: errorContext.setMoreInfo("Check the result map.");
065: ResultMap resultMap = sql.getResultMap(request,
066: parameterObject);
067:
068: request.setResultMap(resultMap);
069: request.setParameterMap(parameterMap);
070:
071: int rows = 0;
072:
073: errorContext.setMoreInfo("Check the parameter map.");
074: Object[] parameters = parameterMap
075: .getParameterObjectValues(request, parameterObject);
076:
077: errorContext.setMoreInfo("Check the SQL statement.");
078: String sqlString = sql.getSql(request, parameterObject);
079:
080: errorContext.setActivity("executing mapped statement");
081: errorContext
082: .setMoreInfo("Check the statement or the result map.");
083: rows = sqlExecuteUpdate(request, trans.getConnection(),
084: sqlString, parameters);
085:
086: errorContext.setMoreInfo("Check the output parameters.");
087: if (parameterObject != null) {
088: postProcessParameterObject(request, parameterObject,
089: parameters);
090: }
091:
092: errorContext.reset();
093: sql.cleanup(request);
094: notifyListeners();
095: return rows;
096: } catch (SQLException e) {
097: errorContext.setCause(e);
098: throw new NestedSQLException(errorContext.toString(), e
099: .getSQLState(), e.getErrorCode(), e);
100: } catch (Exception e) {
101: errorContext.setCause(e);
102: throw new NestedSQLException(errorContext.toString(), e);
103: }
104: }
105:
106: public Object executeQueryForObject(RequestScope request,
107: Transaction trans, Object parameterObject,
108: Object resultObject) throws SQLException {
109: try {
110: Object object = null;
111:
112: DefaultRowHandler rowHandler = new DefaultRowHandler();
113: executeQueryWithCallback(request, trans.getConnection(),
114: parameterObject, resultObject, rowHandler,
115: SqlExecutor.NO_SKIPPED_RESULTS,
116: SqlExecutor.NO_MAXIMUM_RESULTS);
117: List list = rowHandler.getList();
118:
119: if (list.size() > 1) {
120: throw new SQLException(
121: "Error: executeQueryForObject returned too many results.");
122: } else if (list.size() > 0) {
123: object = list.get(0);
124: }
125:
126: return object;
127: } catch (TransactionException e) {
128: throw new NestedSQLException(
129: "Error getting Connection from Transaction. Cause: "
130: + e, e);
131: }
132: }
133:
134: public List executeQueryForList(RequestScope request,
135: Transaction trans, Object parameterObject, int skipResults,
136: int maxResults) throws SQLException {
137: try {
138: DefaultRowHandler rowHandler = new DefaultRowHandler();
139: executeQueryWithCallback(request, trans.getConnection(),
140: parameterObject, null, rowHandler, skipResults,
141: maxResults);
142: return rowHandler.getList();
143: } catch (TransactionException e) {
144: throw new NestedSQLException(
145: "Error getting Connection from Transaction. Cause: "
146: + e, e);
147: }
148: }
149:
150: public void executeQueryWithRowHandler(RequestScope request,
151: Transaction trans, Object parameterObject,
152: RowHandler rowHandler) throws SQLException {
153: try {
154: executeQueryWithCallback(request, trans.getConnection(),
155: parameterObject, null, rowHandler,
156: SqlExecutor.NO_SKIPPED_RESULTS,
157: SqlExecutor.NO_MAXIMUM_RESULTS);
158: } catch (TransactionException e) {
159: throw new NestedSQLException(
160: "Error getting Connection from Transaction. Cause: "
161: + e, e);
162: }
163: }
164:
165: //
166: // PROTECTED METHODS
167: //
168:
169: protected void executeQueryWithCallback(RequestScope request,
170: Connection conn, Object parameterObject,
171: Object resultObject, RowHandler rowHandler,
172: int skipResults, int maxResults) throws SQLException {
173: ErrorContext errorContext = request.getErrorContext();
174: errorContext
175: .setActivity("preparing the mapped statement for execution");
176: errorContext.setObjectId(this .getId());
177: errorContext.setResource(this .getResource());
178:
179: try {
180: parameterObject = validateParameter(parameterObject);
181:
182: Sql sql = getSql();
183:
184: errorContext.setMoreInfo("Check the parameter map.");
185: ParameterMap parameterMap = sql.getParameterMap(request,
186: parameterObject);
187:
188: errorContext.setMoreInfo("Check the result map.");
189: ResultMap resultMap = sql.getResultMap(request,
190: parameterObject);
191:
192: request.setResultMap(resultMap);
193: request.setParameterMap(parameterMap);
194:
195: errorContext.setMoreInfo("Check the parameter map.");
196: Object[] parameters = parameterMap
197: .getParameterObjectValues(request, parameterObject);
198:
199: errorContext.setMoreInfo("Check the SQL statement.");
200: String sqlString = sql.getSql(request, parameterObject);
201:
202: errorContext.setActivity("executing mapped statement");
203: errorContext
204: .setMoreInfo("Check the SQL statement or the result map.");
205: RowHandlerCallback callback = new RowHandlerCallback(
206: resultMap, resultObject, rowHandler);
207: sqlExecuteQuery(request, conn, sqlString, parameters,
208: skipResults, maxResults, callback);
209:
210: errorContext.setMoreInfo("Check the output parameters.");
211: if (parameterObject != null) {
212: postProcessParameterObject(request, parameterObject,
213: parameters);
214: }
215:
216: errorContext.reset();
217: sql.cleanup(request);
218: notifyListeners();
219: } catch (SQLException e) {
220: errorContext.setCause(e);
221: throw new NestedSQLException(errorContext.toString(), e
222: .getSQLState(), e.getErrorCode(), e);
223: } catch (Exception e) {
224: errorContext.setCause(e);
225: throw new NestedSQLException(errorContext.toString(), e);
226: }
227: }
228:
229: protected void postProcessParameterObject(RequestScope request,
230: Object parameterObject, Object[] parameters) {
231: }
232:
233: protected int sqlExecuteUpdate(RequestScope request,
234: Connection conn, String sqlString, Object[] parameters)
235: throws SQLException {
236: if (request.getSession().isInBatch()) {
237: getSqlExecutor().addBatch(request, conn, sqlString,
238: parameters);
239: return 0;
240: } else {
241: return getSqlExecutor().executeUpdate(request, conn,
242: sqlString, parameters);
243: }
244: }
245:
246: protected void sqlExecuteQuery(RequestScope request,
247: Connection conn, String sqlString, Object[] parameters,
248: int skipResults, int maxResults, RowHandlerCallback callback)
249: throws SQLException {
250: getSqlExecutor().executeQuery(request, conn, sqlString,
251: parameters, skipResults, maxResults, callback);
252: }
253:
254: protected Object validateParameter(Object param)
255: throws SQLException {
256: Object newParam = param;
257: Class parameterClass = getParameterClass();
258: if (newParam != null && parameterClass != null) {
259: if (DomTypeMarker.class.isAssignableFrom(parameterClass)) {
260: if (XmlTypeMarker.class
261: .isAssignableFrom(parameterClass)) {
262: if (!(newParam instanceof String)
263: && !(newParam instanceof Document)) {
264: throw new SQLException(
265: "Invalid parameter object type. Expected '"
266: + String.class.getName()
267: + "' or '"
268: + Document.class.getName()
269: + "' but found '"
270: + newParam.getClass().getName()
271: + "'.");
272: }
273: if (!(newParam instanceof Document)) {
274: newParam = stringToDocument((String) newParam);
275: }
276: } else {
277: if (!Document.class.isAssignableFrom(newParam
278: .getClass())) {
279: throw new SQLException(
280: "Invalid parameter object type. Expected '"
281: + Document.class.getName()
282: + "' but found '"
283: + newParam.getClass().getName()
284: + "'.");
285: }
286: }
287: } else {
288: if (!parameterClass.isAssignableFrom(newParam
289: .getClass())) {
290: throw new SQLException(
291: "Invalid parameter object type. Expected '"
292: + parameterClass.getName()
293: + "' but found '"
294: + newParam.getClass().getName()
295: + "'.");
296: }
297: }
298: }
299: return newParam;
300: }
301:
302: private Document stringToDocument(String s) {
303: try {
304: DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
305: .newInstance();
306: DocumentBuilder documentBuilder = documentBuilderFactory
307: .newDocumentBuilder();
308: return documentBuilder.parse(new ReaderInputStream(
309: new StringReader(s)));
310: } catch (Exception e) {
311: throw new RuntimeException("Error occurred. Cause: " + e,
312: e);
313: }
314: }
315: }
|