001/*
002 * ============================================================================
003 * Copyright © 2002-2023 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 * Licensed to the public under the agreements of the GNU Lesser General Public
007 * License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *      http://www.gnu.org/licenses/lgpl.html
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, WITHOUT
013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 * License for the specific language governing permissions and limitations
015 * under the License.
016 */
017
018package org.tquadrat.foundation.sql;
019
020import static org.apiguardian.api.API.Status.INTERNAL;
021import static org.apiguardian.api.API.Status.STABLE;
022import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
023
024import java.sql.Array;
025import java.sql.Blob;
026import java.sql.CallableStatement;
027import java.sql.Clob;
028import java.sql.Connection;
029import java.sql.DatabaseMetaData;
030import java.sql.NClob;
031import java.sql.PreparedStatement;
032import java.sql.SQLClientInfoException;
033import java.sql.SQLException;
034import java.sql.SQLWarning;
035import java.sql.SQLXML;
036import java.sql.Savepoint;
037import java.sql.ShardingKey;
038import java.sql.Statement;
039import java.sql.Struct;
040import java.util.Map;
041import java.util.Properties;
042import java.util.concurrent.Executor;
043
044import org.apiguardian.api.API;
045import org.tquadrat.foundation.annotation.ClassVersion;
046import org.tquadrat.foundation.lang.Status;
047
048/**
049 *  <p>{@summary An implementation of
050 *  {@link ConnectionProvider}
051 *  that returns always the same
052 *  {@link Connection}
053 *  instance.}</p>
054 *  <p>This connection provider should not be used for production purposes! It
055 *  will not allow the connection to be closed, the database session remains
056 *  open for its whole lifetime. In addition, it is by no means
057 *  thread-safe!</p>
058 *  <p>It can be used for testing purposes, or when the database access is
059 *  needed for a very short period of.</p>
060 *
061 *  @version $Id: StaticConnectionProvider.java 1075 2023-10-02 12:37:07Z tquadrat $
062 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
063 *  @UMLGraph.link
064 *  @since 0.1.0
065 */
066@ClassVersion( sourceVersion = "$Id: StaticConnectionProvider.java 1075 2023-10-02 12:37:07Z tquadrat $" )
067@API( status = STABLE, since = "0.1.0" )
068public final class StaticConnectionProvider implements ConnectionProvider
069{
070        /*---------------*\
071    ====** Inner Classes **====================================================
072        \*---------------*/
073    /**
074     *  An implementation of
075     *  {@link Connection}
076     *  that replaces the implementation of the method
077     *  {@link #close()}
078     *  by a dummy that does nothing.
079     *
080     *  @version $Id: StaticConnectionProvider.java 1075 2023-10-02 12:37:07Z tquadrat $
081     *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
082     *  @UMLGraph.link
083     *  @since 0.0.1
084     */
085    @ClassVersion( sourceVersion = "$Id: StaticConnectionProvider.java 1075 2023-10-02 12:37:07Z tquadrat $" )
086    @API( status = INTERNAL, since = "0.0.1" )
087    private final class UncloseableConnection implements Connection
088    {
089            /*--------------*\
090        ====** Constructors **=====================================================
091            \*--------------*/
092        /**
093         *  Creates an instance of {@code UncloseableConnection}.
094         */
095        public UncloseableConnection() { /* Just exists */ }
096
097            /*---------*\
098        ====** Methods **======================================================
099            \*---------*/
100        /**
101         *  {@inheritDoc}
102         */
103        @Override
104        public final void abort( final Executor executor ) throws SQLException {m_Connection.abort( executor );}
105
106        /**
107         *  {@inheritDoc}
108         */
109        @Override
110        public final void beginRequest() throws SQLException {m_Connection.beginRequest();}
111
112        /**
113         *  {@inheritDoc}
114         */
115        @Override
116        public final void clearWarnings() throws SQLException { m_Connection.clearWarnings(); }
117
118        /**
119         *  {@inheritDoc}
120         *  <p>This implementation does nothing!</p>
121         */
122        @Override
123        public final void close() throws SQLException { /* Does nothing! */ }
124
125        /**
126         *  {@inheritDoc}
127         */
128        @Override
129        public final void commit() throws SQLException { m_Connection.commit(); }
130
131        /**
132         *  {@inheritDoc}
133         */
134        @Override
135        public final Array createArrayOf( final String typeName, final Object[] elements ) throws SQLException {return m_Connection.createArrayOf( typeName, elements );}
136
137        /**
138         *  {@inheritDoc}
139         */
140        @Override
141        public final Blob createBlob() throws SQLException {return m_Connection.createBlob();}
142
143        /**
144         *  {@inheritDoc}
145         */
146        @Override
147        public final Clob createClob() throws SQLException {return m_Connection.createClob();}
148
149        /**
150         *  {@inheritDoc}
151         */
152        @Override
153        public final NClob createNClob() throws SQLException {return m_Connection.createNClob();}
154
155        /**
156         *  {@inheritDoc}
157         */
158        @Override
159        public final SQLXML createSQLXML() throws SQLException {return m_Connection.createSQLXML();}
160
161        /**
162         *  {@inheritDoc}
163         */
164        @Override
165        public final Statement createStatement() throws SQLException { return m_Connection.createStatement(); }
166
167        /**
168         *  {@inheritDoc}
169         */
170        @Override
171        public final Statement createStatement( final int resultSetType, final int resultSetConcurrency ) throws SQLException { return m_Connection.createStatement( resultSetType, resultSetConcurrency ); }
172
173        /**
174         *  {@inheritDoc}
175         */
176        @Override
177        public final Statement createStatement( final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability ) throws SQLException {return m_Connection.createStatement( resultSetType, resultSetConcurrency, resultSetHoldability );}
178
179        /**
180         *  {@inheritDoc}
181         */
182        @Override
183        public final Struct createStruct( final String typeName, final Object[] attributes ) throws SQLException {return m_Connection.createStruct( typeName, attributes );}
184
185        /**
186         *  {@inheritDoc}
187         */
188        @Override
189        public final void endRequest() throws SQLException {m_Connection.endRequest();}
190
191        /**
192         *  {@inheritDoc}
193         */
194        @Override
195        public final boolean getAutoCommit() throws SQLException { return m_Connection.getAutoCommit(); }
196
197        /**
198         *  {@inheritDoc}
199         */
200        @Override
201        public final String getCatalog() throws SQLException { return m_Connection.getCatalog(); }
202
203        /**
204         *  {@inheritDoc}
205         */
206        @Override
207        public final String getClientInfo( final String name ) throws SQLException {return m_Connection.getClientInfo( name );}
208
209        /**
210         *  {@inheritDoc}
211         */
212        @Override
213        public final Properties getClientInfo() throws SQLException {return m_Connection.getClientInfo();}
214
215        /**
216         *  {@inheritDoc}
217         */
218        @Override
219        public final int getHoldability() throws SQLException {return m_Connection.getHoldability();}
220
221        /**
222         *  {@inheritDoc}
223         */
224        @Override
225        public final DatabaseMetaData getMetaData() throws SQLException { return m_Connection.getMetaData(); }
226
227        /**
228         *  {@inheritDoc}
229         */
230        @Override
231        public final int getNetworkTimeout() throws SQLException {return m_Connection.getNetworkTimeout();}
232
233        /**
234         *  {@inheritDoc}
235         */
236        @Override
237        public final String getSchema() throws SQLException {return m_Connection.getSchema();}
238
239        /**
240         *  {@inheritDoc}
241         */
242        @Override
243        public final int getTransactionIsolation() throws SQLException { return m_Connection.getTransactionIsolation(); }
244
245        /**
246         *  {@inheritDoc}
247         */
248        @Override
249        public final Map<String, Class<?>> getTypeMap() throws SQLException {return m_Connection.getTypeMap();}
250
251        /**
252         *  {@inheritDoc}
253         */
254        @Override
255        public final SQLWarning getWarnings() throws SQLException { return m_Connection.getWarnings(); }
256
257        /**
258         *  {@inheritDoc}
259         */
260        @Override
261        public final boolean isClosed() throws SQLException { return m_Connection.isClosed(); }
262
263        /**
264         *  {@inheritDoc}
265         */
266        @Override
267        public final boolean isReadOnly() throws SQLException { return m_Connection.isReadOnly(); }
268
269        /**
270         *  {@inheritDoc}
271         */
272        @Override
273        public final boolean isValid( final int timeout ) throws SQLException {return m_Connection.isValid( timeout );}
274
275        /**
276         *  {@inheritDoc}
277         */
278        @Override
279        public final boolean isWrapperFor( final Class<?> iface ) throws SQLException {return m_Connection.isWrapperFor( iface );}
280
281        /**
282         *  {@inheritDoc}
283         */
284        @Override
285        public final String nativeSQL( final String sql ) throws SQLException { return m_Connection.nativeSQL( sql ); }
286
287        /**
288         *  {@inheritDoc}
289         */
290        @Override
291        public final CallableStatement prepareCall( final String sql ) throws SQLException {return m_Connection.prepareCall( sql );}
292
293        /**
294         *  {@inheritDoc}
295         */
296        @Override
297        public final CallableStatement prepareCall( final String sql, final int resultSetType, final int resultSetConcurrency ) throws SQLException {return m_Connection.prepareCall( sql, resultSetType, resultSetConcurrency );}
298
299        /**
300         *  {@inheritDoc}
301         */
302        @Override
303        public final CallableStatement prepareCall( final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability ) throws SQLException {return m_Connection.prepareCall( sql, resultSetType, resultSetConcurrency, resultSetHoldability );}
304
305        /**
306         *  {@inheritDoc}
307         */
308        @Override
309        public final PreparedStatement prepareStatement( final String sql ) throws SQLException { return m_Connection.prepareStatement( sql ); }
310
311        /**
312         *  {@inheritDoc}
313         */
314        @Override
315        public final PreparedStatement prepareStatement( final String sql, final int resultSetType, final int resultSetConcurrency ) throws SQLException {return m_Connection.prepareStatement( sql, resultSetType, resultSetConcurrency );}
316
317        /**
318         *  {@inheritDoc}
319         */
320        @Override
321        public final PreparedStatement prepareStatement( final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability ) throws SQLException {return m_Connection.prepareStatement( sql, resultSetType, resultSetConcurrency, resultSetHoldability );}
322
323        /**
324         *  {@inheritDoc}
325         */
326        @Override
327        public final PreparedStatement prepareStatement( final String sql, final int autoGeneratedKeys ) throws SQLException {return m_Connection.prepareStatement( sql, autoGeneratedKeys );}
328
329        /**
330         *  {@inheritDoc}
331         */
332        @Override
333        public final PreparedStatement prepareStatement( final String sql, final int[] columnIndexes ) throws SQLException {return m_Connection.prepareStatement( sql, columnIndexes );}
334
335        /**
336         *  {@inheritDoc}
337         */
338        @Override
339        public final PreparedStatement prepareStatement( final String sql, final String[] columnNames ) throws SQLException {return m_Connection.prepareStatement( sql, columnNames );}
340
341        /**
342         *  {@inheritDoc}
343         */
344        @Override
345        public final void releaseSavepoint( final Savepoint savepoint ) throws SQLException {m_Connection.releaseSavepoint( savepoint );}
346
347        /**
348         *  {@inheritDoc}
349         */
350        @Override
351        public final void rollback() throws SQLException {m_Connection.rollback();}
352
353        /**
354         *  {@inheritDoc}
355         */
356        @Override
357        public final void rollback( final Savepoint savepoint ) throws SQLException {m_Connection.rollback( savepoint );}
358
359        /**
360         *  {@inheritDoc}
361         */
362        @Override
363        public final void setAutoCommit( final boolean autoCommit ) throws SQLException { m_Connection.setAutoCommit( autoCommit ); }
364
365        /**
366         *  {@inheritDoc}
367         */
368        @Override
369        public final void setCatalog( final String catalog ) throws SQLException { m_Connection.setCatalog( catalog ); }
370
371        /**
372         *  {@inheritDoc}
373         */
374        @Override
375        public final void setClientInfo( final String name, final String value ) throws SQLClientInfoException {m_Connection.setClientInfo( name, value );}
376
377        /**
378         *  {@inheritDoc}
379         */
380        @Override
381        public final void setClientInfo( final Properties properties ) throws SQLClientInfoException {m_Connection.setClientInfo( properties );}
382
383        /**
384         *  {@inheritDoc}
385         */
386        @Override
387        public final void setHoldability( final int holdability ) throws SQLException {m_Connection.setHoldability( holdability );}
388
389        /**
390         *  {@inheritDoc}
391         */
392        @Override
393        public final void setNetworkTimeout( final Executor executor, final int milliseconds ) throws SQLException {m_Connection.setNetworkTimeout( executor, milliseconds );}
394
395        /**
396         *  {@inheritDoc}
397         */
398        @Override
399        public final void setReadOnly( final boolean readOnly ) throws SQLException { m_Connection.setReadOnly( readOnly ); }
400
401        /**
402         *  {@inheritDoc}
403         */
404        @Override
405        public final Savepoint setSavepoint() throws SQLException {return m_Connection.setSavepoint();}
406
407        /**
408         *  {@inheritDoc}
409         */
410        @Override
411        public final Savepoint setSavepoint( final String name ) throws SQLException {return m_Connection.setSavepoint( name );}
412
413        /**
414         *  {@inheritDoc}
415         */
416        @Override
417        public final void setSchema( final String schema ) throws SQLException {m_Connection.setSchema( schema );}
418
419        /**
420         *  {@inheritDoc}
421         */
422        @Override
423        public final void setShardingKey( final ShardingKey shardingKey, final ShardingKey superShardingKey ) throws SQLException {m_Connection.setShardingKey( shardingKey, superShardingKey );}
424
425        /**
426         *  {@inheritDoc}
427         */
428        @Override
429        public final void setShardingKey( final ShardingKey shardingKey ) throws SQLException {m_Connection.setShardingKey( shardingKey );}
430
431        /**
432         *  {@inheritDoc}
433         */
434        @Override
435        public final boolean setShardingKeyIfValid( final ShardingKey shardingKey, final ShardingKey superShardingKey, final int timeout ) throws SQLException {return m_Connection.setShardingKeyIfValid( shardingKey, superShardingKey, timeout );}
436
437        /**
438         *  {@inheritDoc}
439         */
440        @Override
441        public final boolean setShardingKeyIfValid( final ShardingKey shardingKey, final int timeout ) throws SQLException {return m_Connection.setShardingKeyIfValid( shardingKey, timeout );}
442
443        /**
444         *  {@inheritDoc}
445         */
446        @Override
447        public final void setTransactionIsolation( final int level ) throws SQLException { m_Connection.setTransactionIsolation( level ); }
448
449        /**
450         *  {@inheritDoc}
451         */
452        @Override
453        public final void setTypeMap( final Map<String, Class<?>> map ) throws SQLException {m_Connection.setTypeMap( map );}
454
455        /**
456         *  {@inheritDoc}
457         */
458        @Override
459        public final <T> T unwrap( final Class<T> iface ) throws SQLException {return m_Connection.unwrap( iface );}
460    }
461    //  class UncloseableConnection
462
463        /*------------*\
464    ====** Attributes **=======================================================
465        \*------------*/
466    /**
467     *  The connection.
468     */
469    private final Connection m_Connection;
470
471        /*--------------*\
472    ====** Constructors **=====================================================
473        \*--------------*/
474    /**
475     *  <p>{@summary Creates a new instance of
476     *  {@code StaticConnectionProvider}.}</p>
477     *  <p>The provided connection must be open and valid, although this will
478     *  not be checked here.</p>
479     *
480     *  @param  connection  The connection that is returned by each call to
481     */
482    public StaticConnectionProvider( final Connection connection )
483    {
484        m_Connection = requireNonNullArgument( connection, "connection" );
485    }   //  StaticConnectionProvider()
486
487        /*---------*\
488    ====** Methods **==========================================================
489        \*---------*/
490    /**
491     *  {@inheritDoc}
492     */
493    @Override
494    public final Status<Connection,Throwable> getConnection()
495    {
496        Status<Connection,Throwable> retValue;
497        try
498        {
499            //---* Check if connection is (still) open *-----------------------
500            @SuppressWarnings( "unused" )
501            final var metaData = m_Connection.getMetaData();
502            retValue = new Status<>( new UncloseableConnection(), null );
503        }
504        catch( final SQLException e )
505        {
506            retValue = new Status<>( null, e );
507        }
508
509        //---* Done *----------------------------------------------------------
510        return retValue;
511    }   //  getConnection()
512}
513//  class StaticConnectionProvider
514
515/*
516 *  End of File
517 */