001: /*
002: * $Id: AxionConnection.java,v 1.30 2007/11/13 19:04:01 rwald Exp $
003: * =======================================================================
004: * Copyright (c) 2002-2003 Axion Development Team. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb.jdbc;
042:
043: import java.io.File;
044: import java.sql.Array;
045: import java.sql.Blob;
046: import java.sql.CallableStatement;
047: import java.sql.Clob;
048: import java.sql.Connection;
049: import java.sql.DatabaseMetaData;
050: import java.sql.NClob;
051: import java.sql.PreparedStatement;
052: import java.sql.ResultSet;
053: import java.sql.SQLClientInfoException;
054: import java.sql.SQLException;
055: import java.sql.SQLWarning;
056: import java.sql.SQLXML;
057: import java.sql.Savepoint;
058: import java.sql.Statement;
059: import java.sql.Struct;
060: import java.util.Collections;
061: import java.util.Map;
062: import java.util.Properties;
063:
064: import org.axiondb.AxionException;
065: import org.axiondb.Database;
066: import org.axiondb.Transaction;
067: import org.axiondb.TransactionConflictException;
068: import org.axiondb.engine.Databases;
069: import org.axiondb.util.ExceptionConverter;
070:
071: /**
072: * A {@link Connection} implementation.
073: *
074: * @version $Revision: 1.30 $ $Date: 2007/11/13 19:04:01 $
075: * @author Chuck Burdick
076: * @author Jonathan Giron
077: */
078: public class AxionConnection implements Connection {
079: protected AxionConnection(String name, File path, String url)
080: throws AxionException {
081: setUrl(url);
082: setDatabase(Databases.getOrCreateDatabase(name, path));
083: }
084:
085: public AxionConnection(Database db, String url) {
086: setDatabase(db);
087: setUrl(url);
088: }
089:
090: public AxionConnection(Database db) {
091: this (db, null);
092: }
093:
094: public void clearWarnings() throws SQLException {
095: _warning = null;
096: }
097:
098: public void close() throws SQLException {
099: if (isClosed()) {
100: // "Calling the method close on a Connection object that is already closed is
101: // a no-op"
102: } else {
103: if ((!(_db.getTransactionManager().isShutdown()))) {
104: rollback(false);
105: }
106: try {
107: _db.checkpoint();
108: } catch (AxionException e) {
109: throw ExceptionConverter.convert(e);
110: }
111: _db = null;
112: }
113: }
114:
115: public void commit() throws SQLException {
116: commit(true);
117: }
118:
119: public void rollback() throws SQLException {
120: rollback(true);
121: }
122:
123: public Statement createStatement() throws SQLException {
124: return createStatement(ResultSet.TYPE_FORWARD_ONLY,
125: ResultSet.CONCUR_READ_ONLY);
126: }
127:
128: public Statement createStatement(int resultSetType,
129: int resultSetConcurrency) throws SQLException {
130: resultSetType = validateResultSetType(resultSetType);
131: resultSetConcurrency = validateResultSetConcurrency(resultSetConcurrency);
132: return new AxionStatement(this , resultSetType,
133: resultSetConcurrency);
134: }
135:
136: public boolean getAutoCommit() throws SQLException {
137: return _autoCommit;
138: }
139:
140: public String getCatalog() throws SQLException {
141: return "";
142: }
143:
144: public DatabaseMetaData getMetaData() throws SQLException {
145: return new AxionDatabaseMetaData(this , _db);
146: }
147:
148: public int getTransactionIsolation() throws SQLException {
149: return _isolationLevel;
150: }
151:
152: public Map getTypeMap() throws SQLException {
153: return Collections.EMPTY_MAP;
154: }
155:
156: public SQLWarning getWarnings() throws SQLException {
157: if (isClosed()) {
158: // "[Connection.getWarnings] may not be called on a closed connection; doing
159: // so will cause an SQLException to be thrown."
160: throw new SQLException("Already closed");
161: }
162: return _warning;
163: }
164:
165: public boolean isClosed() throws SQLException {
166: return (_db == null);
167: }
168:
169: public boolean isReadOnly() throws SQLException {
170: return false;
171: }
172:
173: public String nativeSQL(String sql) throws SQLException {
174: return sql;
175: }
176:
177: public CallableStatement prepareCall(String sql)
178: throws SQLException {
179: throw new SQLException("not supported");
180: }
181:
182: public CallableStatement prepareCall(String sql, int resultSetType,
183: int resultSetConcurrency) throws SQLException {
184: throw new SQLException("not supported");
185: }
186:
187: public PreparedStatement prepareStatement(String sql)
188: throws SQLException {
189: return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY,
190: ResultSet.CONCUR_READ_ONLY);
191: }
192:
193: public PreparedStatement prepareStatement(String sql,
194: int resultSetType, int resultSetConcurrency)
195: throws SQLException {
196: resultSetType = validateResultSetType(resultSetType);
197: resultSetConcurrency = validateResultSetConcurrency(resultSetConcurrency);
198: return new AxionPreparedStatement(this , sql, resultSetType,
199: resultSetConcurrency);
200: }
201:
202: /**
203: * Validates that the given result set type is supported by Axion, returning the closest
204: * appropriate type if not supported.
205: *
206: * @param resultSetType type to validate, one of {@link ResultSet#TYPE_FORWARD_ONLY},
207: * {@link ResultSet#TYPE_SCROLL_SENSITIVE} or {@link ResultSet#TYPE_SCROLL_INSENSITIVE}
208: * @return <code>resultSetType</code> if it is supported, or the closest supporting
209: * result set type if not.
210: */
211: private int validateResultSetType(int resultSetType)
212: throws SQLException {
213: switch (resultSetType) {
214: case ResultSet.TYPE_FORWARD_ONLY:
215: case ResultSet.TYPE_SCROLL_SENSITIVE:
216: break;
217:
218: case ResultSet.TYPE_SCROLL_INSENSITIVE:
219: createAndAddSQLWarning("Result set type TYPE_SCROLL_INSENSITIVE is currently not supported; returning TYPE_SCROLL_SENSITIVE instead.");
220: resultSetType = ResultSet.TYPE_SCROLL_SENSITIVE;
221: break;
222:
223: default:
224: throw new SQLException(
225: "Unknown or unsupported result set type: "
226: + resultSetType);
227: }
228:
229: return resultSetType;
230: }
231:
232: /**
233: * Validates that the given concurrency type is supported by Axion, returning the closest
234: * appropriate concurrency type if not supported.
235: *
236: * @param resultSetConcurrency concurrency type to validate, one of {@link ResultSet#CONCUR_READ_ONLY}
237: * or {@link ResultSet#CONCUR_UPDATABLE}.
238: * @return <code>resultSetConcurrency</code> if it is supported, or the closest supporting
239: * concurrency type if not.
240: */
241: private int validateResultSetConcurrency(int resultSetConcurrency)
242: throws SQLException {
243: switch (resultSetConcurrency) {
244: case ResultSet.CONCUR_READ_ONLY:
245: case ResultSet.CONCUR_UPDATABLE:
246: break;
247:
248: default:
249: throw new SQLException(
250: "Unknown or unsupported concurrency type: "
251: + resultSetConcurrency);
252: }
253:
254: return resultSetConcurrency;
255: }
256:
257: public void setAutoCommit(boolean autoCommit) throws SQLException {
258: _autoCommit = autoCommit;
259: }
260:
261: public void setCatalog(String catalog) throws SQLException {
262: }
263:
264: public void setReadOnly(boolean readOnly) throws SQLException {
265: }
266:
267: public void setTransactionIsolation(int level) throws SQLException {
268: if (level == Connection.TRANSACTION_SERIALIZABLE) {
269: _isolationLevel = level;
270: } else {
271: throw new SQLException("Transcation isolation level "
272: + level + " is not supported.");
273: }
274: }
275:
276: public String getURL() {
277: return _url;
278: }
279:
280: // **** HELPER METHODS ****
281:
282: public org.axiondb.Database getDatabase() {
283: return _db;
284: }
285:
286: Transaction getCurrentTransaction() throws AxionException {
287: if (null == _currentTransaction) {
288: _currentTransaction = _db.getTransactionManager()
289: .createTransaction();
290: }
291: return _currentTransaction;
292: }
293:
294: Transaction forgetCurrentTransaction() {
295: Transaction temp = _currentTransaction;
296: _currentTransaction = null;
297: return temp;
298: }
299:
300: void commitIfAuto() throws SQLException {
301: if (getAutoCommit()
302: && !(_db.getTransactionManager().isShutdown())) {
303: commit(false);
304: }
305: }
306:
307: /**
308: * Adds the given SQLWarning instance to the current warning chain.
309: *
310: * @param newWarning SQLWarning instance to add to the current warning chain.
311: */
312: protected synchronized void addWarning(SQLWarning newWarning) {
313: if (newWarning != null) {
314: if (_warning != null) {
315: _warning.setNextWarning(newWarning);
316: } else {
317: _warning = newWarning;
318: }
319: }
320: }
321:
322: /**
323: * Creates a new SQLWarning using the given String and adds it to the current SQLWarning chain.
324: *
325: * @param string String to use in creating the new SQLWarning instance
326: */
327: private void createAndAddSQLWarning(String string) {
328: addWarning(new SQLWarning(string));
329: }
330:
331: private void assertNotAutoCommit() throws SQLException {
332: if (getAutoCommit()) {
333: throw new SQLException(
334: "This method should only be used when auto-commit mode has been disabled.");
335: }
336: }
337:
338: private void commit(boolean checkmode) throws SQLException {
339: if (checkmode) {
340: assertNotAutoCommit();
341: }
342: try {
343: if (null != _currentTransaction) {
344: _db.getTransactionManager().commitTransaction(
345: _currentTransaction);
346: _currentTransaction = null;
347: }
348: } catch (TransactionConflictException e) {
349: throw ExceptionConverter.convert(new AxionException(e,
350: 51000));
351: } catch (AxionException e) {
352: throw ExceptionConverter.convert(e);
353: }
354: }
355:
356: private void rollback(boolean checkmode) throws SQLException {
357: if (checkmode) {
358: assertNotAutoCommit();
359: }
360: try {
361: if (null != _currentTransaction) {
362: _db.getTransactionManager().abortTransaction(
363: _currentTransaction);
364: _currentTransaction = null;
365: }
366: } catch (AxionException e) {
367: throw ExceptionConverter.convert(e);
368: }
369: }
370:
371: private Database _db;
372: private String _url;
373: private Transaction _currentTransaction;
374: private int _isolationLevel = Connection.TRANSACTION_SERIALIZABLE;
375: private boolean _autoCommit = true;
376: private SQLWarning _warning;
377:
378: /** Currently unsupported. */
379: public Statement createStatement(int arg0, int arg1, int arg2)
380: throws SQLException {
381: throw new SQLException(
382: "createStatement(int,int,int) is currently not supported");
383: }
384:
385: /** Currently unsupported. */
386: public int getHoldability() throws SQLException {
387: throw new SQLException(
388: "getHoldability is currently not supported");
389: }
390:
391: /** Currently unsupported. */
392: public CallableStatement prepareCall(String arg0, int arg1,
393: int arg2, int arg3) throws SQLException {
394: throw new SQLException(
395: "prepareCall(String,int,int,int) is currently not supported");
396: }
397:
398: /** Currently unsupported. */
399: public PreparedStatement prepareStatement(String arg0, int arg1,
400: int arg2, int arg3) throws SQLException {
401: throw new SQLException(
402: "prepareStatement(String,int,int,int) is currently not supported");
403: }
404:
405: /** Currently unsupported. */
406: public PreparedStatement prepareStatement(String arg0, int arg1)
407: throws SQLException {
408: throw new SQLException(
409: "prepareStatement(String,int) is currently not supported");
410: }
411:
412: /** Currently unsupported. */
413: public PreparedStatement prepareStatement(String arg0, int[] arg1)
414: throws SQLException {
415: throw new SQLException(
416: "prepareStatement(String,int[]) is currently not supported");
417: }
418:
419: /** Currently unsupported. */
420: public PreparedStatement prepareStatement(String arg0, String[] arg1)
421: throws SQLException {
422: throw new SQLException(
423: "prepareStatement(String,String[]) is currently not supported");
424: }
425:
426: /** Currently unsupported. */
427: public void releaseSavepoint(Savepoint arg0) throws SQLException {
428: throw new SQLException(
429: "releaseSavepoint(Savepoint) is currently not supported");
430: }
431:
432: /** Currently unsupported. */
433: public void rollback(Savepoint arg0) throws SQLException {
434: throw new SQLException(
435: "rollback(Savepoint) is currently not supported");
436: }
437:
438: /** Currently unsupported. */
439: public void setHoldability(int arg0) throws SQLException {
440: throw new SQLException(
441: "setHoldability(int) is currently not supported");
442: }
443:
444: /** Currently unsupported. */
445: public Savepoint setSavepoint() throws SQLException {
446: throw new SQLException(
447: "setSavepoint is currently not supported");
448: }
449:
450: /** Currently unsupported. */
451: public Savepoint setSavepoint(String arg0) throws SQLException {
452: throw new SQLException(
453: "setSavepoint(String) is currently not supported");
454: }
455:
456: private void setUrl(String url) {
457: _url = url;
458: }
459:
460: private void setDatabase(Database db) {
461: _db = db;
462: }
463:
464: @Override
465: public Array createArrayOf(String arg0, Object[] arg1)
466: throws SQLException {
467: throw new SQLException("Not implemented");
468: }
469:
470: @Override
471: public Blob createBlob() throws SQLException {
472: throw new SQLException("Not implemented");
473: }
474:
475: @Override
476: public Clob createClob() throws SQLException {
477: throw new SQLException("Not implemented");
478: }
479:
480: @Override
481: public NClob createNClob() throws SQLException {
482: throw new SQLException("Not implemented");
483: }
484:
485: @Override
486: public SQLXML createSQLXML() throws SQLException {
487: throw new SQLException("Not implemented");
488: }
489:
490: @Override
491: public Struct createStruct(String arg0, Object[] arg1)
492: throws SQLException {
493: throw new SQLException("Not implemented");
494: }
495:
496: @Override
497: public Properties getClientInfo() throws SQLException {
498: throw new SQLException("Not implemented");
499: }
500:
501: @Override
502: public String getClientInfo(String arg0) throws SQLException {
503: throw new SQLException("Not implemented");
504: }
505:
506: @Override
507: public boolean isValid(int arg0) throws SQLException {
508: throw new SQLException("Not implemented");
509: }
510:
511: @Override
512: public void setClientInfo(Properties arg0)
513: throws SQLClientInfoException {
514: throw new RuntimeException("Not implemented");
515: }
516:
517: @Override
518: public void setClientInfo(String arg0, String arg1)
519: throws SQLClientInfoException {
520: throw new RuntimeException("Not implemented");
521: }
522:
523: @Override
524: public void setTypeMap(Map<String, Class<?>> arg0)
525: throws SQLException {
526: throw new SQLException("Not implemented");
527: }
528:
529: @Override
530: public boolean isWrapperFor(Class<?> arg0) throws SQLException {
531: throw new SQLException("Not implemented");
532: }
533:
534: @Override
535: public <T> T unwrap(Class<T> arg0) throws SQLException {
536: throw new SQLException("Not implemented");
537: }
538:
539: }
|