org.ow2.frascati.tinfi.oasis.ServiceReferenceImpl Maven / Gradle / Ivy
The newest version!
/***
* OW2 FraSCAti Tinfi
* Copyright (C) 2007-2018 Inria, Univ. Lille
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: [email protected]
*
* Author: Lionel Seinturier
*/
package org.ow2.frascati.tinfi.oasis;
import org.oasisopen.sca.ServiceReference;
import org.osoa.sca.ConversationEndedException;
import org.osoa.sca.NoRegisteredCallbackException;
import org.osoa.sca.annotations.Conversational;
import org.ow2.frascati.tinfi.CallbackManager;
import org.ow2.frascati.tinfi.TinfiComponentOutInterface;
import org.ow2.frascati.tinfi.osoa.ConversationImpl;
import org.ow2.frascati.tinfi.osoa.ConversationManager;
import org.ow2.frascati.tinfi.osoa.ConversationState;
/**
* Implementation of a service reference.
*
* @author Lionel Seinturier
* @author Romain Rouvoy
*/
public class ServiceReferenceImpl implements ServiceReference {
/*
* Since version 1.4.2 all methods in this class are prefixed with
* underscore to avoid conflicts when generating proxy classes for
* interfaces with method names that collapse with these methods. The
* case was encountered by Nicolas Petitprez who needed to generate code for
* services implementing the existing javax.persistence.EntityManager
* interface. This type contains a getDelegate() method that was conflicting
* with the existing getDelegate() method defined in this class.
*/
private static final long serialVersionUID = -6320574328183281789L;
private Class businessInterface;
protected B service;
public ServiceReferenceImpl( Class businessInterface, B service ) {
this.businessInterface = businessInterface;
this.service = service;
this.conversationAnnotation =
businessInterface.getAnnotation(Conversational.class);
}
// ----------------------------------------------------------------------
// Management of the ServiceReferenceImpl chain.
//
// This chain is used by the CallbackManager. Prior to 1.4.5 I was using a
// Stack in CallbackManager but Romain suggested this smarter
// implementation.
// ----------------------------------------------------------------------
/** @since 1.4.5 */
private ServiceReferenceImpl> previous;
/** @since 1.4.5 */
public void setPrevious( ServiceReferenceImpl> previous ) {
this.previous = previous;
}
/** @since 1.4.5 */
public ServiceReferenceImpl> getPrevious() { return previous; }
// ----------------------------------------------------------------------
// Callback retated methods
// ----------------------------------------------------------------------
private Object callback;
protected Object _getCallback() {
if( callback == null ) {
throw new NoRegisteredCallbackException();
}
return callback;
}
protected Object _getCallbackID() {
return callbackID;
}
protected void _setCallback( Object callback ) {
this.callback = callback;
}
protected void _setCallbackID( Object callbackID ) {
this.callbackID = callbackID;
}
/** @since 1.4.5 */
protected void _pushCallback( ServiceReferenceImpl> sr ) {
CallbackManager cm = CallbackManager.get();
cm.push(sr);
}
/** @since 1.4.5 */
protected void _popCallback() {
CallbackManager cm = CallbackManager.get();
cm.pop();
}
// ----------------------------------------------------------------------
// Conversation related methods
// ----------------------------------------------------------------------
private Conversational conversationAnnotation;
private Object callbackID;
/** The conversation associated with the current reference. */
private ThreadLocal conversation;
protected boolean _isConversational() {
return (conversationAnnotation != null);
}
protected ConversationImpl _getConversation() throws IllegalStateException {
if( ! _isConversational() ) {
String msg = "This reference is not conversational";
throw new IllegalStateException(msg);
}
if( conversation == null ) {
conversation = new ThreadLocal();
}
ConversationImpl conv = conversation.get();
if( conv == null ) {
conv = new ConversationImpl();
conversation.set(conv);
}
return conv;
}
protected Object _getConversationID() {
if( ! _isConversational() ) {
String msg = "This reference is not conversational";
throw new IllegalStateException(msg);
}
return _getConversation().getConversationID();
}
/**
* Set the id to associate with any conversation started through this
* reference. If the value supplied is null
then the id will be
* generated by the implementation.
*
* @param conversationId
* the user-defined id to associated with a conversation
* @throws IllegalStateException
* if a conversation is currently associated with this reference
*/
protected void _setConversationID( Object conversationId )
throws IllegalStateException {
if( ! _isConversational() ) {
String msg = "This reference is not conversational";
throw new IllegalStateException(msg);
}
if( _getConversation().getConversationID() != null ) {
String msg =
"A conversion has already been associated with this service "+
"reference";
throw new IllegalStateException(msg);
}
if( conversationId == null ) {
conversationId = Math.random();
}
_getConversation().setConversationID(conversationId);
}
// ----------------------------------------------------------------------
// Implementation of the ServiceReference interface
// ----------------------------------------------------------------------
public Class getBusinessInterface() {
return businessInterface;
}
public B getService() {
/*
* Up until Tinfi 1.3.1 included, this method was returning
* "this.service".
*
* Since 1.4, we changed to the following piece of code. The idea is
* that the object returned by this method must implement the business
* interface while yet being able to execute the control logic (such as
* pushing conversations on the conversation stack) when invoked. This
* control logic is implemented by the generated subclasses of
* ServiceReferenceImpl. A typical usage scenario which motivated this
* change came from a mail discussion in August 2010 with David Feliot
* from ScalAgent:
*
* ServiceReference actionRef =
* componentContext.getServiceReference(Action.class,"action");
* actionRef.getService().someAction(actionOccurrence);
*
* When invoking method someAction on the reference returned by
* getService, the control logic must be executed.
*/
@SuppressWarnings("unchecked")
TinfiComponentOutInterface tco =
(TinfiComponentOutInterface) this.service;
ServiceReference sr = tco.getServiceReference();
@SuppressWarnings("unchecked")
B service = (B) sr;
return service;
}
// ----------------------------------------------------------------------
// Implementation specific
// ----------------------------------------------------------------------
/**
* Return the reference this callable reference delegates to. This method is
* invoked by methods setReferenceValue and unsetReferenceValue in {@link
* org.ow2.frascati.tinfi.control.content.SCAContentControllerMixin} to
* manage reference injection for collection interfaces.
*
* @since 1.4
*/
public B _getDelegate() {
return service;
}
// ----------------------------------------------------------------------
// Methods used by generated subclasses
// ----------------------------------------------------------------------
/**
* @since 1.1.1
*/
protected void _pushConversation( ConversationImpl conv )
throws ConversationEndedException {
ConversationState convstate = conv.getFcState();
if( convstate.equals(ConversationState.STOPPED) ) {
throw new ConversationEndedException();
}
if( convstate.equals(ConversationState.CREATED) ) {
String conversationId =
Thread.currentThread().toString()+':'+getService().toString();
conv.setConversationID(conversationId);
conv.start();
}
ConversationManager cm = ConversationManager.get();
cm.push(conv);
}
/**
* @since 1.1.1
*/
protected ConversationImpl _popConversation() {
ConversationManager cm = ConversationManager.get();
ConversationImpl conv = cm.pop();
return conv;
}
/**
* @since 1.4
*/
protected ConversationImpl _peekConversation() {
ConversationManager cm = ConversationManager.get();
ConversationImpl conv = cm.peek();
return conv;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy