/**
*
* Copyright 2004 Hiram Chirino
*
* 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.activemq.ra;
import org.activemq.ActiveMQSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.jms.ServerSessionPool;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.jms.XASession;
import javax.jms.ServerSession;
import javax.transaction.xa.XAResource;
import javax.resource.spi.endpoint.MessageEndpoint;
import javax.resource.spi.UnavailableException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
/**
* @version $Revision: 1.1.1.1 $ $Date: 2005/03/11 21:15:11 $
*/
public class ServerSessionPoolImpl implements ServerSessionPool {
private static final Log log = LogFactory.getLog(ServerSessionPoolImpl.class);
private final ActiveMQAsfEndpointWorker activeMQAsfEndpointWorker;
private final int maxSessions;
private ArrayList idleSessions = new ArrayList();
private LinkedList activeSessions = new LinkedList();
private boolean closing = false;
public ServerSessionPoolImpl(ActiveMQAsfEndpointWorker activeMQAsfEndpointWorker, int maxSessions) {
this.activeMQAsfEndpointWorker = activeMQAsfEndpointWorker;
this.maxSessions=maxSessions;
}
private ServerSessionImpl createServerSessionImpl() throws JMSException {
int acknowledge = (activeMQAsfEndpointWorker.transacted) ? Session.SESSION_TRANSACTED : activeMQAsfEndpointWorker.endpointActivationKey.getActivationSpec().getAcknowledgeModeForSession();
final ActiveMQSession session = (ActiveMQSession) activeMQAsfEndpointWorker.connection.createSession(activeMQAsfEndpointWorker.transacted,acknowledge);
final XAResource xaResource = (session instanceof XASession) ? ((XASession) session).getXAResource() : null;
MessageEndpoint endpoint;
try {
// Give the endpoint a LocalTransaction and XAResource interface to manage the tx.
endpoint = createEndpoint(new LocalAndXATransaction(session.getTransactionContext()));
} catch (UnavailableException e) {
// The container could be limiting us on the number of endpoints
// that are being created.
session.close();
return null;
}
return new ServerSessionImpl(this, (ActiveMQSession)session, activeMQAsfEndpointWorker.workManager, endpoint);
}
private MessageEndpoint createEndpoint(LocalAndXATransaction txResourceProxy) throws UnavailableException {
MessageEndpoint endpoint;
endpoint = activeMQAsfEndpointWorker.endpointFactory.createEndpoint(txResourceProxy);
MessageEndpointProxy endpointProxy = new MessageEndpointProxy(endpoint);
return endpointProxy;
}
/**
*/
synchronized public ServerSession getServerSession() throws JMSException {
log.debug("ServerSession requested.");
if (closing) {
throw new JMSException("Session Pool Shutting Down.");
}
if (idleSessions.size() > 0) {
ServerSessionImpl ss = (ServerSessionImpl) idleSessions.remove(idleSessions.size() - 1);
activeSessions.addLast(ss);
log.debug("Using idle session: " + ss);
return ss;
} else {
// Are we at the upper limit?
if (activeSessions.size() >= maxSessions) {
// then reuse the allready created sessions..
// This is going to queue up messages into a session for
// processing.
return getExistingServerSession();
}
ServerSessionImpl ss = createServerSessionImpl();
// We may not be able to create a session due to the conatiner
// restricting us.
if (ss == null) {
return getExistingServerSession();
}
activeSessions.addLast(ss);
log.debug("Created a new session: " + ss);
return ss;
}
}
/**
* @return
*/
private ServerSession getExistingServerSession() {
ServerSessionImpl ss = (ServerSessionImpl) activeSessions.removeFirst();
activeSessions.addLast(ss);
log.debug("Reusing an active session: " + ss);
return ss;
}
synchronized public void returnToPool(ServerSessionImpl ss) {
log.debug("Session returned to pool: " + ss);
activeSessions.remove(ss);
idleSessions.add(ss);
notify();
}
synchronized public void removeFromPool(ServerSessionImpl ss) {
activeSessions.remove(ss);
ss.close();
notify();
}
public void close() {
synchronized (this) {
closing = true;
closeIdleSessions();
while( activeSessions.size() > 0 ) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
closeIdleSessions();
}
}
}
private void closeIdleSessions() {
for (Iterator iter = idleSessions.iterator(); iter.hasNext();) {
ServerSessionImpl ss = (ServerSessionImpl) iter.next();
ss.close();
}
}
}