/**
*
* Copyright 2004 Protique Ltd
*
* 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.codehaus.activemq.ra;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.ServerSession;
import javax.jms.Session;
import javax.resource.ResourceException;
import javax.resource.spi.endpoint.MessageEndpoint;
import javax.resource.spi.work.Work;
import javax.resource.spi.work.WorkEvent;
import javax.resource.spi.work.WorkException;
import javax.resource.spi.work.WorkListener;
import javax.resource.spi.work.WorkManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.activemq.ActiveMQRASession;
/**
* @version $Revision: 1.6 $
*/
public class ServerSessionImpl implements ServerSession, SessionAndProducer, Work {
private static final Log log = LogFactory.getLog(ServerSessionImpl.class);
private Session session;
private WorkManager workManager;
private MessageEndpoint endpoint;
private MessageProducer messageProducer;
private final ActiveMQAsfEndpointWorker.ServerSessionPoolImpl pool;
private Object runControlMutex = new Object();
private boolean workPendingFlag = false;
private boolean runningFlag = false;
private int runCounter = 0;
public ServerSessionImpl(ActiveMQAsfEndpointWorker.ServerSessionPoolImpl pool, Session session, WorkManager workManager, MessageEndpoint endpoint) throws JMSException {
this.pool = pool;
this.session = session;
this.workManager = workManager;
this.endpoint = endpoint;
this.session.setMessageListener((MessageListener) endpoint);
}
public Session getSession() throws JMSException {
return session;
}
public MessageProducer getMessageProducer() throws JMSException {
if (messageProducer == null) {
messageProducer = getSession().createProducer(null);
}
return messageProducer;
}
/**
* @see javax.jms.ServerSession#start()
*/
public void start() throws JMSException {
log.debug("ServerSession started.");
synchronized (runControlMutex) {
runCounter++;
// Is our thread allready running
if (runningFlag || workPendingFlag) {
// let it know that it should do more work..
workPendingFlag = true;
log.debug("ServerSession allready running.");
return;
}
workPendingFlag = true;
}
// We get here because we need to start a async worker.
log.debug("ServerSession queuing request for a run.");
try {
workManager.scheduleWork(this, WorkManager.INDEFINITE, null,
new WorkListener() {
//The work listener is useful only for debugging...
public void workAccepted(WorkEvent event) {
log.debug("Work accepted: " + event);
}
public void workRejected(WorkEvent event) {
log.debug("Work rejected: " + event);
}
public void workStarted(WorkEvent event) {
log.debug("Work started: " + event);
}
public void workCompleted(WorkEvent event) {
log.debug("Work completed: " + event);
}
});
}
catch (WorkException e) {
throw (JMSException) new JMSException("Work could not be started: " + e).initCause(e);
}
}
/**
* @see java.lang.Runnable#run()
*/
public void run() {
while (true) {
synchronized (runControlMutex) {
workPendingFlag = false;
runningFlag = true;
}
log.debug("Running: " + this);
try {
SessionAndProducerHelper.register(this);
endpoint.beforeDelivery(ActiveMQBaseEndpointWorker.ON_MESSAGE_METHOD);
session.run();
}
catch (Throwable e) {
log.info(e);
}
finally {
try {
endpoint.afterDelivery();
} catch (ResourceException e) {
log.info("Endpoint afterDelivery() Failed:", e);
}
SessionAndProducerHelper.unregister(this);
// Sanitiy Check: If the local transaction has not been commited..
// Commit it now.
if( ((ActiveMQRASession)session).isInLocalTransaction() ) {
log.warn("Local transaction had not been commited. Commiting now.");
try {
((ActiveMQRASession)session).commit();
} catch (JMSException e) {
log.info("Commit failed:", e);
}
}
}
synchronized (runControlMutex) {
runCounter--;
runningFlag = false;
if (!workPendingFlag) {
if (runCounter == 0) {
pool.returnToPool(this);
}
break;
}
}
}
}
/**
* @see javax.resource.spi.work.Work#release()
*/
public void release() {
log.debug("release called");
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
return "ServerSessionImpl[session=" + session + "]";
}
}