diff --git a/src/interfaces/jdbc/.cvsignore b/src/interfaces/jdbc/.cvsignore deleted file mode 100644 index f8de598047..0000000000 --- a/src/interfaces/jdbc/.cvsignore +++ /dev/null @@ -1,6 +0,0 @@ -.classpath -.project -.externalToolBuilders -build -build.properties -jars diff --git a/src/interfaces/jdbc/org/postgresql/.cvsignore b/src/interfaces/jdbc/org/postgresql/.cvsignore deleted file mode 100644 index 3e0ef3de58..0000000000 --- a/src/interfaces/jdbc/org/postgresql/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Driver.java diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java deleted file mode 100644 index 417cf87c10..0000000000 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java +++ /dev/null @@ -1,265 +0,0 @@ -package org.postgresql.jdbc2.optional; - -import javax.naming.*; -import java.io.PrintWriter; -import java.sql.*; - -/** - * Base class for data sources and related classes. - * - * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.3 $ - */ -public abstract class BaseDataSource implements Referenceable -{ - // Load the normal driver, since we'll use it to actually connect to the - // database. That way we don't have to maintain the connecting code in - // multiple places. - static { - try - { - Class.forName("org.postgresql.Driver"); - } - catch (ClassNotFoundException e) - { - System.err.println("PostgreSQL DataSource unable to load PostgreSQL JDBC Driver"); - } - } - - // Needed to implement the DataSource/ConnectionPoolDataSource interfaces - private transient PrintWriter logger; - // Don't track loginTimeout, since we'd just ignore it anyway - - // Standard properties, defined in the JDBC 2.0 Optional Package spec - private String serverName = "localhost"; - private String databaseName; - private String user; - private String password; - private int portNumber; - - /** - * Gets a connection to the PostgreSQL database. The database is identified by the - * DataSource properties serverName, databaseName, and portNumber. The user to - * connect as is identified by the DataSource properties user and password. - * - * @return A valid database connection. - * @throws SQLException - * Occurs when the database connection cannot be established. - */ - public Connection getConnection() throws SQLException - { - return getConnection(user, password); - } - - /** - * Gets a connection to the PostgreSQL database. The database is identified by the - * DataAource properties serverName, databaseName, and portNumber. The user to - * connect as is identified by the arguments user and password, which override - * the DataSource properties by the same name. - * - * @return A valid database connection. - * @throws SQLException - * Occurs when the database connection cannot be established. - */ - public Connection getConnection(String user, String password) throws SQLException - { - try - { - Connection con = DriverManager.getConnection(getUrl(), user, password); - if (logger != null) - { - logger.println("Created a non-pooled connection for " + user + " at " + getUrl()); - } - return con; - } - catch (SQLException e) - { - if (logger != null) - { - logger.println("Failed to create a non-pooled connection for " + user + " at " + getUrl() + ": " + e); - } - throw e; - } - } - - /** - * This DataSource does not support a configurable login timeout. - * @return 0 - */ - public int getLoginTimeout() throws SQLException - { - return 0; - } - - /** - * This DataSource does not support a configurable login timeout. Any value - * provided here will be ignored. - */ - public void setLoginTimeout(int i) throws SQLException - {} - - /** - * Gets the log writer used to log connections opened. - */ - public PrintWriter getLogWriter() throws SQLException - { - return logger; - } - - /** - * The DataSource will note every connection opened to the provided log writer. - */ - public void setLogWriter(PrintWriter printWriter) throws SQLException - { - logger = printWriter; - } - - /** - * Gets the name of the host the PostgreSQL database is running on. - */ - public String getServerName() - { - return serverName; - } - - /** - * Sets the name of the host the PostgreSQL database is running on. If this - * is changed, it will only affect future calls to getConnection. The default - * value is localhost. - */ - public void setServerName(String serverName) - { - if (serverName == null || serverName.equals("")) - { - this.serverName = "localhost"; - } - else - { - this.serverName = serverName; - } - } - - /** - * Gets the name of the PostgreSQL database, running on the server identified - * by the serverName property. - */ - public String getDatabaseName() - { - return databaseName; - } - - /** - * Sets the name of the PostgreSQL database, running on the server identified - * by the serverName property. If this is changed, it will only affect - * future calls to getConnection. - */ - public void setDatabaseName(String databaseName) - { - this.databaseName = databaseName; - } - - /** - * Gets a description of this DataSource-ish thing. Must be customized by - * subclasses. - */ - public abstract String getDescription(); - - /** - * Gets the user to connect as by default. If this is not specified, you must - * use the getConnection method which takes a user and password as parameters. - */ - public String getUser() - { - return user; - } - - /** - * Sets the user to connect as by default. If this is not specified, you must - * use the getConnection method which takes a user and password as parameters. - * If this is changed, it will only affect future calls to getConnection. - */ - public void setUser(String user) - { - this.user = user; - } - - /** - * Gets the password to connect with by default. If this is not specified but a - * password is needed to log in, you must use the getConnection method which takes - * a user and password as parameters. - */ - public String getPassword() - { - return password; - } - - /** - * Sets the password to connect with by default. If this is not specified but a - * password is needed to log in, you must use the getConnection method which takes - * a user and password as parameters. If this is changed, it will only affect - * future calls to getConnection. - */ - public void setPassword(String password) - { - this.password = password; - } - - /** - * Gets the port which the PostgreSQL server is listening on for TCP/IP - * connections. - * - * @return The port, or 0 if the default port will be used. - */ - public int getPortNumber() - { - return portNumber; - } - - /** - * Gets the port which the PostgreSQL server is listening on for TCP/IP - * connections. Be sure the -i flag is passed to postmaster when PostgreSQL - * is started. If this is not set, or set to 0, the default port will be used. - */ - public void setPortNumber(int portNumber) - { - this.portNumber = portNumber; - } - - /** - * Generates a DriverManager URL from the other properties supplied. - */ - private String getUrl() - { - return "jdbc:postgresql://" + serverName + (portNumber == 0 ? "" : ":" + portNumber) + "/" + databaseName; - } - - /** - * Generates a reference using the appropriate object factory. This - * implementation uses the JDBC 2 optional package object factory. - */ - protected Reference createReference() - { - return new Reference(getClass().getName(), PGObjectFactory.class.getName(), null); - } - - public Reference getReference() throws NamingException - { - Reference ref = createReference(); - ref.add(new StringRefAddr("serverName", serverName)); - if (portNumber != 0) - { - ref.add(new StringRefAddr("portNumber", Integer.toString(portNumber))); - } - ref.add(new StringRefAddr("databaseName", databaseName)); - if (user != null) - { - ref.add(new StringRefAddr("user", user)); - } - if (password != null) - { - ref.add(new StringRefAddr("password", password)); - } - return ref; - } - -} diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/ConnectionPool.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/ConnectionPool.java deleted file mode 100644 index f7700698e2..0000000000 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/ConnectionPool.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.postgresql.jdbc2.optional; - -import javax.sql.ConnectionPoolDataSource; -import javax.sql.PooledConnection; -import java.sql.SQLException; -import java.io.Serializable; - -/** - * PostgreSQL implementation of ConnectionPoolDataSource. The app server or - * middleware vendor should provide a DataSource implementation that takes advantage - * of this ConnectionPoolDataSource. If not, you can use the PostgreSQL implementation - * known as PoolingDataSource, but that should only be used if your server or middleware - * vendor does not provide their own. Why? The server may want to reuse the same - * Connection across all EJBs requesting a Connection within the same Transaction, or - * provide other similar advanced features. - * - *

In any case, in order to use this ConnectionPoolDataSource, you must set the property - * databaseName. The settings for serverName, portNumber, user, and password are - * optional. Note: these properties are declared in the superclass.

- * - *

This implementation supports JDK 1.3 and higher.

- * - * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.2 $ - */ -public class ConnectionPool extends BaseDataSource implements Serializable, ConnectionPoolDataSource -{ - private boolean defaultAutoCommit = false; - - /** - * Gets a description of this DataSource. - */ - public String getDescription() - { - return "ConnectionPoolDataSource from " + org.postgresql.Driver.getVersion(); - } - - /** - * Gets a connection which may be pooled by the app server or middleware - * implementation of DataSource. - * - * @throws java.sql.SQLException - * Occurs when the physical database connection cannot be established. - */ - public PooledConnection getPooledConnection() throws SQLException - { - return new PooledConnectionImpl(getConnection(), defaultAutoCommit); - } - - /** - * Gets a connection which may be pooled by the app server or middleware - * implementation of DataSource. - * - * @throws java.sql.SQLException - * Occurs when the physical database connection cannot be established. - */ - public PooledConnection getPooledConnection(String user, String password) throws SQLException - { - return new PooledConnectionImpl(getConnection(user, password), defaultAutoCommit); - } - - /** - * Gets whether connections supplied by this pool will have autoCommit - * turned on by default. The default value is false, so that - * autoCommit will be turned off by default. - */ - public boolean isDefaultAutoCommit() - { - return defaultAutoCommit; - } - - /** - * Sets whether connections supplied by this pool will have autoCommit - * turned on by default. The default value is false, so that - * autoCommit will be turned off by default. - */ - public void setDefaultAutoCommit(boolean defaultAutoCommit) - { - this.defaultAutoCommit = defaultAutoCommit; - } - -} diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java deleted file mode 100644 index 48778e0e55..0000000000 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.postgresql.jdbc2.optional; - -import javax.naming.spi.ObjectFactory; -import javax.naming.*; -import java.util.Hashtable; - -/** - * Returns a DataSource-ish thing based on a JNDI reference. In the case of a - * SimpleDataSource or ConnectionPool, a new instance is created each time, as - * there is no connection state to maintain. In the case of a PoolingDataSource, - * the same DataSource will be returned for every invocation within the same - * VM/ClassLoader, so that the state of the connections in the pool will be - * consistent. - * - * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.3 $ - */ -public class PGObjectFactory implements ObjectFactory -{ - /** - * Dereferences a PostgreSQL DataSource. Other types of references are - * ignored. - */ - public Object getObjectInstance(Object obj, Name name, Context nameCtx, - Hashtable environment) throws Exception - { - Reference ref = (Reference)obj; - if (ref.getClassName().equals(SimpleDataSource.class.getName())) - { - return loadSimpleDataSource(ref); - } - else if (ref.getClassName().equals(ConnectionPool.class.getName())) - { - return loadConnectionPool(ref); - } - else if (ref.getClassName().equals(PoolingDataSource.class.getName())) - { - return loadPoolingDataSource(ref); - } - else - { - return null; - } - } - - private Object loadPoolingDataSource(Reference ref) - { - // If DataSource exists, return it - String name = getProperty(ref, "dataSourceName"); - PoolingDataSource pds = PoolingDataSource.getDataSource(name); - if (pds != null) - { - return pds; - } - // Otherwise, create a new one - pds = new PoolingDataSource(); - pds.setDataSourceName(name); - loadBaseDataSource(pds, ref); - String min = getProperty(ref, "initialConnections"); - if (min != null) - { - pds.setInitialConnections(Integer.parseInt(min)); - } - String max = getProperty(ref, "maxConnections"); - if (max != null) - { - pds.setMaxConnections(Integer.parseInt(max)); - } - return pds; - } - - private Object loadSimpleDataSource(Reference ref) - { - SimpleDataSource ds = new SimpleDataSource(); - return loadBaseDataSource(ds, ref); - } - - private Object loadConnectionPool(Reference ref) - { - ConnectionPool cp = new ConnectionPool(); - return loadBaseDataSource(cp, ref); - } - - protected Object loadBaseDataSource(BaseDataSource ds, Reference ref) - { - ds.setDatabaseName(getProperty(ref, "databaseName")); - ds.setPassword(getProperty(ref, "password")); - String port = getProperty(ref, "portNumber"); - if (port != null) - { - ds.setPortNumber(Integer.parseInt(port)); - } - ds.setServerName(getProperty(ref, "serverName")); - ds.setUser(getProperty(ref, "user")); - return ds; - } - - protected String getProperty(Reference ref, String s) - { - RefAddr addr = ref.get(s); - if (addr == null) - { - return null; - } - return (String)addr.getContent(); - } - -} diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java deleted file mode 100644 index 687441fecf..0000000000 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java +++ /dev/null @@ -1,392 +0,0 @@ -package org.postgresql.jdbc2.optional; - -import javax.sql.*; -import java.sql.*; -import java.util.*; -import java.lang.reflect.*; -import org.postgresql.PGConnection; - -/** - * PostgreSQL implementation of the PooledConnection interface. This shouldn't - * be used directly, as the pooling client should just interact with the - * ConnectionPool instead. - * @see ConnectionPool - * - * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @author Csaba Nagy (ncsaba@yahoo.com) - * @version $Revision: 1.8 $ - */ -public class PooledConnectionImpl implements PooledConnection -{ - private List listeners = new LinkedList(); - private Connection con; - private ConnectionHandler last; - private boolean autoCommit; - - /** - * Creates a new PooledConnection representing the specified physical - * connection. - */ - protected PooledConnectionImpl(Connection con, boolean autoCommit) - { - this.con = con; - this.autoCommit = autoCommit; - } - - /** - * Adds a listener for close or fatal error events on the connection - * handed out to a client. - */ - public void addConnectionEventListener(ConnectionEventListener connectionEventListener) - { - listeners.add(connectionEventListener); - } - - /** - * Removes a listener for close or fatal error events on the connection - * handed out to a client. - */ - public void removeConnectionEventListener(ConnectionEventListener connectionEventListener) - { - listeners.remove(connectionEventListener); - } - - /** - * Closes the physical database connection represented by this - * PooledConnection. If any client has a connection based on - * this PooledConnection, it is forcibly closed as well. - */ - public void close() throws SQLException - { - if (last != null) - { - last.close(); - if (!con.getAutoCommit()) - { - try - { - con.rollback(); - } - catch (SQLException e) - {} - } - } - try - { - con.close(); - } - finally - { - con = null; - } - } - - /** - * Gets a handle for a client to use. This is a wrapper around the - * physical connection, so the client can call close and it will just - * return the connection to the pool without really closing the - * pgysical connection. - * - *

According to the JDBC 2.0 Optional Package spec (6.2.3), only one - * client may have an active handle to the connection at a time, so if - * there is a previous handle active when this is called, the previous - * one is forcibly closed and its work rolled back.

- */ - public Connection getConnection() throws SQLException - { - if (con == null) - { - // Before throwing the exception, let's notify the registered listeners about the error - final SQLException sqlException = new SQLException("This PooledConnection has already been closed!"); - fireConnectionFatalError(sqlException); - throw sqlException; - } - // If any error occures while opening a new connection, the listeners - // have to be notified. This gives a chance to connection pools to - // elliminate bad pooled connections. - try - { - // Only one connection can be open at a time from this PooledConnection. See JDBC 2.0 Optional Package spec section 6.2.3 - if (last != null) - { - last.close(); - if (!con.getAutoCommit()) - { - try - { - con.rollback(); - } - catch (SQLException e) - {} - } - con.clearWarnings(); - } - con.setAutoCommit(autoCommit); - } - catch (SQLException sqlException) - { - fireConnectionFatalError(sqlException); - throw (SQLException)sqlException.fillInStackTrace(); - } - ConnectionHandler handler = new ConnectionHandler(con); - last = handler; - Connection con = (Connection)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Connection.class, PGConnection.class}, handler); - last.setProxy(con); - return con; - } - - /** - * Used to fire a connection closed event to all listeners. - */ - void fireConnectionClosed() - { - ConnectionEvent evt = null; - // Copy the listener list so the listener can remove itself during this method call - ConnectionEventListener[] local = (ConnectionEventListener[]) listeners.toArray(new ConnectionEventListener[listeners.size()]); - for (int i = 0; i < local.length; i++) - { - ConnectionEventListener listener = local[i]; - if (evt == null) - { - evt = new ConnectionEvent(this); - } - listener.connectionClosed(evt); - } - } - - /** - * Used to fire a connection error event to all listeners. - */ - void fireConnectionFatalError(SQLException e) - { - ConnectionEvent evt = null; - // Copy the listener list so the listener can remove itself during this method call - ConnectionEventListener[] local = (ConnectionEventListener[])listeners.toArray(new ConnectionEventListener[listeners.size()]); - for (int i = 0; i < local.length; i++) - { - ConnectionEventListener listener = local[i]; - if (evt == null) - { - evt = new ConnectionEvent(this, e); - } - listener.connectionErrorOccurred(evt); - } - } - - /** - * Instead of declaring a class implementing Connection, which would have - * to be updated for every JDK rev, use a dynamic proxy to handle all - * calls through the Connection interface. This is the part that - * requires JDK 1.3 or higher, though JDK 1.2 could be supported with a - * 3rd-party proxy package. - */ - private class ConnectionHandler implements InvocationHandler - { - private Connection con; - private Connection proxy; // the Connection the client is currently using, which is a proxy - private boolean automatic = false; - - public ConnectionHandler(Connection con) - { - this.con = con; - } - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable - { - // From Object - if (method.getDeclaringClass().getName().equals("java.lang.Object")) - { - if (method.getName().equals("toString")) - { - return "Pooled connection wrapping physical connection " + con; - } - if (method.getName().equals("hashCode")) - { - return new Integer(con.hashCode()); - } - if (method.getName().equals("equals")) - { - if (args[0] == null) - { - return Boolean.FALSE; - } - try - { - return Proxy.isProxyClass(args[0].getClass()) && ((ConnectionHandler) Proxy.getInvocationHandler(args[0])).con == con ? Boolean.TRUE : Boolean.FALSE; - } - catch (ClassCastException e) - { - return Boolean.FALSE; - } - } - try - { - return method.invoke(con, args); - } - catch (InvocationTargetException e) - { - throw e.getTargetException(); - } - } - // All the rest is from the Connection or PGConnection interface - if (method.getName().equals("isClosed")) - { - return con == null ? Boolean.TRUE : Boolean.FALSE; - } - if (con == null) - { - throw new SQLException(automatic ? "Connection has been closed automatically because a new connection was opened for the same PooledConnection or the PooledConnection has been closed" : "Connection has been closed"); - } - if (method.getName().equals("close")) - { - SQLException ex = null; - if (!con.getAutoCommit()) - { - try - { - con.rollback(); - } - catch (SQLException e) - { - ex = e; - } - } - con.clearWarnings(); - con = null; - proxy = null; - last = null; - fireConnectionClosed(); - if (ex != null) - { - throw ex; - } - return null; - } - else if(method.getName().equals("createStatement")) - { - Statement st = (Statement)method.invoke(con, args); - return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Statement.class, org.postgresql.PGStatement.class}, new StatementHandler(this, st)); - } - else if(method.getName().equals("prepareCall")) - { - Statement st = (Statement)method.invoke(con, args); - return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{CallableStatement.class, org.postgresql.PGStatement.class}, new StatementHandler(this, st)); - } - else if(method.getName().equals("prepareStatement")) - { - Statement st = (Statement)method.invoke(con, args); - return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{PreparedStatement.class, org.postgresql.PGStatement.class}, new StatementHandler(this, st)); - } - else - { - return method.invoke(con, args); - } - } - - Connection getProxy() { - return proxy; - } - - void setProxy(Connection proxy) { - this.proxy = proxy; - } - - public void close() - { - if (con != null) - { - automatic = true; - } - con = null; - proxy = null; - // No close event fired here: see JDBC 2.0 Optional Package spec section 6.3 - } - - public boolean isClosed() { - return con == null; - } - } - - /** - * Instead of declaring classes implementing Statement, PreparedStatement, - * and CallableStatement, which would have to be updated for every JDK rev, - * use a dynamic proxy to handle all calls through the Statement - * interfaces. This is the part that requires JDK 1.3 or higher, though - * JDK 1.2 could be supported with a 3rd-party proxy package. - * - * The StatementHandler is required in order to return the proper - * Connection proxy for the getConnection method. - */ - private static class StatementHandler implements InvocationHandler { - private ConnectionHandler con; - private Statement st; - - public StatementHandler(ConnectionHandler con, Statement st) { - this.con = con; - this.st = st; - } - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable - { - // From Object - if (method.getDeclaringClass().getName().equals("java.lang.Object")) - { - if (method.getName().equals("toString")) - { - return "Pooled statement wrapping physical statement " + st; - } - if (method.getName().equals("hashCode")) - { - return new Integer(st.hashCode()); - } - if (method.getName().equals("equals")) - { - if (args[0] == null) - { - return Boolean.FALSE; - } - try - { - return Proxy.isProxyClass(args[0].getClass()) && ((StatementHandler) Proxy.getInvocationHandler(args[0])).st == st ? Boolean.TRUE : Boolean.FALSE; - } - catch (ClassCastException e) - { - return Boolean.FALSE; - } - } - return method.invoke(st, args); - } - // All the rest is from the Statement interface - if (st == null || con.isClosed()) - { - throw new SQLException("Statement has been closed"); - } - if (method.getName().equals("close")) - { - try { - st.close(); - } finally { - con = null; - st = null; - return null; - } - } - else if (method.getName().equals("getConnection")) - { - return con.getProxy(); // the proxied connection, not a physical connection - } - else - { - try - { - return method.invoke(st, args); - } - catch (InvocationTargetException e) - { - throw e.getTargetException(); - } - } - } - } -} diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java deleted file mode 100644 index 1d6c7daeac..0000000000 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java +++ /dev/null @@ -1,494 +0,0 @@ -package org.postgresql.jdbc2.optional; - -import javax.sql.*; -import javax.naming.*; -import java.util.*; -import java.sql.Connection; -import java.sql.SQLException; - -/** - * DataSource which uses connection pooling. Don't use this if - * your server/middleware vendor provides a connection pooling implementation - * which interfaces with the PostgreSQL ConnectionPoolDataSource implementation! - * This class is provided as a convenience, but the JDBC Driver is really not - * supposed to handle the connection pooling algorithm. Instead, the server or - * middleware product is supposed to handle the mechanics of connection pooling, - * and use the PostgreSQL implementation of ConnectionPoolDataSource to provide - * the connections to pool. - * - *

If you're sure you want to use this, then you must set the properties - * dataSourceName, databaseName, user, and password (if required for the user). - * The settings for serverName, portNumber, initialConnections, and - * maxConnections are optional. Note that only connections - * for the default user will be pooled! Connections for other users will - * be normal non-pooled connections, and will not count against the maximum pool - * size limit.

- * - *

If you put this DataSource in JNDI, and access it from different JVMs (or - * otherwise load this class from different ClassLoaders), you'll end up with one - * pool per ClassLoader or VM. This is another area where a server-specific - * implementation may provide advanced features, such as using a single pool - * across all VMs in a cluster.

- * - *

This implementation supports JDK 1.3 and higher.

- * - * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.3 $ - */ -public class PoolingDataSource extends BaseDataSource implements DataSource -{ - private static Map dataSources = new HashMap(); - - static PoolingDataSource getDataSource(String name) - { - return (PoolingDataSource)dataSources.get(name); - } - - // Additional Data Source properties - protected String dataSourceName; // Must be protected for subclasses to sync updates to it - private int initialConnections = 0; - private int maxConnections = 0; - // State variables - private boolean initialized = false; - private Stack available = new Stack(); - private Stack used = new Stack(); - private Object lock = new Object(); - private ConnectionPool source; - - /** - * Gets a description of this DataSource. - */ - public String getDescription() - { - return "Pooling DataSource '" + dataSourceName + " from " + org.postgresql.Driver.getVersion(); - } - - /** - * Ensures the DataSource properties are not changed after the DataSource has - * been used. - * - * @throws java.lang.IllegalStateException - * The Server Name cannot be changed after the DataSource has been - * used. - */ - public void setServerName(String serverName) - { - if (initialized) - { - throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); - } - super.setServerName(serverName); - } - - /** - * Ensures the DataSource properties are not changed after the DataSource has - * been used. - * - * @throws java.lang.IllegalStateException - * The Database Name cannot be changed after the DataSource has been - * used. - */ - public void setDatabaseName(String databaseName) - { - if (initialized) - { - throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); - } - super.setDatabaseName(databaseName); - } - - /** - * Ensures the DataSource properties are not changed after the DataSource has - * been used. - * - * @throws java.lang.IllegalStateException - * The User cannot be changed after the DataSource has been - * used. - */ - public void setUser(String user) - { - if (initialized) - { - throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); - } - super.setUser(user); - } - - /** - * Ensures the DataSource properties are not changed after the DataSource has - * been used. - * - * @throws java.lang.IllegalStateException - * The Password cannot be changed after the DataSource has been - * used. - */ - public void setPassword(String password) - { - if (initialized) - { - throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); - } - super.setPassword(password); - } - - /** - * Ensures the DataSource properties are not changed after the DataSource has - * been used. - * - * @throws java.lang.IllegalStateException - * The Port Number cannot be changed after the DataSource has been - * used. - */ - public void setPortNumber(int portNumber) - { - if (initialized) - { - throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); - } - super.setPortNumber(portNumber); - } - - /** - * Gets the number of connections that will be created when this DataSource - * is initialized. If you do not call initialize explicitly, it will be - * initialized the first time a connection is drawn from it. - */ - public int getInitialConnections() - { - return initialConnections; - } - - /** - * Sets the number of connections that will be created when this DataSource - * is initialized. If you do not call initialize explicitly, it will be - * initialized the first time a connection is drawn from it. - * - * @throws java.lang.IllegalStateException - * The Initial Connections cannot be changed after the DataSource has been - * used. - */ - public void setInitialConnections(int initialConnections) - { - if (initialized) - { - throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); - } - this.initialConnections = initialConnections; - } - - /** - * Gets the maximum number of connections that the pool will allow. If a request - * comes in and this many connections are in use, the request will block until a - * connection is available. Note that connections for a user other than the - * default user will not be pooled and don't count against this limit. - * - * @return The maximum number of pooled connection allowed, or 0 for no maximum. - */ - public int getMaxConnections() - { - return maxConnections; - } - - /** - * Sets the maximum number of connections that the pool will allow. If a request - * comes in and this many connections are in use, the request will block until a - * connection is available. Note that connections for a user other than the - * default user will not be pooled and don't count against this limit. - * - * @param maxConnections The maximum number of pooled connection to allow, or - * 0 for no maximum. - * - * @throws java.lang.IllegalStateException - * The Maximum Connections cannot be changed after the DataSource has been - * used. - */ - public void setMaxConnections(int maxConnections) - { - if (initialized) - { - throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); - } - this.maxConnections = maxConnections; - } - - /** - * Gets the name of this DataSource. This uniquely identifies the DataSource. - * You cannot use more than one DataSource in the same VM with the same name. - */ - public String getDataSourceName() - { - return dataSourceName; - } - - /** - * Sets the name of this DataSource. This is required, and uniquely identifies - * the DataSource. You cannot create or use more than one DataSource in the - * same VM with the same name. - * - * @throws java.lang.IllegalStateException - * The Data Source Name cannot be changed after the DataSource has been - * used. - * @throws java.lang.IllegalArgumentException - * Another PoolingDataSource with the same dataSourceName already - * exists. - */ - public void setDataSourceName(String dataSourceName) - { - if (initialized) - { - throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); - } - if (this.dataSourceName != null && dataSourceName != null && dataSourceName.equals(this.dataSourceName)) - { - return ; - } - synchronized (dataSources) - { - if (getDataSource(dataSourceName) != null) - { - throw new IllegalArgumentException("DataSource with name '" + dataSourceName + "' already exists!"); - } - if (this.dataSourceName != null) - { - dataSources.remove(this.dataSourceName); - } - this.dataSourceName = dataSourceName; - dataSources.put(dataSourceName, this); - } - } - - /** - * Initializes this DataSource. If the initialConnections is greater than zero, - * that number of connections will be created. After this method is called, - * the DataSource properties cannot be changed. If you do not call this - * explicitly, it will be called the first time you get a connection from the - * DataSource. - * @throws java.sql.SQLException - * Occurs when the initialConnections is greater than zero, but the - * DataSource is not able to create enough physical connections. - */ - public void initialize() throws SQLException - { - synchronized (lock) - { - source = createConnectionPool(); - source.setDatabaseName(getDatabaseName()); - source.setPassword(getPassword()); - source.setPortNumber(getPortNumber()); - source.setServerName(getServerName()); - source.setUser(getUser()); - while (available.size() < initialConnections) - { - available.push(source.getPooledConnection()); - } - initialized = true; - } - } - - protected boolean isInitialized() { - return initialized; - } - - /** - * Creates the appropriate ConnectionPool to use for this DataSource. - */ - protected ConnectionPool createConnectionPool() { - return new ConnectionPool(); - } - - /** - * Gets a non-pooled connection, unless the user and password are the - * same as the default values for this connection pool. - * - * @return A pooled connection. - * @throws SQLException - * Occurs when no pooled connection is available, and a new physical - * connection cannot be created. - */ - public Connection getConnection(String user, String password) throws SQLException - { - // If this is for the default user/password, use a pooled connection - if (user == null || - (user.equals(getUser()) && ((password == null && getPassword() == null) || (password != null && password.equals(getPassword()))))) - { - return getConnection(); - } - // Otherwise, use a non-pooled connection - if (!initialized) - { - initialize(); - } - return super.getConnection(user, password); - } - - /** - * Gets a connection from the connection pool. - * - * @return A pooled connection. - * @throws SQLException - * Occurs when no pooled connection is available, and a new physical - * connection cannot be created. - */ - public Connection getConnection() throws SQLException - { - if (!initialized) - { - initialize(); - } - return getPooledConnection(); - } - - /** - * Closes this DataSource, and all the pooled connections, whether in use or not. - */ - public void close() - { - synchronized (lock) - { - while (available.size() > 0) - { - PooledConnectionImpl pci = (PooledConnectionImpl)available.pop(); - try - { - pci.close(); - } - catch (SQLException e) - {} - } - available = null; - while (used.size() > 0) - { - PooledConnectionImpl pci = (PooledConnectionImpl)used.pop(); - pci.removeConnectionEventListener(connectionEventListener); - try - { - pci.close(); - } - catch (SQLException e) - {} - } - used = null; - } - removeStoredDataSource(); - } - - protected void removeStoredDataSource() { - synchronized (dataSources) - { - dataSources.remove(dataSourceName); - } - } - - /** - * Gets a connection from the pool. Will get an available one if - * present, or create a new one if under the max limit. Will - * block if all used and a new one would exceed the max. - */ - private Connection getPooledConnection() throws SQLException - { - PooledConnection pc = null; - synchronized (lock) - { - if (available == null) - { - throw new SQLException("DataSource has been closed."); - } - while (true) - { - if (available.size() > 0) - { - pc = (PooledConnection)available.pop(); - used.push(pc); - break; - } - if (maxConnections == 0 || used.size() < maxConnections) - { - pc = source.getPooledConnection(); - used.push(pc); - break; - } - else - { - try - { - // Wake up every second at a minimum - lock.wait(1000L); - } - catch (InterruptedException e) - {} - } - } - } - pc.addConnectionEventListener(connectionEventListener); - return pc.getConnection(); - } - - /** - * Notified when a pooled connection is closed, or a fatal error occurs - * on a pooled connection. This is the only way connections are marked - * as unused. - */ - private ConnectionEventListener connectionEventListener = new ConnectionEventListener() - { - public void connectionClosed(ConnectionEvent event) - { - ((PooledConnection)event.getSource()).removeConnectionEventListener(this); - synchronized (lock) - { - if (available == null) - { - return ; // DataSource has been closed - } - boolean removed = used.remove(event.getSource()); - if (removed) - { - available.push(event.getSource()); - // There's now a new connection available - lock.notify(); - } - else - { - // a connection error occured - } - } - } - - /** - * This is only called for fatal errors, where the physical connection is - * useless afterward and should be removed from the pool. - */ - public void connectionErrorOccurred(ConnectionEvent event) - { - ((PooledConnection) event.getSource()).removeConnectionEventListener(this); - synchronized (lock) - { - if (available == null) - { - return ; // DataSource has been closed - } - used.remove(event.getSource()); - // We're now at least 1 connection under the max - lock.notify(); - } - } - }; - - /** - * Adds custom properties for this DataSource to the properties defined in - * the superclass. - */ - public Reference getReference() throws NamingException - { - Reference ref = super.getReference(); - ref.add(new StringRefAddr("dataSourceName", dataSourceName)); - if (initialConnections > 0) - { - ref.add(new StringRefAddr("initialConnections", Integer.toString(initialConnections))); - } - if (maxConnections > 0) - { - ref.add(new StringRefAddr("maxConnections", Integer.toString(maxConnections))); - } - return ref; - } -} diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/SimpleDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/SimpleDataSource.java deleted file mode 100644 index 6d9ef39fff..0000000000 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/SimpleDataSource.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.postgresql.jdbc2.optional; - -import javax.sql.DataSource; -import java.io.Serializable; - -/** - * Simple DataSource which does not perform connection pooling. In order to use - * the DataSource, you must set the property databaseName. The settings for - * serverName, portNumber, user, and password are optional. Note: these properties - * are declared in the superclass. - * - * @author Aaron Mulder (ammulder@chariotsolutions.com) - * @version $Revision: 1.2 $ - */ -public class SimpleDataSource extends BaseDataSource implements Serializable, DataSource -{ - /** - * Gets a description of this DataSource. - */ - public String getDescription() - { - return "Non-Pooling DataSource from " + org.postgresql.Driver.getVersion(); - } -} diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/BlobInputStream.java b/src/interfaces/jdbc/org/postgresql/largeobject/BlobInputStream.java deleted file mode 100644 index eb97273269..0000000000 --- a/src/interfaces/jdbc/org/postgresql/largeobject/BlobInputStream.java +++ /dev/null @@ -1,194 +0,0 @@ -/*------------------------------------------------------------------------- - * - * BlobInputStream.java - * This is an implementation of an InputStream from a large object. - * - * Copyright (c) 2003, PostgreSQL Global Development Group - * - * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/jdbc/org/postgresql/largeobject/BlobInputStream.java,v 1.6 2003/11/29 19:52:11 pgsql Exp $ - * - *------------------------------------------------------------------------- - */ -package org.postgresql.largeobject; - -import java.io.InputStream; -import java.io.IOException; -import java.sql.SQLException; - -public class BlobInputStream extends InputStream -{ - /* - * The parent LargeObject - */ - private LargeObject lo; - - /* - * Buffer used to improve performance - */ - private byte[] buffer; - - /* - * Position within buffer - */ - private int bpos; - - /* - * The buffer size - */ - private int bsize; - - /* - * The mark position - */ - private int mpos = 0; - - /* - * @param lo LargeObject to read from - */ - public BlobInputStream(LargeObject lo) - { - this(lo, 1024); - } - - /* - * @param lo LargeObject to read from - * @param bsize buffer size - */ - public BlobInputStream(LargeObject lo, int bsize) - { - this.lo = lo; - buffer = null; - bpos = 0; - this.bsize = bsize; - } - - /* - * The minimum required to implement input stream - */ - public int read() throws java.io.IOException - { - try - { - if (buffer == null || bpos >= buffer.length) - { - buffer = lo.read(bsize); - bpos = 0; - } - - // Handle EOF - if (bpos >= buffer.length) - { - return -1; - } - - int ret = (buffer[bpos] & 0x7F); - if ((buffer[bpos] &0x80) == 0x80) - { - ret |= 0x80; - } - - bpos++; - - return ret; - } - catch (SQLException se) - { - throw new IOException(se.toString()); - } - } - - - /* - * Closes this input stream and releases any system resources associated - * with the stream. - * - *

The close method of InputStream does - * nothing. - * - * @exception IOException if an I/O error occurs. - */ - public void close() throws IOException - { - try - { - lo.close(); - lo = null; - } - catch (SQLException se) - { - throw new IOException(se.toString()); - } - } - - /* - * Marks the current position in this input stream. A subsequent call to - * the reset method repositions this stream at the last marked - * position so that subsequent reads re-read the same bytes. - * - *

The readlimit arguments tells this input stream to - * allow that many bytes to be read before the mark position gets - * invalidated. - * - *

The general contract of mark is that, if the method - * markSupported returns true, the stream somehow - * remembers all the bytes read after the call to mark and - * stands ready to supply those same bytes again if and whenever the method - * reset is called. However, the stream is not required to - * remember any data at all if more than readlimit bytes are - * read from the stream before reset is called. - * - *

The mark method of InputStream does - * nothing. - * - * @param readlimit the maximum limit of bytes that can be read before - * the mark position becomes invalid. - * @see java.io.InputStream#reset() - */ - public synchronized void mark(int readlimit) - { - try - { - mpos = lo.tell(); - } - catch (SQLException se) - { - //throw new IOException(se.toString()); - } - } - - /* - * Repositions this stream to the position at the time the - * mark method was last called on this input stream. - * NB: If mark is not called we move to the begining. - * @see java.io.InputStream#mark(int) - * @see java.io.IOException - */ - public synchronized void reset() - throws IOException - { - try - { - lo.seek(mpos); - } - catch (SQLException se) - { - throw new IOException(se.toString()); - } - } - - /* - * Tests if this input stream supports the mark and - * reset methods. The markSupported method of - * InputStream returns false. - * - * @return true if this true type supports the mark and reset - * method; false otherwise. - * @see java.io.InputStream#mark(int) - * @see java.io.InputStream#reset() - */ - public boolean markSupported() - { - return true; - } -} diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java b/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java deleted file mode 100644 index d6690499ed..0000000000 --- a/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java +++ /dev/null @@ -1,148 +0,0 @@ -/*------------------------------------------------------------------------- - * - * BlobOutputStream.java - * This implements a basic output stream that writes to a LargeObject - * - * Copyright (c) 2003, PostgreSQL Global Development Group - * - * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java,v 1.7 2003/11/29 19:52:11 pgsql Exp $ - * - *------------------------------------------------------------------------- - */ -package org.postgresql.largeobject; - -import java.io.IOException; -import java.io.OutputStream; -import java.sql.SQLException; - -public class BlobOutputStream extends OutputStream -{ - /* - * The parent LargeObject - */ - private LargeObject lo; - - /* - * Buffer - */ - private byte buf[]; - - /* - * Size of the buffer (default 1K) - */ - private int bsize; - - /* - * Position within the buffer - */ - private int bpos; - - /* - * Create an OutputStream to a large object - * @param lo LargeObject - */ - public BlobOutputStream(LargeObject lo) - { - this(lo, 1024); - } - - /* - * Create an OutputStream to a large object - * @param lo LargeObject - * @param bsize The size of the buffer used to improve performance - */ - public BlobOutputStream(LargeObject lo, int bsize) - { - this.lo = lo; - this.bsize = bsize; - buf = new byte[bsize]; - bpos = 0; - } - - public void write(int b) throws java.io.IOException - { - try - { - if (bpos >= bsize) - { - lo.write(buf); - bpos = 0; - } - buf[bpos++] = (byte)b; - } - catch (SQLException se) - { - throw new IOException(se.toString()); - } - } - - public void write(byte[] buf, int off, int len) throws java.io.IOException - { - try - { - // If we have any internally buffered data, send it first - if ( bpos > 0 ) - flush(); - - if ( off == 0 && len == buf.length ) - lo.write(buf); // save a buffer creation and copy since full buffer written - else - lo.write(buf,off,len); - } - catch (SQLException se) - { - throw new IOException(se.toString()); - } - } - - - /* - * Flushes this output stream and forces any buffered output bytes - * to be written out. The general contract of flush is - * that calling it is an indication that, if any bytes previously - * written have been buffered by the implementation of the output - * stream, such bytes should immediately be written to their - * intended destination. - * - * @exception IOException if an I/O error occurs. - */ - public void flush() throws IOException - { - try - { - if (bpos > 0) - lo.write(buf, 0, bpos); - bpos = 0; - } - catch (SQLException se) - { - throw new IOException(se.toString()); - } - } - - /* - * Closes this output stream and releases any system resources - * associated with this stream. The general contract of close - * is that it closes the output stream. A closed stream cannot perform - * output operations and cannot be reopened. - *

- * The close method of OutputStream does nothing. - * - * @exception IOException if an I/O error occurs. - */ - public void close() throws IOException - { - try - { - flush(); - lo.close(); - lo = null; - } - catch (SQLException se) - { - throw new IOException(se.toString()); - } - } - -} diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java b/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java deleted file mode 100644 index f175cd03ce..0000000000 --- a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java +++ /dev/null @@ -1,328 +0,0 @@ -/*------------------------------------------------------------------------- - * - * LargeObject.java - * This class implements the large object interface to org.postgresql. - * - * Copyright (c) 2003, PostgreSQL Global Development Group - * - * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java,v 1.11 2003/11/29 19:52:11 pgsql Exp $ - * - *------------------------------------------------------------------------- - */ -package org.postgresql.largeobject; - -import java.io.InputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.sql.SQLException; -import org.postgresql.fastpath.Fastpath; -import org.postgresql.fastpath.FastpathArg; - -/* - * This class provides the basic methods required to run the interface, plus - * a pair of methods that provide InputStream and OutputStream classes - * for this object. - * - *

Normally, client code would use the getAsciiStream, getBinaryStream, - * or getUnicodeStream methods in ResultSet, or setAsciiStream, - * setBinaryStream, or setUnicodeStream methods in PreparedStatement to - * access Large Objects. - * - *

However, sometimes lower level access to Large Objects are required, - * that are not supported by the JDBC specification. - * - *

Refer to org.postgresql.largeobject.LargeObjectManager on how to gain access - * to a Large Object, or how to create one. - * - * @see org.postgresql.largeobject.LargeObjectManager - * @see java.sql.ResultSet#getAsciiStream - * @see java.sql.ResultSet#getBinaryStream - * @see java.sql.ResultSet#getUnicodeStream - * @see java.sql.PreparedStatement#setAsciiStream - * @see java.sql.PreparedStatement#setBinaryStream - * @see java.sql.PreparedStatement#setUnicodeStream - * - */ -public class LargeObject -{ - /* - * Indicates a seek from the begining of a file - */ - public static final int SEEK_SET = 0; - - /* - * Indicates a seek from the current position - */ - public static final int SEEK_CUR = 1; - - /* - * Indicates a seek from the end of a file - */ - public static final int SEEK_END = 2; - - private Fastpath fp; // Fastpath API to use - private int oid; // OID of this object - private int fd; // the descriptor of the open large object - - private BlobOutputStream os; // The current output stream - - private boolean closed = false; // true when we are closed - - /* - * This opens a large object. - * - *

If the object does not exist, then an SQLException is thrown. - * - * @param fp FastPath API for the connection to use - * @param oid of the Large Object to open - * @param mode Mode of opening the large object - * (defined in LargeObjectManager) - * @exception SQLException if a database-access error occurs. - * @see org.postgresql.largeobject.LargeObjectManager - */ - protected LargeObject(Fastpath fp, int oid, int mode) throws SQLException - { - this.fp = fp; - this.oid = oid; - - FastpathArg args[] = new FastpathArg[2]; - args[0] = new FastpathArg(oid); - args[1] = new FastpathArg(mode); - this.fd = fp.getInteger("lo_open", args); - } - - /* Release large object resources during garbage cleanup */ - protected void finalize() throws SQLException - { - //This code used to call close() however that was problematic - //because the scope of the fd is a transaction, thus if commit - //or rollback was called before garbage collection ran then - //the call to close would error out with an invalid large object - //handle. So this method now does nothing and lets the server - //handle cleanup when it ends the transaction. - } - - /* - * @return the OID of this LargeObject - */ - public int getOID() - { - return oid; - } - - /* - * This method closes the object. You must not call methods in this - * object after this is called. - * @exception SQLException if a database-access error occurs. - */ - public void close() throws SQLException - { - if (!closed) - { - // flush any open output streams - if (os != null) - { - try - { - // we can't call os.close() otherwise we go into an infinite loop! - os.flush(); - } - catch (IOException ioe) - { - throw new SQLException(ioe.getMessage()); - } - finally - { - os = null; - } - } - - // finally close - FastpathArg args[] = new FastpathArg[1]; - args[0] = new FastpathArg(fd); - fp.fastpath("lo_close", false, args); // true here as we dont care!! - closed = true; - } - } - - /* - * Reads some data from the object, and return as a byte[] array - * - * @param len number of bytes to read - * @return byte[] array containing data read - * @exception SQLException if a database-access error occurs. - */ - public byte[] read(int len) throws SQLException - { - // This is the original method, where the entire block (len bytes) - // is retrieved in one go. - FastpathArg args[] = new FastpathArg[2]; - args[0] = new FastpathArg(fd); - args[1] = new FastpathArg(len); - return fp.getData("loread", args); - - // This version allows us to break this down into 4k blocks - //if (len<=4048) { - //// handle as before, return the whole block in one go - //FastpathArg args[] = new FastpathArg[2]; - //args[0] = new FastpathArg(fd); - //args[1] = new FastpathArg(len); - //return fp.getData("loread",args); - //} else { - //// return in 4k blocks - //byte[] buf=new byte[len]; - //int off=0; - //while (len>0) { - //int bs=4048; - //len-=bs; - //if (len<0) { - //bs+=len; - //len=0; - //} - //read(buf,off,bs); - //off+=bs; - //} - //return buf; - //} - } - - /* - * Reads some data from the object into an existing array - * - * @param buf destination array - * @param off offset within array - * @param len number of bytes to read - * @return the number of bytes actually read - * @exception SQLException if a database-access error occurs. - */ - public int read(byte buf[], int off, int len) throws SQLException - { - byte b[] = read(len); - if (b.length < len) - len = b.length; - System.arraycopy(b, 0, buf, off, len); - return len; - } - - /* - * Writes an array to the object - * - * @param buf array to write - * @exception SQLException if a database-access error occurs. - */ - public void write(byte buf[]) throws SQLException - { - FastpathArg args[] = new FastpathArg[2]; - args[0] = new FastpathArg(fd); - args[1] = new FastpathArg(buf); - fp.fastpath("lowrite", false, args); - } - - /* - * Writes some data from an array to the object - * - * @param buf destination array - * @param off offset within array - * @param len number of bytes to write - * @exception SQLException if a database-access error occurs. - */ - public void write(byte buf[], int off, int len) throws SQLException - { - byte data[] = new byte[len]; - System.arraycopy(buf, off, data, 0, len); - write(data); - } - - /* - * Sets the current position within the object. - * - *

This is similar to the fseek() call in the standard C library. It - * allows you to have random access to the large object. - * - * @param pos position within object - * @param ref Either SEEK_SET, SEEK_CUR or SEEK_END - * @exception SQLException if a database-access error occurs. - */ - public void seek(int pos, int ref) throws SQLException - { - FastpathArg args[] = new FastpathArg[3]; - args[0] = new FastpathArg(fd); - args[1] = new FastpathArg(pos); - args[2] = new FastpathArg(ref); - fp.fastpath("lo_lseek", false, args); - } - - /* - * Sets the current position within the object. - * - *

This is similar to the fseek() call in the standard C library. It - * allows you to have random access to the large object. - * - * @param pos position within object from begining - * @exception SQLException if a database-access error occurs. - */ - public void seek(int pos) throws SQLException - { - seek(pos, SEEK_SET); - } - - /* - * @return the current position within the object - * @exception SQLException if a database-access error occurs. - */ - public int tell() throws SQLException - { - FastpathArg args[] = new FastpathArg[1]; - args[0] = new FastpathArg(fd); - return fp.getInteger("lo_tell", args); - } - - /* - * This method is inefficient, as the only way to find out the size of - * the object is to seek to the end, record the current position, then - * return to the original position. - * - *

A better method will be found in the future. - * - * @return the size of the large object - * @exception SQLException if a database-access error occurs. - */ - public int size() throws SQLException - { - int cp = tell(); - seek(0, SEEK_END); - int sz = tell(); - seek(cp, SEEK_SET); - return sz; - } - - /* - * Returns an InputStream from this object. - * - *

This InputStream can then be used in any method that requires an - * InputStream. - * - * @exception SQLException if a database-access error occurs. - */ - public InputStream getInputStream() throws SQLException - { - return new BlobInputStream(this, 4096); - } - - /* - * Returns an OutputStream to this object - * - *

This OutputStream can then be used in any method that requires an - * OutputStream. - * - * @exception SQLException if a database-access error occurs. - */ - public OutputStream getOutputStream() throws SQLException - { - if (os == null) - os = new BlobOutputStream(this, 4096); - return os; - } - -} diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java b/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java deleted file mode 100644 index 2958fb0498..0000000000 --- a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java +++ /dev/null @@ -1,229 +0,0 @@ -/*------------------------------------------------------------------------- - * - * LargeObjectManager.java - * This class implements the large object interface to org.postgresql. - * - * It provides methods that allow client code to create, open and delete - * large objects from the database. When opening an object, an instance of - * org.postgresql.largeobject.LargeObject is returned, and its methods - * then allow access to the object. - * - * Copyright (c) 2003, PostgreSQL Global Development Group - * - * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java,v 1.12 2003/12/17 15:38:42 davec Exp $ - * - *------------------------------------------------------------------------- - */ -package org.postgresql.largeobject; - - -import java.sql.ResultSet; -import java.sql.SQLException; -import org.postgresql.Driver; -import org.postgresql.core.BaseConnection; -import org.postgresql.fastpath.Fastpath; -import org.postgresql.fastpath.FastpathArg; -import org.postgresql.util.PSQLException; - -/* - * This class implements the large object interface to org.postgresql. - * - *

It provides methods that allow client code to create, open and delete - * large objects from the database. When opening an object, an instance of - * org.postgresql.largeobject.LargeObject is returned, and its methods then allow - * access to the object. - * - *

This class can only be created by org.postgresql.Connection - * - *

To get access to this class, use the following segment of code: - *

- * import org.postgresql.largeobject.*;
- *
- * Connection  conn;
- * LargeObjectManager lobj;
- *
- * ... code that opens a connection ...
- *
- * lobj = ((org.postgresql.PGConnection)myconn).getLargeObjectAPI();
- * 
- * - *

Normally, client code would use the getAsciiStream, getBinaryStream, - * or getUnicodeStream methods in ResultSet, or setAsciiStream, - * setBinaryStream, or setUnicodeStream methods in PreparedStatement to - * access Large Objects. - * - *

However, sometimes lower level access to Large Objects are required, - * that are not supported by the JDBC specification. - * - *

Refer to org.postgresql.largeobject.LargeObject on how to manipulate the - * contents of a Large Object. - * - * @see java.sql.ResultSet#getAsciiStream - * @see java.sql.ResultSet#getBinaryStream - * @see java.sql.ResultSet#getUnicodeStream - * @see java.sql.PreparedStatement#setAsciiStream - * @see java.sql.PreparedStatement#setBinaryStream - * @see java.sql.PreparedStatement#setUnicodeStream - */ -public class LargeObjectManager -{ - // the fastpath api for this connection - private Fastpath fp; - - /* - * This mode indicates we want to write to an object - */ - public static final int WRITE = 0x00020000; - - /* - * This mode indicates we want to read an object - */ - public static final int READ = 0x00040000; - - /* - * This mode is the default. It indicates we want read and write access to - * a large object - */ - public static final int READWRITE = READ | WRITE; - - /* - * This prevents us being created by mere mortals - */ - private LargeObjectManager() - {} - - /* - * Constructs the LargeObject API. - * - *

Important Notice - *
This method should only be called by org.postgresql.Connection - * - *

There should only be one LargeObjectManager per Connection. The - * org.postgresql.Connection class keeps track of the various extension API's - * and it's advised you use those to gain access, and not going direct. - */ - public LargeObjectManager(BaseConnection conn) throws SQLException - { - // We need Fastpath to do anything - this.fp = conn.getFastpathAPI(); - - // Now get the function oid's for the api - // - // This is an example of Fastpath.addFunctions(); - // - String sql; - if (conn.getMetaData().supportsSchemasInTableDefinitions()) { - sql = "SELECT p.proname,p.oid "+ - " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "+ - " WHERE p.pronamespace=n.oid AND n.nspname='pg_catalog' AND ("; - } else { - sql = "SELECT proname,oid FROM pg_proc WHERE "; - } - sql += " proname = 'lo_open'" + - " or proname = 'lo_close'" + - " or proname = 'lo_creat'" + - " or proname = 'lo_unlink'" + - " or proname = 'lo_lseek'" + - " or proname = 'lo_tell'" + - " or proname = 'loread'" + - " or proname = 'lowrite'"; - - if (conn.getMetaData().supportsSchemasInTableDefinitions()) { - sql += ")"; - } - - ResultSet res = conn.createStatement().executeQuery(sql); - - if (res == null) - throw new PSQLException("postgresql.lo.init"); - - fp.addFunctions(res); - res.close(); - if (Driver.logDebug) - Driver.debug("Large Object initialised"); - } - - /* - * This opens an existing large object, based on its OID. This method - * assumes that READ and WRITE access is required (the default). - * - * @param oid of large object - * @return LargeObject instance providing access to the object - * @exception SQLException on error - */ - public LargeObject open(int oid) throws SQLException - { - return new LargeObject(fp, oid, READWRITE); - } - - /* - * This opens an existing large object, based on its OID - * - * @param oid of large object - * @param mode mode of open - * @return LargeObject instance providing access to the object - * @exception SQLException on error - */ - public LargeObject open(int oid, int mode) throws SQLException - { - return new LargeObject(fp, oid, mode); - } - - /* - * This creates a large object, returning its OID. - * - *

It defaults to READWRITE for the new object's attributes. - * - * @return oid of new object - * @exception SQLException on error - */ - public int create() throws SQLException - { - FastpathArg args[] = new FastpathArg[1]; - args[0] = new FastpathArg(READWRITE); - return fp.getInteger("lo_creat", args); - } - - /* - * This creates a large object, returning its OID - * - * @param mode a bitmask describing different attributes of the new object - * @return oid of new object - * @exception SQLException on error - */ - public int create(int mode) throws SQLException - { - FastpathArg args[] = new FastpathArg[1]; - args[0] = new FastpathArg(mode); - return fp.getInteger("lo_creat", args); - } - - /* - * This deletes a large object. - * - * @param oid describing object to delete - * @exception SQLException on error - */ - public void delete(int oid) throws SQLException - { - FastpathArg args[] = new FastpathArg[1]; - args[0] = new FastpathArg(oid); - fp.fastpath("lo_unlink", false, args); - } - - /* - * This deletes a large object. - * - *

It is identical to the delete method, and is supplied as the C API uses - * unlink. - * - * @param oid describing object to delete - * @exception SQLException on error - */ - public void unlink(int oid) throws SQLException - { - delete(oid); - } - -}