/* * � Copyright IBM Corp. 2010, 2014 * * 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 com.ibm.xsp.extlib.relational.jdbc.jndi; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.faces.context.FacesContext; import javax.sql.DataSource; import com.ibm.designer.runtime.Application; import com.ibm.designer.runtime.resources.ResourceFactoriesException; import com.ibm.designer.runtime.resources.ResourceFactoriesPool; import com.ibm.xsp.context.FacesContextEx; import com.ibm.xsp.event.FacesContextListener; import com.ibm.xsp.extlib.relational.RelationalLogger; import com.ibm.xsp.extlib.relational.resources.IJdbcResourceFactory; /** * JNDI proxy for JDBC data sources. * <p> * This a the data source proxy actually bind to the JNDI registry that delegates * to the actual data source to be used. The data source is retrieved contextually * from the resources pool. * </p> * @author priand */ public class JndiDataSourceProxy implements DataSource { private String name; public JndiDataSourceProxy(String name) { this.name = name; } // ================================================================ // Actual Datasource implementation // ================================================================ private static final String JDBC_CONNECTION_LIST = "extlib.jdbc.connections"; // $NON-NLS-1$ private static class ConnectionList implements FacesContextListener { List<Connection> connections = new ArrayList<Connection>(); ConnectionList() { } public void beforeContextReleased(FacesContext facesContext) { // Ok, the request is done - clear all the connections closeConnections(); } public void beforeRenderingPhase(FacesContext facesContext) { // PHIL: 12/16/2012 // The connections can be acquired in the POST phase and continue to be used in // the rendering phase, so we should not clear them here // // Clear all the connections allocated during the previous phases and before rendering // closeConnections(); } private void closeConnections() { int count = connections.size(); for(int i=0; i<count; i++) { try { Connection c = connections.get(i); if(!c.isClosed()) { c.close(); } } catch(SQLException ex) { if(RelationalLogger.RELATIONAL.isErrorEnabled()) { RelationalLogger.RELATIONAL.errorp(this, "closeConnections", ex, "Exception occured closing the list of connections "); // $NON-NLS-1$ $NLE-JndiDataSourceProxy.Exceptionoccuredclosingthelistofc-2$ } } } } } private static ConnectionList getConnectionList(FacesContext context) { if(context!=null) { Map requestScope = context.getExternalContext().getRequestMap(); ConnectionList l = (ConnectionList)requestScope.get(JDBC_CONNECTION_LIST); if(l==null) { l = new ConnectionList(); ((FacesContextEx)context).addRequestListener(l); requestScope.put(JDBC_CONNECTION_LIST, l); } return l; } return null; } // ================================================================ // Access to the wrapped data source // ================================================================ public DataSource getWrappedDatasource() throws ResourceFactoriesException { // Look for an application+global specific data source Application app = Application.getRuntimeApplicationObject(); if(app!=null) { return (IJdbcResourceFactory)app.getResourceFactoriesPool().getResourceFactory(IJdbcResourceFactory.TYPE, name); } // Else, look for a simply global one return (IJdbcResourceFactory)ResourceFactoriesPool.getGlobalPool().getResourceFactory(IJdbcResourceFactory.TYPE, name); } // ================================================================ // Actual Datasource implementation // ================================================================ public Connection getConnection() throws SQLException { try { DataSource r = getWrappedDatasource(); Connection c = r.getConnection(); ConnectionList list = getConnectionList(FacesContext.getCurrentInstance()); if(list!=null) { list.connections.add(c); } return c; } catch(ResourceFactoriesException ex) { throw (SQLException)new SQLException().initCause(ex); } } public Connection getConnection(String username, String password) throws SQLException { try { DataSource r = getWrappedDatasource(); Connection c = r.getConnection(username,password); ConnectionList list = getConnectionList(FacesContext.getCurrentInstance()); if(list!=null) { list.connections.add(c); } return c; } catch(ResourceFactoriesException ex) { throw (SQLException)new SQLException().initCause(ex); } } public PrintWriter getLogWriter() throws SQLException { try { DataSource r = getWrappedDatasource(); return r.getLogWriter(); } catch(ResourceFactoriesException ex) { throw (SQLException)new SQLException().initCause(ex); } } public void setLogWriter(PrintWriter out) throws SQLException { try { DataSource r = getWrappedDatasource(); r.setLogWriter(out); } catch(ResourceFactoriesException ex) { throw (SQLException)new SQLException().initCause(ex); } } public int getLoginTimeout() throws SQLException { try { DataSource r = getWrappedDatasource(); return r.getLoginTimeout(); } catch(ResourceFactoriesException ex) { throw (SQLException)new SQLException().initCause(ex); } } public void setLoginTimeout(int seconds) throws SQLException { try { DataSource r = getWrappedDatasource(); r.setLoginTimeout(seconds); } catch(ResourceFactoriesException ex) { throw (SQLException)new SQLException().initCause(ex); } } public boolean isWrapperFor(Class<?> arg0) throws SQLException { return isWrapperFor(arg0); } public <T> T unwrap(Class<T> arg0) throws SQLException { return unwrap(arg0); } }