Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinationState.java URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinationState.java?view=auto&rev=548471 ============================================================================== --- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinationState.java (added) +++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinationState.java Mon Jun 18 13:10:02 2007 @@ -0,0 +1,473 @@ +/* + * 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.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.kandula.coordinator.ba.ProtocolType; +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.StateTransitionState; +import org.apache.kandula.coordinator.ba.participant.ParticipantState; + +/** + * Implementation of State with the Hashmap set for the different states of a + * Coordinator. + * + * @author Hannes Erven, Georg Hicker (C) 2006 + * + */ +public class CoordinationState extends State { + + /** + * The state table. + */ + protected final static HashMap states = new HashMap(); + + + static { + /* + * Initializing the HashMap for the ParticipantCompletion - Protocol + */ + { + // HashMap for ParticipantCompletion + final HashMap pc = new HashMap(); + { + // Messages in state ACTIVE + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionState( + STATE_EXITING)); + hm.put(MESSAGE_FAULT, new StateTransitionState( + STATE_FAULTING_ACTIVE)); + hm.put(MESSAGE_COMPLETED, new StateTransitionState( + STATE_COMPLETED)); + pc.put(STATE_ACTIVE, hm); + } + { + // Messages in state CANCELLING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionState( + STATE_ENDED)); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionState( + STATE_EXITING)); + hm.put(MESSAGE_FAULT, new StateTransitionState( + STATE_FAULTING_ACTIVE)); + hm.put(MESSAGE_COMPLETED, new StateTransitionState( + STATE_COMPLETED)); + pc.put(STATE_CANCELLING, hm); + } + { + // Messages in state COMPLETED + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_FAULT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPLETED, new StateTransitionIgnore()); + pc.put(STATE_COMPLETED, hm); + } + { + // Messages in state CLOSING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionState( + STATE_ENDED)); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_FAULT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPLETED, new StateTransitionResend( + MESSAGE_CLOSE)); + pc.put(STATE_CLOSING, hm); + } + { + // Messages in state COMPENSATING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionState( + STATE_ENDED)); + hm.put(MESSAGE_EXIT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_FAULT, new StateTransitionState( + STATE_FAULTING_COMPENSATING)); + hm.put(MESSAGE_COMPLETED, new StateTransitionResend( + MESSAGE_COMPENSATE)); + pc.put(STATE_COMPENSATING, hm); + } + { + // Messages in state FAULTING_ACTIVE + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_FAULT, new StateTransitionIgnore()); + hm.put(MESSAGE_COMPLETED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + pc.put(STATE_FAULTING_ACTIVE, hm); + } + + { + // Messages in state FAULTING_COMPENSATING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_FAULT, new StateTransitionIgnore()); + hm.put(MESSAGE_COMPLETED, new StateTransitionIgnore()); + pc.put(STATE_FAULTING_COMPENSATING, hm); + } + { + // Messages in state EXITING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionIgnore()); + hm.put(MESSAGE_FAULT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPLETED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + pc.put(STATE_EXITING, hm); + } + { + // Messages in state ENDED + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionIgnore()); + hm.put(MESSAGE_CLOSED, new StateTransitionIgnore()); + hm.put(MESSAGE_COMPENSATED, new StateTransitionIgnore()); + hm.put(MESSAGE_EXIT, new StateTransitionResend(MESSAGE_EXITED)); + hm.put(MESSAGE_FAULT, new StateTransitionResend(MESSAGE_FAULTED)); + hm.put(MESSAGE_COMPLETED, new StateTransitionIgnore()); + pc.put(STATE_ENDED, hm); + } + + states.put(ProtocolType.PROTOCOL_ID_PC, pc); + } + + { + /* + * Initializing the HashMap for the CoordinatorCompletion - Protocol + */ + final HashMap cc = new HashMap(); + + { + // Messages in state ACTIVE + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionState( + STATE_EXITING)); + hm.put(MESSAGE_FAULT, new StateTransitionState( + STATE_FAULTING_ACTIVE)); + hm.put(MESSAGE_COMPLETED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + cc.put(STATE_ACTIVE, hm); + } + { + // Messages in state CANCELLING_ACTIVE + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionState( + STATE_ENDED)); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionState( + STATE_EXITING)); + hm.put(MESSAGE_FAULT, new StateTransitionState( + STATE_FAULTING_ACTIVE)); + hm.put(MESSAGE_COMPLETED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + cc.put(STATE_CANCELLING_ACTIVE, hm); + } + { + // Messages in state CANCELLING_COMPLETING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionState( + STATE_ENDED)); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionState( + STATE_EXITING)); + hm.put(MESSAGE_FAULT, new StateTransitionState( + STATE_FAULTING_ACTIVE)); + hm.put(MESSAGE_COMPLETED, new StateTransitionState( + STATE_COMPLETED)); + cc.put(STATE_CANCELLING_COMPLETING, hm); + } + { + // Messages in state COMPLETED + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_FAULT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPLETED, new StateTransitionIgnore()); + cc.put(STATE_COMPLETED, hm); + } + { + // Messages in state COMPLETING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionState( + STATE_EXITING)); + hm.put(MESSAGE_FAULT, new StateTransitionState( + STATE_FAULTING_ACTIVE)); + hm.put(MESSAGE_COMPLETED, new StateTransitionState( + STATE_COMPLETED)); + cc.put(STATE_COMPLETING, hm); + } + { + // Messages in state CLOSING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionState( + STATE_ENDED)); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_FAULT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPLETED, new StateTransitionResend( + MESSAGE_CLOSE)); + cc.put(STATE_CLOSING, hm); + } + { + // Messages in state COMPENSATING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionState( + STATE_ENDED)); + hm.put(MESSAGE_EXIT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_FAULT, new StateTransitionState( + STATE_FAULTING_COMPENSATING)); + hm.put(MESSAGE_COMPLETED, new StateTransitionResend( + MESSAGE_COMPENSATE)); + cc.put(STATE_COMPENSATING, hm); + } + { + // Messages in state FAULTING ACTIVE + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_FAULT, new StateTransitionIgnore()); + hm.put(MESSAGE_COMPLETED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + cc.put(STATE_FAULTING_ACTIVE, hm); + } + { + // Messages in state FAULTING_COMPENSATING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_FAULT, new StateTransitionIgnore()); + hm.put(MESSAGE_COMPLETED, new StateTransitionIgnore()); + cc.put(STATE_FAULTING_COMPENSATING, hm); + } + { + // Messages in state EXITING + + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_CLOSED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPENSATED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_EXIT, new StateTransitionIgnore()); + hm.put(MESSAGE_FAULT, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + hm.put(MESSAGE_COMPLETED, new StateTransitionFault( + GET_INVALID_STATE_SOAP_FAULT())); + cc.put(STATE_EXITING, hm); + } + { + final HashMap hm = new HashMap(); + hm.put(MESSAGE_CANCELED, new StateTransitionIgnore()); + hm.put(MESSAGE_CLOSED, new StateTransitionIgnore()); + hm.put(MESSAGE_COMPENSATED, new StateTransitionIgnore()); + hm.put(MESSAGE_EXIT, new StateTransitionResend(MESSAGE_EXITED)); + hm.put(MESSAGE_FAULT, new StateTransitionResend(MESSAGE_FAULTED)); + hm.put(MESSAGE_COMPLETED, new StateTransitionIgnore()); + cc.put(STATE_ENDED, hm); + } + states.put(ProtocolType.PROTOCOL_ID_CC, cc); + } + } + + /** + * Default constructor.</br> Calls super constructor with + * protocolIdentifier to be able to follow statetransitions of chosen + * protocol. Sets the current state to active. + * + * @param protocolIdentifierX The protocol this state table will be used with. + */ + public CoordinationState(QName protocolIdentifierX) { + super(protocolIdentifierX); + setCurrentState(STATE_ACTIVE); + } + + /** + * Fetch the state table. + * @return The state table. + */ + protected Map getStates() { + return states; + } + + /** + * Fetch the global state table. + * @return The global state table. + */ + public static HashMap states() { + return (HashMap)states.clone(); + } + + /** + * Return the peer's state table. + * + * @see org.apache.kandula.coordinator.ba.State#getOtherStates() + */ + protected HashMap getOtherStates() { + return ParticipantState.states(); + } + + /** + * If the protocol is CoordinationCompletion and the state (<code>state</code>) + * is either <code>STATE_CANCELLING_ACTIVE</code> or + * <code>STATE_CANCELLING_COMPLETING</code> then the variable state has to + * be changed to reference <code>STATE_CANCELLING</code> since + * <code>ParticipantState</code> is called. + * + * @param prevState + * is not necessary for this method + * @see org.apache.kandula.coordinator.ba.State#translateState(javax.xml.namespace.QName, + * javax.xml.namespace.QName) + */ + protected QName translateState(final QName state, final QName prevState) { + return State.translateStateToParticipantView(state, prevState); + } + + /** + * If the protocol is CoordinationCompletion and the state (<code>state</code>) + * is <code>STATE_CANCELLING</code> then the variable state has to be + * changed to reference <code>STATE_CANCELLING_ACTIVE</code> or + * <code>STATE_CANCELLING_COMPLETING</code> since this is + * <code>CoordinationState</code>. + * + * @see org.apache.kandula.coordinator.ba.State#reverseTranslateState(javax.xml.namespace.QName, + * javax.xml.namespace.QName) + */ + protected QName reverseTranslateState(QName state, final QName prevState) { + return State.translateStateToCoordinatorView(this.protocolIdentifier, state, prevState); + } +}
Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService.java URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService.java?view=auto&rev=548471 ============================================================================== --- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService.java (added) +++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService.java Mon Jun 18 13:10:02 2007 @@ -0,0 +1,195 @@ +/* + * 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.ba.State; +import org.apache.kandula.wscoor.CreateCoordinationContextResponseType; + +import org.apache.kandula.wsbai.CoordinatorInitiatorProtocolPortType_AllProtocols; +import org.apache.kandula.wsbai.BAParticipantReferenceType; +import org.apache.kandula.wsbai.BAParticipantType; +import org.apache.kandula.wsbai.GetCoordCtxWCodeReqType; +import org.apache.kandula.wsbai.ListParticipantsReqType; + + +/** + * This class handles requests sent from the initiator to the coordinator. It receives + * the messages, correlates them to a running business activity and either fetches the requested + * information from the business activity coordinator or forwards commands to it. + * + * To avoid inconsistencies, access to BACoordinator's fields is always synchronized on the + * BACoordinator object, even if the intended access is read-only. + * + * @author Hannes Erven, Georg Hicker (C) 2006 + * + */ + +public abstract class CoordinatorIService +implements CoordinatorInitiatorProtocolPortType_AllProtocols +{ + + /** + * Return a coordination context response, containing a registration service that + * is tagged with the given matchcode. + * throws faults if called with an empty or in-use matchcode. + * + * Synchronization is handled by the BACoordinator. + * @param withMatchcode The matchcode request. + * @return The Coordination Context, tagged with the match code. + * @throws RemoteException + */ + public CreateCoordinationContextResponseType getCoordinationContextWithMatchcode(final GetCoordCtxWCodeReqType withMatchcode) throws RemoteException { + final BACoordinator context = BACoordinatorService.getBACoordinatorOrThrowFault(); + + context.ensureRequestOriginatesFromInitiatorOrThrowFault(); + + return new CreateCoordinationContextResponseType( + context.registerMatchcode(withMatchcode.getMatchcode()), + null + ); + } + + + /** + * List the current participants of the coordination context, complete by matchcode + * and with their current states. + * @param req The Request. + * + * @return An unsorted array of the current participants, complete with state and matchcode. + * @throws RemoteException + */ + public BAParticipantType[] listParticipants( + final ListParticipantsReqType req + ) throws RemoteException { + // to avoid warning + if (req != null) { + req.toString(); + } + + final BACoordinator context = BACoordinatorService.getBACoordinatorOrThrowFault(); + context.ensureRequestOriginatesFromInitiatorOrThrowFault(); + + synchronized (context) { + return context.buildParticipantList(); + } + } + + + /** + * Tells the coordinator to complete the selected participants. This is valid + * both in transaction with the "mixed outcome" and the "atomic outcome" assertions. + * + * This method may be called as many times as the initiator wishes. If a + * selected participant is in a state where it is not allowed to complete, + * it is silently ignored. + * Hence, the initiator must check the return for the participants' current + * states to ensure its request was satisfactorily fulfilled. + * @param participantsToComplete References to the participants that shall be completed. + * + * @return A list of the current participants and their states. + * @throws RemoteException + */ + public BAParticipantType[] completeParticipants( + final BAParticipantReferenceType[] participantsToComplete + ) throws RemoteException { + return notifyParticipants(null, participantsToComplete, State.MESSAGE_COMPLETE, false, true); + } + + /** + * Send some message to the given participants. + * @param checkOutcomeType If supplied, check if the outcome type is equal to checkOutcomeType + * @param participants References to the participants that shall be notified. + * @param message The message to send. + * @param notifyPC Notify PC participants? + * @param notifyCC Notify CC participants? + * @return Updated list of participant information. + * @throws RemoteException + */ + protected BAParticipantType[] notifyParticipants( + final String checkOutcomeType, + final BAParticipantReferenceType[] participants, + final QName message, + final boolean notifyPC, + final boolean notifyCC + ) throws RemoteException{ + final BACoordinator context = BACoordinatorService.getBACoordinatorOrThrowFault(); + context.ensureRequestOriginatesFromInitiatorOrThrowFault(); + + /* + * Synchronize on the context to ensure that only one thread + * sends out messages and performs state changes + */ + synchronized(context){ + + if (checkOutcomeType != null && + (! checkOutcomeType.equals(context.getOutcomeType() ) ) + ){ + throw new RemoteException(checkOutcomeType+" initiator method called, but the given context's outcome type is: "+context.getOutcomeType()); + } + + + if (participants != null && participants.length>0){ + for(int i=0; i<participants.length; i++){ + // Skip empty slots + if (participants[i] == null) + continue; + + // Fetch the current match code + final String matchCode = participants[i].getParticipantMatchcode(); + + // Check if the participant is known + final AbstractCoordParticipant part = + context.getParticipantByMatchcode(matchCode); + + if (part == null) + { + // No participant found - ignore + continue ; + } + + try{ + /* + * TODO WSBA When sending notifications, we perhaps have to + * record the target state if the participant has not + * yet progressed far enough to receive the requested + * message. + */ + + // Participant found - check if PC + if (part instanceof BAwPCCoordParticipant && notifyPC){ + part.tell(message); + } + // Participant found - check if CC + if (part instanceof BAwCCCoordParticipant && notifyCC){ + part.tell(message); + } + }catch(Exception e){ + // ignore any fault thrown by the participant + e.printStackTrace(); + } + } // end iterate through the requested match codes + } // end check if at least one participant was requested to complet + + return context.buildParticipantList(); + } // end synchronized + } +} Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService_Atomic.java URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService_Atomic.java?view=auto&rev=548471 ============================================================================== --- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService_Atomic.java (added) +++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService_Atomic.java Mon Jun 18 13:10:02 2007 @@ -0,0 +1,209 @@ +/* + * 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.ba.State; + +import org.apache.kandula.wsbai.CoordinatorInitiatorProtocolPortType_Atomic; +import org.apache.kandula.wsbai.BAParticipantReferenceType; +import org.apache.kandula.wsbai.BAParticipantType; + + +/** + * This class handles requests sent from the initiator to the coordinator. It receives + * the messages, correlates them to a running business activity and either fetches the requested + * information from the business activity coordinator or forwards commands to it. + * + * @author Hannes Erven, Georg Hicker (C) 2006 + * + */ + +public class CoordinatorIService_Atomic +extends CoordinatorIService +implements CoordinatorInitiatorProtocolPortType_Atomic +{ + + /** + * Tells the coordinator to cancel or compensate all participants. This is only valid + * in transactions with the "atomic outcome" assertion. + * + * Once called, the coordinator will issue appropriate commands so that eventually + * all participants (depending on their state when this method was called) either + * - canceled (and ended), + * - compensated (and ended), or + * - faulted (and ended). + * + * If a participant reports a fault, it is the initiator's responsibility to take + * appropriate action. + * + * When calling this method, all registered participants must be in one of the following states: + * <ul> + * <li>ACTIVE (will be cancelled) + * <li>COMPLETED (will be compensated) + * <li>COMPLETING (will be compensated) + * <li>EXITING (will be ignored) + * <li>ENDED (will be ignored) + * </ul> + * + * + * The initiator may in each transaction issue one call to either @see #cancelOrCompensateAllParticipants() + * or @see #closeAllParticipants() , not both. + * + * @return A list of the current participants and their states. + * @throws RemoteException + */ + public BAParticipantType[] cancelOrCompensateAllParticipants() throws RemoteException { + final BAwithAtomicOutcomeCoordinator context = + (BAwithAtomicOutcomeCoordinator) BACoordinatorService.getBACoordinatorOrThrowFault(); + + context.ensureRequestOriginatesFromInitiatorOrThrowFault(); + + synchronized (context) { + final BAParticipantType[] participantsToCancelOrCompensate = context.buildParticipantList(); + + if (participantsToCancelOrCompensate != null && participantsToCancelOrCompensate.length>0){ + for(int i=0; i<participantsToCancelOrCompensate.length; i++){ + // Fetch the current match code + final String matchCode = participantsToCancelOrCompensate[i].getParticipantMatchcode().getParticipantMatchcode(); + + // Check if the participant is known + final AbstractCoordParticipant part = + context.getParticipantByMatchcode(matchCode); + + if (part == null){ + // No participant found - ignore + continue ; + } + + final QName pstate = part.getCurrentState(); + if (false + || pstate.equals(State.STATE_ACTIVE) + || pstate.equals(State.STATE_COMPLETING) + ){ + // State is good, proceed with cancel + }else if ( false + || pstate.equals(State.STATE_COMPLETED) + ){ + // State is good, compensate + }else if (false + || pstate.equals(State.STATE_EXITING) + || pstate.equals(State.STATE_ENDED) + ){ + // state is good, ignore + + }else{ + // state is bad, throw back + throw State.GET_INVALID_STATE_SOAP_FAULT(pstate); + } + } // end iterate through the requested match codes and check participant states + } // end check if there are any participants + + // Up until now, everything was alright + // So proceed with setting the decision, even if there were no participants + context.getOutcomeDecision().decideToCancelOrCompensate(); + context.executeDecision(); + + return context.buildParticipantList(); + } + } + + /** + * Tells the coordinator to close all participants. This is only valid + * in transactions with the "atomic outcome" assertion. + * + * Once called, the coordinator will issue appropriate commands so that eventually + * all participants either + * - closed (and ended), or + * - faulted (and ended). + * + * If a participant reports a fault, it is the initiator's responsibility to take + * appropriate action. + * + * + * The initiator may in each transaction issue one call to either @see #cancelOrCompensateAllParticipants() + * or @see #closeAllParticipants() , not both. + * + * @return A list of the current participants and their states. + * @throws RemoteException + */ + public BAParticipantType[] closeAllParticipants() throws RemoteException { + final BAwithAtomicOutcomeCoordinator context = + (BAwithAtomicOutcomeCoordinator) BACoordinatorService.getBACoordinatorOrThrowFault(); + + context.ensureRequestOriginatesFromInitiatorOrThrowFault(); + + synchronized(context){ + final BAParticipantType[] participantsToClose = context.buildParticipantList(); + + + /* + * First step: compile a participant list and check, for each participant, whether + * it is in a state where a decision to close or compensate is allowed. + * + * The call to closeAllParticipants is only allowed if ALL registered participants + * are in one of the following states: + * <ul> + * <li>COMPLETED</li> + * <li>EXITING</li> + * <li>ENDED (after Exiting)</li> + * </ul> + */ + final BAParticipantReferenceType[] participantsToCloseByMatchcode = new BAParticipantReferenceType[participantsToClose.length]; + for(int i=0; i<participantsToClose.length; i++){ + final BAParticipantType participant = participantsToClose[i]; + + final QName pstate = participant.getStatus().getState().getValue(); + + if (pstate == null){ + // The state is null if a matchcode was activated, but no participant has registered for it + continue; + } + + if (false + || pstate.equals(State.STATE_COMPLETED) + ){ + // The state is OK, send the message + participantsToCloseByMatchcode[i]= participant.getParticipantMatchcode(); + + }else if (false + || pstate.equals(State.STATE_EXITING) + || pstate.equals(State.STATE_ENDED) + ){ + // The state is OK, but ignore this participant + continue ; + + }else{ + // Illegal state! + + throw State.GET_INVALID_STATE_SOAP_FAULT(pstate); + } + } + + context.getOutcomeDecision().decideToClose(); + context.executeDecision(); + + return context.buildParticipantList(); + } // end synchronized on context + } + +} Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService_Mixed.java URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService_Mixed.java?view=auto&rev=548471 ============================================================================== --- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService_Mixed.java (added) +++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/CoordinatorIService_Mixed.java Mon Jun 18 13:10:02 2007 @@ -0,0 +1,125 @@ +/* + * 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 org.apache.kandula.coordinator.ba.State; + +import org.apache.kandula.wsbai.CoordinatorInitiatorProtocolPortType_Mixed; +import org.apache.kandula.wsbai.BAParticipantReferenceType; +import org.apache.kandula.wsbai.BAParticipantType; + + +/** + * This class handles requests sent from the initiator to the coordinator. It receives + * the messages, correlates them to a running business activity and either fetches the requested + * information from the business activity coordinator or forwards commands to it. + * + * @author Hannes Erven, Georg Hicker (C) 2006 + * + */ + +public class CoordinatorIService_Mixed +extends CoordinatorIService +implements CoordinatorInitiatorProtocolPortType_Mixed +{ + + /* + * + * Methods for managing coordination contexts with + * + * MIXED OUTCOME + * + * + */ + + /** + * Tells the coordinator to cancel the selected participants. This is only + * valid in transaction with the "mixed outcome" assertion. + * + * This method may be called as many times as the initiator wishes. If a + * selected participant is in a state where it is not allowed to cancel, + * it is silently ignored. + * Hence, the initiator must check the return for the participants' current + * states. + * + * @param participantsToCancel References to the participants that shall be cancelled. + * + * @return A list of the current participants and their states. + * @throws RemoteException + */ + public BAParticipantType[] cancelParticipants( + final BAParticipantReferenceType[] participantsToCancel + ) throws RemoteException { + return this.notifyParticipants( + BACoordinator.COORDINATION_TYPE__MIXED, + participantsToCancel, + State.MESSAGE_CANCEL, + true, + true + ); + } + + /** + * Tells the coordinator to close the selected participants. This is only + * valid in transaction with the "mixed outcome" assertion. + * + * This method may be called as many times as the initiator wishes. If a + * selected participant is in a state where it is not allowed to close, + * it is silently ignored. + * Hence, the initiator must check the return for the participants' current + * states. + * @param participantsToClose References to the participants that shall be closed. + * + * @return A list of the current participants and their states. + * @throws RemoteException + */ + public BAParticipantType[] closeParticipants( + final BAParticipantReferenceType[] participantsToClose + ) throws RemoteException { + return this.notifyParticipants( + BACoordinator.COORDINATION_TYPE__MIXED, + participantsToClose, State.MESSAGE_CLOSE, true, true + ); + } + + /** + * Tells the coordinator to compensate the selected participants. This is only + * valid in transaction with the "mixed outcome" assertion. + * + * This method may be called as many times as the initiator wishes. If a + * selected participant is in a state where it is not allowed to compensate, + * it is silently ignored. + * Hence, the initiator must check the return for the participants' current + * states. + * @param participantsToCompensate References to the participants that shall be compensated. + * + * @return A list of the current participants and their states. + * @throws RemoteException + */ + + public BAParticipantType[] compensateParticipants( + final BAParticipantReferenceType[] participantsToCompensate + ) throws RemoteException { + return this.notifyParticipants( + BACoordinator.COORDINATION_TYPE__MIXED, + participantsToCompensate, State.MESSAGE_COMPENSATE, true, true + ); + } +} Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/InitiatorProxy.java URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/InitiatorProxy.java?view=auto&rev=548471 ============================================================================== --- webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/InitiatorProxy.java (added) +++ webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/InitiatorProxy.java Mon Jun 18 13:10:02 2007 @@ -0,0 +1,57 @@ +/* + * 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.message.addressing.EndpointReference; + +/** + * Placeholder for the InitiatorProxy class - requires the protocol + * between initiator and coordinator to be defined first. + * + * @author Hannes Erven, Georg Hicker (C) 2006 + * + */ +public class InitiatorProxy { + + /** + * The participant ID requests from the genuine initiator carry with them. + */ + protected final String myID; + + /** + * The endpoint where the initiator can be reached. + */ + protected final EndpointReference myEndpoint; + + /** + * Constructor for a new Initiator - every business activity should have one :-) + * @param id The initiator ID (used to authenticate requests from them) + * @param epr The EPR the initiator can be reached at. + */ + public InitiatorProxy(final String id, final EndpointReference epr){ + if (id == null || id.length()==0) + throw new IllegalArgumentException("Sorry, Initator ID must not be null or empty"); + + if (epr == null) + throw new IllegalArgumentException("Sorry, Initiator EPR must not be null"); + + this.myID = id; + this.myEndpoint = epr; + } + +} Added: webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/InvalidOutcomeAssertion.java URL: http://svn.apache.org/viewvc/webservices/kandula/branches/Kandula_1/src/java/org/apache/kandula/coordinator/ba/coordinator/InvalidOutcomeAssertion.java?view=auto&rev=548471 ============================================================================== --- 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/InvalidOutcomeAssertion.java Mon Jun 18 13:10:02 2007 @@ -0,0 +1,36 @@ +/* + * 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 exception should be thrown when creating a Business Activity Coordination + * Context with an unknown Outcome assertion. + * + * Supported outcome asserations are listed in the Coordinator implementation. + * + * @author Hannes Erven, Georg Hicker (C) 2006 + * + */ +public class InvalidOutcomeAssertion extends Exception { + + /** + * Generated UUID. + */ + private static final long serialVersionUID = -5173230826976571976L; +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
