You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by cb...@apache.org on 2012/03/09 17:23:32 UTC
svn commit: r1298906 [8/14] - in /velocity/sandbox/velosurf: ./ docs/
examples/ examples/ant-vpp/ examples/ant-vpp/lib/ examples/auth-l10n/
examples/auth-l10n/WEB-INF/ examples/auth-l10n/WEB-INF/lib/
examples/auth-l10n/WEB-INF/src/ examples/auth-l10n/e...
Added: velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/ConnectionWrapper.java.jdk5
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/ConnectionWrapper.java.jdk5?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/ConnectionWrapper.java.jdk5 (added)
+++ velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/ConnectionWrapper.java.jdk5 Fri Mar 9 16:23:25 2012
@@ -0,0 +1,712 @@
+/*
+ * Copyright 2003 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+package org.apache.velocity.velosurf.sql;
+
+import java.lang.reflect.Method;
+import java.sql.*;
+import java.util.Map;
+import java.util.Properties;
+import org.apache.velocity.velosurf.util.Logger;
+
+/**
+ * Connection wrapper class. Allows the handling of a busy state
+ *
+ * @author <a href="mailto:claude.brisson@gmail.com">Claude Brisson</a>
+ */
+
+public class ConnectionWrapper
+ implements Connection
+{
+
+ /**
+ * Constructor.
+ * @param driver infos on the driver
+ * @param connection connection to be wrapped
+ */
+ public ConnectionWrapper(DriverInfo driver,Connection connection)
+ {
+ this.driver = driver;
+ this.connection = connection;
+ }
+
+ /**
+ * Unwrap the connection.
+ * @return the unwrapped connection
+ */
+ public Connection unwrap()
+ {
+ return connection;
+ }
+
+ /**
+ * Create a statement.
+ * @return created statement
+ * @throws SQLException
+ */
+ public Statement createStatement()
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.createStatement();
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a callable statement.
+ * @param s SQL query
+ * @return prepared callable statement
+ * @throws SQLException
+ */
+ public synchronized CallableStatement prepareCall(String s)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareCall(s);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Gets native SQL for a query.
+ * @param s query
+ * @return native SQL
+ * @throws SQLException
+ */
+ public synchronized String nativeSQL(String s)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.nativeSQL(s);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Set autocommit flag.
+ * @param flag autocommit
+ * @throws SQLException
+ */
+ public void setAutoCommit(boolean flag)
+ throws SQLException
+ {
+ connection.setAutoCommit(flag);
+ }
+
+ /**
+ * Get autocommit flag.
+ *
+ * @return autocommit flag
+ * @throws SQLException
+ */
+ public boolean getAutoCommit()
+ throws SQLException
+ {
+ return connection.getAutoCommit();
+ }
+
+ /**
+ * Commit.
+ *
+ * @throws SQLException
+ */
+ public synchronized void commit()
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ connection.commit();
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Rollback.
+ *
+ * @throws SQLException
+ */
+ public synchronized void rollback()
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ connection.rollback();
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Close.
+ *
+ * @throws SQLException
+ */
+ public void close()
+ throws SQLException
+ {
+ // since some sql drivers refuse to close a connection that has been interrupted,
+ // better handle this also ourselves
+ closed = true;
+ connection.close();
+ }
+
+ /**
+ * Check the closed state.
+ * @return closed state
+ * @throws SQLException
+ */
+ public boolean isClosed()
+ throws SQLException
+ {
+ return (closed || connection.isClosed());
+ }
+
+ /**
+ * Get meta data
+ * @return database meta data
+ * @throws SQLException
+ */
+ public DatabaseMetaData getMetaData()
+ throws SQLException
+ {
+ return connection.getMetaData();
+ }
+
+ /**
+ * set read-only flag
+ * @param flag read-only
+ * @throws SQLException
+ */
+ public void setReadOnly(boolean flag)
+ throws SQLException
+ {
+ connection.setReadOnly(flag);
+ }
+
+ /**
+ * Check the read-only state.
+ * @return read-only state
+ * @throws SQLException
+ */
+ public boolean isReadOnly()
+ throws SQLException
+ {
+ return connection.isReadOnly();
+ }
+
+ /**
+ * Catalog setter.
+ * @param s catalog
+ * @throws SQLException
+ */
+ public void setCatalog(String s)
+ throws SQLException
+ {
+ connection.setCatalog(s);
+ }
+
+ /**
+ * Catalog getter.
+ * @return catalog
+ * @throws SQLException
+ */
+
+ public String getCatalog()
+ throws SQLException
+ {
+ return connection.getCatalog();
+ }
+ /**
+ * Transaction isolation setter.
+ * @param i transaction isolation
+ * @throws SQLException
+ */
+
+ public void setTransactionIsolation(int i)
+ throws SQLException
+ {
+ connection.setTransactionIsolation(i);
+ }
+
+ /**
+ * Transaction isolation getter.
+ * @return transaction isolation
+ * @throws SQLException
+ */
+ public int getTransactionIsolation()
+ throws SQLException
+ {
+ return connection.getTransactionIsolation();
+ }
+
+ /**
+ * Get SQL warnings.
+ * @return next SQL Warning.
+ * @throws SQLException
+ */
+ public SQLWarning getWarnings()
+ throws SQLException
+ {
+ return connection.getWarnings();
+ }
+
+ /**
+ * Clear SQL warnings.
+ * @throws SQLException
+ */
+ public void clearWarnings()
+ throws SQLException
+ {
+ connection.clearWarnings();
+ }
+
+ /**
+ * Create a statement.
+ *
+ * @param i result set type
+ * @param j result set concurrency
+ * @return new statement
+ * @throws SQLException
+ */
+ public synchronized Statement createStatement(int i, int j)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.createStatement(i, j);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @param i result set type
+ * @param j result set concurrency
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s, int i, int j)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s, i, j);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a call.
+ * @param s SQL query
+ * @param i result set type
+ * @param j result set concurrency
+ * @return callable statement
+ * @throws SQLException
+ */
+ public synchronized CallableStatement prepareCall(String s, int i, int j)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareCall(s, i, j);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Get type map.
+ * @return type map
+ * @throws SQLException
+ */
+ public Map getTypeMap()
+ throws SQLException
+ {
+ return connection.getTypeMap();
+ }
+
+ /**
+ * Set type map.
+ * @param map type map
+ * @throws SQLException
+ */
+ public void setTypeMap(Map map)
+ throws SQLException
+ {
+ connection.setTypeMap(map);
+ }
+
+ /**
+ * Set holdability.
+ * @param i holdability
+ * @throws SQLException
+ */
+ public void setHoldability(int i)
+ throws SQLException
+ {
+ connection.setHoldability(i);
+ }
+
+ /**
+ * Get holdability.
+ * @return holdability
+ * @throws SQLException
+ */
+ public int getHoldability()
+ throws SQLException
+ {
+ return connection.getHoldability();
+ }
+
+ /**
+ * Savepoint setter.
+ * @return save point
+ * @throws SQLException
+ */
+ public synchronized Savepoint setSavepoint()
+ throws SQLException
+ {
+ return connection.setSavepoint();
+ }
+
+ /**
+ * Set named savepoint.
+ * @param s savepoint name
+ * @return savepoint
+ * @throws SQLException
+ */
+ public synchronized Savepoint setSavepoint(String s)
+ throws SQLException
+ {
+ return connection.setSavepoint(s);
+ }
+
+ /**
+ * Rollback.
+ * @param savepoint savepoint
+ * @throws SQLException
+ */
+ public synchronized void rollback(Savepoint savepoint)
+ throws SQLException
+ {
+ connection.rollback(savepoint);
+ }
+ /**
+ * Release savepoint.
+ *
+ * @param savepoint savepoint
+ * @throws SQLException
+ */
+ public synchronized void releaseSavepoint(Savepoint savepoint)
+ throws SQLException
+ {
+ connection.releaseSavepoint(savepoint);
+ }
+
+ /**
+ * Create a statement.
+ * @param i result set type
+ * @param j result set concurrency
+ * @param k result set holdability
+ * @return created statement
+ * @throws SQLException
+ */
+ public synchronized Statement createStatement(int i, int j, int k)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.createStatement(i, j, k);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @param i result set type
+ * @param j result set concurrency
+ * @param k result set holdability
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s, int i, int j, int k)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s, i, j, k);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a callable statement.
+ * @param s SQL query
+ * @param i result set type
+ * @param j result set concurrency
+ * @param k result set holdability
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized CallableStatement prepareCall(String s, int i, int j, int k)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareCall(s, i, j, k);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @param i autogenerated keys
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s, int i)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s, i);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @param ai autogenerated keys column indexes
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s, int ai[])
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s, ai);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @param as autogenerated keys column names
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s, String as[])
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s,as);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Enter busy state.
+ */
+ public void enterBusyState()
+ {
+ //Logger.trace("connection #"+toString()+": entering busy state.");
+ busy++;
+ }
+
+ /**
+ * Leave busy state.
+ */
+ public void leaveBusyState()
+ {
+ lastUse = System.currentTimeMillis();
+ busy--;
+ //Logger.trace("connection #"+toString()+": leaving busy state.");
+ }
+
+ /**
+ * Check busy state.
+ * @return busy state
+ */
+ public boolean isBusy()
+ {
+ return busy>0;
+ }
+
+ /**
+ * Get last use timestamp
+ *
+ * @return last use
+ */
+ public long getLastUse()
+ {
+ return lastUse;
+ }
+
+ /**
+ * Get last inserted ID.
+ *
+ * @param statement
+ * @return last inserted id
+ * @throws SQLException
+ */
+ public long getLastInsertId(Statement statement) throws SQLException
+ {
+ return driver.getLastInsertId(statement);
+ }
+
+ /**
+ * Check connection.
+ *
+ * @return true if the connection is ok
+ */
+ public synchronized boolean check()
+ {
+ try
+ {
+ String checkQuery = driver.getPingQuery();
+ if (checkQuery == null)
+ {
+ // at least, call isOpen
+ if (isClosed())
+ {
+ throw new Exception ("Connection is closed");
+ }
+ }
+ else
+ {
+ if (checkStatement == null)
+ {
+ checkStatement = prepareStatement(checkQuery);
+ }
+ checkStatement.executeQuery();
+ }
+ return true;
+ }
+ catch (Exception e)
+ {
+ Logger.warn("Exception while checking connection!");
+ Logger.info("Refreshing...");
+ return false;
+ }
+ }
+
+ /** Infos on the driver. */
+ private DriverInfo driver = null;
+
+ /** Wrapped connection. */
+ private Connection connection = null;
+
+ /** Busy state. */
+ private int busy = 0;
+
+ /** Last use */
+ private long lastUse = System.currentTimeMillis();
+
+ /** Closed state. */
+ private boolean closed = false;
+
+ /** statement used to check connection ("select 1").
+ */
+ private PreparedStatement checkStatement = null;
+}
Added: velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/ConnectionWrapper.java.jdk6
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/ConnectionWrapper.java.jdk6?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/ConnectionWrapper.java.jdk6 (added)
+++ velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/ConnectionWrapper.java.jdk6 Fri Mar 9 16:23:25 2012
@@ -0,0 +1,1090 @@
+/*
+ * Copyright 2003 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+package org.apache.velocity.velosurf.sql;
+
+import java.lang.reflect.Method;
+import java.sql.*;
+import java.util.Map;
+import java.util.Properties;
+import org.apache.velocity.velosurf.util.Logger;
+
+/**
+ * Connection wrapper class. Allows the handling of a busy state
+ *
+ * @author <a href="mailto:claude.brisson@gmail.com">Claude Brisson</a>
+ */
+
+public class ConnectionWrapper
+ implements Connection
+{
+
+ /**
+ * Constructor.
+ * @param driver infos on the driver
+ * @param connection connection to be wrapped
+ */
+ public ConnectionWrapper(DriverInfo driver,Connection connection)
+ {
+ this.driver = driver;
+ this.connection = connection;
+ }
+
+ /**
+ * Unwrap the connection.
+ * @return the unwrapped connection
+ */
+ public Connection unwrap()
+ {
+ return connection;
+ }
+
+ /**
+ * Create a statement.
+ * @return created statement
+ * @throws SQLException
+ */
+ public Statement createStatement()
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.createStatement();
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a callable statement.
+ * @param s SQL query
+ * @return prepared callable statement
+ * @throws SQLException
+ */
+ public synchronized CallableStatement prepareCall(String s)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareCall(s);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Gets native SQL for a query.
+ * @param s query
+ * @return native SQL
+ * @throws SQLException
+ */
+ public synchronized String nativeSQL(String s)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.nativeSQL(s);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Set autocommit flag.
+ * @param flag autocommit
+ * @throws SQLException
+ */
+ public void setAutoCommit(boolean flag)
+ throws SQLException
+ {
+ connection.setAutoCommit(flag);
+ }
+
+ /**
+ * Get autocommit flag.
+ *
+ * @return autocommit flag
+ * @throws SQLException
+ */
+ public boolean getAutoCommit()
+ throws SQLException
+ {
+ return connection.getAutoCommit();
+ }
+
+ /**
+ * Commit.
+ *
+ * @throws SQLException
+ */
+ public synchronized void commit()
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ connection.commit();
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Rollback.
+ *
+ * @throws SQLException
+ */
+ public synchronized void rollback()
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ connection.rollback();
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Close.
+ *
+ * @throws SQLException
+ */
+ public void close()
+ throws SQLException
+ {
+ // since some sql drivers refuse to close a connection that has been interrupted,
+ // better handle this also ourselves
+ closed = true;
+ connection.close();
+ }
+
+ /**
+ * Check the closed state.
+ * @return closed state
+ * @throws SQLException
+ */
+ public boolean isClosed()
+ throws SQLException
+ {
+ return (closed || connection.isClosed());
+ }
+
+ /**
+ * Get meta data
+ * @return database meta data
+ * @throws SQLException
+ */
+ public DatabaseMetaData getMetaData()
+ throws SQLException
+ {
+ return connection.getMetaData();
+ }
+
+ /**
+ * set read-only flag
+ * @param flag read-only
+ * @throws SQLException
+ */
+ public void setReadOnly(boolean flag)
+ throws SQLException
+ {
+ connection.setReadOnly(flag);
+ }
+
+ /**
+ * Check the read-only state.
+ * @return read-only state
+ * @throws SQLException
+ */
+ public boolean isReadOnly()
+ throws SQLException
+ {
+ return connection.isReadOnly();
+ }
+
+ /**
+ * Catalog setter.
+ * @param s catalog
+ * @throws SQLException
+ */
+ public void setCatalog(String s)
+ throws SQLException
+ {
+ connection.setCatalog(s);
+ }
+
+ /**
+ * Catalog getter.
+ * @return catalog
+ * @throws SQLException
+ */
+
+ public String getCatalog()
+ throws SQLException
+ {
+ return connection.getCatalog();
+ }
+ /**
+ * Transaction isolation setter.
+ * @param i transaction isolation
+ * @throws SQLException
+ */
+
+ public void setTransactionIsolation(int i)
+ throws SQLException
+ {
+ connection.setTransactionIsolation(i);
+ }
+
+ /**
+ * Transaction isolation getter.
+ * @return transaction isolation
+ * @throws SQLException
+ */
+ public int getTransactionIsolation()
+ throws SQLException
+ {
+ return connection.getTransactionIsolation();
+ }
+
+ /**
+ * Get SQL warnings.
+ * @return next SQL Warning.
+ * @throws SQLException
+ */
+ public SQLWarning getWarnings()
+ throws SQLException
+ {
+ return connection.getWarnings();
+ }
+
+ /**
+ * Clear SQL warnings.
+ * @throws SQLException
+ */
+ public void clearWarnings()
+ throws SQLException
+ {
+ connection.clearWarnings();
+ }
+
+ /**
+ * Create a statement.
+ *
+ * @param i result set type
+ * @param j result set concurrency
+ * @return new statement
+ * @throws SQLException
+ */
+ public synchronized Statement createStatement(int i, int j)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.createStatement(i, j);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @param i result set type
+ * @param j result set concurrency
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s, int i, int j)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s, i, j);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a call.
+ * @param s SQL query
+ * @param i result set type
+ * @param j result set concurrency
+ * @return callable statement
+ * @throws SQLException
+ */
+ public synchronized CallableStatement prepareCall(String s, int i, int j)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareCall(s, i, j);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Get type map.
+ * @return type map
+ * @throws SQLException
+ */
+ public Map getTypeMap()
+ throws SQLException
+ {
+ return connection.getTypeMap();
+ }
+
+ /**
+ * Set type map.
+ * @param map type map
+ * @throws SQLException
+ */
+ public void setTypeMap(Map map)
+ throws SQLException
+ {
+ connection.setTypeMap(map);
+ }
+
+ /**
+ * Set holdability.
+ * @param i holdability
+ * @throws SQLException
+ */
+ public void setHoldability(int i)
+ throws SQLException
+ {
+ connection.setHoldability(i);
+ }
+
+ /**
+ * Get holdability.
+ * @return holdability
+ * @throws SQLException
+ */
+ public int getHoldability()
+ throws SQLException
+ {
+ return connection.getHoldability();
+ }
+
+ /**
+ * Savepoint setter.
+ * @return save point
+ * @throws SQLException
+ */
+ public synchronized Savepoint setSavepoint()
+ throws SQLException
+ {
+ return connection.setSavepoint();
+ }
+
+ /**
+ * Set named savepoint.
+ * @param s savepoint name
+ * @return savepoint
+ * @throws SQLException
+ */
+ public synchronized Savepoint setSavepoint(String s)
+ throws SQLException
+ {
+ return connection.setSavepoint(s);
+ }
+
+ /**
+ * Rollback.
+ * @param savepoint savepoint
+ * @throws SQLException
+ */
+ public synchronized void rollback(Savepoint savepoint)
+ throws SQLException
+ {
+ connection.rollback(savepoint);
+ }
+ /**
+ * Release savepoint.
+ *
+ * @param savepoint savepoint
+ * @throws SQLException
+ */
+ public synchronized void releaseSavepoint(Savepoint savepoint)
+ throws SQLException
+ {
+ connection.releaseSavepoint(savepoint);
+ }
+
+ /**
+ * Create a statement.
+ * @param i result set type
+ * @param j result set concurrency
+ * @param k result set holdability
+ * @return created statement
+ * @throws SQLException
+ */
+ public synchronized Statement createStatement(int i, int j, int k)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.createStatement(i, j, k);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @param i result set type
+ * @param j result set concurrency
+ * @param k result set holdability
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s, int i, int j, int k)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s, i, j, k);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a callable statement.
+ * @param s SQL query
+ * @param i result set type
+ * @param j result set concurrency
+ * @param k result set holdability
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized CallableStatement prepareCall(String s, int i, int j, int k)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareCall(s, i, j, k);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @param i autogenerated keys
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s, int i)
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s, i);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @param ai autogenerated keys column indexes
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s, int ai[])
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s, ai);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Prepare a statement.
+ * @param s SQL query
+ * @param as autogenerated keys column names
+ * @return prepared statement
+ * @throws SQLException
+ */
+ public synchronized PreparedStatement prepareStatement(String s, String as[])
+ throws SQLException
+ {
+ try
+ {
+ enterBusyState();
+ return connection.prepareStatement(s,as);
+ }
+ finally
+ {
+ leaveBusyState();
+ }
+ }
+
+ /**
+ * Enter busy state.
+ */
+ public void enterBusyState()
+ {
+ //Logger.trace("connection #"+toString()+": entering busy state.");
+ busy++;
+ }
+
+ /**
+ * Leave busy state.
+ */
+ public void leaveBusyState()
+ {
+ lastUse = System.currentTimeMillis();
+ busy--;
+ //Logger.trace("connection #"+toString()+": leaving busy state.");
+ }
+
+ /**
+ * Check busy state.
+ * @return busy state
+ */
+ public boolean isBusy()
+ {
+ return busy>0;
+ }
+
+ /**
+ * Get last use timestamp
+ *
+ * @return last use
+ */
+ public long getLastUse()
+ {
+ return lastUse;
+ }
+
+ /**
+ * Get last inserted ID.
+ *
+ * @param statement
+ * @return last inserted id
+ * @throws SQLException
+ */
+ public long getLastInsertId(Statement statement) throws SQLException
+ {
+ return driver.getLastInsertId(statement);
+ }
+
+ /**
+ * Check connection.
+ *
+ * @return true if the connection is ok
+ */
+ public synchronized boolean check()
+ {
+ try
+ {
+ String checkQuery = driver.getPingQuery();
+ if (checkQuery == null)
+ {
+ // at least, call isOpen
+ if (isClosed())
+ {
+ throw new Exception ("Connection is closed");
+ }
+ }
+ else
+ {
+ if (checkStatement == null)
+ {
+ checkStatement = prepareStatement(checkQuery);
+ }
+ checkStatement.executeQuery();
+ }
+ return true;
+ }
+ catch (Exception e)
+ {
+ Logger.warn("Exception while checking connection!");
+ Logger.info("Refreshing...");
+ return false;
+ }
+ }
+
+ /** Infos on the driver. */
+ private DriverInfo driver = null;
+
+ /** Wrapped connection. */
+ private Connection connection = null;
+
+ /** Busy state. */
+ private int busy = 0;
+
+ /** Last use */
+ private long lastUse = System.currentTimeMillis();
+
+ /** Closed state. */
+ private boolean closed = false;
+
+ /** statement used to check connection ("select 1").
+ */
+ private PreparedStatement checkStatement = null;
+
+ /*
+ * stores new 1.6 methods using reflection api to ensure backward compatibility
+ */
+
+ static Method _createClob = null;
+ static Method _createBlob = null;
+ static Method _createNClob = null;
+ static Method _createSQLXML = null;
+ static Method _isValid = null;
+ static Method _setClientInfo = null;
+ static Method _setClientInfo2 = null;
+ static Method _getClientInfo = null;
+ static Method _getClientInfo2 = null;
+ static Method _createArrayOf = null;
+ static Method _createStruct = null;
+ static Method _isWrapperFor = null;
+
+ static
+ {
+ try
+ {
+ _createClob = getConnectionMethod("createClob",new Class[]{});
+ _createBlob = getConnectionMethod("createBlob",new Class[]{});
+ _createNClob = getConnectionMethod("createNClob",new Class[]{});
+ _createSQLXML = getConnectionMethod("createSQLXML",new Class[]{});
+ _isValid = getConnectionMethod("isValid",new Class[]{int.class});
+ _setClientInfo = getConnectionMethod("setClientInfo",new Class[]{String.class,String.class});
+ _setClientInfo2 = getConnectionMethod("setClientInfo",new Class[]{Properties.class});
+ _getClientInfo = getConnectionMethod("getClientInfo",new Class[]{});
+ _getClientInfo2 = getConnectionMethod("getClientInfo",new Class[]{String.class});
+ _createArrayOf = getConnectionMethod("createArrayOf",new Class[]{String.class,Class.forName("[Ljava.lang.Object;")});
+ _createStruct = getConnectionMethod("createStruct",new Class[]{String.class,Class.forName("[Ljava.lang.Object;")});
+ _isWrapperFor = getConnectionMethod("isWrapperFor",new Class[]{Class.class});
+ }
+ catch(Exception e)
+ {
+ }
+ }
+
+ static private Method getConnectionMethod(String name,Class[] parameterTypes)
+ {
+ try
+ {
+ return Connection.class.getMethod(name,parameterTypes);
+ }
+ catch(NoSuchMethodException nsme)
+ {
+ return null;
+ }
+ }
+
+ public Clob createClob() throws SQLException
+ {
+ if(_createClob == null)
+ {
+ throw new SQLException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ return (Clob)_createClob.invoke(connection, new Object[] {});
+ }
+ catch(Exception e)
+ {
+ Throwable cause = e.getCause();
+ if (cause == null)
+ {
+ cause = e;
+ }
+ if(cause instanceof SQLException)
+ {
+ throw (SQLException)cause;
+ }
+ else
+ {
+ throw new SQLException(cause);
+ }
+ }
+ }
+ }
+
+ public Blob createBlob() throws SQLException
+ {
+ if(_createBlob == null)
+ {
+ throw new SQLException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ return (Blob)_createBlob.invoke(connection, new Object[] {});
+ }
+ catch(Exception e)
+ {
+ Throwable cause = e.getCause();
+ if (cause == null)
+ {
+ cause = e;
+ }
+ if(cause instanceof SQLException)
+ {
+ throw (SQLException)cause;
+ }
+ else
+ {
+ throw new SQLException(cause);
+ }
+ }
+ }
+ }
+
+ public NClob createNClob() throws SQLException
+ {
+ if(_createNClob == null)
+ {
+ throw new SQLException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ return (NClob)_createNClob.invoke(connection, new Object[] {});
+ }
+ catch(Exception e)
+ {
+ Throwable cause = e.getCause();
+ if (cause == null)
+ {
+ cause = e;
+ }
+ if(cause instanceof SQLException)
+ {
+ throw (SQLException)cause;
+ }
+ else
+ {
+ throw new SQLException(cause);
+ }
+ }
+ }
+ }
+
+ public SQLXML createSQLXML() throws SQLException
+ {
+ if(_createSQLXML == null)
+ {
+ throw new SQLException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ return (SQLXML)_createSQLXML.invoke(connection, new Object[] {});
+ }
+ catch(Exception e)
+ {
+ Throwable cause = e.getCause();
+ if (cause == null)
+ {
+ cause = e;
+ }
+ if(cause instanceof SQLException)
+ {
+ throw (SQLException)cause;
+ }
+ else
+ {
+ throw new SQLException(cause);
+ }
+ }
+ }
+ }
+
+ public boolean isValid(int timeout) throws SQLException
+ {
+ if(_isValid == null)
+ {
+ throw new SQLException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ return (Boolean)_isValid.invoke(connection, new Object[] {timeout});
+ }
+ catch(Exception e)
+ {
+ Throwable cause = e.getCause();
+ if (cause == null)
+ {
+ cause = e;
+ }
+ if(cause instanceof SQLException)
+ {
+ throw (SQLException)cause;
+ }
+ else
+ {
+ throw new SQLException(cause);
+ }
+ }
+ }
+ }
+
+ public void setClientInfo(String name,String value)
+ {
+ if(_setClientInfo == null)
+ {
+ throw new RuntimeException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ _setClientInfo.invoke(connection, new Object[] {name,value});
+ }
+ catch(Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public void setClientInfo(Properties properties)
+ {
+ if(_setClientInfo2 == null)
+ {
+ throw new RuntimeException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ _setClientInfo2.invoke(connection, new Object[] {properties});
+ }
+ catch(Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public Properties getClientInfo() throws SQLException
+ {
+ if(_getClientInfo == null)
+ {
+ throw new SQLException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ return (Properties)_getClientInfo.invoke(connection, new Object[] {});
+ }
+ catch(Exception e)
+ {
+ Throwable cause = e.getCause();
+ if (cause == null)
+ {
+ cause = e;
+ }
+ if(cause instanceof SQLException)
+ {
+ throw (SQLException)cause;
+ }
+ else
+ {
+ throw new SQLException(cause);
+ }
+ }
+ }
+ }
+
+ public String getClientInfo(String name) throws SQLException
+ {
+ if(_getClientInfo2 == null)
+ {
+ throw new SQLException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ return (String)_getClientInfo2.invoke(connection, new Object[] {name});
+ }
+ catch(Exception e)
+ {
+ Throwable cause = e.getCause();
+ if (cause == null)
+ {
+ cause = e;
+ }
+ if(cause instanceof SQLException)
+ {
+ throw (SQLException)cause;
+ }
+ else
+ {
+ throw new SQLException(cause);
+ }
+ }
+ }
+ }
+
+ public Array createArrayOf(String typeName, Object[] elements) throws SQLException
+ {
+ if(_createArrayOf == null)
+ {
+ throw new SQLException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ return (Array)_createArrayOf.invoke(connection, new Object[] {typeName,elements});
+ }
+ catch(Exception e)
+ {
+ Throwable cause = e.getCause();
+ if (cause == null)
+ {
+ cause = e;
+ }
+ if(cause instanceof SQLException)
+ {
+ throw (SQLException)cause;
+ }
+ else
+ {
+ throw new SQLException(cause);
+ }
+ }
+ }
+ }
+
+ public Struct createStruct(String typeName, Object[] attributes) throws SQLException
+ {
+ if(_createStruct == null)
+ {
+ throw new SQLException("Unsupported method.");
+ }
+ else
+ {
+ try
+ {
+ return (Struct)_createStruct.invoke(connection, new Object[] {typeName,attributes});
+ }
+ catch(Exception e)
+ {
+ Throwable cause = e.getCause();
+ if (cause == null)
+ {
+ cause = e;
+ }
+ if(cause instanceof SQLException)
+ {
+ throw (SQLException)cause;
+ }
+ else
+ {
+ throw new SQLException(cause);
+ }
+ }
+ }
+ }
+
+ public boolean isWrapperFor(Class<?> iface) throws SQLException
+ {
+ throw new SQLException("Unsupported method.");
+ }
+
+ public <T> T unwrap(Class<T> iface) throws SQLException
+ {
+ throw new SQLException("Unsupported method.");
+ }
+}
Added: velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/Database.java
URL: http://svn.apache.org/viewvc/velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/Database.java?rev=1298906&view=auto
==============================================================================
--- velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/Database.java (added)
+++ velocity/sandbox/velosurf/src/java/org/apache/velocity/velosurf/sql/Database.java Fri Mar 9 16:23:25 2012
@@ -0,0 +1,1148 @@
+/*
+ * Copyright 2003 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+package org.apache.velocity.velosurf.sql;
+
+import java.io.*;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.*;
+import org.apache.velocity.velosurf.cache.Cache;
+import org.apache.velocity.velosurf.context.RowIterator;
+import org.apache.velocity.velosurf.model.Attribute;
+import org.apache.velocity.velosurf.model.Entity;
+import org.apache.velocity.velosurf.model.Action;
+import org.apache.velocity.velosurf.util.Logger;
+import org.apache.velocity.velosurf.util.LineWriterOutputStream;
+import org.apache.velocity.velosurf.util.Cryptograph;
+import org.apache.velocity.velosurf.util.XIncludeResolver;
+import org.apache.velocity.velosurf.util.UserContext;
+
+/**
+ * This class encapsulates a connection to the database and contains all the stuff relative to it.
+ *
+ * <p>To get a new instance, client classes should call one of the getInstance static methods.</p>
+ *
+ * @author <a href=mailto:claude.brisson@gmail.com>Claude Brisson</a>
+ *
+ */
+public class Database
+{
+ /**
+ * Builds a new connection.
+ */
+ private Database()
+ {
+ }
+
+ /**
+ * Builds a new connection.
+ *
+ * @param user user name
+ * @param password password
+ * @param url database url
+ * @param driver driver java class name
+ * @param schema schema name to use
+ * @exception SQLException thrown by the database engine
+ */
+ private Database(String user,String password,String url,String driver,String schema) throws SQLException
+ {
+ open(user,password,url,driver,schema);
+ }
+
+ /**
+ * Get a unique Database from connection params.
+ *
+ * @param user user name
+ * @param password password
+ * @param url database url
+ * @exception SQLException thrown by the database engine
+ * @return a new connection
+ */
+ public static Database getInstance(String user,String password,String url) throws SQLException
+ {
+ return getInstance(user,password,url,null,null);
+ }
+
+ /**
+ * Get a unique Database from connection params.
+ *
+ * @param user user name
+ * @param password password
+ * @param url database url
+ * @param driver driver java class name
+ * @exception SQLException thrown by the database engine
+ * @return a new connection
+ */
+ public static Database getInstance(String user,String password,String url,String driver) throws SQLException
+ {
+ return getInstance(user,password,url,driver,null);
+ }
+
+ /**
+ * Get a unique Database from connection params.
+ *
+ * @param user user name
+ * @param password password
+ * @param url database url
+ * @param driver driver java class name
+ * @param schema schema
+ * @exception SQLException thrown by the database engine
+ * @return a new connection
+ */
+ public static Database getInstance(String user,String password,String url,String driver,String schema) throws SQLException
+ {
+ Integer hash = Integer.valueOf((user==null?0:user.hashCode()) ^ (password==null?0:password.hashCode()) ^ url.hashCode() ^ (driver==null?0:driver.hashCode()) ^ (schema==null?0:schema.hashCode()) );
+ Database instance = (Database)connectionsByParams.get(hash);
+ if (instance == null)
+ {
+ instance = new Database(user,password,url,driver,schema);
+ connectionsByParams.put(hash,instance);
+ }
+ return instance;
+ }
+
+ /**
+ * Get a unique Database from config filename.
+ *
+ * @param configFilename config filename
+ * @exception SQLException thrown by the database engine
+ * @return a new connection
+ */
+ public static Database getInstance(String configFilename) throws SQLException,FileNotFoundException,IOException
+ {
+ Integer hash = Integer.valueOf(configFilename.hashCode());
+ Database instance = (Database)connectionsByConfigFile.get(hash);
+ if (instance == null)
+ {
+ String base = null;
+ configFilename = configFilename.replace('\\','/');
+ int i = configFilename.lastIndexOf('/');
+ if (i == -1)
+ {
+ base = ".";
+ }
+ else
+ {
+ base = configFilename.substring(0,i);
+ }
+ instance = getInstance(new FileInputStream(configFilename),new XIncludeResolver(base));
+ connectionsByConfigFile.put(hash,instance);
+ }
+ return instance;
+ }
+
+ /**
+ * Get a new connection.
+ * @param config config filename
+ * @exception SQLException thrown by the database engine
+ * @return a new connection
+ */
+ public static Database getInstance(InputStream config) throws SQLException
+ {
+ return Database.getInstance(config,null);
+ }
+
+ /**
+ * Get a new connection.
+ * @param config config filename
+ * @exception SQLException thrown by the database engine
+ * @return a new connection
+ */
+ public static Database getInstance(InputStream config,XIncludeResolver xincludeResolver) throws SQLException
+ {
+ Database instance = new Database();
+ instance.readConfigFile(config,xincludeResolver);
+ instance.initCryptograph();
+ instance.connect();
+ instance.getReverseEngineer().readMetaData();
+
+ // startup action
+ Action startup = instance.getRootEntity().getAction("startup");
+ if (startup != null)
+ {
+ startup.perform(null);
+ }
+
+ return instance;
+ }
+
+ /**
+ * Open the connection.
+ *
+ * @param user user name
+ * @param password password
+ * @param url database url
+ * @param driver driver java class name
+ * @param schema schema name
+ * @exception SQLException thrown by the database engine
+ */
+ private void open(String user,String password,String url,String driver,String schema) throws SQLException
+ {
+
+ this.user = user;
+ this.password = password;
+ this.url = url;
+ this.schema = schema;
+ driverClass = driver;
+ initCryptograph();
+ connect();
+ getReverseEngineer().readMetaData();
+ }
+
+ /**
+ * Connect the database.
+ *
+ * @throws SQLException
+ */
+ private void connect() throws SQLException
+ {
+ Logger.info("opening database "+url+" for user "+user+(schema == null?"":" using schema "+schema));
+
+ loadDriver();
+
+ connectionPool = new ConnectionPool(url,user,password,schema,driverInfo,true,minConnections,maxConnections);
+ transactionConnectionPool = new ConnectionPool(url,user,password,schema,driverInfo,false,1,maxConnections);
+
+ statementPool = new StatementPool(connectionPool,checkConnections,checkInterval);
+ preparedStatementPool = new PreparedStatementPool(connectionPool,checkConnections,checkInterval);
+
+ transactionStatementPool = new StatementPool(transactionConnectionPool,checkConnections,checkInterval);
+ transactionPreparedStatementPool = new PreparedStatementPool(transactionConnectionPool,checkConnections,checkInterval);
+
+ if(rootEntity == null)
+ {
+ Entity root = new Entity(this,"velosurf.root",false,Cache.NO_CACHE);
+ addEntity(root);
+ }
+ }
+
+ /**
+ * Set the read-only state.
+ * @param readOnly read-only state
+ */
+ public void setReadOnly(boolean readOnly)
+ {
+ this.readOnly = readOnly;
+ }
+
+ /**
+ * Set the caching method.
+ * @param cachingMethod caching method
+ */
+ public void setCaching(int cachingMethod)
+ {
+ caching = cachingMethod;
+ }
+
+ /** Set the database user.
+ *
+ * @param user user name.
+ */
+ public void setUser(String user)
+ {
+ this.user = user;
+ }
+
+ /**
+ * Set the database password.
+ * @param password password
+ */
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ /**
+ * Set the database URL.
+ * @param url database url
+ */
+ public void setURL(String url)
+ {
+ this.url = url;
+ }
+
+ /**
+ * Set driver class.
+ * @param driverClass driver class
+ */
+ public void setDriver(String driverClass)
+ {
+ this.driverClass = driverClass;
+ }
+
+ /**
+ * Set schema name.
+ * @param schema schema name
+ */
+ public void setSchema(String schema)
+ {
+ this.schema = schema;
+ if(this.schema != null)
+ {
+ // share entities
+ sharedCatalog.put(getMagicNumber(this.schema),entities);
+ }
+ }
+
+ /**
+ * Set minimum number of connections.
+ * @param minConnections minimum number of connections
+ */
+ public void setMinConnections(int minConnections)
+ {
+ this.minConnections = minConnections;
+ }
+
+ /**
+ * Set the maximum number of connections.
+ * @param maxConnections maximum number of connections
+ */
+ public void setMaxConnections(int maxConnections)
+ {
+ this.maxConnections = maxConnections;
+ }
+
+ /**
+ * Set the encryption seed.
+ * @param seed encryption seed
+ */
+ public void setSeed(String seed)
+ {
+ this.seed = seed;
+ }
+
+ /**
+ * Set the case policy.
+ * Possible values are CASE_SENSITIVE, CASE_LOWERCASE and CASE_UPPERCASE.
+ * @param caseSensivity case policy
+ */
+ public void setCase(int caseSensivity)
+ {
+ this.caseSensivity = caseSensivity;
+ }
+
+ /**
+ * Set whether or not connections are to be checked or not
+ * @param checkConnections read-only check or not
+ */
+ public void setCheckConnections(boolean checkConnections)
+ {
+ this.checkConnections = checkConnections;
+ }
+
+ /**
+ * Set the minimum check interval (in milliseconds)
+ * - connections are only checked when their last use
+ * is older than this interval.
+ * @param checkInterval
+ */
+ public void setCheckInterval(long checkInterval)
+ {
+ this.checkInterval = checkInterval;
+ }
+
+ /**
+ * oad the appropriate driver.
+ */
+ @SuppressWarnings("deprecation") protected void loadDriver()
+ {
+ if (driverLoaded)
+ {
+ return;
+ }
+
+ if (Logger.getLogLevel() == Logger.TRACE_ID)
+ {
+ /* Initialize log */
+ DriverManager.setLogWriter(Logger.getWriter()); /* -> doesn't work with jdbc 1.0 drivers
+ * so use the deprecated form
+ * TODO: detect driver jdbc conformance
+ */
+/* if(Logger.getLogLevel() <= Logger.DEBUG_ID) {
+Logger.debug("setting driver manager log");
+ DriverManager.setLogStream(new PrintStream(new LineWriterOutputStream(Logger.getWriter())));
+ }*/
+ }
+
+ /* driver behaviour */
+ driverInfo = DriverInfo.getDriverInfo(url,driverClass);
+
+ reverseEngineer.setDriverInfo(driverInfo);
+
+ if (driverClass!=null)
+ {
+ try
+ {
+ Logger.debug("loading class "+driverClass);
+ Class.forName(driverClass);
+ driverLoaded = true;
+ }
+ catch (Exception e)
+ {
+ Logger.log(e);
+ }
+ }
+ else if (driverInfo != null)
+ {
+ // try to load one of the known drivers
+ String[] drivers = driverInfo.getDrivers();
+ for (int i=0;i<drivers.length;i++)
+ try
+ {
+ Class.forName(drivers[i]);
+ driverLoaded = true;
+ break;
+ }
+ catch (Exception e) {}
+ }
+ }
+
+ /**
+ * Init cryptograph.
+ *
+ */
+ protected void initCryptograph()
+ {
+ if (cryptograph != null) return;
+ // to initialize the cryptograph, we need a chunk of user-provided bytes
+ // they must be persistent, so that urls that use encrypted params remain valid
+ // => use the database url if null
+ if (seed == null)
+ {
+ seed = url;
+ }
+ try
+ {
+ cryptograph = (Cryptograph)Class.forName("org.apache.velocity.velosurf.util.DESCryptograph").getDeclaredConstructor(new Class[] {}).newInstance(new Object[] {});
+ cryptograph.init(seed);
+ }
+ catch(Exception e)
+ {
+ Logger.error("Cannot initialize the cryptograph");
+ Logger.log(e);
+ }
+ }
+
+ /**
+ * Get reverse engineer.
+ * @return reverse engineer.
+ */
+ public ReverseEngineer getReverseEngineer()
+ {
+ return reverseEngineer;
+ }
+
+ /**
+ * Issue a query.
+ *
+ * @param query an SQL query
+ * @return the resulting RowIterator
+ */
+ public RowIterator query(String query) throws SQLException
+ {
+ return query(query,null);
+ }
+
+ /**
+ * Issue a query, knowing the resulting entity.
+ *
+ * @param query an SQL query
+ * @param entity the resulting entity
+ * @return return the resulting row iterator
+ */
+ public RowIterator query(String query,Entity entity) throws SQLException
+ {
+ PooledSimpleStatement statement = null;
+ statement=statementPool.getStatement();
+ return statement.query(query,entity == null ? getRootEntity() : entity);
+ }
+
+ /**
+ * Evaluate a query to a scalar.
+ *
+ * @param query an sql query
+ * @return the resulting scalar
+ */
+ public Object evaluate(String query)
+ {
+ PooledSimpleStatement statement = null;
+ try
+ {
+ statement=statementPool.getStatement();
+ return statement.evaluate(query);
+ }
+ catch (SQLException sqle)
+ {
+ Logger.log(sqle);
+ return null;
+ }
+ }
+
+ /**
+ * Prepare a query.
+ *
+ * @param query an sql query
+ * @return the pooled prepared statement corresponding to the query
+ */
+ public PooledPreparedStatement prepare(String query)
+ {
+ PooledPreparedStatement statement = null;
+ try
+ {
+ statement = preparedStatementPool.getPreparedStatement(query);
+ return statement;
+ }
+ catch (SQLException sqle)
+ {
+ Logger.log(sqle);
+ return null;
+ }
+ }
+
+ /**
+ * Prepare a query which is part of a transaction.
+ *
+ * @param query an sql query
+ * @return the prepared statemenet corresponding to the query
+ */
+ public PooledPreparedStatement transactionPrepare(String query)
+ {
+ PooledPreparedStatement statement = null;
+ try
+ {
+ statement = transactionPreparedStatementPool.getPreparedStatement(query);
+ return statement;
+ }
+ catch (SQLException sqle)
+ {
+ Logger.log(sqle);
+ return null;
+ }
+ }
+
+ /**
+ * Issue an update query.
+ *
+ * @param query an sql query
+ * @return the number of affected rows
+ */
+ public int update(String query)
+ {
+ try
+ {
+ PooledSimpleStatement statement = statementPool.getStatement();
+ return statement.update(query);
+ }
+ catch (SQLException sqle)
+ {
+ Logger.log(sqle);
+ return -1;
+ }
+ }
+
+ /**
+ * Issue an update query that is part of a transaction.
+ *
+ * @param query an sql query
+ * @return the number of affected rows
+ */
+ public int transactionUpdate(String query)
+ {
+ try
+ {
+ PooledSimpleStatement statement = transactionStatementPool.getStatement();
+ return statement.update(query);
+ }
+ catch (SQLException sqle)
+ {
+ Logger.log(sqle);
+ return -1;
+ }
+ }
+
+ /**
+ * Close the connection.
+ *
+ * @exception SQLException thrown by the database engine
+ */
+ public void close() throws SQLException
+ {
+ connectionPool.clear();
+ connectionPool = null;
+ transactionConnectionPool.clear();
+ transactionConnectionPool = null;
+ statementPool.clear();
+ statementPool = null;
+ transactionStatementPool.clear();
+ transactionStatementPool = null;
+ preparedStatementPool.clear();
+ preparedStatementPool = null;
+ transactionPreparedStatementPool.clear();
+ transactionPreparedStatementPool = null;
+ }
+
+ /**
+ * Display statistics about the statements pools.
+ */
+ public void displayStats()
+ {
+ System.out.println("DB statistics:");
+ int [] normalStats = statementPool.getUsageStats();
+ int [] preparedStats = preparedStatementPool.getUsageStats();
+ System.out.println("\tsimple statements - "+normalStats[0]+" free statements out of "+normalStats[1]);
+ System.out.println("\tprepared statements - "+preparedStats[0]+" free statements out of "+preparedStats[1]);
+ }
+
+ /**
+ * Get a jdbc connection.
+ *
+ * @return a jdbc connection wrapper (which extends java.sql.Connection)
+ */
+ public ConnectionWrapper getConnection() throws SQLException
+ {
+ ConnectionWrapper c = connectionPool.getConnection();
+ c.setReadOnly(readOnly);
+ return c;
+ }
+
+ /**
+ * Get the underlying jdbc connection used for transactions, and mark it right away as busy.
+ *
+ * @return a jdbc connection wrapper (which extends java.sql.Connection)
+ */
+ public synchronized ConnectionWrapper getTransactionConnection() throws SQLException {
+ ConnectionWrapper ret = transactionConnectionPool.getConnection();
+ ret.setReadOnly(readOnly);
+ ret.enterBusyState();
+ return ret;
+ }
+
+ /**
+ * Read model configuration from the given input stream.
+ *
+ * @param config input stream on the config file
+ */
+ private void readConfigFile(InputStream config,XIncludeResolver xincludeResolver)
+ {
+ try
+ {
+ new ConfigLoader(this,xincludeResolver).loadConfig(config);
+ }
+ catch (Exception e)
+ {
+ Logger.error("could not load model!");
+ Logger.log(e);
+ }
+ }
+
+ /**
+ * Changes to lowercase or uppercase if needed.
+ *
+ * @param identifier
+ * @return changed identifier
+ */
+ public String adaptCase(String identifier)
+ {
+ if (identifier == null)
+ {
+ return null;
+ }
+ String ret;
+ switch(caseSensivity)
+ {
+ case CASE_SENSITIVE:
+ case CASE_UNKNOWN:
+ ret = identifier;
+ break;
+ case UPPERCASE:
+ ret = identifier.toUpperCase();
+ break;
+ case LOWERCASE:
+ ret = identifier.toLowerCase();
+ break;
+ default:
+ Logger.error("bad case-sensivity!");
+ ret = identifier;
+ }
+ return ret;
+ }
+
+ /**
+ * Add a new entity.
+ *
+ * @param entity entity to add
+ */
+ public void addEntity(Entity entity)
+ {
+ String name = entity.getName();
+ Entity previous = entities.put(adaptCase(name),entity);
+ if (previous != null)
+ {
+ Logger.warn("replacing an existing entity with a new one ("+name+")");
+ }
+ if(name.equals("velosurf.root"))
+ {
+ /* this is the root entity */
+ rootEntity = entity;
+ }
+ }
+
+ /**
+ * Get root entity.
+ * @return root entity
+ */
+ public Entity getRootEntity()
+ {
+ return rootEntity;
+ }
+
+ /**
+ * Get a named entity or creeate it if it doesn't exist
+ *
+ * @param name name of an entity
+ * @return the named entity
+ */
+ public Entity getEntityCreate(String name)
+ {
+ Entity entity = getEntity(name);
+ if (entity == null)
+ {
+ Logger.trace("Created entity: "+name);
+ entity = new Entity(this,name,readOnly,caching);
+ entities.put(adaptCase(name),entity);
+ }
+ return entity;
+ }
+
+ /**
+ * Get an existing entity.
+ *
+ * @param name the name of an entity
+ * @return the named entity
+ */
+ public Entity getEntity(String name)
+ {
+ int i;
+ Entity entity=(Entity)entities.get(adaptCase(name));
+ if (entity == null && name != null && (i=name.indexOf('.')) != -1)
+ {
+ // imported from another schema ?
+ String schema = name.substring(0,i);
+ name = name.substring(i+1);
+ Map external = (Map)sharedCatalog.get(getMagicNumber(schema));
+ if (external != null)
+ {
+ entity = (Entity)external.get(name);
+ }
+ }
+ return entity;
+ }
+
+ /**
+ * Entities map getter.
+ *
+ * @return entities map
+ */
+ public Map<String,Entity> getEntities()
+ {
+ return entities;
+ }
+
+ /**
+ * Get a root attribute.
+ *
+ * @param name name of an attribute
+ * @return the named attribute
+ */
+ public Attribute getAttribute(String name)
+ {
+ return rootEntity.getAttribute(adaptCase(name));
+ }
+
+ /**
+ * Get a root action.
+ *
+ * @param name name of an attribute
+ * @return the named attribute
+ */
+ public Action getAction(String name)
+ {
+ return rootEntity.getAction(adaptCase(name));
+ }
+
+ /**
+ * Obfuscate the given value.
+ * @param value value to obfuscate
+ *
+ * @return obfuscated value
+ */
+ public String obfuscate(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ String encoded = cryptograph.encrypt(value.toString());
+
+ // we want to avoid some characters fot HTTP GET
+ encoded = encoded.replace('=','$');
+ encoded = encoded.replace('/','_');
+ encoded = encoded.replace('+','-');
+
+ return encoded;
+ }
+
+ /**
+ * De-obfuscate the given value.
+ * @param value value to de-obfuscate
+ *
+ * @return obfuscated value
+ */
+ public String deobfuscate(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+
+ String ret = value.toString();
+
+ // recover exact encoded string
+ ret = ret.replace('$','=');
+ ret = ret.replace('_','/');
+ ret = ret.replace('-','+');
+
+ ret = cryptograph.decrypt(ret);
+
+ if (ret == null)
+ {
+ Logger.error("deobfuscation of value '"+value+"' failed!");
+ return null;
+ }
+
+ return ret;
+ }
+
+ /**
+ * Get database driver infos.
+ * @return the database vendor
+ */
+ public DriverInfo getDriverInfo()
+ {
+ return driverInfo;
+ }
+
+ /**
+ * Get database case-sensivity policy.
+ *
+ * @return case-sensivity
+ */
+ public int getCaseSensivity()
+ {
+ return caseSensivity;
+ }
+
+ /**
+ * Get the integer key used to share schema entities among instances.
+ */
+ private Integer getMagicNumber(String schema)
+ {
+ // url is not checked for now because for some databases, the schema is part of the url.
+ return Integer.valueOf((user/*+url*/+schema).hashCode());
+ }
+
+ /**
+ * Get the schema.
+ * @return the schema
+ */
+ public String getSchema()
+ {
+ return schema;
+ }
+
+ /**
+ * Database user.
+ */
+ private String user = null;
+
+ /**
+ * Database user's password.
+ */
+ private String password = null;
+
+ /**
+ * Database url.
+ */
+ private String url = null;
+
+ /**
+ * Schema.
+ */
+ private String schema = null;
+
+ /**
+ * Whether the JDBC driver has been loaded.
+ */
+ private boolean driverLoaded = false;
+
+ /**
+ * Driver class name, if provided in the config file.
+ */
+ private String driverClass = null;
+
+ /**
+ * Pool of connections.
+ */
+ private ConnectionPool connectionPool = null;
+
+ /**
+ * Min connections.
+ */
+ private int minConnections = 1; // applies to connectionPool (min connections is always 1 for transactionConnectionPool)
+
+ /**
+ * Max connections.
+ */
+ private int maxConnections = 50; // applies to connectionPool and transactionConnectionPool
+
+ /**
+ * Pool of connections for transactions.
+ */
+ private ConnectionPool transactionConnectionPool = null;
+
+ /**
+ * Pool of statements.
+ */
+ private StatementPool statementPool = null;
+
+ /**
+ * Pool of statements for transactions.
+ */
+ private StatementPool transactionStatementPool = null;
+
+ /**
+ * Pool of prepared statements.
+ */
+ private PreparedStatementPool preparedStatementPool = null;
+
+ /**
+ * Pool of prepared statements for transactions.
+ */
+ private PreparedStatementPool transactionPreparedStatementPool = null;
+
+ /**
+ * Default access mode.
+ */
+ private boolean readOnly = true;
+
+ /**
+ * Default connections checking
+ */
+ private boolean checkConnections = true;
+
+ /**
+ * Default check interval
+ */
+ private long checkInterval = 1000 * 60 * 10; // 10 minutes by default
+
+ /**
+ * Default caching mode.
+ */
+ private int caching = Cache.NO_CACHE;
+
+ /**
+ * Map name->entity.
+ */
+ private Map<String,Entity> entities = new HashMap<String,Entity>();
+
+ /**
+ * Root entity that contains all root attributes and actions.
+ */
+ private Entity rootEntity = null;
+
+ /**
+ * Driver infos (database vendor specific).
+ */
+ private DriverInfo driverInfo = null;
+
+ /**
+ * Random seed used to initialize the cryptograph.
+ */
+ private String seed = null;
+
+ /**
+ * Cryptograph used to encrypt/decrypt database ids.
+ */
+ private Cryptograph cryptograph = null;
+
+ /**
+ * 'unknown' case-sensitive policy.
+ */
+ public static final int CASE_UNKNOWN = 0;
+
+ /**
+ * 'sensitive' case-sensitive policy.
+ */
+ public static final int CASE_SENSITIVE = 1;
+
+ /**
+ * 'uppercase' case-sensitive policy.
+ */
+ public static final int UPPERCASE = 2;
+
+ /**
+ * 'lowercase' case-sensitive policy.
+ */
+ public static final int LOWERCASE = 3;
+
+ /**
+ * Case-sensivity.
+ */
+ private int caseSensivity = CASE_UNKNOWN;
+
+ /**
+ * Case-sensivity for context.
+ */
+ private static int contextCase = CASE_SENSITIVE;
+
+ /* context case implemented as a system property for now...
+ *TODO: check also other model configuration realms or use model.xml
+ */
+ static
+ {
+ String contextCase = System.getProperty("velosurf.case");
+ if (contextCase != null)
+ {
+ if ("uppercase".equals(contextCase))
+ {
+ Database.contextCase = UPPERCASE;
+ }
+ else if ("lowercase".equals(contextCase))
+ {
+ Database.contextCase = LOWERCASE;
+ }
+ else if("sensitive".equals(contextCase))
+ {
+ Database.contextCase = CASE_SENSITIVE;
+ }
+ else
+ {
+ Logger.error("system property 'velosurf.case' should be 'lowercase', 'uppercase' or 'sensitive'");
+ }
+ }
+ }
+
+ /**
+ * Adapt a string to the context case.
+ *
+ * @param str string to adapt
+ * @return adapted string
+ */
+ public static String adaptContextCase(String str)
+ {
+ if(str == null)
+ {
+ return null;
+ }
+ switch(contextCase)
+ {
+ case LOWERCASE:
+ return str.toLowerCase();
+ case UPPERCASE:
+ return str.toUpperCase();
+ case CASE_SENSITIVE:
+ return str;
+ default:
+ Logger.error("unknown context case policy!");
+ return str;
+ }
+ }
+
+ /**
+ * Set this database user context (thread local)
+ * @param userContext user context
+ */
+ public void setUserContext(UserContext userContext)
+ {
+ this.userContext.set(userContext);
+ }
+
+ /**
+ * Get this database user context (thread local)
+ *
+ * @return the thread local user context
+ */
+ public UserContext getUserContext()
+ {
+ UserContext ret = userContext.get();
+ if (ret == null)
+ {
+ /* create one */
+ ret = new UserContext();
+ userContext.set(ret);
+ }
+ return ret;
+ }
+
+ /**
+ * Set error message.
+ */
+ public void setError(String errormsg)
+ {
+ getUserContext().setError(errormsg);
+ }
+
+ /**
+ * Map parameters -> instances.
+ */
+ private static Map<Integer,Database> connectionsByParams = new HashMap<Integer,Database>();
+
+ /**
+ * Map config files -> instances.
+ */
+ private static Map<Integer,Database> connectionsByConfigFile = new HashMap<Integer,Database>();
+
+ /**
+ * <p>Shared catalog, to share entities among instances.</p>
+ *
+ * <p>Key is hashcode of (name+password+url+schema), value is an entities map.</p>
+ */
+ private static Map<Integer,Map<String,Entity>> sharedCatalog = new HashMap<Integer,Map<String,Entity>>();
+
+ /**
+ * Reverse engineer.
+ */
+ private ReverseEngineer reverseEngineer = new ReverseEngineer(this);
+
+ /**
+ * Thread-local user context.
+ */
+ private ThreadLocal<UserContext> userContext = new ThreadLocal<UserContext>();
+
+ /**
+ * Driver specific value filter
+ *
+ * @param value value to be filtered
+ * @return filtered value
+ */
+ public Object filterParam(Object value)
+ {
+ return driverInfo.filterValue(value);
+ }
+}