ws-kandula-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dasar...@apache.org
Subject svn commit: r548471 [1/2] - /webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/
Date Mon, 18 Jun 2007 20:10:03 GMT
Author: dasarath
Date: Mon Jun 18 13:10:02 2007
New Revision: 548471

URL: http://svn.apache.org/viewvc?view=rev&rev=548471
Log:
Hannes Erven, Georg Hicker

Added:
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/AbstractCoordParticipant.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/AbstractCoordParticipantProxy.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAAtomicOutcome.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BACoordinator.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BACoordinatorService.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwCCCoordParticipant.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwCCParticipantProxy.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwPCCoordParticipant.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwPCParticipantProxy.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwithAtomicOutcomeCoordinator.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwithMixedOutcomeCoordinator.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinationState.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService_Atomic.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService_Mixed.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/InitiatorProxy.java
    webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/InvalidOutcomeAssertion.java

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/AbstractCoordParticipant.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/AbstractCoordParticipant.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/AbstractCoordParticipant.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/AbstractCoordParticipant.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,461 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+import java.rmi.RemoteException;
+
+import javax.xml.namespace.QName;
+import javax.xml.soap.Name;
+
+import org.apache.axis.encoding.AnyContentType;
+import org.apache.axis.message.addressing.EndpointReference;
+import org.apache.kandula.coordinator.Callback;
+import org.apache.kandula.coordinator.Coordinator;
+import org.apache.kandula.coordinator.TimedOutException;
+import org.apache.kandula.coordinator.ba.AbstractStateTransition;
+import org.apache.kandula.coordinator.ba.State;
+import org.apache.kandula.coordinator.ba.StateTransitionFault;
+import org.apache.kandula.coordinator.ba.StateTransitionIgnore;
+import org.apache.kandula.coordinator.ba.StateTransitionResend;
+import org.apache.kandula.coordinator.ba.StateTransitionResendPreviousState;
+import org.apache.kandula.coordinator.ba.StateTransitionState;
+import org.apache.kandula.coordinator.ba.WrongMethodCallException;
+import org.apache.kandula.wsba.ExceptionType;
+import org.apache.kandula.wsba.NotificationType;
+import org.apache.kandula.wsba.StateType;
+import org.apache.kandula.wsba.StatusType;
+
+/**
+ * Instances of this class represent business activity participants that are registered
+ * for a specific protocol in a given coordination context, as seen by the coordinator.
+ * 
+ * Participant instances on the "client" (participant) side are represented by @see org.apache.kandula.coordinator.ba.participant.AbstractParticipant and its
+ * subclasses.
+ * 
+ * For each coordination protocol exists a subclass implementing providing
+ * the specific behaviour required:
+ * <ul>
+ * <li>for the Participant Completion protocol, @see org.apache.kandula.coordinator.ba.coordinator.BAwPCCoordParticipant
+ * <li>for the Coordinator Completion protocol, @see org.apache.kandula.coordinator.ba.coordinator.BAwCCCoordParticipant
+ * </ul>
+ * 
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ * 
+ */
+public abstract class AbstractCoordParticipant implements Callback {
+
+	/**
+	 * The participant's state, as seen by the coordinator
+	 */
+	protected CoordinationState currState;
+
+	/**
+	 * My participant ID
+	 */
+	private final String myParticipantID;
+
+	/**
+	 * My participant's EPR (this is where the coordinator
+	 * sends messages intended for the participant to)
+	 */
+	private final EndpointReference myParticipantEPR;
+
+	/**
+	 * My transaction context
+	 */
+	private final BACoordinator transactionContext;
+	
+	/**
+	 * Matchcode provided by the initiator to identify the participant,
+	 * unique in a given coordination context
+	 */
+	private final String matchcode;
+	
+	/**
+	 * The default constructor. Use this to create a new Participant.
+	 * EnpointReference and Protocoltype can not be changed afterwards.
+	 * 
+	 * This constructor is used by the BACoordinator when processing a register
+	 * request, after all preconditions have been successfully checked and
+	 * the participant is finally enrolled.
+	 * (Actually, the BACoordinator invokes the constructor on one of the subclasses,
+	 * which in turn pushes the request up here.)
+
+	 * @param participantID 
+	 * 			  This participant's participant ID, generated by the coordinator.
+	 * @param participantEPR
+	 *            The EndpointReference of the Participant.
+	 * @param context
+	 * 			  The transaction context the participant registered for.
+	 * @param matchcodeP 
+	 * 			  The matchcode the initiator assigned to this participant.
+	 */
+	protected AbstractCoordParticipant(
+			final String participantID, 
+			final EndpointReference participantEPR,
+			final BACoordinator context,
+			final String matchcodeP
+	) {
+		super();
+		this.myParticipantID = participantID;
+		this.myParticipantEPR = participantEPR;
+		this.currState = new CoordinationState(getProtocolIdentifier());
+		this.transactionContext = context;
+		this.matchcode = matchcodeP;
+	}
+
+	/**
+	 * Getter for the ProtocolType
+	 * 
+	 * @return The ProtocolType
+	 */
+	public abstract QName getProtocolIdentifier();
+
+	/**
+	 * Getter for the State the Participant is in.
+	 * 
+	 * @return The State
+	 */
+	public QName getCurrentState() {
+		return this.currState.getCurrentState();
+	}
+
+	/**
+	 * Gets the participant proxy for this participant.
+	 * @return The participant proxy object.
+	 */
+	public abstract AbstractCoordParticipantProxy getParticipantProxy();
+	
+	/*
+	 * Below are the methods that can be called on any WS-BA participant
+	 * These methods are OUTGOING ! 
+	 */
+	
+	/**
+	 * Tells the participant to cancel
+	 * @throws RemoteException A RemoteException that occured while sending a message to the participant.
+	 */
+	public void tellCancel() throws RemoteException{
+		this.tell(State.MESSAGE_CANCEL);
+	}
+
+	/**
+	 * Tells the participant to close
+	 * @throws RemoteException A RemoteException that occured while sending a message to the participant.
+	 */
+	public void tellClose() throws RemoteException{
+		this.tell(State.MESSAGE_CLOSE);
+	}
+
+	/**
+	 * Tells the participant the current coordinator's state.
+	 * 
+	 * Attention: this method does *direct* calls to the participant's
+	 * web service and skips the use of @see #tell(QName) and @see #tellAgain(QName),
+	 * since state queries are always allowed and do not modify anything here.
+	 * 
+	 * @throws RemoteException A RemoteException that occured while sending a message to the participant.
+	 */
+	public void tellStatus() throws RemoteException {
+		final StatusType st = new StatusType(
+				StateType.fromValue(this.currState.getCurrentState()),
+				null
+		);
+		this.getParticipantProxy().statusOperation(st);
+	}
+
+	/**
+	 * Tell the participant to report its state
+	 * @throws RemoteException A RemoteException that occured while sending a message to the participant.
+	 */
+	public void tellGetStatus() throws RemoteException {
+		this.tell(State.MESSAGE_STATUS);
+	}
+
+	/**
+	 * Tell the participant to compensate
+	 * @throws RemoteException A RemoteException that occured while sending a message to the participant.
+	 */
+	public void tellCompensate() throws RemoteException {
+		this.tell(State.MESSAGE_COMPENSATE);
+	}
+
+	/**
+	 * Tell the participant that "fault" was accepted
+	 * @throws RemoteException A RemoteException that occured while sending a message to the participant.
+	 */
+	public void tellFaulted() throws RemoteException {
+		this.tell(State.MESSAGE_FAULTED);
+	}
+
+	/**
+	 * Tell the participant that "exit" was accepted
+	 * @throws RemoteException A RemoteException that occured while sending a message to the participant.
+	 */
+	public void tellExited() throws RemoteException {
+		this.tell(State.MESSAGE_EXITED);
+	}
+	
+	/*
+	 * Here come the Callback implementation methods
+	 */
+
+	/**
+	 * Get this participant's ID
+	 * (Don't mix this one up with the matchcode: the participant ID is
+	 *  created by the BACoordinator, the matchcode is assigned
+	 *  by the initiator)
+	 *  
+	 *  @return This participant's id.
+	 */
+	public String getID() {
+		return this.myParticipantID;
+	}
+
+	/**
+	 * Handle fault
+	 * @param code The fault code. 
+	 */
+	public void onFault(final Name code) {
+		// TODO WSBA Handle faults
+		if (code != null)
+			code.toString();
+	}
+
+	/**
+	 * Handle timeout
+	 * @throws TimedOutException //TODO WSBA Handle timeouts
+	 */
+	public void timeout() throws TimedOutException {
+		// TODO WSBA Handle faults
+		
+		if (false)
+			throw new TimedOutException();
+	}
+
+	/**
+	 * Get the participant's EPR. This EPR is used
+	 * to send messages to the participant. 
+	 * @return This participant's endpoint reference.
+	 */
+	public EndpointReference getEndpointReference() {
+		return this.myParticipantEPR;
+	}
+	
+	/**
+	 * Accept an incoming message and do what is to be done.
+	 * 
+	 * @param messageType The incoming message's type
+	 * @param params The params the message contained
+	 * @throws RemoteException A RemoteException that occured while sending a message to the participant.
+	 */
+	protected void handleIncomingMessage(final QName messageType, final NotificationType params) throws RemoteException{
+		try{
+			final AbstractStateTransition transition =  this.currState.transistStateByMessage(messageType);
+			System.out.println("Participant Incoming "+messageType+", Transition: "+transition);
+			
+			handleTransition(transition, params);
+		}catch(RemoteException e){
+			throw e;
+		}catch(Exception e){
+			throw Coordinator.INVALID_STATE_SOAP_FAULT() ;
+		}
+	}
+	/**
+	 * Accept an incoming message and do what is to be done.
+	 * 
+	 * @param messageType The incoming message's type
+	 * @param params The params the message contained
+	 * @throws RemoteException A RemoteException that occured while sending a message to the participant.
+	 */
+	protected void handleIncomingMessage(final QName messageType, final StatusType params) throws RemoteException{
+		try{
+			final AbstractStateTransition transition =  this.currState.transistStateByMessage(messageType);
+			System.out.println("+ Transition: "+transition);
+			
+			handleTransition(transition, params);
+		}catch(RemoteException e){
+			throw e;
+		}catch(Exception e){
+			throw Coordinator.INVALID_STATE_SOAP_FAULT();
+		}
+	}
+	/**
+	 * Accept an incoming message and do what is to be done.
+	 * 
+	 * @param messageType The incoming message's type
+	 * @param params The params the message contained
+	 * @throws RemoteException A RemoteException that occured while sending a message to the participant.
+	 */
+	public void handleIncomingMessage(final QName messageType, final ExceptionType params) throws RemoteException{
+		try{
+			final AbstractStateTransition transition =  this.currState.transistStateByMessage(messageType);
+			System.out.println("+ Transition: "+transition);
+			
+			handleTransition(transition, params);		
+		}catch(RemoteException e){
+			throw e;
+		}catch(Exception e){
+			throw Coordinator.INVALID_STATE_SOAP_FAULT() ;
+		}
+	}
+	
+	/**
+	 * Handle a state transition. This method accepts a transition that was obtained by comparing
+	 * the participant's current state and the incoming message against the protocol state table.
+	 * 
+	 * This method executes the actions given by the transition, e.g. moving into new state, notifying
+	 * the initiator about that, throwing faults, sending acknownledgements etc.
+	 * 
+	 * 
+	 * @param transition The transition object from State
+	 * @param params Any parameters that the participant sent along
+	 * @throws WrongMethodCallException 
+	 * @throws RemoteException 
+	 */
+	private void handleTransition(
+			final AbstractStateTransition transition, 
+			final AnyContentType params
+	) throws WrongMethodCallException, RemoteException{
+		
+		// Suppress compiler warning about unused parameter
+		if (params != null)
+			params.toString();
+		
+		// Check if there actually is a transition 
+		if (transition == null)
+			return;
+		
+		if (transition instanceof StateTransitionFault){
+			final StateTransitionFault stf = (StateTransitionFault) transition;
+			throw stf.getAxisFault();
+			
+		}else if(transition instanceof StateTransitionIgnore){
+			// Ignore
+			
+		}else if (transition instanceof StateTransitionResend){
+			final StateTransitionResend str = (StateTransitionResend) transition;
+			this.tellAgain(str.getMessageToResend());
+		
+		}else if (transition instanceof StateTransitionResendPreviousState){
+			final QName messageToResend = this.currState.getMessageForTransition(this.currState.getLastState(), this.currState.getSecondLastState());
+			tellAgain(messageToResend);
+
+		}else if (transition instanceof StateTransitionState){
+			final StateTransitionState sts = (StateTransitionState) transition;
+			System.out.println(" Participant changed state to "+sts.getState());
+			this.transactionContext.handleStateTransition(this, sts.getState());
+
+		}else{
+			throw new IllegalArgumentException("Sorry, handleTransition does not know how to handle "+transition);
+		}
+	}
+	
+	/**
+	 * Send some message to the participant. This method may only be used with participant operations
+	 * that do not require arguments.
+	 * This method ensures that the message to be sent is valid in the
+	 * current state of the participant and throws an exception if not.
+	 * If the message is OK, it is sent out and the associated state change is performed.
+	 * 
+	 * Calls @see #tellAgain(QName) to actually deliver the message.
+	 * 
+	 * This method is called from all the public tellXXX() methods in this class,
+	 * e.g. @see #tellCancel().
+	 * 
+	 * @param message The message to send.
+	 * @throws RemoteException If the participant did not accept the message
+	 */
+	protected synchronized void tell(final QName message) throws RemoteException{
+		final QName stateBefore = this.currState.getCurrentState();
+		
+		if (this.currState.handleOutgoingMessage(message) ){
+			// Message was OK and the new state has been set
+		
+			final QName stateAfter = this.currState.getCurrentState();
+			
+			if (stateBefore != null && (! stateBefore.equals(stateAfter))){
+				this.transactionContext.handleStateTransition(this, stateAfter);
+			}
+			
+			this.tellAgain(message);
+		}else{
+			// Error !
+			throw State.GET_INVALID_STATE_SOAP_FAULT();
+		}
+	}
+	/**
+	 * Forward some message to the participant. This method may only be used with participant operations
+	 * that do not require arguments.
+	 * This method does no more than send the message out.
+	 * @param message The message to send.
+	 * @throws RemoteException If the participant did not accept the message
+	 */
+	protected void tellAgain(final QName message) throws RemoteException{
+		final AbstractCoordParticipantProxy proxy =
+			this.getParticipantProxy();
+
+		if (State.MESSAGE_CANCEL.equals(message)){
+			proxy.cancelOperation(null);
+			
+		}else if (State.MESSAGE_COMPENSATE.equals(message)){
+			proxy.compensateOperation(null);
+
+		}else if (State.MESSAGE_CLOSE.equals(message)){
+			proxy.closeOperation(null);
+			
+		}else if (State.MESSAGE_EXITED.equals(message)){
+			proxy.exitedOperation(null);
+			
+		}else if (State.MESSAGE_FAULTED.equals(message)){
+			proxy.faultedOperation(null);
+			
+		}else if (State.MESSAGE_GETSTATUS.equals(message)){
+			proxy.getStatusOperation(null);
+			
+		}else{
+			throw new IllegalArgumentException("Sorry, cannot tell a participant "+message);
+		}
+	}
+
+	/**
+	 * Get the participant matchcode that was set for this participant.
+	 * @return This participant's matchcode.
+	 */
+	public String getMatchcode() {
+		return this.matchcode;
+	}
+
+	/**
+	 * Return the result state of the participant, either
+	 *  Completing
+	 *  Canceling
+	 *  Exiting
+	 *  Faulting
+	 * when ended;
+	 * 
+	 * Completed, when completed;
+	 * 
+	 * else Active .
+	 * @return The state characterizing the participant's outcome best.
+	 */
+	public QName getResultState() {
+		return this.currState.getResultState();
+	}
+}

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/AbstractCoordParticipantProxy.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/AbstractCoordParticipantProxy.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/AbstractCoordParticipantProxy.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/AbstractCoordParticipantProxy.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+/**
+ * This interface defines common methods all BusinessActivity participants share.
+ * 
+ * In fact, as the BAwPC and BAwCC protocols only differ by one single state and one single message,
+ * this interface helps reduce duplicate code. 
+ *  
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ *
+ */
+public interface AbstractCoordParticipantProxy {
+
+	/**
+	 * Invoke the "close" operation on the participant.
+	 * @param parameters Parameters.
+	 * @throws java.rmi.RemoteException A fault from the participant.
+	 */
+    public void closeOperation(org.apache.kandula.wsba.NotificationType parameters) throws java.rmi.RemoteException;
+
+	/**
+	 * Invoke the "cancel" operation on the participant.
+	 * @param parameters Parameters.
+	 * @throws java.rmi.RemoteException A fault from the participant.
+	 */
+    public void cancelOperation(org.apache.kandula.wsba.NotificationType parameters) throws java.rmi.RemoteException;
+    
+	/**
+	 * Invoke the "compensate" operation on the participant.
+	 * @param parameters Parameters.
+	 * @throws java.rmi.RemoteException A fault from the participant.
+	 */
+    public void compensateOperation(org.apache.kandula.wsba.NotificationType parameters) throws java.rmi.RemoteException;
+    
+	/**
+	 * Invoke the "faulted" operation on the participant.
+	 * @param parameters Parameters.
+	 * @throws java.rmi.RemoteException A fault from the participant.
+	 */
+    public void faultedOperation(org.apache.kandula.wsba.NotificationType parameters) throws java.rmi.RemoteException;
+    
+	/**
+	 * Invoke the "exited" operation on the participant.
+	 * @param parameters Parameters.
+	 * @throws java.rmi.RemoteException A fault from the participant.
+	 */
+    public void exitedOperation(org.apache.kandula.wsba.NotificationType parameters) throws java.rmi.RemoteException;
+    
+	/**
+	 * Invoke the "getStatus" operation on the participant.
+	 * @param parameters Parameters.
+	 * @throws java.rmi.RemoteException A fault from the participant.
+	 */
+    public void getStatusOperation(org.apache.kandula.wsba.NotificationType parameters) throws java.rmi.RemoteException ;
+    
+	/**
+	 * Invoke the "status" operation on the participant.
+	 * @param parameters Parameters.
+	 * @throws java.rmi.RemoteException A fault from the participant.
+	 */
+    public void statusOperation(org.apache.kandula.wsba.StatusType parameters) throws java.rmi.RemoteException;
+}

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAAtomicOutcome.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAAtomicOutcome.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAAtomicOutcome.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAAtomicOutcome.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+import javax.xml.namespace.QName;
+
+/**
+ * This class is a container for atomic business activity outcomes.
+ * 
+ * After instantiating it, the result is undecided. At any given point,
+ * the BACoordinator may call either @see #decideToClose() or @see #decideToCancelOrCompensate() ,
+ * which sets the final outcome.
+ * After that, no more methods may be called.
+ * 
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ *
+ */
+public class BAAtomicOutcome {
+	/**
+	 * The result QName for coordination contexts that are not yet decided.
+	 */
+	public static final QName RESULT_UNDECIDED = new QName(BACoordinator.PROTOCOL_ID_INITIATOR, "AtomicOutcome_Undecided");
+	
+	/**
+	 * The result QName for coordination contexts that are decided to close.
+	 */
+	public static final QName RESULT_CLOSE = new QName(BACoordinator.PROTOCOL_ID_INITIATOR, "AtomicOutcome_Close");
+	
+	/**
+	 * The result QName for coordination contexts that are decided to cancel or compensate.
+	 */
+	public static final QName RESULT_COMPENSATE = new QName(BACoordinator.PROTOCOL_ID_INITIATOR, "AtomicOutcome_Compensate");
+
+
+	/**
+	 * The private field where the result qname is stored.
+	 */
+	private QName myOutcome = RESULT_UNDECIDED;
+	
+	/**
+	 * Set the final outcome to CLOSE.
+	 * If isDecided() is already true, this method will throw an IllegalStateException. 
+	 *
+	 */
+	public void decideToClose(){
+		synchronized(this){
+			if (isDecided()){
+				throw new IllegalStateException("Sorry, this outcome has already been decided: "+this.myOutcome);
+			}
+
+			this.myOutcome = RESULT_CLOSE;
+		}
+	}
+
+	/**
+	 * Set the final outcome to CANCEL or COMPENSATE.
+	 * If isDecided() is already true, this method will throw an IllegalStateException. 
+	 *
+	 */
+	public void decideToCancelOrCompensate(){
+		synchronized(this){
+			if (isDecided()){
+				throw new IllegalStateException("Sorry, this outcome has already been decided: "+this.myOutcome);
+			}
+			this.myOutcome = RESULT_COMPENSATE;
+		}
+	}
+
+	/**
+	 * Query if the outcome has alredy been decided.
+	 * @return true, if the outcome has already been decided; false, if not.
+	 *
+	 */
+	public boolean isDecided(){
+		if (RESULT_UNDECIDED.equals( this.myOutcome )){
+			return false;
+		}
+		
+		return true;
+	}
+
+	/**
+	 * Query if the outcome has alredy been decided to successfully close the transaction. 
+	 * @return true, if the outcome has already been decided to close; false, if not.
+	 *
+	 */
+	public boolean isDecidedToClose(){
+		return RESULT_CLOSE.equals( this.myOutcome );
+	}
+
+	/**
+	 * Query if the outcome has alredy been decided to roll back (cancel or compensate) the transaction. 
+	 * @return true, if the outcome has already been decided to cancel or compensate; false, if not.
+	 *
+	 */
+	public boolean isDecidedToCancelOrCompensate(){
+		return RESULT_COMPENSATE.equals( this.myOutcome );
+	}
+
+	/**
+	 * Query the outcome decision.
+	 * @return null, if undecided; or one of @see #RESULT_CLOSE and @see #RESULT_COMPENSATE , if
+	 * already decided.
+	 *
+	 */
+	public QName getOutcomeDecision(){
+		if (this.isDecided())
+			return this.myOutcome;
+			
+		return null;
+	}
+
+	/**
+	 * Query the current outcome.
+	 * @return @see #RESULT_UNDECIDED if undecided, or one of @see #RESULT_CLOSE and @see #RESULT_COMPENSATE , if
+	 * already decided.
+	 *
+	 */
+	public QName getOutcome(){
+		return this.myOutcome;
+	}
+}

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BACoordinator.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BACoordinator.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BACoordinator.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BACoordinator.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,525 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+
+import java.rmi.RemoteException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.soap.Name;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.components.uuid.UUIDGen;
+import org.apache.axis.components.uuid.UUIDGenFactory;
+import org.apache.axis.message.addressing.EndpointReference;
+import org.apache.axis.types.URI;
+import org.apache.axis.types.URI.MalformedURIException;
+import org.apache.kandula.coordinator.CallbackRegistry;
+import org.apache.kandula.coordinator.CoordinationContext;
+import org.apache.kandula.coordinator.CoordinationService;
+import org.apache.kandula.coordinator.Coordinator;
+import org.apache.kandula.coordinator.CoordinatorImpl;
+import org.apache.kandula.coordinator.InvalidCoordinationProtocolException;
+import org.apache.kandula.coordinator.TimedOutException;
+import org.apache.kandula.coordinator.ba.ProtocolType;
+import org.apache.kandula.coordinator.ba.State;
+import org.apache.kandula.wsba.StateType;
+import org.apache.kandula.wsba.StatusType;
+import org.apache.kandula.wscoor.CreateCoordinationContextTypeCurrentContext;
+
+import org.apache.kandula.wsbai.BAParticipantReferenceType;
+import org.apache.kandula.wsbai.BAParticipantType;
+
+/**
+ * Base class for all WS-BusinessActivity coordinators.
+ * 
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ *
+ */
+public abstract class BACoordinator extends CoordinatorImpl {
+	/**
+	 * The QName used to identify the BA with Coordinator Completion protocol.
+	 * TODO WSBA Change this to the final initiator protocol identifier
+	 */
+	public final static String PROTOCOL_ID_INITIATOR = "http://big.tuwien.ac.at/ws-ba--extensions/protocol/initiator";
+	
+	/**
+	 * The QName used to identify the Business Activity "Atomic" Outcome
+	 */
+	public final static String COORDINATION_TYPE__ATOMIC = "http://schemas.xmlsoap.org/ws/2004/10/wsba/AtomicOutcome";
+	
+	/**
+	 * The QName used to identify the Business Activity "Mixed" Outcome
+	 */
+	public final static String COORDINATION_TYPE__MIXED = "http://schemas.xmlsoap.org/ws/2004/10/wsba/MixedOutcome";
+	
+	/**
+	 * This QName is used to pass around the initiator's uuid.
+	 */
+	public static final QName INITIATOR_REF = new QName(
+			"http://ws.apache.org/kandula", "InitiatorRef"
+	);
+	
+	/**
+	 * This QName identifies an error that is thrown when attempting to register
+	 * a given matchcode twice in a context
+	 */
+	public static final QName DUPLICATE_MATCHCODE_FAULT = new QName(
+			PROTOCOL_ID_INITIATOR, "duplicateMatchcodeFault"
+	);
+	
+	/**
+	 * Return a new AxisFault instance with its faultCode set to
+	 * the  @see #DUPLICATE_MATCHCODE_FAULT QName.
+	 * @param matchcode The matchcode that was requested twice.
+	 * @return AxisFault
+	 */
+	public AxisFault DUPLICATE_MATCHCODE_SOAP_FAULT(final String matchcode){
+		return new AxisFault(
+				DUPLICATE_MATCHCODE_FAULT,
+				"Attempted to register a matchcode that was already in use: "+matchcode,
+				"", null
+		);
+	}
+	
+	/*
+	 * = = = = = = = = = = = = = = =
+	 */
+	
+	/**
+	 * This field stores the chosen outcome Type (mixed/atomic).
+	 */
+	private final String outcomeType ;
+	
+	/**
+	 * The participants map contains all registered participants, accessible by
+	 * their Participant UUID.
+	 * Access to this map should be synchronized for any write access and for methods
+	 * that use iterators or enumerations derived from the map. The map is expected
+	 * to only extend, it never loses entries.
+	 */
+	private final Map participants = new HashMap();
+	
+	/**
+	 * This map contains a matchcode --> participant association. matchcodes
+	 * are inserted with a null value as soon as the initiator requests 
+	 * a registration service endpoint for a matchcode.
+	 * Synchronize access to this map!! 
+	 */
+	private final Map participantMatchcodes = new HashMap();
+	
+	/**
+	 * A reference to the initiator, if they already registered.
+	 */
+	private InitiatorProxy initiator = null;
+	
+	/**
+	 * The default constructor. Use this to create a new Business Activity Coordinator.
+	 * If superContext is given, this coordinator will register itself as a CoordinatorCompletion
+	 * participant in the supercontext and will provide the initiator with all messages and state
+	 * changes related to the supercontext. See the WSBAI specification for more detail.
+	 *  
+	 * @param pOutcomeType The outcome type for this coordination context.
+	 * @param superContext The super context, if this is a subcontext
+	 * @throws MalformedURIException Exception if the OutcomeType could not be parsed
+	 * @throws InvalidOutcomeAssertion  Exception if the OutcomeType could be parsed, but not accepted
+	 */
+	protected BACoordinator(
+			final String pOutcomeType,
+			final CreateCoordinationContextTypeCurrentContext superContext
+	) 
+		throws MalformedURIException, InvalidOutcomeAssertion
+	{		
+		super(pOutcomeType);
+		
+		if (superContext != null){
+			// Check the super context 
+			if (false
+					|| COORDINATION_TYPE__ATOMIC.equals( superContext.getCoordinationType().toString() ) 
+					|| COORDINATION_TYPE__MIXED.equals( superContext.getCoordinationType().toString() )
+			){
+				// Super's coordination type is OK
+			}else{
+				throw new IllegalArgumentException("The Kandula Business Activity coordination service currently can only create subordinate coordination contexts to a WS-BA parent context.");
+			}
+			
+			// TODO HE set super context and act appropriately...
+			
+			
+		} // end supercontext checks
+		
+		if (COORDINATION_TYPE__ATOMIC.equals(pOutcomeType)){
+			this.outcomeType = pOutcomeType;
+		}else if (COORDINATION_TYPE__MIXED.equals(pOutcomeType)){
+			this.outcomeType = pOutcomeType;
+		}else {
+			throw new InvalidOutcomeAssertion();
+		}
+	}
+	
+	
+	/**
+	 * Check if a particular match code has already been asked for.
+	 * @param matchcode The match code to check.
+	 * @return true, if the match code is available; false, if not.
+	 */
+	protected boolean isMatchCodeAvailable(final String matchcode){
+		return (! this.participantMatchcodes.containsKey(matchcode));
+	}
+	
+	/**
+	 * Activate a particular matchcode. A matchcode is used by the initiator to identify
+	 * the transaction's participants.
+	 * By default, we only allow registrations for protocols that include a valid matchcode
+	 * that is activated, but not yet taken.
+	 * This method returns an registrationService endpoint that is already tagged with
+	 * the requested matchcode, if it was available.
+	 * If the requested matchcode has already been taken, an invalidargumentexception is thrown.
+	 *  
+	 * @param matchcode The match code to register and activate
+	 * @return Endpoint to this context's registration service, tagged with the match code.
+	 * @throws AxisFault A ready-made fault, if the match code is already reserved or taken.
+	 */
+	public CoordinationContext registerMatchcode(final String matchcode) throws AxisFault{
+		synchronized (this.participantMatchcodes) {
+			if (matchcode == null || matchcode.length()==0 )
+				throw new IllegalArgumentException("The matchcode must not be null or emtpy!");
+			
+			if (! this.isMatchCodeAvailable(matchcode)){
+				throw DUPLICATE_MATCHCODE_SOAP_FAULT(matchcode);
+			}
+			
+			this.participantMatchcodes.put(matchcode, null);
+			
+			return this.getCoordinationContext(matchcode);
+		} // end synchronized participantMatchcodes
+	}
+	/**
+	 * Register a participant for one of the BAwCC or BAwPC protocols and
+	 * return the protocol service's endpoint reference.
+	 * 
+	 * @param protocol The requested protocol.
+	 * @param participantEndpoint The participant's endpoint.
+	 * @param matchcode The match code the participant asked for.
+	 * @return The endpoint reference of the coordinator's protocol service, tagged with the
+	 *  participant and transaction identifiers.
+	 *  
+	 * @throws InvalidCoordinationProtocolException 
+	 */
+	public EndpointReference register(
+			final String protocol, 
+			final EndpointReference participantEndpoint,
+			final String matchcode
+	) 
+	throws InvalidCoordinationProtocolException {
+		
+		// Check, whether a "valid" callback was supplied
+		if (participantEndpoint == null)
+			throw new IllegalArgumentException("Register: Participant Endpoint must not be null");
+		
+		
+		// Calculate the new participant's GUID
+		// The kandula coordination service
+		final CoordinationService cs = CoordinationService.getInstance();
+		
+		final UUIDGen gen = UUIDGenFactory.getUUIDGen();
+		final String newRef = "uuid:" + gen.nextUUID();
+		
+		final EndpointReference  epr;
+		
+		try{
+			// Check whether a valid protocol was supplied and register
+			if (protocol.equals(PROTOCOL_ID_INITIATOR)){
+				// OK, register as initiator; synchronize and set the initiator fields
+
+				synchronized(this){				
+					if (this.initiator != null)
+						throw new IllegalStateException("Sorry, there already is an initiator registered!");
+					
+					this.initiator = new InitiatorProxy(newRef, participantEndpoint);
+					epr = cs.getInitiatorCoordinatorService(this, newRef);
+				} // end synchronized this
+			}else{
+				// Other protocols
+				final AbstractCoordParticipant newParticipant;
+				
+				/*
+				 * While registration is in progress, lock the match code table
+				 * 
+				 */
+				synchronized(this.participantMatchcodes){
+					if (! this.participantMatchcodes.containsKey(matchcode)){
+						throw new IllegalArgumentException("Sorry, the matchcode "+matchcode+" has not been activated.");
+					}
+					if (this.participantMatchcodes.get(matchcode) != null){
+						final IllegalArgumentException x = new IllegalArgumentException("Sorry, the matchcode "+matchcode+" has already been taken.");
+						throw x;
+					}
+	
+					if (! this.isRegistrationPossible() ){
+						final AxisFault af = CONTEXT_REFUSED_SOAP_FAULT();
+						af.addFaultDetailString("The context exists, but work has progressed so far that no more registrations are accepted.");
+						throw af;
+					}
+					
+					if (protocol.equals(ProtocolType.PROTOCOL_ID_CC.getNamespaceURI()+ProtocolType.PROTOCOL_ID_CC.getLocalPart())){
+						// OK, register for Coordinator Completion 
+						
+						newParticipant = new BAwCCCoordParticipant(newRef, participantEndpoint, this, matchcode);
+					}else if (protocol.equals(ProtocolType.PROTOCOL_ID_PC.getNamespaceURI()+ProtocolType.PROTOCOL_ID_PC.getLocalPart())){
+						
+						// OK, register for Participant Completion
+						
+						newParticipant = new BAwPCCoordParticipant(newRef, participantEndpoint, this, matchcode);
+					}else{
+						throw new InvalidCoordinationProtocolException();
+					}
+					
+					// Register participant object
+					this.participantMatchcodes.put(matchcode, newParticipant);
+				} // End synchronized (this.participantMatchcode)
+
+				/*
+				 * Synchronize on both this (used by buildParticipantList) and this.participants
+				 * (used by registration) to lock participant lists before adding
+				 */
+				synchronized(this){
+					synchronized (this.participants) {
+						this.participants.put(newRef, newParticipant);
+					}
+				}
+				epr = cs.getCoordinatorService(this, newRef, protocol);
+				CallbackRegistry.getInstance().registerCallback(newParticipant);
+			} // End protocol switch 
+		}
+		catch(AxisFault f){
+			throw new IllegalArgumentException("Sorry, could not instantiate a participant: "+f);
+		}
+		return epr;
+	}
+	
+	/**
+	 * Check if enrolling a new participant is allowed in the current state
+	 * of the transaction.
+	 * @return false, if registration requests shall be rejected.
+	 */
+	abstract boolean isRegistrationPossible();
+
+
+	/**
+	 * Registers an incoming fault.
+	 * @param code The fault code.
+	 */
+	public void onFault(Name code) {
+		// TODO WSBA Handle faults
+		
+		System.out.println("[BACoordinator] onFault: " + code);
+	}
+	
+	/**
+	 * The transaction context timed out. Notify all participants 
+	 * and get outta here!
+	 * @throws TimedOutException ???
+	 */
+	public void timeout() throws TimedOutException {
+		// TODO WSBA Handle timeouts
+		
+		if (false)
+			throw new TimedOutException();
+	}
+	
+	/**
+	 * This coordinator's endpoint reference.
+	 * (Seems to be an unused method, since there is always an UnsupportedOperationException thrown)
+	 * @return ERROR !
+	 */
+	public EndpointReference getEndpointReference() {
+		throw new UnsupportedOperationException();
+	}
+	
+	/**
+	 * Returns this Coordinator's coordination type.
+	 * 
+	 * @return One of COORDINATION_TYPE__ATOMIC and COORDINATION_TYPE__MIXED
+	 * @see #COORDINATION_TYPE__ATOMIC
+	 * @see #COORDINATION_TYPE__MIXED
+	 */
+	public String getOutcomeType() {
+		return this.outcomeType;
+	}
+	
+	/**
+	 * Check, if the given participant is a registered participant in this context.
+	 * @param participant The participant.
+	 * @return true, if the participant is registered in the current transaction; false, if not.
+	 */
+	public boolean containsParticipant(final AbstractCoordParticipant participant){
+	
+		// Doesn't need synchronization since de-registration is not possible
+		
+		return this.participants.containsValue(participant);
+	}
+	
+	/**
+	 * This method is used by participant objects to signal state changes to the coordination context.
+	 * It is synchronized to avoid any problems that may arise when multiple participants change
+	 * states at the same time.
+	 *
+	 * This method contains any process logic that does not need business logic and hence may be 
+	 * implemented in the coordinator, e.g. automatically
+	 * acknowledging state changes as ACTIVE->EXIT->EXITING->EXITED->ENDED .
+	 * 
+	 * Any state change will also be automatically be forwarded to the initiator. For those state
+	 * changes where the coordinator does not have sufficient knowledge of the initiator's goals to
+	 * direct the participant to the next state, it will wait for the initiator to issue new commands.
+	 * 
+	 * @param participant The participant that changed states
+	 * @param newState The state after the transition (= current state of the participant)
+	 * @throws RemoteException Exception while handling the transition. 
+	 */
+	public void handleStateTransition(
+			final AbstractCoordParticipant participant,
+			final QName newState
+	) throws RemoteException {
+		// TODO WSBA Forward any state change to the initiator
+
+		// Ensure we may change participant states
+		// (this should be the case anyways)
+		synchronized(this){
+			if (State.STATE_EXITING.equals(newState)){
+				// Participant is in state EXITING, send EXITED and set state to ENDED.
+				participant.tellExited();
+			}else if (false 
+					|| State.STATE_FAULTING.equals(newState)
+					|| State.STATE_FAULTING_ACTIVE.equals(newState)
+					|| State.STATE_FAULTING_COMPENSATING.equals(newState)
+			){
+				participant.tellFaulted();
+			}else{
+				System.out.println("State transition to "+newState+" must be handled by initiator!");
+			}
+
+			/*
+			 *  As soon as the ENDED state is reached, we no longer accept
+			 *  messages from the client and hence remove them from the
+			 *  callback registry. (This also aborts the timeout timertask.)
+			 *  We dont remove them from the participants map, so the initiator
+			 *  can still see the participant and their state.
+			 */
+			if (State.STATE_ENDED.equals(newState)){
+				CallbackRegistry.getInstance().remove(participant);
+			}
+		}
+	}
+	
+	
+	/**
+	 * Return a participant list. This method is synchronized on "this"
+	 * and "this.participants" to ensure maximum consistency.
+	 * 
+	 * @return An array of BAParticipantType objects.
+	 */
+	public BAParticipantType[] buildParticipantList() {
+		final BAParticipantType[] result ;
+		
+		synchronized (this){
+			synchronized (this.participants) {
+				result = new BAParticipantType[this.participants.size()];
+				
+				final Iterator it = this.participants.values().iterator();
+				int count   = 0;
+				
+				// circle through the participants...
+				while(it.hasNext()){
+					final AbstractCoordParticipant participant = (AbstractCoordParticipant) it.next();
+					
+					final URI proto;
+					{
+						URI tmpProto = null;
+						try{
+							tmpProto = new org.apache.axis.types.URI(
+									participant.getProtocolIdentifier().getNamespaceURI()+
+									participant.getProtocolIdentifier().getLocalPart()
+							);
+						}
+						catch(MalformedURIException x){
+							// forget it
+						}
+						proto = tmpProto;
+					}
+					
+					final StateType resultState = StateType.fromValue(participant.getResultState());
+					
+					// Fill all fields...
+					result[count] = new BAParticipantType(
+							new BAParticipantReferenceType(participant.getMatchcode()),
+							new StatusType(StateType.fromValue(participant.getCurrentState()), null),
+							new StatusType(resultState, null),
+							proto
+					);
+					
+					count++;
+				}
+			} // end synchronized this.participants
+		} // end synchronized this
+		return result;
+	}
+	
+	/**
+	 * Fetches the participant associated to the given matchcode in the current context.
+	 * Returns null if either the matchcode was not registered in the context, or 
+	 * the matchcode is valid but no participant has yet registered for it.
+	 * @param matchCode
+	 * @return The participant that registered for the requested matchcode, or null
+	 * 	if the matchcode is either unused or no participant registered for it.
+	 */
+	public AbstractCoordParticipant getParticipantByMatchcode(final String matchCode){
+		return (AbstractCoordParticipant) this.participantMatchcodes.get(matchCode);
+	}
+	
+	/**
+	 * Returns the collection of participants who are registered in the transaction. 
+	 * @return The participant collection.
+	 */
+	protected final Collection getParticipants(){
+		return this.participants.values();
+	}
+	
+	/**
+	 * Checks if the current request has all properties a request from the genuine
+	 * initiator must have. At this time, we check that the @see 
+	 * @throws RemoteException
+	 */
+	public void ensureRequestOriginatesFromInitiatorOrThrowFault() throws RemoteException{
+		final String initiatorRef = CallbackRegistry.getRef(BACoordinator.INITIATOR_REF);
+		
+		if (initiatorRef != null
+				&& initiatorRef.equals(this.initiator.myID) 
+		){
+			// OK
+		}else{
+			throw Coordinator.CONTEXT_REFUSED_SOAP_FAULT();
+		}
+	}
+
+}

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BACoordinatorService.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BACoordinatorService.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BACoordinatorService.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BACoordinatorService.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+import java.rmi.RemoteException;
+
+import javax.xml.namespace.QName;
+
+import org.apache.kandula.coordinator.Callback;
+import org.apache.kandula.coordinator.CallbackRegistry;
+import org.apache.kandula.coordinator.Coordinator;
+import org.apache.kandula.coordinator.ba.State;
+import org.apache.kandula.wsba.BusinessAgreementWithCoordinatorCompletionCoordinatorPortType;
+import org.apache.kandula.wsba.BusinessAgreementWithParticipantCompletionCoordinatorPortType;
+import org.apache.kandula.wsba.ExceptionType;
+import org.apache.kandula.wsba.NotificationType;
+import org.apache.kandula.wsba.StatusType;
+
+/**
+ * This is the class that represents the Business Activity protocol web service
+ * to the client.
+ * Internally, on an incoming message, it checks whether that message can be correlated
+ * to an existing business activity, and forwards it to the BACoordinator object
+ * managing that activity.
+ * 
+ * 
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ * 
+ *
+ */
+public class BACoordinatorService implements
+		BusinessAgreementWithCoordinatorCompletionCoordinatorPortType,
+		BusinessAgreementWithParticipantCompletionCoordinatorPortType {
+
+	/**
+	 * Retrieves the BACoordinator associated with the coordinator context attached to
+	 * the current message.
+	 * If no context could be associated, an exception is thrown. This method never returns null.
+	 * @return The BACoordinator.
+	 * @throws RemoteException
+	 */
+	public static BACoordinator getBACoordinatorOrThrowFault() throws RemoteException{
+		final Callback c = CallbackRegistry.getInstance().correlateMessage(
+				CallbackRegistry.CALLBACK_REF, false
+		);
+			
+		if (c == null)
+			throw Coordinator.CONTEXT_REFUSED_SOAP_FAULT();
+			
+		if (! (c instanceof BACoordinator) || c == null)
+			throw Coordinator.CONTEXT_REFUSED_SOAP_FAULT();
+		
+		return (BACoordinator) c;
+	}
+	
+	/**
+	 * Retrieves the Participant who sent the current message.
+	 * @param context The current transaction's context.
+	 * @return The participant, if found
+	 * @throws RemoteException if no participant could be found
+	 */
+	protected static AbstractCoordParticipant getBAParticipantOrThrowFault(final BACoordinator context) throws RemoteException {
+		final AbstractCoordParticipant p = (AbstractCoordParticipant) CallbackRegistry.getInstance().correlateMessage(
+				Coordinator.PARTICIPANT_REF, false
+		);
+
+		// The message could not be correlated to a registered participant
+		if (p == null){
+			throw Coordinator.CONTEXT_REFUSED_SOAP_FAULT() ;
+		}
+
+		// The message contained a reference to a participant and a context,
+		// but the participant is not registered in the context
+		if (! context.containsParticipant(p)){
+			throw Coordinator.CONTEXT_REFUSED_SOAP_FAULT();
+		}
+		
+		return p;
+	}
+
+	/*
+	 * Below are the web service's methods 
+	 */
+	
+	/**
+	 * Completed.
+	 * @param parameters Any parameters. 
+	 * @throws RemoteException Any fault thrown while processing the incoming message.
+	 */
+	public void completedOperation(final NotificationType parameters)
+			throws RemoteException {
+		handleIncomingMessage(State.MESSAGE_COMPLETED, parameters);
+	}
+
+	/**
+	 * Fault.
+	 * @param parameters Any parameters. 
+	 * @throws RemoteException Any fault thrown while processing the incoming message.
+	 */
+	public void faultOperation(final ExceptionType parameters) throws RemoteException {
+		handleIncomingMessage(State.MESSAGE_FAULT, parameters);
+	}
+
+	/**
+	 * Compensated.
+	 * @param parameters Any parameters. 
+	 * @throws RemoteException Any fault thrown while processing the incoming message.
+	 */
+	public void compensatedOperation(final NotificationType parameters)
+			throws RemoteException {
+		handleIncomingMessage(State.MESSAGE_COMPENSATED, parameters);
+	}
+
+	/**
+	 * Closed
+	 * @param parameters Any parameters. 
+	 * @throws RemoteException Any fault thrown while processing the incoming message.
+	 */
+	public void closedOperation(final NotificationType parameters)
+			throws RemoteException {
+		handleIncomingMessage(State.MESSAGE_CLOSED, parameters);
+	}
+
+	/**
+	 * Canceled
+	 * @param parameters Any parameters. 
+	 * @throws RemoteException Any fault thrown while processing the incoming message.
+	 */
+	public void canceledOperation(final NotificationType parameters)
+			throws RemoteException {
+		handleIncomingMessage(State.MESSAGE_CANCELED, parameters);
+	}
+
+	/**
+	 * Exit
+	 * @param parameters Any parameters. 
+	 * @throws RemoteException Any fault thrown while processing the incoming message.
+	 */
+	public void exitOperation(final NotificationType parameters)
+			throws RemoteException {
+		handleIncomingMessage(State.MESSAGE_EXIT, parameters);
+	}
+
+	/**
+	 * GetStatus
+	 * @param parameters Any parameters. 
+	 * @throws RemoteException Any fault thrown while processing the incoming message.
+	 */
+	public void getStatusOperation(final NotificationType parameters)
+			throws RemoteException {
+		handleIncomingMessage(State.MESSAGE_GETSTATUS, parameters);
+	}
+
+	/**
+	 * Status
+	 * @param parameters Any parameters. 
+	 * @throws RemoteException Any fault thrown while processing the incoming message.
+	 */
+	public void statusOperation(final StatusType parameters) throws RemoteException {
+		handleIncomingMessage(State.MESSAGE_STATUS, parameters);
+	}
+
+	/*
+	 * End Web Service Methods
+	 */
+	
+	
+	/**
+	 * Handle an incoming messages. That is, fetch the coordination context associated 
+	 * with the given coordination context references; fetch the participant associated
+	 * with the given participant references;
+	 * and pass further message processing to the coordinator-side participant object.
+	 * @param messageType The message's type. @see CoordinationStates
+	 * @param params The message's parameters.
+	 * @throws RemoteException If context or participant could not be created, or message processing
+	 *   by the participant was not successfull, we throw an error back to the calling party.
+	 */
+	protected void handleIncomingMessage(final QName messageType, final NotificationType params) throws RemoteException{
+
+		final BACoordinator coord = getBACoordinatorOrThrowFault();
+		final AbstractCoordParticipant part = getBAParticipantOrThrowFault(coord);
+
+		System.out.println("+++ CoordIncoming: "+messageType+" ("+params+"+ in TX "+coord+" from participant "+part);
+	
+		if (messageType.equals(State.MESSAGE_GETSTATUS)){
+			// Reply with the status
+			
+			part.tellStatus();
+		}else{
+			part.handleIncomingMessage(messageType, params);
+		}
+	}
+	/**
+	 * Handle an incoming messages. That is, fetch the coordination context associated 
+	 * with the given coordination context references; fetch the participant associated
+	 * with the given participant references;
+	 * and pass further message processing to the coordinator-side participant object.
+	 * @param messageType The message's type. @see CoordinationStates
+	 * @param params The message's parameters.
+	 * @throws RemoteException If context or participant could not be created, or message processing
+	 *   by the participant was not successfull, we throw an error back to the calling party.
+	 */
+	protected void handleIncomingMessage(final QName messageType, final ExceptionType params) throws RemoteException{
+
+		final BACoordinator coord = getBACoordinatorOrThrowFault();
+		final AbstractCoordParticipant part = getBAParticipantOrThrowFault(coord);
+
+		System.out.println("+++ CoordIncoming: "+messageType+" ("+params+"+ in TX "+coord+" from participant "+part);
+		part.handleIncomingMessage(messageType, params);		
+	}
+	/**
+	 * Handle an incoming messages. That is, fetch the coordination context associated 
+	 * with the given coordination context references; fetch the participant associated
+	 * with the given participant references;
+	 * and pass further message processing to the coordinator-side participant object.
+	 * @param messageType The message's type. @see CoordinationStates
+	 * @param params The message's parameters.
+	 * @throws RemoteException If context or participant could not be created, or message processing
+	 *   by the participant was not successfull, we throw an error back to the calling party.
+	 */
+	protected void handleIncomingMessage(final QName messageType, final StatusType params) throws RemoteException{
+
+		final BACoordinator coord = getBACoordinatorOrThrowFault();
+		final AbstractCoordParticipant part = getBAParticipantOrThrowFault(coord);
+
+		System.out.println("+++ CoordIncoming: "+messageType+" ("+params+"+ in TX "+coord+" from participant "+part);
+		part.handleIncomingMessage(messageType, params);
+	}
+}

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwCCCoordParticipant.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwCCCoordParticipant.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwCCCoordParticipant.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwCCCoordParticipant.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+import java.net.MalformedURLException;
+import java.rmi.RemoteException;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.message.addressing.EndpointReference;
+import org.apache.kandula.coordinator.ba.ProtocolType;
+import org.apache.kandula.coordinator.ba.State;
+
+
+/**
+ * A server-side WS-BA transaction particpant, registered for the
+ * CoordinatorCompletion Protocol.
+ * 
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ *
+ */
+public class BAwCCCoordParticipant extends AbstractCoordParticipant {
+
+	private final BAwCCParticipantProxy myPCProxy;
+	
+	/**
+	 * The default constructor for the new participant.
+	 * 
+	 * @param participantID The participant's ID.
+	 * @param participantEPR The participant's protocol service endpoint reference.
+	 * @param coordinationContext The coordination context the participant is registered in.
+	 * @param matchcode The matchcode the participant was given by the initiator.
+	 * @throws AxisFault Any fault while initializing the participant object.
+	 */
+	public BAwCCCoordParticipant(
+			final String participantID, 
+			final EndpointReference participantEPR,
+			final BACoordinator coordinationContext, 
+			final String matchcode
+			
+	) throws AxisFault {
+		super(participantID, participantEPR, coordinationContext, matchcode);
+		
+		try {
+			this.myPCProxy = new BAwCCParticipantProxy(participantID, participantEPR);
+		} catch (MalformedURLException e) {
+			throw new AxisFault("ERROR!!! "+e);
+		}
+	}
+
+	/**
+	 * As this is a CC participant, always returns CC.
+	 * @return This particpant's protocol identifier.
+	 * @see ProtocolType#PROTOCOL_ID_CC
+	 */
+	public QName getProtocolIdentifier() {
+		return ProtocolType.PROTOCOL_ID_CC;
+	}
+
+	/*
+	 * Methods for the PC participant
+	 */
+	
+	/**
+	 * Tell the participant to complete
+	 * @throws java.rmi.RemoteException A fault from the participant.
+	 */
+	public void tellComplete() throws RemoteException {
+		this.tell(State.MESSAGE_COMPLETE);
+	}
+	
+	/**
+	 * Return the participant proxy
+	 * @return The participant proxy.
+	 */
+	public AbstractCoordParticipantProxy getParticipantProxy() {
+		return this.myPCProxy;
+	}
+	
+	/**
+	 * Overrides @see AbstractCoordParticipant#tellAgain(QName) , as the BAwCC participant
+	 * needs an additional message: @see State#MESSAGE_COMPLETED
+	 * @param message The message type to send.
+	 * @throws java.rmi.RemoteException A fault from the participant.
+	 */
+	protected void tellAgain(final QName message) throws RemoteException {
+		if (State.MESSAGE_COMPLETE.equals(message)){
+			this.myPCProxy.completeOperation(null);
+		}else{
+			super.tellAgain(message);
+		}
+	}
+
+}

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwCCParticipantProxy.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwCCParticipantProxy.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwCCParticipantProxy.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwCCParticipantProxy.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.message.addressing.EndpointReference;
+import org.apache.kandula.utils.AddressingHeaders;
+import org.apache.kandula.utils.Service;
+import org.apache.kandula.utils.TCPSnifferHelper;
+import org.apache.kandula.wsba.BusinessAgreementWithCoordinatorCompletionParticipantPortTypeBindingStub;
+
+/**
+ * This class is a wrapper around the autogenerated axis web service stubs.
+ * 
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ *
+ */
+public class BAwCCParticipantProxy
+	extends	BusinessAgreementWithCoordinatorCompletionParticipantPortTypeBindingStub
+	implements AbstractCoordParticipantProxy
+{
+
+	/**
+	 * The participant ID.
+	 */
+	protected final String myID;
+	
+	/**
+	 * The endpoint where the participant can be reached.
+	 */
+	protected final EndpointReference myEndpoint;
+
+	
+	/**
+	 * Current Addressing Headers
+	 */
+	final AddressingHeaders headers;
+
+	/**
+	 * Constructor for a new participant.
+	 * @param id The participant ID
+	 * @param epr The EPR the participant can be reached at.
+	 * @throws AxisFault ???
+	 * @throws MalformedURLException ??? 
+	 */
+	public BAwCCParticipantProxy(final String id, final EndpointReference epr)
+	throws AxisFault, MalformedURLException{
+		super(new URL(TCPSnifferHelper.redirect(epr.getAddress().toString())),
+				new Service());
+		this.headers = new AddressingHeaders(epr, null);
+		((Service) this.service).setAddressingHeaders(this.headers);
+
+		
+		if (id == null || id.length()==0)
+			throw new IllegalArgumentException("Sorry, participant ID must not be null or empty");
+		
+		if (epr == null)
+			throw new IllegalArgumentException("Sorry, participant EPR must not be null");
+		
+		this.myID = id;
+		this.myEndpoint = epr;
+	}
+
+	/**
+	 * The addressing headers this proxy is using.
+	 * @return The addressing headers.
+	 */
+	public AddressingHeaders getAddressingHeaders(){
+		return this.headers;
+	}
+
+}

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwPCCoordParticipant.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwPCCoordParticipant.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwPCCoordParticipant.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwPCCoordParticipant.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+import java.net.MalformedURLException;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.message.addressing.EndpointReference;
+import org.apache.kandula.coordinator.ba.ProtocolType;
+
+
+/**
+ * A server-side WS-BA transaction particpant, registered for the
+ * ParticipantCompletion Protocol.
+ * 
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ *
+ */
+public class BAwPCCoordParticipant extends AbstractCoordParticipant {
+
+	private final BAwPCParticipantProxy myPCProxy;
+	
+	/**
+	 * Build a coordinator side PC participant object and proxy.
+	 * 
+	 * @param participantID The participant's ID.
+	 * @param participantEPR The participant's EPR.
+	 * @param coordinationContext The coordination context the participant is enrolled in.
+	 * @param matchcode The participant's matchcode in the context.
+	 * @throws AxisFault Any fault from within.
+	 */
+	public BAwPCCoordParticipant(
+			final String participantID, 
+			final EndpointReference participantEPR,
+			final BACoordinator coordinationContext, 
+			final String matchcode
+	) throws AxisFault {
+		super(participantID, participantEPR, coordinationContext, matchcode);
+		
+		try{
+			this.myPCProxy = new BAwPCParticipantProxy(participantID, participantEPR);
+		}catch(MalformedURLException x){
+			throw new AxisFault("ERROR: "+x);
+		}
+	}
+	
+	/**
+	 * As this is a PC participant, always returns PC.
+	 * @see ProtocolType#PROTOCOL_ID_PC
+	 * @return The PC protocol's QName
+	 */
+	public QName getProtocolIdentifier() {
+		return ProtocolType.PROTOCOL_ID_PC;
+	}
+
+	/**
+	 * Return the participant proxy
+	 * @return The participant proxy.
+	 */
+	public AbstractCoordParticipantProxy getParticipantProxy() {
+		return this.myPCProxy;
+	}
+
+	/**
+	 * Methods for the PC participant - already implemented in @see org.apache.kandula.coordinator.ba.coordinator.AbstractCoordParticipant
+	 */
+	
+
+}

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwPCParticipantProxy.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwPCParticipantProxy.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwPCParticipantProxy.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwPCParticipantProxy.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.message.addressing.EndpointReference;
+import org.apache.kandula.utils.AddressingHeaders;
+import org.apache.kandula.utils.Service;
+import org.apache.kandula.utils.TCPSnifferHelper;
+import org.apache.kandula.wsba.BusinessAgreementWithParticipantCompletionParticipantPortTypeBindingStub;
+
+/**
+ * This class is a wrapper around the autogenerated axis web service stubs.
+ * 
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ *
+ */
+public class BAwPCParticipantProxy 
+	extends	BusinessAgreementWithParticipantCompletionParticipantPortTypeBindingStub
+	implements AbstractCoordParticipantProxy
+{
+
+	/**
+	 * The participant ID.
+	 */
+	protected final String myID;
+	
+	/**
+	 * The endpoint where the participant can be reached.
+	 */
+	protected final EndpointReference myEndpoint;
+
+	/**
+	 * Current addressing headers.
+	 */
+	final AddressingHeaders headers;
+
+	/**
+	 * Constructor for a new participant.
+	 * @param id The participant ID
+	 * @param epr The EPR the participant can be reached at.
+	 * @throws AxisFault ???
+	 * @throws MalformedURLException ??? 
+	 */
+	public BAwPCParticipantProxy(final String id, final EndpointReference epr)
+	throws AxisFault, MalformedURLException {
+		super(new URL(TCPSnifferHelper.redirect(epr.getAddress().toString())),
+				new Service());
+		this.headers = new AddressingHeaders(epr, null);
+		((Service) this.service).setAddressingHeaders(this.headers);
+
+		
+		if (id == null || id.length()==0)
+			throw new IllegalArgumentException("Sorry, participant ID must not be null or empty");
+		
+		if (epr == null)
+			throw new IllegalArgumentException("Sorry, participant EPR must not be null");
+		
+		this.myID = id;
+		this.myEndpoint = epr;
+	}
+
+	
+	/**
+	 * Current addressing headers.
+	 * @return Addressing headers.
+	 */
+	public AddressingHeaders getAddressingHeaders(){
+		return this.headers;
+	}
+
+}

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwithAtomicOutcomeCoordinator.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwithAtomicOutcomeCoordinator.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwithAtomicOutcomeCoordinator.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwithAtomicOutcomeCoordinator.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+
+import java.rmi.RemoteException;
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axis.types.URI.MalformedURIException;
+import org.apache.kandula.coordinator.ba.State;
+import org.apache.kandula.wscoor.CreateCoordinationContextTypeCurrentContext;
+
+
+/**
+ * This class represents an Business Activity coordinator for a context
+ * with Atomic Outcome assertion.
+ * 
+ * Atomic outcome means that all participants will be directed to either
+ *  - close, or
+ *  - cancel/compensate
+ *
+ * depending on the progress the participants made. If the transaction's state
+ * does not require the coordinator to automatically choose one of these
+ * options, the initiator must decide which outcome they desire.
+ * 
+ * The following rules apply to business activities with atomic outcome:
+ * <ul>
+ * <li>participants who 'exit' do not affect the progress of other participants and are discarded.
+ * <li>participants who 'fault' require all other participants to cancel or compensate, depending
+ * 	on their progress.
+ * <li>participants who 'cancel' while active or completing also require all other participants
+ * 	to cancel or compensate, again depending on their progress.
+ * <li>only if all participants progress to the 'completed' state may the initiator decide on the
+ * 	way to go.
+ * </ul>
+ *  
+ * This class overrides the handleTransition method of BACoordinator and adds handling for
+ * participants who reach one of the 'completed', 'exiting' or 'faulting' states and hence
+ * require action on the other participants.
+ * 
+ * 
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ *
+ */
+public class BAwithAtomicOutcomeCoordinator extends BACoordinator {
+
+	/**
+	 * The object containing the outcome decision. 
+	 */
+	private final BAAtomicOutcome myOutcome = new BAAtomicOutcome();
+	
+	/**
+	 * Default constructor, called by the activation service. Prepares a new
+	 * empty business activity context.
+	 * @param superContext The super context, null if there is no super context.
+	 *  
+	 * @throws MalformedURIException Indicates a severe programming error in the @see BACoordinator#COORDINATION_TYPE__ATOMIC constant.
+	 * @throws InvalidOutcomeAssertion Indicates a severe programming error in the @see BACoordinator#COORDINATION_TYPE__ATOMIC constant.
+	 */
+	public BAwithAtomicOutcomeCoordinator(
+			final CreateCoordinationContextTypeCurrentContext superContext
+	)
+		throws MalformedURIException, InvalidOutcomeAssertion
+	{
+		super(BACoordinator.COORDINATION_TYPE__ATOMIC, superContext);
+	}
+
+	/**
+	 * This method adds handling logic for participants that reach one of the
+	 * 'completed' or 'faulting' states and hence
+	 * may require action on the other participants.
+	 * 
+	 * This method uses the following process logic:
+	 * <ul>
+	 * <li>faulting: decide to cancel or compensate all participants
+	 * <li>completed: check if the outcome has already been decided. If yes, compensate; if no, check if all participants
+	 * 	are in state 'completed' and wait for the initiator to decide.
+	 * </ul> 
+	 * 
+	 * 
+	 * @see org.apache.kandula.coordinator.ba.coordinator.BACoordinator#handleStateTransition(org.apache.kandula.coordinator.ba.coordinator.AbstractCoordParticipant, javax.xml.namespace.QName)
+	 */
+	public void handleStateTransition(
+			final AbstractCoordParticipant participant, 
+			final QName newState
+	) throws RemoteException {
+		
+		synchronized(this){
+//			if (false
+//					|| State.STATE_FAULTING.equals(newState)
+//					|| State.STATE_FAULTING_ACTIVE.equals(newState)
+//			){
+				// new State: Faulting! decide to cancel/compensate if not already done
+				// remark: it is impossible that at this point it has already been decided to close, since
+				// fault is no valid message when closing.
+//				
+				// TODO BA Perhaps it is better to support this as an optional feature.
+				
+//				if (! this.myOutcome.isDecided()){
+//					System.out.println("Auto-deciding "+this.getID()+" to cancel/compensate due to participant fault ");
+//					this.myOutcome.decideToCancelOrCompensate();
+//				}
+				
+//				executeDecision();
+//			}else 
+			if (false
+					|| State.STATE_COMPLETED.equals(newState)
+			){
+				// If it has already been decided to abort the transaction,
+				// and a participant reports completed, automatically
+				// compensate them.
+				if (this.myOutcome.isDecidedToCancelOrCompensate()){
+					participant.tellCompensate();
+				}
+			}
+			
+			super.handleStateTransition(participant, newState);
+		}
+	}
+
+	/**
+	 * Execute a given decision.
+	 * This means, if decision is
+	 * <ul>
+	 * <li>undecided: throw illegalstateexception
+	 * <li>close: tell all participants who are in state completed to close.
+	 * <li>cancel or compensate: tell all participants who are in active or completing to cancel,
+	 *  participants who are in completed to compensate and ignore all others.
+	 * </ul>
+	 *
+	 */
+	protected void executeDecision() {
+		if (! this.myOutcome.isDecided())
+			throw new IllegalStateException("No decision to execute: it's still undecided!");
+
+		synchronized (this) {
+			final Collection participants = this.getParticipants();
+			final Iterator it = participants.iterator();
+
+			while(it.hasNext()){
+				final AbstractCoordParticipant part = (AbstractCoordParticipant) it.next();
+
+				if (this.myOutcome.isDecidedToClose()){
+					if (State.STATE_COMPLETED.equals( part.getCurrentState() ) ){
+						// We expect all participants to be in this state...
+						
+						try{
+							part.tellClose();
+						}catch(Exception e){
+							e.printStackTrace();
+							// Ignore exceptions
+						}
+					}
+					//	end Close Outcome 
+				}else if (this.myOutcome.isDecidedToCancelOrCompensate()){
+					final QName cState = part.getCurrentState();
+					
+					try{
+					if (false 
+							|| State.STATE_ACTIVE.equals( cState )
+							|| State.STATE_COMPLETING.equals( cState )
+					){
+						part.tellCancel();
+					}else if (false
+							|| State.STATE_COMPLETED.equals( cState )
+					){
+						part.tellCompensate();
+					}
+					}catch(Exception e){
+						e.printStackTrace();
+						// ignore exception
+					}
+					
+					// end cancel/compensate outcome
+				}else{
+					throw new IllegalArgumentException("Sorry, unknown decided outcome: "+this.myOutcome.getOutcome());
+				}
+			}
+		}
+	}
+
+	/**
+	 * Check if the current state of the transaction allows for additional
+	 * @see #myOutcome
+	 * @return true, if registration is possible.
+	 *         false, if no more registrations are accepted.
+	 * 
+	 */
+	boolean isRegistrationPossible() {
+		return (! this.myOutcome.isDecided());
+	}
+
+	/**
+	 * Return the outcome object.
+	 * @return The outcome container. 
+	 */
+	public BAAtomicOutcome getOutcomeDecision() {
+		return this.myOutcome;
+	}
+
+	
+}

Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwithMixedOutcomeCoordinator.java
URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwithMixedOutcomeCoordinator.java?view=auto&rev=548471
==============================================================================
--- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwithMixedOutcomeCoordinator.java (added)
+++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/BAwithMixedOutcomeCoordinator.java Mon Jun 18 13:10:02 2007
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007 The Apache Software Foundation.
+ * 
+ * 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.
+ *
+ *  @author Hannes Erven, Georg Hicker
+ */
+
+package org.apache.kandula.coordinator.ba.coordinator;
+
+import org.apache.axis.types.URI.MalformedURIException;
+import org.apache.kandula.wscoor.CreateCoordinationContextTypeCurrentContext;
+
+/**
+ * 
+ * @author Hannes Erven, Georg Hicker (C) 2006
+ *
+ */
+public class BAwithMixedOutcomeCoordinator extends BACoordinator {
+
+	/**
+	 * Create a new mixed outcome BA Coordinator.
+	 * 
+	 * @param superContext The super context, if any
+	 * @throws MalformedURIException Invalid URI.
+	 * @throws InvalidOutcomeAssertion Invalid Outcome Type
+	 */
+	public BAwithMixedOutcomeCoordinator(
+			final CreateCoordinationContextTypeCurrentContext superContext
+	) throws MalformedURIException, InvalidOutcomeAssertion {
+		super(BACoordinator.COORDINATION_TYPE__MIXED, superContext);
+	}
+
+	/**
+	 * Check if additional participants are allowed to register. With mixed
+	 * outcome, this is always true.
+	 * @return true
+	 */
+	boolean isRegistrationPossible() {
+		return true;
+	}
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: kandula-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: kandula-dev-help@ws.apache.org


Mime
View raw message