/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2004-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.internal.sql;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import org.apache.sis.util.logging.Logging;
/**
* An entry in {@link StatementPool}.
*
* {@note We could define a <code>StatementAdapter</code> class which implement the
* <code>PreparedStatement</code> interface and delegate every method calls to the
* wrapped statement. Then this <code>StatementEntry</code> class could extend that
* <code>StatementAdapter</code> class. But for now we prefer to avoid the weight of
* such a big adapter and force every usage of <code>StatementEntry</code> to work
* directly with the wrapped statement.}
*
* {@section Synchronization}
* This class is <strong>not</strong> thread-safe. Callers must perform their own synchronization
* in such a way that only one query is executed on the same connection (JDBC connections can not
* be assumed thread-safe). The synchronization block shall be the {@link StatementPool} which
* contain this entry.
*
* {@section Closing}
* This class does not implement {@link java.lang.AutoCloseable} because it is typically closed
* by method (and even a thread) different than the one that created the {@code StatementEntry}
* instance. It normally closed by {@link StatementPool#close()}.
*
* @author Martin Desruisseaux (Geomatys)
* @version 3.03
*
* @since 3.03
* @module
*/
public class StatementEntry {
/**
* The expiration time of this result. This is read and updated by {@link StatementPool} only.
*/
long expireTime;
/**
* The statement associated with this entry.
* This is the statement given to the constructor.
*/
public final PreparedStatement statement;
/**
* Constructs a metadata result for the specified statement.
*
* @param statement The prepared statement.
*/
public StatementEntry(final PreparedStatement statement) {
this.statement = statement;
}
/**
* Closes the statement and free all resources. After this method
* has been invoked, this object can't be used anymore.
* <p>
* This method should be invoked instead than a direct call to {@code statement.close()}
* because some subclasses override this method in order to release additional resources
* hold by this {@code StatementEntry}.
* <p>
* This method is usually not invoked by the method or thread that created the
* {@code StatementEntry} instance. It is invoked by {@link StatementPool#close()} instead.
*
* @throws SQLException If an error occurred while closing the statement.
*/
public void close() throws SQLException {
statement.close();
}
/**
* Closes the statement and free all resources. In case of failure while closing JDBC objects,
* the message is logged but the process continue since we are not supposed to use the statement
* anymore. This method is invoked from other methods that can not throws an SQL exception.
*/
final void closeQuietly() {
try {
close();
} catch (Exception e) {
// Catch Exception rather than SQLException because this method is invoked from semi-
// critical code which need to never fail, otherwise some memory leak could occur.
/*
* Use the logger of the package that subclass this entry, and pretend that the
* message comme from PreparedStatement.close() which is the closest we can get
* to a public API.
*/
Logging.recoverableException(DefaultDataSource.LOGGER, PreparedStatement.class, "close", e);
}
}
}