/* * 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.ra.spi; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.resource.NotSupportedException; import javax.resource.ResourceException; import javax.resource.spi.ConnectionEvent; import javax.resource.spi.ConnectionEventListener; import javax.resource.spi.ConnectionRequestInfo; import javax.resource.spi.LocalTransaction; import javax.resource.spi.ManagedConnection; import javax.resource.spi.ManagedConnectionMetaData; import javax.security.auth.Subject; import javax.transaction.SystemException; import javax.transaction.xa.XAResource; import org.apache.geode.LogWriter; import org.apache.geode.cache.CacheFactory; import org.apache.geode.internal.cache.GemFireCacheImpl; import org.apache.geode.internal.cache.TXManagerImpl; import org.apache.geode.internal.ra.GFConnectionImpl; /** * * */ public class JCAManagedConnection implements ManagedConnection { private final List<ConnectionEventListener> listeners; private volatile TXManagerImpl gfTxMgr; // private volatile TransactionId currentTxID; private volatile GemFireCacheImpl cache; private volatile boolean initDone = false; private volatile PrintWriter logger; private JCAManagedConnectionFactory factory; private volatile Set<GFConnectionImpl> connections; private volatile JCALocalTransaction localTran; private final static boolean DEBUG = false; public JCAManagedConnection(JCAManagedConnectionFactory fact) { this.factory = fact; this.listeners = Collections .<ConnectionEventListener>synchronizedList(new ArrayList<ConnectionEventListener>()); this.localTran = new JCALocalTransaction(); this.connections = Collections.<GFConnectionImpl>synchronizedSet(new HashSet<GFConnectionImpl>()); } public void addConnectionEventListener(ConnectionEventListener listener) { this.listeners.add(listener); } public void associateConnection(Object conn) throws ResourceException { if (!(conn instanceof GFConnectionImpl)) { throw new ResourceException("Connection is not of type GFConnection"); } ((GFConnectionImpl) conn).resetManagedConnection(this); this.connections.add((GFConnectionImpl) conn); } public void cleanup() throws ResourceException { if (DEBUG) { try { throw new NullPointerException("Asif:JCAManagedConnection:cleanup"); } catch (NullPointerException npe) { npe.printStackTrace(); } } synchronized (this.connections) { Iterator<GFConnectionImpl> connsItr = this.connections.iterator(); while (connsItr.hasNext()) { GFConnectionImpl conn = connsItr.next(); conn.invalidate(); connsItr.remove(); } } if (this.localTran == null || this.localTran.transactionInProgress()) { if (this.initDone && !this.cache.isClosed()) { this.localTran = new JCALocalTransaction(cache, gfTxMgr); } else { this.localTran = new JCALocalTransaction(); } } } public void destroy() throws ResourceException { if (DEBUG) { try { throw new NullPointerException("Asif:JCAManagedConnection:destroy"); } catch (NullPointerException npe) { npe.printStackTrace(); } } synchronized (this.connections) { Iterator<GFConnectionImpl> connsItr = this.connections.iterator(); while (connsItr.hasNext()) { GFConnectionImpl conn = connsItr.next(); conn.invalidate(); connsItr.remove(); } } this.gfTxMgr = null; this.cache = null; this.localTran = null; this.listeners.clear(); } public Object getConnection(Subject arg0, ConnectionRequestInfo arg1) throws ResourceException { if (DEBUG) { try { throw new NullPointerException("Asif:JCAManagedConnection:getConnection"); } catch (NullPointerException npe) { npe.printStackTrace(); } } try { if (!this.initDone || this.cache.isClosed()) { init(); } LogWriter logger = this.cache.getLogger(); if (logger.fineEnabled()) { logger.fine("JCAManagedConnection:getConnection. Returning new Connection"); } GFConnectionImpl conn = new GFConnectionImpl(this); this.connections.add(conn); return conn; } catch (SystemException e) { this.onError(e); throw new ResourceException("GemFire Resource unavailable", e); } } private void init() throws SystemException { this.cache = (GemFireCacheImpl) CacheFactory.getAnyInstance(); LogWriter logger = this.cache.getLogger(); if (logger.fineEnabled()) { logger.fine("JCAManagedConnection:init. Inside init"); } gfTxMgr = cache.getTxManager(); this.initDone = true; } public LocalTransaction getLocalTransaction() throws ResourceException { if (DEBUG) { try { throw new NullPointerException("Asif:JCAManagedConnection:getLocalTransaction"); } catch (NullPointerException npe) { npe.printStackTrace(); } } return this.localTran; } public PrintWriter getLogWriter() throws ResourceException { return this.logger; } public ManagedConnectionMetaData getMetaData() throws ResourceException { if (DEBUG) { try { throw new NullPointerException("Asif:JCAManagedConnection:getMetaData"); } catch (NullPointerException npe) { npe.printStackTrace(); } } if (this.initDone && !this.cache.isClosed()) { LogWriter logger = this.cache.getLogger(); if (logger.fineEnabled()) { logger.fine("JCAManagedConnection:getMetaData"); } } return new JCAManagedConnectionMetaData(this.factory.getProductName(), this.factory.getVersion(), this.factory.getUserName()); } public XAResource getXAResource() throws ResourceException { throw new NotSupportedException("XA Transaction not supported"); } public void removeConnectionEventListener(ConnectionEventListener arg0) { this.listeners.remove(arg0); } public void setLogWriter(PrintWriter logger) throws ResourceException { this.logger = logger; } private void onError(Exception e) { this.localTran = null; synchronized (this.connections) { Iterator<GFConnectionImpl> connsItr = this.connections.iterator(); while (connsItr.hasNext()) { GFConnectionImpl conn = connsItr.next(); conn.invalidate(); synchronized (this.listeners) { Iterator<ConnectionEventListener> itr = this.listeners.iterator(); ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.CONNECTION_ERROR_OCCURRED, e); ce.setConnectionHandle(conn); while (itr.hasNext()) { itr.next().connectionErrorOccurred(ce); } } connsItr.remove(); } } } public void onClose(GFConnectionImpl conn) throws ResourceException { conn.invalidate(); this.connections.remove(conn); synchronized (this.listeners) { Iterator<ConnectionEventListener> itr = this.listeners.iterator(); ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.CONNECTION_CLOSED); ce.setConnectionHandle(conn); while (itr.hasNext()) { itr.next().connectionClosed(ce); } } if (this.connections.isEmpty()) { // safe to dissociate this managedconnection so that it can go to pool if (this.initDone && !this.cache.isClosed()) { this.localTran = new JCALocalTransaction(this.cache, this.gfTxMgr); } else { this.localTran = new JCALocalTransaction(); } } } }