001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.servicemix.jdbc.adapter;
018:
019: import java.io.IOException;
020: import java.sql.Connection;
021: import java.sql.PreparedStatement;
022: import java.sql.ResultSet;
023: import java.sql.SQLException;
024: import java.sql.Statement;
025: import java.util.ArrayList;
026: import java.util.List;
027:
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030: import org.apache.servicemix.jdbc.JDBCAdapter;
031: import org.apache.servicemix.jdbc.JDBCAdapterFactory;
032: import org.apache.servicemix.jdbc.Statements;
033:
034: /**
035: * Implements all the default JDBC operations that are used by the
036: * JDBCPersistenceAdapter. <p/> sub-classing is encouraged to override the
037: * default implementation of methods to account for differences in JDBC Driver
038: * implementations. <p/> The JDBCAdapter inserts and extracts BLOB data using
039: * the getBytes()/setBytes() operations. <p/> The databases/JDBC drivers that
040: * use this adapter are:
041: * <ul>
042: * <li></li>
043: * </ul>
044: *
045: * @org.apache.xbean.XBean element="defaultJDBCAdapter"
046: *
047: * @version $Revision: 1.10 $
048: */
049: public class DefaultJDBCAdapter implements JDBCAdapter {
050:
051: private static final Log LOG = LogFactory
052: .getLog(DefaultJDBCAdapter.class);
053:
054: protected Statements statements;
055:
056: protected void setBinaryData(PreparedStatement s, int index,
057: byte data[]) throws SQLException {
058: s.setBytes(index, data);
059: }
060:
061: protected byte[] getBinaryData(ResultSet rs, int index)
062: throws SQLException {
063: return rs.getBytes(index);
064: }
065:
066: public void doCreateTables(Connection connection)
067: throws SQLException, IOException {
068: Statement s = null;
069: try {
070: // Check to see if the table already exists. If it does, then don't
071: // log warnings during startup.
072: // Need to run the scripts anyways since they may contain ALTER
073: // statements that upgrade a previous version of the table
074: boolean alreadyExists = false;
075: ResultSet rs = null;
076: try {
077: rs = connection.getMetaData().getTables(null, null,
078: statements.getFullStoreTableName(),
079: new String[] { "TABLE" });
080: alreadyExists = rs.next();
081: } catch (Throwable ignore) {
082: // Do nothing
083: } finally {
084: close(rs);
085: }
086:
087: // If the dataSource is a managed DataSource, executing a statement
088: // that throws
089: // an exception will make the connection unusable.
090: // So if the table already exists, do not try to re-create them
091: if (alreadyExists) {
092: return;
093: }
094:
095: s = connection.createStatement();
096: String[] createStatments = statements
097: .getCreateSchemaStatements();
098: for (int i = 0; i < createStatments.length; i++) {
099: // This will fail usually since the tables will be
100: // created already.
101: try {
102: LOG.debug("Executing SQL: " + createStatments[i]);
103: s.execute(createStatments[i]);
104: } catch (SQLException e) {
105: if (alreadyExists) {
106: LOG
107: .debug("Could not create JDBC tables; The message table already existed."
108: + " Failure was: "
109: + createStatments[i]
110: + " Message: "
111: + e.getMessage()
112: + " SQLState: "
113: + e.getSQLState()
114: + " Vendor code: "
115: + e.getErrorCode());
116: } else {
117: LOG
118: .warn("Could not create JDBC tables; they could already exist."
119: + " Failure was: "
120: + createStatments[i]
121: + " Message: "
122: + e.getMessage()
123: + " SQLState: "
124: + e.getSQLState()
125: + " Vendor code: "
126: + e.getErrorCode());
127: JDBCAdapterFactory.log("Failure details: ", e);
128: }
129: }
130: }
131: } finally {
132: close(s);
133: }
134: }
135:
136: public void doDropTables(Connection connection)
137: throws SQLException, IOException {
138: Statement s = null;
139: try {
140: s = connection.createStatement();
141: String[] dropStatments = statements
142: .getDropSchemaStatements();
143: for (int i = 0; i < dropStatments.length; i++) {
144: // This will fail usually since the tables will be
145: // created already.
146: try {
147: s.execute(dropStatments[i]);
148: } catch (SQLException e) {
149: LOG
150: .warn("Could not drop JDBC tables; they may not exist."
151: + " Failure was: "
152: + dropStatments[i]
153: + " Message: "
154: + e.getMessage()
155: + " SQLState: "
156: + e.getSQLState()
157: + " Vendor code: "
158: + e.getErrorCode());
159: JDBCAdapterFactory.log("Failure details: ", e);
160: }
161: }
162: } finally {
163: close(s);
164: }
165: }
166:
167: public void doStoreData(Connection connection, String id,
168: byte[] data) throws SQLException, IOException {
169: PreparedStatement s = null;
170: try {
171: if (s == null) {
172: s = connection.prepareStatement(statements
173: .getStoreDataStatement());
174: }
175: s.setString(1, id);
176: setBinaryData(s, 2, data);
177: if (s.executeUpdate() != 1) {
178: throw new SQLException("Failed to insert data");
179: }
180: } finally {
181: close(s);
182: }
183: }
184:
185: public byte[] doLoadData(Connection connection, String id)
186: throws SQLException, IOException {
187: PreparedStatement s = null;
188: ResultSet rs = null;
189: try {
190: s = connection.prepareStatement(statements
191: .getFindDataStatement());
192: s.setString(1, id);
193: rs = s.executeQuery();
194: if (!rs.next()) {
195: return null;
196: }
197: return getBinaryData(rs, 1);
198: } finally {
199: close(rs);
200: close(s);
201: }
202: }
203:
204: public void doUpdateData(Connection connection, String id,
205: byte[] data) throws SQLException, IOException {
206: PreparedStatement s = null;
207: try {
208: if (s == null) {
209: s = connection.prepareStatement(statements
210: .getUpdateDataStatement());
211: }
212: s.setString(2, id);
213: setBinaryData(s, 1, data);
214: if (s.executeUpdate() != 1) {
215: throw new SQLException("Failed to update data");
216: }
217: } finally {
218: close(s);
219: }
220: }
221:
222: public void doRemoveData(Connection connection, String id)
223: throws SQLException, IOException {
224: PreparedStatement s = null;
225: try {
226: s = connection.prepareStatement(statements
227: .getRemoveDataStatement());
228: s.setString(1, id);
229: if (s.executeUpdate() != 1) {
230: throw new SQLException("Failed to remove data");
231: }
232: } finally {
233: close(s);
234: }
235: }
236:
237: private static void close(Statement s) {
238: try {
239: if (s != null) {
240: s.close();
241: }
242: } catch (Throwable e) {
243: // Do nothing
244: }
245: }
246:
247: private static void close(ResultSet rs) {
248: try {
249: if (rs != null) {
250: rs.close();
251: }
252: } catch (Throwable e) {
253: // Do nothing
254: }
255: }
256:
257: public Statements getStatements() {
258: return statements;
259: }
260:
261: public void setStatements(Statements statements) {
262: this .statements = statements;
263: }
264:
265: public byte[][] doLoadData(Connection connection, String[] ids)
266: throws SQLException, IOException {
267: PreparedStatement s = null;
268: byte[][] datas = new byte[ids.length][];
269: try {
270: s = connection.prepareStatement(statements
271: .getFindDataStatement());
272: for (int i = 0; i < ids.length; i++) {
273: s.setString(1, ids[i]);
274: ResultSet rs = s.executeQuery();
275: if (rs.next()) {
276: datas[i] = getBinaryData(rs, 1);
277: }
278: close(rs);
279: }
280: return datas;
281: } finally {
282: close(s);
283: }
284: }
285:
286: public void doRemoveData(Connection connection, String[] ids)
287: throws SQLException, IOException {
288: PreparedStatement s = null;
289: try {
290: s = connection.prepareStatement(statements
291: .getRemoveDataStatement());
292: for (int i = 0; i < ids.length; i++) {
293: s.setString(1, ids[i]);
294: s.executeUpdate();
295: }
296: } finally {
297: close(s);
298: }
299: }
300:
301: public int doGetCount(Connection connection) throws SQLException,
302: IOException {
303: PreparedStatement s = null;
304: ResultSet rs = null;
305: try {
306: s = connection.prepareStatement(statements
307: .getCountStatement());
308: rs = s.executeQuery();
309: rs.next();
310: return rs.getInt(1);
311: } finally {
312: close(rs);
313: close(s);
314: }
315: }
316:
317: public String[] doGetIds(Connection connection)
318: throws SQLException, IOException {
319: PreparedStatement s = null;
320: ResultSet rs = null;
321: try {
322: List<String> ids = new ArrayList<String>();
323: s = connection.prepareStatement(statements
324: .getFindAllIdsStatement());
325: rs = s.executeQuery();
326: while (rs.next()) {
327: ids.add(rs.getString(1));
328: }
329: return ids.toArray(new String[ids.size()]);
330: } finally {
331: close(rs);
332: close(s);
333: }
334: }
335:
336: public String[] doGetIds(Connection connection, int fromIndex,
337: int toIndex) throws SQLException, IOException {
338: Statement s = null;
339: ResultSet rs = null;
340: try {
341: s = connection.createStatement(
342: ResultSet.TYPE_SCROLL_INSENSITIVE,
343: ResultSet.CONCUR_READ_ONLY);
344: s.setFetchSize(toIndex - fromIndex);
345: rs = s.executeQuery(statements.getFindAllIdsStatement());
346: rs.absolute(fromIndex + 1);
347: String[] ids = new String[toIndex - fromIndex];
348: for (int row = 0; row < toIndex - fromIndex; row++) {
349: ids[row] = rs.getString(1);
350: if (!rs.next()) {
351: break;
352: }
353: }
354: return ids;
355: } finally {
356: close(rs);
357: close(s);
358: }
359: }
360:
361: }
|