001: /*
002: Copyright (C) 2002-2007 MySQL AB
003:
004: This program is free software; you can redistribute it and/or modify
005: it under the terms of version 2 of the GNU General Public License as
006: published by the Free Software Foundation.
007:
008: There are special exceptions to the terms and conditions of the GPL
009: as it is applied to this software. View the full text of the
010: exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
011: software distribution.
012:
013: This program is distributed in the hope that it will be useful,
014: but WITHOUT ANY WARRANTY; without even the implied warranty of
015: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: GNU General Public License for more details.
017:
018: You should have received a copy of the GNU General Public License
019: along with this program; if not, write to the Free Software
020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021:
022: */
023:
024: package com.mysql.jdbc;
025:
026: import java.sql.Blob;
027: import java.sql.Clob;
028: import java.sql.SQLClientInfoException;
029: import java.sql.SQLException;
030: import java.sql.SQLXML;
031: import java.sql.NClob;
032: import java.sql.Struct;
033: import java.util.Properties;
034: import java.util.TimerTask;
035:
036: import com.mysql.jdbc.ConnectionImpl;
037: import com.mysql.jdbc.Messages;
038: import com.mysql.jdbc.SQLError;
039: import com.mysql.jdbc.exceptions.NotYetImplementedException;
040:
041: public class JDBC4Connection extends ConnectionImpl {
042: private JDBC4ClientInfoProvider infoProvider;
043:
044: public JDBC4Connection(String hostToConnectTo, int portToConnectTo,
045: Properties info, String databaseToConnectTo, String url)
046: throws SQLException {
047: super (hostToConnectTo, portToConnectTo, info,
048: databaseToConnectTo, url);
049: // TODO Auto-generated constructor stub
050: }
051:
052: public SQLXML createSQLXML() throws SQLException {
053: return new JDBC4MysqlSQLXML();
054: }
055:
056: public java.sql.Array createArrayOf(String typeName,
057: Object[] elements) throws SQLException {
058: throw new NotYetImplementedException();
059: }
060:
061: public Struct createStruct(String typeName, Object[] attributes)
062: throws SQLException {
063: throw new NotYetImplementedException();
064: }
065:
066: public Properties getClientInfo() throws SQLException {
067: return getClientInfoProviderImpl().getClientInfo(this );
068: }
069:
070: public String getClientInfo(String name) throws SQLException {
071: return getClientInfoProviderImpl().getClientInfo(this , name);
072: }
073:
074: /**
075: * Returns true if the connection has not been closed and is still valid.
076: * The driver shall submit a query on the connection or use some other
077: * mechanism that positively verifies the connection is still valid when
078: * this method is called.
079: * <p>
080: * The query submitted by the driver to validate the connection shall be
081: * executed in the context of the current transaction.
082: *
083: * @param timeout - The time in seconds to wait for the database operation
084: * used to validate the connection to complete. If
085: * the timeout period expires before the operation
086: * completes, this method returns false. A value of
087: * 0 indicates a timeout is not applied to the
088: * database operation.
089: * <p>
090: * @return true if the connection is valid, false otherwise
091: * @exception SQLException if the value supplied for <code>timeout</code>
092: * is less then 0
093: * @since 1.6
094: */
095: public synchronized boolean isValid(int timeout)
096: throws SQLException {
097: if (isClosed()) {
098: return false;
099: }
100:
101: TimerTask timeoutTask = null;
102:
103: if (timeout != 0) {
104: getCancelTimer().schedule(new TimerTask() {
105: public void run() {
106: new Thread() {
107: public void run() {
108: try {
109: abortInternal();
110: } catch (Throwable t) {
111: throw new RuntimeException(t);
112: }
113: }
114: }.start();
115: }
116: }, timeout * 1000);
117: }
118:
119: try {
120: synchronized (getMutex()) {
121: try {
122: pingInternal(false);
123:
124: if (timeoutTask != null) {
125: timeoutTask.cancel();
126: }
127:
128: timeoutTask = null;
129: } catch (Throwable t) {
130: try {
131: abortInternal();
132: } catch (Throwable ignoreThrown) {
133: // we're dead now anyway
134: }
135:
136: return false;
137: } finally {
138: if (timeoutTask != null) {
139: timeoutTask.cancel();
140: }
141: }
142: }
143: } catch (Throwable t) {
144: return false;
145: }
146:
147: return true;
148: }
149:
150: public void setClientInfo(Properties properties)
151: throws SQLClientInfoException {
152: try {
153: getClientInfoProviderImpl().setClientInfo(this , properties);
154: } catch (SQLClientInfoException ciEx) {
155: throw ciEx;
156: } catch (SQLException sqlEx) {
157: SQLClientInfoException clientInfoEx = new SQLClientInfoException();
158: clientInfoEx.initCause(sqlEx);
159:
160: throw clientInfoEx;
161: }
162: }
163:
164: public void setClientInfo(String name, String value)
165: throws SQLClientInfoException {
166: try {
167: getClientInfoProviderImpl()
168: .setClientInfo(this , name, value);
169: } catch (SQLClientInfoException ciEx) {
170: throw ciEx;
171: } catch (SQLException sqlEx) {
172: SQLClientInfoException clientInfoEx = new SQLClientInfoException();
173: clientInfoEx.initCause(sqlEx);
174:
175: throw clientInfoEx;
176: }
177: }
178:
179: /**
180: * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
181: * for an object that does. Returns false otherwise. If this implements the interface then return true,
182: * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
183: * object. If this does not implement the interface and is not a wrapper, return false.
184: * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
185: * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
186: * returns true then calling <code>unwrap</code> with the same argument should succeed.
187: *
188: * @param interfaces a Class defining an interface.
189: * @return true if this implements the interface or directly or indirectly wraps an object that does.
190: * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper
191: * for an object with the given interface.
192: * @since 1.6
193: */
194: public boolean isWrapperFor(Class<?> iface) throws SQLException {
195: checkClosed();
196:
197: // This works for classes that aren't actually wrapping
198: // anything
199: return iface.isInstance(this );
200: }
201:
202: /**
203: * Returns an object that implements the given interface to allow access to non-standard methods,
204: * or standard methods not exposed by the proxy.
205: * The result may be either the object found to implement the interface or a proxy for that object.
206: * If the receiver implements the interface then that is the object. If the receiver is a wrapper
207: * and the wrapped object implements the interface then that is the object. Otherwise the object is
208: * the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
209: * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
210: *
211: * @param iface A Class defining an interface that the result must implement.
212: * @return an object that implements the interface. May be a proxy for the actual implementing object.
213: * @throws java.sql.SQLException If no object found that implements the interface
214: * @since 1.6
215: */
216: public <T> T unwrap(java.lang.Class<T> iface)
217: throws java.sql.SQLException {
218: try {
219: // This works for classes that aren't actually wrapping
220: // anything
221: return iface.cast(this );
222: } catch (ClassCastException cce) {
223: throw SQLError.createSQLException("Unable to unwrap to "
224: + iface.toString(),
225: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
226: }
227: }
228:
229: /**
230: * @see java.sql.Connection#createBlob()
231: */
232: public Blob createBlob() {
233: return new com.mysql.jdbc.Blob();
234: }
235:
236: /**
237: * @see java.sql.Connection#createClob()
238: */
239: public Clob createClob() {
240: return new com.mysql.jdbc.Clob();
241: }
242:
243: /**
244: * @see java.sql.Connection#createNClob()
245: */
246: public NClob createNClob() {
247: return new com.mysql.jdbc.JDBC4NClob();
248: }
249:
250: protected synchronized JDBC4ClientInfoProvider getClientInfoProviderImpl()
251: throws SQLException {
252: if (this .infoProvider == null) {
253: try {
254: try {
255: this .infoProvider = (JDBC4ClientInfoProvider) Util
256: .getInstance(getClientInfoProvider(),
257: new Class[0], new Object[0]);
258: } catch (SQLException sqlEx) {
259: if (sqlEx.getCause() instanceof ClassCastException) {
260: // try with package name prepended
261: this .infoProvider = (JDBC4ClientInfoProvider) Util
262: .getInstance("com.mysql.jdbc."
263: + getClientInfoProvider(),
264: new Class[0], new Object[0]);
265: }
266: }
267: } catch (ClassCastException cce) {
268: throw SQLError.createSQLException(Messages.getString(
269: "JDBC4Connection.ClientInfoNotImplemented",
270: new Object[] { getClientInfoProvider() }),
271: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
272: }
273:
274: this.infoProvider.initialize(this, this.props);
275: }
276:
277: return this.infoProvider;
278: }
279: }
|