| /* |
| * 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.geode.internal.datasource; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import javax.resource.ResourceException; |
| import javax.resource.spi.ConnectionEvent; |
| import javax.resource.spi.ConnectionEventListener; |
| import javax.resource.spi.ConnectionManager; |
| import javax.resource.spi.ConnectionRequestInfo; |
| import javax.resource.spi.ManagedConnection; |
| import javax.resource.spi.ManagedConnectionFactory; |
| import javax.security.auth.Subject; |
| import javax.transaction.RollbackException; |
| import javax.transaction.Synchronization; |
| import javax.transaction.SystemException; |
| import javax.transaction.Transaction; |
| import javax.transaction.TransactionManager; |
| import javax.transaction.xa.XAResource; |
| |
| import org.apache.logging.log4j.Logger; |
| |
| import org.apache.geode.internal.jndi.JNDIInvoker; |
| import org.apache.geode.internal.jta.TransactionManagerImpl; |
| import org.apache.geode.logging.internal.log4j.api.LogService; |
| |
| /** |
| * This class implements a connection pool manager for managed connections (JCA) for transactional |
| * and non-transactional resource connection. Implements ConnectionManager interface. QoS |
| * (Transaction, Security etc is taken into account while allocating a connection). Security related |
| * features are remaining. |
| * |
| */ |
| public class FacetsJCAConnectionManagerImpl |
| implements ConnectionManager, ConnectionEventListener, Synchronization { |
| |
| private static final Logger logger = LogService.getLogger(); |
| |
| private static final long serialVersionUID = 2454746064736724758L; |
| |
| protected transient TransactionManager transManager; |
| protected ConnectionPoolCache mannPoolCache; |
| protected ConnectionRequestInfo conReqInfo = null; |
| protected Subject subject = null; |
| protected boolean isActive = true; |
| private transient ThreadLocal xalistThreadLocal = new ThreadLocal() { |
| |
| @Override |
| protected Object initialValue() { |
| return new ArrayList(); |
| } |
| }; |
| |
| /* |
| * Constructor. |
| * |
| */ |
| public FacetsJCAConnectionManagerImpl(ManagedConnectionFactory mcf, |
| ConfiguredDataSourceProperties configs) { |
| // Get the security info and form the Subject |
| // Initialize the Pool. |
| try { |
| isActive = true; |
| mannPoolCache = new ManagedPoolCacheImpl(mcf, null, null, this, configs); |
| } catch (Exception ex) { |
| logger.fatal(String.format( |
| "FacetsJCAConnectionManagerImpl::Constructor: An Exception was caught while initializing due to %s", |
| ex.getMessage()), |
| ex); |
| } |
| } |
| |
| /* |
| * allocates a ManagedConnection from the ConnectionPool or creates a new |
| * ManagedConnection. @param javax.resource.spi.ManagedConnectionFactory |
| * |
| * @param javax.resource.spi.ConnectionRequestInfo |
| * |
| */ |
| @Override |
| public Object allocateConnection(ManagedConnectionFactory mcf, ConnectionRequestInfo reqInfo) |
| throws ResourceException { |
| if (!isActive) { |
| throw new ResourceException( |
| "FacetsJCAConnectionManagerImpl::allocateConnection::No valid Connection available"); |
| } |
| ManagedConnection conn = null; |
| try { |
| conn = (ManagedConnection) mannPoolCache.getPooledConnectionFromPool(); |
| } catch (PoolException ex) { |
| ex.printStackTrace(); |
| throw new ResourceException( |
| String.format( |
| "FacetsJCAConnectionManagerImpl:: allocateConnection : in getting connection from pool due to %s", |
| ex.getMessage()), |
| ex); |
| } |
| // Check if a connection is having a transactional context |
| // if a transactional context is used, get the XA Resource |
| // from the ManagedConnection and register it with the |
| // Transaction Manager. |
| try { |
| synchronized (this) { |
| if (transManager == null) { |
| transManager = JNDIInvoker.getTransactionManager(); |
| } |
| } |
| |
| Transaction txn = transManager.getTransaction(); |
| if (txn != null) { |
| // Check if Data Source provides XATransaction |
| // if(configs.getTransactionType = "XATransaction") |
| XAResource xar = conn.getXAResource(); |
| txn.enlistResource(xar); |
| java.util.List resList = (List) xalistThreadLocal.get(); |
| if (resList.size() == 0) { |
| // facets specific implementation |
| // register syschronisation only once |
| txn.registerSynchronization(this); |
| } |
| resList.add(conn); |
| // xalistThreadLocal.set(resList); |
| // Asif :Add in the Map after successful registration of XAResource |
| // xaResourcesMap.put(conn, xar); |
| // else throw a resource exception |
| } |
| } catch (RollbackException ex) { |
| String exception = |
| String.format( |
| "FacetsJCAConnectionManagerImpl:: An Exception was caught while allocating a connection due to %s", |
| ex.getMessage()); |
| throw new ResourceException(exception, ex); |
| } catch (SystemException ex) { |
| throw new ResourceException( |
| String.format( |
| "FacetsJCAConnectionManagerImpl:: allocateConnection :system exception due to %s", |
| ex.getMessage()), |
| ex); |
| } |
| return conn.getConnection(subject, reqInfo); |
| } |
| |
| /** |
| * CallBack for Connection Error. |
| * |
| * @param event ConnectionEvent |
| */ |
| @Override |
| public void connectionErrorOccurred(ConnectionEvent event) { |
| if (isActive) { |
| // If its an XAConnection |
| ManagedConnection conn = (ManagedConnection) event.getSource(); |
| // XAResource xar = (XAResource) xaResourcesMap.get(conn); |
| ((List) xalistThreadLocal.get()).remove(conn); |
| TransactionManagerImpl transManager = TransactionManagerImpl.getTransactionManager(); |
| try { |
| Transaction txn = transManager.getTransaction(); |
| if (txn == null) { |
| mannPoolCache.returnPooledConnectionToPool(conn); |
| } else { |
| // do nothing. |
| } |
| } catch (Exception se) { |
| se.printStackTrace(); |
| } |
| try { |
| mannPoolCache.expirePooledConnection(conn); |
| // mannPoolCache.destroyPooledConnection(conn); |
| } catch (Exception ex) { |
| String exception = |
| "FacetsJCAConnectionManagerImpl::connectionErrorOccurred: Exception occurred due to " |
| + ex.getMessage(); |
| if (logger.isDebugEnabled()) { |
| logger.debug(exception, ex); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Callback for Connection Closed. |
| * |
| * @param event ConnectionEvent Object. |
| */ |
| @Override |
| public void connectionClosed(ConnectionEvent event) { |
| if (isActive) { |
| ManagedConnection conn = (ManagedConnection) event.getSource(); |
| TransactionManagerImpl transManager = TransactionManagerImpl.getTransactionManager(); |
| try { |
| Transaction txn = transManager.getTransaction(); |
| if (txn == null) { |
| mannPoolCache.returnPooledConnectionToPool(conn); |
| } |
| } catch (Exception se) { |
| String exception = |
| "FacetsJCAConnectionManagerImpl::connectionClosed: Exception occurred due to " |
| + se.getMessage(); |
| if (logger.isDebugEnabled()) { |
| logger.debug(exception, se); |
| } |
| } |
| } |
| } |
| |
| /* |
| * Local Transactions are not supported by Gemfire cache. |
| */ |
| @Override |
| public void localTransactionCommitted(ConnectionEvent arg0) { |
| // do nothing. |
| } |
| |
| /* |
| * Local Transactions are not supported by Gemfire cache. |
| */ |
| @Override |
| public void localTransactionRolledback(ConnectionEvent arg0) { |
| // do nothing. |
| } |
| |
| /* |
| * Local Transactions are not supported by Gemfire cache. |
| */ |
| @Override |
| public void localTransactionStarted(ConnectionEvent arg0) { |
| // do nothing |
| } |
| |
| public void clearUp() { |
| isActive = false; |
| mannPoolCache.clearUp(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see javax.transaction.Synchronization#afterCompletion(int) |
| */ |
| @Override |
| public void afterCompletion(int arg0) { |
| // DELIST THE XARESOURCE FROM THE LIST. RETURN ALL THE CONNECTIONS TO THE |
| // POOL. |
| java.util.List lsConn = (ArrayList) xalistThreadLocal.get(); |
| Iterator itr = lsConn.iterator(); |
| while (itr.hasNext()) { |
| ManagedConnection conn = (ManagedConnection) itr.next(); |
| mannPoolCache.returnPooledConnectionToPool(conn); |
| } |
| lsConn.clear(); |
| // return all the connections to pool. |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see javax.transaction.Synchronization#beforeCompletion() |
| */ |
| @Override |
| public void beforeCompletion() { |
| // TODO Auto-generated method stub |
| } |
| } |