package org.mobicents.slee.resource;
import javax.slee.Address;
import javax.slee.SLEEException;
import javax.slee.TransactionRequiredLocalException;
import javax.slee.resource.ActivityAlreadyExistsException;
import javax.slee.resource.ActivityFlags;
import javax.slee.resource.ActivityHandle;
import javax.slee.resource.ActivityIsEndingException;
import javax.slee.resource.EventFlags;
import javax.slee.resource.FireEventException;
import javax.slee.resource.FireableEventType;
import javax.slee.resource.IllegalEventException;
import javax.slee.resource.ReceivableService;
import javax.slee.resource.SleeEndpoint;
import javax.slee.resource.StartActivityException;
import javax.slee.resource.UnrecognizedActivityHandleException;
import javax.transaction.Transaction;
import org.apache.log4j.Logger;
import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.component.EventTypeComponent;
import org.mobicents.slee.runtime.activity.ActivityContext;
import org.mobicents.slee.runtime.activity.ActivityContextHandle;
import org.mobicents.slee.runtime.activity.ActivityContextHandlerFactory;
import org.mobicents.slee.runtime.eventrouter.ActivityEventQueueManager;
import org.mobicents.slee.runtime.transaction.SleeTransactionManager;
import org.mobicents.slee.runtime.transaction.TransactionalAction;
/**
*
* Implementation of SLEE 1.1 {@link SleeEndpoint}
*
* @author Eduardo Martins
*/
public class SleeEndpointImpl implements SleeEndpoint {
private final SleeContainer sleeContainer;
private static Logger logger = Logger
.getLogger(SleeEndpointImpl.class);
private final ResourceAdaptorEntity raEntity;
private final SleeEndpointFireEventNotTransactedExecutor fireEventNotTransactedExecutor;
private final SleeEndpointStartActivityNotTransactedExecutor startActivityNotTransactedExecutor;
private final SleeEndpointEndActivityNotTransactedExecutor endActivityNotTransactedExecutor;
public SleeEndpointImpl(ResourceAdaptorEntity raEntity,SleeContainer container) {
this.sleeContainer = container;
this.raEntity = raEntity;
this.fireEventNotTransactedExecutor = new SleeEndpointFireEventNotTransactedExecutor(sleeContainer, this);
this.startActivityNotTransactedExecutor = new SleeEndpointStartActivityNotTransactedExecutor(sleeContainer, this);
this.endActivityNotTransactedExecutor = new SleeEndpointEndActivityNotTransactedExecutor(sleeContainer, this);
}
// --- ACTIVITY START
public void startActivity(ActivityHandle handle, Object activity)
throws NullPointerException, IllegalStateException,
ActivityAlreadyExistsException, StartActivityException,
SLEEException {
startActivity(handle, activity, ActivityFlags.NO_FLAGS);
}
public void startActivity(final ActivityHandle handle, Object activity,
final int activityFlags) throws NullPointerException,
IllegalStateException, ActivityAlreadyExistsException,
StartActivityException, SLEEException {
checkStartActivityParameters(handle,activity);
startActivityNotTransactedExecutor.execute(handle, activityFlags);
}
public void startActivitySuspended(ActivityHandle handle, Object activity)
throws NullPointerException, IllegalStateException,
TransactionRequiredLocalException, ActivityAlreadyExistsException,
StartActivityException, SLEEException {
startActivitySuspended(handle, activity, ActivityFlags.NO_FLAGS);
}
public void startActivitySuspended(ActivityHandle handle, Object activity,
int activityFlags) throws NullPointerException,
IllegalStateException, TransactionRequiredLocalException,
ActivityAlreadyExistsException, StartActivityException,
SLEEException {
// need to check tx before doing out of tx scope activity start
sleeContainer.getTransactionManager().mandateTransaction();
startActivity(handle, activity,activityFlags);
suspendActivity(handle);
}
public void startActivityTransacted(ActivityHandle handle, Object activity)
throws NullPointerException, IllegalStateException,
TransactionRequiredLocalException, ActivityAlreadyExistsException,
StartActivityException, SLEEException {
startActivityTransacted(handle, activity, ActivityFlags.NO_FLAGS);
}
public void startActivityTransacted(ActivityHandle handle, Object activity,
int activityFlags) throws NullPointerException,
IllegalStateException, TransactionRequiredLocalException,
ActivityAlreadyExistsException, StartActivityException,
SLEEException {
checkStartActivityParameters(handle,activity);
// check tx state
sleeContainer.getTransactionManager().mandateTransaction();
_startActivity(handle,activityFlags);
}
/**
* Checks the parameters of startActivity* methods
* @param handle
* @param activity
* @throws NullPointerException
* @throws IllegalStateException
*/
private void checkStartActivityParameters(ActivityHandle handle, Object activity) throws NullPointerException,IllegalStateException {
if (logger.isDebugEnabled()) {
logger.debug("Starting activity : "+ handle);
}
// check args
if (handle == null) {
throw new NullPointerException("null handle");
}
if (activity == null) {
throw new NullPointerException("null activity");
}
// check ra state
if(raEntity.getResourceAdaptorObject().getState() != ResourceAdaptorObjectState.ACTIVE) {
throw new IllegalStateException("ra is in state "+raEntity.getResourceAdaptorObject().getState());
}
}
/**
* Start activity logic, independent of transaction management.
*
* @param handle
* @param activityFlags
*/
void _startActivity(ActivityHandle handle, int activityFlags) {
// create activity context
ActivityContextHandle ach = ActivityContextHandlerFactory.createExternalActivityContextHandle(raEntity.getName(),handle);
sleeContainer.getActivityContextFactory().createActivityContext(ach,activityFlags);
if (logger.isDebugEnabled()) {
logger.debug("Activity started: "+ ach);
}
}
// --- ACTIVITY END
public void endActivity(final ActivityHandle handle) throws NullPointerException,
UnrecognizedActivityHandleException {
if (handle == null)
throw new NullPointerException("handle is null");
endActivityNotTransactedExecutor.execute(handle);
}
public void endActivityTransacted(ActivityHandle handle)
throws NullPointerException, TransactionRequiredLocalException,
UnrecognizedActivityHandleException {
if (handle == null)
throw new NullPointerException("handle is null");
sleeContainer.getTransactionManager().mandateTransaction();
_endActivity(handle);
}
/**
* End activity logic independent of transaction management.
*
* @param handle
*/
void _endActivity(ActivityHandle handle) throws UnrecognizedActivityHandleException {
ActivityContextHandle ach = ActivityContextHandlerFactory
.createExternalActivityContextHandle(raEntity.getName(), handle);
// get ac
ActivityContext ac = sleeContainer.getActivityContextFactory().getActivityContext(ach);
if (ac != null) {
// end the activity
ac.endActivity();
} else {
throw new UnrecognizedActivityHandleException(handle.toString());
}
}
// EVENT FIRING
public void fireEvent(ActivityHandle handle, FireableEventType eventType,
Object event, Address address, ReceivableService receivableService)
throws NullPointerException, UnrecognizedActivityHandleException,
IllegalEventException, ActivityIsEndingException,
FireEventException, SLEEException {
fireEvent(handle,eventType,event,address,receivableService,EventFlags.NO_FLAGS);
}
public void fireEvent(final ActivityHandle handle, final FireableEventType eventType,
final Object event, final Address address, final ReceivableService receivableService, final int eventFlags)
throws NullPointerException, UnrecognizedActivityHandleException,
IllegalEventException, ActivityIsEndingException,
FireEventException, SLEEException {
checkFireEventPreconditions(handle,eventType,event);
fireEventNotTransactedExecutor.execute(handle, eventType, event, address, receivableService, eventFlags);
}
public void fireEventTransacted(ActivityHandle handle, FireableEventType eventType,
Object event, Address address, ReceivableService receivableService) throws NullPointerException,
UnrecognizedActivityHandleException, IllegalEventException,
TransactionRequiredLocalException, ActivityIsEndingException,
FireEventException, SLEEException {
fireEventTransacted(handle,eventType,event,address,receivableService,EventFlags.NO_FLAGS);
}
public void fireEventTransacted(ActivityHandle handle, FireableEventType eventType,
Object event, Address address, ReceivableService receivableService, int eventFlags) throws NullPointerException,
UnrecognizedActivityHandleException, IllegalEventException,
TransactionRequiredLocalException, ActivityIsEndingException,
FireEventException, SLEEException {
checkFireEventPreconditions(handle,eventType,event);
sleeContainer.getTransactionManager().mandateTransaction();
_fireEvent(handle,eventType,event,address,receivableService,eventFlags);
}
/**
* Checks that fire event methods can be invoked
* @param handle
* @param eventType
* @param event
* @throws NullPointerException
* @throws IllegalEventException
* @throws IllegalStateException
*/
private void checkFireEventPreconditions(ActivityHandle handle, FireableEventType eventType,
Object event) throws NullPointerException,IllegalEventException,IllegalStateException {
if (logger.isDebugEnabled()) {
logger.debug("Firing event "+ event + " of type " +eventType.getEventType() + " on activity " + handle);
}
if (event == null)
throw new NullPointerException("event is null");
if (handle == null)
throw new NullPointerException("handle is null");
if (eventType == null) {
throw new NullPointerException("eventType is null");
}
EventTypeComponent eventTypeComponent = sleeContainer.getComponentRepositoryImpl().getComponentByID(eventType.getEventType());
if (eventTypeComponent == null) {
throw new IllegalEventException("event type not installed (more on SLEE 1.1 specs 15.14.8)");
}
if (!eventTypeComponent.getEventTypeClass().isAssignableFrom(event.getClass())) {
throw new IllegalEventException("the class of the event object fired is not assignable to the event class of the event type (more on SLEE 1.1 specs 15.14.8) ");
}
if (eventType.getClass() != FireableEventTypeImpl.class) {
throw new IllegalEventException("unknown implementation of FireableEventType");
}
if (raEntity.getAllowedEventTypes() != null && !raEntity.getAllowedEventTypes().contains(eventType.getEventType())) {
throw new IllegalEventException("Resource Adaptor configured to not ignore ra type event checking and the event "+eventType.getEventType()+" does not belongs to any of the ra types implemented by the resource adaptor");
}
// uncomment if tck enforces ra object state
/*
ResourceAdaptorObjectState raObjectState = raEntity.getObject().getState();
if (raObjectState != ResourceAdaptorObjectState.ACTIVE && raObjectState != ResourceAdaptorObjectState.STOPPING) {
throw new IllegalStateException("ra object is in state "+raObjectState);
}
*/
}
/**
* Event firing logic independent of transaction management.
*
* @param handle
* @param eventType
* @param event
* @param address
* @param receivableService
* @param eventFlags
*/
void _fireEvent(ActivityHandle handle, FireableEventType eventType,
Object event, Address address, ReceivableService receivableService, int eventFlags) throws ActivityIsEndingException, SLEEException {
ActivityContextHandle ach = ActivityContextHandlerFactory.createExternalActivityContextHandle(raEntity.getName(),handle);
// get ac
ActivityContext ac = sleeContainer.getActivityContextFactory().getActivityContext(ach);
if (ac == null) {
throw new UnrecognizedActivityHandleException(handle.toString());
}
else {
ac.fireEvent(eventType.getEventType(),event,address, (receivableService == null ? null : receivableService.getService()),eventFlags);
}
}
// OTHER ...
public void suspendActivity(ActivityHandle handle)
throws NullPointerException, TransactionRequiredLocalException,
UnrecognizedActivityHandleException, SLEEException {
if (handle == null)
throw new NullPointerException("handle is null");
SleeTransactionManager tm = sleeContainer.getTransactionManager();
tm.mandateTransaction();
ActivityContextHandle ach = ActivityContextHandlerFactory
.createExternalActivityContextHandle(raEntity.getName(), handle);
// get ac
ActivityContext ac = sleeContainer.getActivityContextFactory().getActivityContext(ach);
if (ac != null) {
try {
// suspend activity
final Transaction transaction = tm.getTransaction();
final ActivityEventQueueManager eventQueue = sleeContainer.getEventRouter().getEventRouterActivity(ac.getActivityContextHandle()).getEventQueueManager();
eventQueue.createBarrier(transaction);
TransactionalAction action = new TransactionalAction() {
public void execute() {
eventQueue.removeBarrier(transaction);
}
};
tm.addAfterCommitAction(action);
tm.addAfterRollbackAction(action);
}
catch (Throwable e) {
throw new SLEEException(e.getMessage(),e);
}
} else {
throw new UnrecognizedActivityHandleException(handle.toString());
}
}
}