You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2007/09/11 09:39:11 UTC

svn commit: r574496 - /myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/

Author: skitching
Date: Tue Sep 11 00:39:10 2007
New Revision: 574496

URL: http://svn.apache.org/viewvc?rev=574496&view=rev
Log:
Save old code that was deleted from the core module. It might be useful some day.

Added:
    myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/
    myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/AbstractConnectionManagerListener.java
    myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerDataSource.java
    myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerListener.java
    myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnection.java
    myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnectionFactory.java
    myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/package.html

Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/AbstractConnectionManagerListener.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/AbstractConnectionManagerListener.java?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/AbstractConnectionManagerListener.java (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/AbstractConnectionManagerListener.java Tue Sep 11 00:39:10 2007
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.myfaces.orchestra.connectionManager;
+
+import java.sql.Connection;
+
+/**
+ * @see ConnectionManagerListener  
+ */
+public abstract class AbstractConnectionManagerListener implements ConnectionManagerListener
+{
+	public void borrowConnection(Connection con)
+	{
+	}
+
+	public void releaseConnection(Connection con)
+	{
+	}
+}

Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerDataSource.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerDataSource.java?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerDataSource.java (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerDataSource.java Tue Sep 11 00:39:10 2007
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.myfaces.orchestra.connectionManager;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Manage all borrowed connections and hand out
+ * {@link org.apache.myfaces.orchestra.connectionManager.DisconnectableConnection}
+ * objects so that we can close them again after the HTTP request has been finished.
+ * <p>
+ * This datasource can be configured as a "wrapper" for a real datasource. When a connection is
+ * requested from this object, a proxy is returned that simply forwards all calls transparently
+ * to the real connection. This manager keeps track of all the Connections borrowed by each
+ * thread. At some point (eg from a servlet filter) this object can be asked to check for 
+ * unreturned connections held by the current thread. If any exist then the real connection
+ * is returned to the underlying datasource and the proxy's connection reference is set to null.
+ * This ensures that a thread cannot leak real database connections.
+ * <p>
+ * Of course all code should return its connections; this is only a workaround/hack useful when the
+ * real problem cannot be fixed. This is particularly useful for JPA implementations that do not free
+ * their connection again after a lazy-init.
+ *
+ * @see org.apache.myfaces.orchestra.connectionManager.DisconnectableConnection
+ */
+public class ConnectionManagerDataSource implements DataSource
+{
+	private DataSource dataSource;
+	private String jndiName;
+	private ConnectionManagerListener[] listeners;
+
+	// List of connections that have been borrowed by this thread but not returned.
+	// When using a threadpool, it is required that the releaseAllBorrowedConnections
+	// method be called before the thread is returned to the pool; that ensures this
+	// threadlocal is reset to null.
+	private static ThreadLocal borrowedConnections = new ThreadLocal()
+	{
+		protected Object initialValue()
+		{
+			return new HashSet();
+		}
+	};
+
+	public ConnectionManagerDataSource()
+	{
+	}
+
+	void onAfterBorrowConnection(Connection con)
+	{
+		((Set) borrowedConnections.get()).add(con);
+
+		if (listeners != null)
+		{
+			for (int i = 0; i<listeners.length; i++)
+			{
+				listeners[i].borrowConnection(con);
+			}
+		}
+	}
+
+	public void onBeforeReleaseConnection(Connection con)
+	{
+		if (listeners != null)
+		{
+			for (int i = 0; i<listeners.length; i++)
+			{
+				listeners[i].releaseConnection(con);
+			}
+		}
+	}
+
+	void onAfterReleaseConnection(Connection con)
+	{
+		((Set) borrowedConnections.get()).remove(con);
+	}
+
+	public static void releaseAllBorrowedConnections()
+	{
+		DisconnectableConnection[] connections = new DisconnectableConnection[((Set) borrowedConnections.get()).size()];
+		((Set) borrowedConnections.get()).toArray(connections);
+
+		for (int i = 0; i<connections.length; i++)
+		{
+			DisconnectableConnection connection = connections[i];
+			connection.disconnect();
+		}
+
+		((Set) borrowedConnections.get()).clear();
+	}
+
+	public void setListeners(ConnectionManagerListener[] listeners)
+	{
+		this.listeners = listeners;
+	}
+
+	public void setDataSource(DataSource dataSource)
+	{
+		this.dataSource = dataSource;
+	}
+
+	public DataSource getDataSource()
+	{
+		if (dataSource != null)
+		{
+			return dataSource;
+		}
+
+		try
+		{
+			Context ctx = new InitialContext();
+			dataSource = (DataSource) ctx.lookup(jndiName);
+		}
+		catch (NamingException e)
+		{
+			throw (IllegalArgumentException) new IllegalArgumentException(jndiName).initCause(e);
+		}
+
+		return dataSource;
+	}
+
+	public void setJndiName(String jndiName)
+	{
+		this.jndiName = jndiName;
+	}
+
+	public Connection getConnection() throws SQLException
+	{
+		return DisconnectableConnectionFactory.create(this);
+	}
+
+	public Connection getConnection(String username, String password) throws SQLException
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	public PrintWriter getLogWriter() throws SQLException
+	{
+		return getDataSource().getLogWriter();
+	}
+
+	public void setLogWriter(PrintWriter out) throws SQLException
+	{
+		getDataSource().setLogWriter(out);
+	}
+
+	public void setLoginTimeout(int seconds) throws SQLException
+	{
+		getDataSource().setLoginTimeout(seconds);
+	}
+
+	public int getLoginTimeout() throws SQLException
+	{
+		return getDataSource().getLoginTimeout();
+	}
+
+	public Object unwrap(Class iface) throws SQLException
+	{
+		throw new UnsupportedOperationException();
+		/*
+		try
+		{
+			if (iface.isAssignableFrom(dataSource.getClass()))
+			{
+				return dataSource;
+			}
+
+			Method method = dataSource.getClass().getMethod("unwrap", new Class[]{Class.class});
+			return method.invoke(dataSource, new Object[] { iface });
+		}
+		catch (NoSuchMethodException e)
+		{
+			throw new UnsupportedOperationException();
+		}
+		catch (IllegalAccessException e)
+		{
+			throw new SQLException(e);
+		}
+		catch (InvocationTargetException e)
+		{
+			throw new SQLException(e);
+		}
+		*/
+	}
+
+	public boolean isWrapperFor(Class iface) throws SQLException
+	{
+		throw new UnsupportedOperationException();
+
+		/*
+		try
+		{
+			if (iface.isAssignableFrom(dataSource.getClass()))
+			{
+				return true;
+			}
+			Method method = dataSource.getClass().getMethod("isWrapperFor", new Class[]{Class.class});
+			return Boolean.TRUE.equals(method.invoke(dataSource, new Object[] { iface }));
+		}
+		catch (NoSuchMethodException e)
+		{
+			throw new UnsupportedOperationException();
+		}
+		catch (IllegalAccessException e)
+		{
+			throw new SQLException(e);
+		}
+		catch (InvocationTargetException e)
+		{
+			throw new SQLException(e);
+		}
+		*/
+	}
+}

Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerListener.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerListener.java?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerListener.java (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/ConnectionManagerListener.java Tue Sep 11 00:39:10 2007
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.myfaces.orchestra.connectionManager;
+
+import java.sql.Connection;
+
+/**
+ * Implement this class if you would like to add a listener to the ConnectionManager which e.g. allows
+ * you to do some database setup/shutdown procedures.<br />
+ * Its recommended to extend from the {@link AbstractConnectionManagerListener} class to be prepared
+ * for future interface enhancements. 
+ * 
+ * @see org.apache.myfaces.orchestra.connectionManager.AbstractConnectionManagerListener
+ */
+public interface ConnectionManagerListener
+{
+	public void borrowConnection(Connection con);
+	public void releaseConnection(Connection con);
+}

Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnection.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnection.java?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnection.java (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnection.java Tue Sep 11 00:39:10 2007
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.myfaces.orchestra.connectionManager;
+
+import java.sql.Connection;
+
+/**
+ * A workaround to the lazy-init-in-view problem.<br />
+ *
+ * We hand out DisconnectableConnections to the JPA-implementation, now,
+ * if a lazy-init happens during the view rendering we are able to disconnect it again
+ * at the end of the request (using a servlet filter). Once the JPA-implementation would like to
+ * do something with the connection again, we simply request a new from the connection pool
+ */
+public interface DisconnectableConnection extends Connection
+{
+	public void disconnect();
+	public Connection getConnection();
+}

Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnectionFactory.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnectionFactory.java?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnectionFactory.java (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/DisconnectableConnectionFactory.java Tue Sep 11 00:39:10 2007
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.myfaces.orchestra.connectionManager;
+
+import org.apache.commons.logging.LogFactory;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Proxy connections to being able to handle disconnection.
+ *
+ * @see org.apache.myfaces.orchestra.connectionManager.DisconnectableConnection
+ */
+public class DisconnectableConnectionFactory
+{
+	private DisconnectableConnectionFactory()
+	{
+	}
+
+	public static DisconnectableConnection create(final ConnectionManagerDataSource connectionManager)
+	{
+		return (DisconnectableConnection) Proxy.newProxyInstance(
+
+			DisconnectableConnection.class.getClassLoader(),
+
+			new Class[]
+				{
+					DisconnectableConnection.class
+				},
+
+			new InvocationHandler()
+			{
+				private Map connectionConfiguration = new HashMap();
+				private Connection connection;
+
+				public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+				{
+					if ("equals".equals(method.getName()) || "hashCode".equals(method.getName())) // NON-NLS
+					{
+						// do not pass these methods to the connection as we dont want to change the
+						// identity of the connection proxy
+						return method.invoke(this, args);
+					}
+					else if ("close".equals(method.getName())) // NON-NLS
+					{
+						try
+						{
+							connectionManager.onBeforeReleaseConnection((Connection) proxy);
+							if (connection != null)
+							{
+								connection.close();
+							}
+							connection = null;
+						}
+						finally
+						{
+							connectionManager.onAfterReleaseConnection((Connection) proxy);
+						}
+						return null;
+					}
+					else if ("disconnect".equals(method.getName())) // NON-NLS
+					{
+						connectionManager.onBeforeReleaseConnection((Connection) proxy);
+						try
+						{
+							if (connection != null)
+							{
+								try
+								{
+									if (!connection.isClosed())
+									{
+										connection.close();
+									}
+								}
+								catch (SQLException e)
+								{
+									LogFactory.getLog(DisconnectableConnectionFactory.class).warn(e.getLocalizedMessage(), e);
+								}
+							}
+						}
+						finally
+						{
+							connectionManager.onAfterReleaseConnection((Connection) proxy);
+							connection = null;
+						}
+						return null;
+					}
+					else if ("getConnection".equals(method.getName())) // NON-NLS
+					{
+						return connection;
+					}
+
+					if (connection == null)
+					{
+						connection = connectionManager.getDataSource().getConnection();
+
+						// if we have a configuration, we have to replay it now
+						Iterator iterConfiguration = connectionConfiguration.entrySet().iterator();
+						while (iterConfiguration.hasNext())
+						{
+							Map.Entry config = (Map.Entry) iterConfiguration.next();
+							((Method) config.getKey()).invoke(connection, (Object[]) config.getValue());
+						}
+
+						connectionManager.onAfterBorrowConnection((Connection) proxy);
+					}
+
+					Object ret = method.invoke(connection, args);
+
+					// capture the connection configuration
+					if (method.getName().startsWith("set")) // NON-NLS
+					{
+						connectionConfiguration.put(method, args);
+					}
+
+					return ret;
+				}
+			});
+	}
+}

Added: myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/package.html
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/package.html?rev=574496&view=auto
==============================================================================
--- myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/package.html (added)
+++ myfaces/orchestra/trunk/sandbox/src/main/java/org/apache/myfaces/orchestra/connectionManager/package.html Tue Sep 11 00:39:10 2007
@@ -0,0 +1,13 @@
+<html>
+<body>
+The code in this package is a copy of code that was originally implemented in core, but
+which was later simplified.
+<p>
+This code does two things: track "leaked" database connections, and provide a generic
+mechanism for getting notifications when a connection is borrowed or returned from a
+datasource. This second feature was not actually needed for core Orchestra so was
+deleted. At some future time the code here might be worth modifying to provide
+ONLY this notification functionality. It might then find a home somewhere like
+apache commons dbcp.
+</body>
+</html>