/*
* 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.
*/
package org.apache.sandesha2.faulttests;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.util.List;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.impl.llom.soap11.SOAP11Factory;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisOperation;
import org.apache.sandesha2.RMMsgContext;
import org.apache.sandesha2.Sandesha2Constants;
import org.apache.sandesha2.SandeshaTestCase;
import org.apache.sandesha2.client.SandeshaClient;
import org.apache.sandesha2.client.SandeshaClientConstants;
import org.apache.sandesha2.client.SequenceReport;
import org.apache.sandesha2.msgreceivers.RMMessageReceiver;
import org.apache.sandesha2.storage.StorageManager;
import org.apache.sandesha2.storage.Transaction;
import org.apache.sandesha2.storage.beanmanagers.RMDBeanMgr;
import org.apache.sandesha2.storage.beans.RMDBean;
import org.apache.sandesha2.util.RangeString;
import org.apache.sandesha2.util.SandeshaUtil;
import org.apache.sandesha2.util.SpecSpecificConstants;
import org.apache.sandesha2.wsrm.AckRequested;
import org.apache.sandesha2.wsrm.CloseSequence;
import org.apache.sandesha2.wsrm.Identifier;
import org.apache.sandesha2.wsrm.MessageNumber;
import org.apache.sandesha2.wsrm.Sequence;
public class SequenceTerminatedFaultTest extends SandeshaTestCase {
private static final String server_repoPath = "target" + File.separator
+ "repos" + File.separator + "server";
private static final String server_axis2_xml = "target" + File.separator
+ "repos" + File.separator + "server" + File.separator
+ "server_axis2.xml";
private static ConfigurationContext serverConfigContext;
private boolean serverStarted = false;
public SequenceTerminatedFaultTest() {
super("SequenceTerminatedFaultTest");
}
public void setUp() throws Exception {
super.setUp();
if (!serverStarted) {
serverConfigContext = startServer(server_repoPath, server_axis2_xml);
}
serverStarted = true;
}
public void tearDown () throws Exception {
super.tearDown();
}
/**
* Sends an application message to the RMD.
* The RMD should reject the message with a sequence terminated fault
*
* @throws Exception
*/
public void testSequenceTerminatedFault() throws Exception {
// Open a connection to the endpoint
HttpURLConnection connection =
FaultTestUtils.getHttpURLConnection("http://127.0.0.1:" + serverPort + "/axis2/services/RMSampleService",
pingAction);
StorageManager storageManager =
SandeshaUtil.getSandeshaStorageManager(serverConfigContext, serverConfigContext.getAxisConfiguration());
RMDBeanMgr rmdBeanMgr = storageManager.getRMDBeanMgr();
String seqID = SandeshaUtil.getUUID();
// Mockup an RMDBean
RMDBean rmdBean = new RMDBean();
rmdBean.setSequenceID(seqID);
rmdBean.setToEPR(AddressingConstants.Final.WSA_ANONYMOUS_URL);
rmdBean.setAcksToEPR(AddressingConstants.Final.WSA_ANONYMOUS_URL);
rmdBean.setReplyToEPR(AddressingConstants.Final.WSA_ANONYMOUS_URL);
rmdBean.setRMVersion(Sandesha2Constants.SPEC_VERSIONS.v1_1);
rmdBean.setServerCompletedMessages(new RangeString());
// Flag that the sequence is terminated.
rmdBean.setTerminated(true);
// Create a transaction and insert the RMSBean
Transaction tran = storageManager.getTransaction();
rmdBeanMgr.insert(rmdBean);
tran.commit();
OutputStream tmpOut2 = connection.getOutputStream();
byte ar[] = getAppMessageAsBytes(seqID);
// Send the message to the socket.
tmpOut2.write(ar);
tmpOut2.flush();
// Get the response message from the connection
String message = FaultTestUtils.retrieveResponseMessage(connection);
// Check that the fault message isn't null
assertNotNull(message);
// Check that the response contains the Sequence Terminated tag
assertTrue(message.indexOf("wsrm:SequenceTerminated") > -1);
// Check that the <wsrm:Identifier>seqID</wsrm:Identifier> matches the sequence ID specified
String faultID = message.substring(message.indexOf("<wsrm:Identifier>") + 17, message.indexOf("</wsrm:Identifier>"));
assertEquals(seqID, faultID);
// Disconnect at the end of the test
connection.disconnect();
}
/**
* Sends a Close message to the RMD.
* The RMD should reject the message with a sequence terminated fault
*
* @throws Exception
*/
public void testSequenceTerminatedOnCloseFault() throws Exception {
// Open a connection to the endpoint
HttpURLConnection connection =
FaultTestUtils.getHttpURLConnection("http://127.0.0.1:" + serverPort + "/axis2/services/RMSampleService",
Sandesha2Constants.SPEC_2007_02.Actions.ACTION_CLOSE_SEQUENCE);
StorageManager storageManager =
SandeshaUtil.getSandeshaStorageManager(serverConfigContext, serverConfigContext.getAxisConfiguration());
RMDBeanMgr rmdBeanMgr = storageManager.getRMDBeanMgr();
String seqID = SandeshaUtil.getUUID();
// Mockup an RMDBean
RMDBean rmdBean = new RMDBean();
rmdBean.setSequenceID(seqID);
rmdBean.setToEPR(AddressingConstants.Final.WSA_ANONYMOUS_URL);
rmdBean.setAcksToEPR(AddressingConstants.Final.WSA_ANONYMOUS_URL);
rmdBean.setReplyToEPR(AddressingConstants.Final.WSA_ANONYMOUS_URL);
rmdBean.setRMVersion(Sandesha2Constants.SPEC_VERSIONS.v1_1);
rmdBean.setServerCompletedMessages(new RangeString());
// Flag that the sequence is terminated.
rmdBean.setTerminated(true);
// Create a transaction and insert the RMSBean
Transaction tran = storageManager.getTransaction();
rmdBeanMgr.insert(rmdBean);
tran.commit();
OutputStream tmpOut2 = connection.getOutputStream();
byte ar[] = getCloseMessageAsBytes(seqID);
// Send the message to the socket.
tmpOut2.write(ar);
tmpOut2.flush();
// Get the response message from the connection
String message = FaultTestUtils.retrieveResponseMessage(connection);
// Check that the fault message isn't null
assertNotNull(message);
// Check that the response contains the Sequence Terminated tag
assertTrue(message.indexOf("wsrm:SequenceTerminated") > -1);
// Check that the <wsrm:Identifier>seqID</wsrm:Identifier> matches the sequence ID specified
String faultID = message.substring(message.indexOf("<wsrm:Identifier>") + 17, message.indexOf("</wsrm:Identifier>"));
assertEquals(seqID, faultID);
// Disconnect at the end of the test
connection.disconnect();
}
/**
* Sends a AckRequest message to the RMD.
* The RMD should reject the message with a sequence terminated fault
*
* @throws Exception
*/
public void testSequenceTerminatedOnAckRequestFault() throws Exception {
// Open a connection to the endpoint
HttpURLConnection connection =
FaultTestUtils.getHttpURLConnection("http://127.0.0.1:" + serverPort + "/axis2/services/RMSampleService",
Sandesha2Constants.SPEC_2007_02.Actions.ACTION_ACK_REQUEST);
StorageManager storageManager =
SandeshaUtil.getSandeshaStorageManager(serverConfigContext, serverConfigContext.getAxisConfiguration());
RMDBeanMgr rmdBeanMgr = storageManager.getRMDBeanMgr();
String seqID = SandeshaUtil.getUUID();
// Mockup an RMDBean
RMDBean rmdBean = new RMDBean();
rmdBean.setSequenceID(seqID);
rmdBean.setToEPR(AddressingConstants.Final.WSA_ANONYMOUS_URL);
rmdBean.setAcksToEPR(AddressingConstants.Final.WSA_ANONYMOUS_URL);
rmdBean.setReplyToEPR(AddressingConstants.Final.WSA_ANONYMOUS_URL);
rmdBean.setRMVersion(Sandesha2Constants.SPEC_VERSIONS.v1_1);
rmdBean.setServerCompletedMessages(new RangeString());
// Flag that the sequence is terminated.
rmdBean.setTerminated(true);
// Create a transaction and insert the RMSBean
Transaction tran = storageManager.getTransaction();
rmdBeanMgr.insert(rmdBean);
tran.commit();
OutputStream tmpOut2 = connection.getOutputStream();
byte ar[] = getAckRequestMessageAsBytes(seqID);
// Send the message to the socket.
tmpOut2.write(ar);
tmpOut2.flush();
// Get the response message from the connection
String message = FaultTestUtils.retrieveResponseMessage(connection);
// Check that the fault message isn't null
assertNotNull(message);
// Check that the response contains the Sequence Terminated tag
assertTrue(message.indexOf("wsrm:SequenceTerminated") > -1);
// Check that the <wsrm:Identifier>seqID</wsrm:Identifier> matches the sequence ID specified
String faultID = message.substring(message.indexOf("<wsrm:Identifier>") + 17, message.indexOf("</wsrm:Identifier>"));
assertEquals(seqID, faultID);
// Disconnect at the end of the test
connection.disconnect();
}
/**
* When sending application messages, if the RMD sequence returns a sequence terminated
* fault, then the RMS Sequence should be terminated
*/
public void testRMSSequenceTerminatedOnSequenceTerminatedFault() throws Exception {
runSequenceTerminated(false, false);
}
/**
* When sending application messages, if the RMD sequence returns a sequence terminated
* fault, then the RMS Sequence should be terminated.
*
* Runs at SOAP12 level
*/
public void testRMSSequenceTerminatedOnSequenceTerminatedFaultSOAP12() throws Exception {
runSequenceTerminated(false, true);
}
/**
* When sending application messages, if the RMD sequence returns a sequence terminated
* fault, then the RMS Sequence should be terminated
*/
public void testRMSSequenceTerminatedOnSequenceUnknownFault() throws Exception {
runSequenceTerminated(true, false);
}
/**
* When sending application messages, if the RMD sequence returns a sequence terminated
* fault, then the RMS Sequence should be terminated
*
* Runs at SOAP12 level
*/
public void testRMSSequenceTerminatedOnSequenceUnknownFaultSOAP12() throws Exception {
runSequenceTerminated(true, true);
}
private void runSequenceTerminated(boolean deleteRMSBean, boolean soap12) throws Exception {
String to = "http://127.0.0.1:" + serverPort + "/axis2/services/RMSampleService";
String repoPath = "target" + File.separator + "repos" + File.separator + "client";
String axis2_xml = "target" + File.separator + "repos" + File.separator + "client" + File.separator + "client_axis2.xml";
ConfigurationContext configContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(repoPath,axis2_xml);
Options clientOptions = new Options ();
clientOptions.setAction(pingAction);
clientOptions.setTo(new EndpointReference (to));
clientOptions.setFaultTo(new EndpointReference(AddressingConstants.Final.WSA_ANONYMOUS_URL));
String sequenceKey = SandeshaUtil.getUUID();
clientOptions.setProperty(SandeshaClientConstants.SEQUENCE_KEY,sequenceKey);
clientOptions.setProperty(SandeshaClientConstants.RM_SPEC_VERSION,Sandesha2Constants.SPEC_VERSIONS.v1_1);
if (soap12)
clientOptions.setSoapVersionURI(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
ServiceClient serviceClient = new ServiceClient (configContext,null);
serviceClient.setOptions(clientOptions);
// Send a single ping message
serviceClient.fireAndForget(getPingOMBlock("ping1"));
long limit = System.currentTimeMillis() + waitTime;
Error lastError = null;
while(System.currentTimeMillis() < limit) {
Thread.sleep(tickTime); // Try the assertions each tick interval, until they pass or we time out
// Check that the sequence has been deleted.
StorageManager storageManager =
SandeshaUtil.getSandeshaStorageManager(serverConfigContext, serverConfigContext.getAxisConfiguration());
Transaction tran = storageManager.getTransaction();
RMDBean finderBean = new RMDBean();
finderBean.setTerminated(false);
List rmdBeans = storageManager.getRMDBeanMgr().find(finderBean);
tran.commit();
lastError = null;
if (rmdBeans.isEmpty())
lastError = new Error("rmdBeans empty " + rmdBeans);
else {
RMDBean bean = (RMDBean)rmdBeans.get(0);
if (!bean.getServerCompletedMessages().getContainedElementsAsNumbersList().contains(new Integer(1))) {
tran = storageManager.getTransaction();
if (deleteRMSBean) {
storageManager.getRMDBeanMgr().delete(bean.getSequenceID());
} else {
bean.setTerminated(true);
storageManager.getRMDBeanMgr().update(bean);
}
tran.commit();
break;
}
lastError = new Error("App message has not arrived");
}
}
if(lastError != null) throw lastError;
// Send a second application message.
serviceClient.fireAndForget(getPingOMBlock("ping2"));
while(System.currentTimeMillis() < limit) {
Thread.sleep(tickTime); // Try the assertions each tick interval, until they pass or we time out
try {
//Check that the outgoing sequence is terminated
SequenceReport sequenceReport = SandeshaClient.getOutgoingSequenceReport(serviceClient);
assertEquals(sequenceReport.getSequenceStatus(),SequenceReport.SEQUENCE_STATUS_TERMINATED);
assertEquals(sequenceReport.getSequenceDirection(),SequenceReport.SEQUENCE_DIRECTION_OUT);
lastError = null;
break;
} catch(Error e) {
lastError = e;
}
}
if(lastError != null) throw lastError;
configContext.getListenerManager().stop();
serviceClient.cleanup();
}
/**
* Get an application message as bytes
*
* @return
*/
private byte[] getAppMessageAsBytes(String uuid) throws Exception
{
SOAPFactory factory = new SOAP11Factory();
SOAPEnvelope dummyEnvelope = factory.getDefaultEnvelope();
// Create a "new" application message
MessageContext messageContext = new MessageContext();
messageContext.setConfigurationContext(serverConfigContext);
messageContext.setAxisService(serverConfigContext.getAxisConfiguration().getService("RMSampleService"));
messageContext.setEnvelope(dummyEnvelope);
RMMsgContext applicationRMMsg = new RMMsgContext(messageContext);
// Generate the Sequence field.
// -------------------------------
String rmNamespaceValue = SpecSpecificConstants.getRMNamespaceValue(Sandesha2Constants.SPEC_VERSIONS.v1_1);
Sequence sequence = new Sequence(rmNamespaceValue);
MessageNumber msgNumber = new MessageNumber(rmNamespaceValue);
msgNumber.setMessageNumber(1);
sequence.setMessageNumber(msgNumber);
Identifier id1 = new Identifier(rmNamespaceValue);
id1.setIndentifer(uuid);
sequence.setIdentifier(id1);
applicationRMMsg.setMessagePart(Sandesha2Constants.MessageParts.SEQUENCE, sequence);
applicationRMMsg.addSOAPEnvelope();
// --------------------------------------------
// Finished generating Sequence part
// Create an RMSBean so the create sequence message can be created
messageContext.setWSAAction(pingAction);
// Set the AxisOperation to be InOut
AxisOperation operation = messageContext.getAxisService().getOperation(Sandesha2Constants.RM_IN_OUT_OPERATION);
operation.setMessageReceiver(new RMMessageReceiver());
messageContext.setAxisOperation(operation);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// Serialize the application message
applicationRMMsg.getMessageContext().getEnvelope().serialize(outputStream);
return outputStream.toByteArray();
}
/**
* Get a close message as bytes
*
* @return
*/
private byte[] getCloseMessageAsBytes(String uuid) throws Exception
{
SOAPFactory factory = new SOAP11Factory();
SOAPEnvelope dummyEnvelope = factory.getDefaultEnvelope();
// Create a "new" application message
MessageContext messageContext = new MessageContext();
messageContext.setConfigurationContext(serverConfigContext);
messageContext.setAxisService(serverConfigContext.getAxisConfiguration().getService("RMSampleService"));
messageContext.setEnvelope(dummyEnvelope);
RMMsgContext applicationRMMsg = new RMMsgContext(messageContext);
// Generate the Close field.
// -------------------------------
String rmNamespaceValue = SpecSpecificConstants.getRMNamespaceValue(Sandesha2Constants.SPEC_VERSIONS.v1_1);
CloseSequence sequence = new CloseSequence(rmNamespaceValue);
Identifier id1 = new Identifier(rmNamespaceValue);
id1.setIndentifer(uuid);
sequence.setIdentifier(id1);
applicationRMMsg.setMessagePart(Sandesha2Constants.MessageParts.CLOSE_SEQUENCE, sequence);
applicationRMMsg.addSOAPEnvelope();
// --------------------------------------------
// Finished generating Close part
// Create an RMSBean so the create sequence message can be created
messageContext.setWSAAction(pingAction);
// Set the AxisOperation to be InOut
AxisOperation operation = messageContext.getAxisService().getOperation(Sandesha2Constants.RM_IN_OUT_OPERATION);
operation.setMessageReceiver(new RMMessageReceiver());
messageContext.setAxisOperation(operation);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// Serialize the application message
applicationRMMsg.getMessageContext().getEnvelope().serialize(outputStream);
return outputStream.toByteArray();
}
/**
* Get a close message as bytes
*
* @return
*/
private byte[] getAckRequestMessageAsBytes(String uuid) throws Exception
{
SOAPFactory factory = new SOAP11Factory();
SOAPEnvelope dummyEnvelope = factory.getDefaultEnvelope();
// Create a "new" application message
MessageContext messageContext = new MessageContext();
messageContext.setConfigurationContext(serverConfigContext);
messageContext.setAxisService(serverConfigContext.getAxisConfiguration().getService("RMSampleService"));
messageContext.setEnvelope(dummyEnvelope);
RMMsgContext applicationRMMsg = new RMMsgContext(messageContext);
// Generate the Close field.
// -------------------------------
String rmNamespaceValue = SpecSpecificConstants.getRMNamespaceValue(Sandesha2Constants.SPEC_VERSIONS.v1_1);
AckRequested sequence = new AckRequested(rmNamespaceValue);
Identifier id1 = new Identifier(rmNamespaceValue);
id1.setIndentifer(uuid);
sequence.setIdentifier(id1);
applicationRMMsg.setMessagePart(Sandesha2Constants.MessageParts.CLOSE_SEQUENCE, sequence);
applicationRMMsg.addSOAPEnvelope();
// --------------------------------------------
// Finished generating Close part
// Create an RMSBean so the create sequence message can be created
messageContext.setWSAAction(pingAction);
// Set the AxisOperation to be InOut
AxisOperation operation = messageContext.getAxisService().getOperation(Sandesha2Constants.RM_IN_OUT_OPERATION);
operation.setMessageReceiver(new RMMessageReceiver());
messageContext.setAxisOperation(operation);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// Serialize the application message
applicationRMMsg.getMessageContext().getEnvelope().serialize(outputStream);
return outputStream.toByteArray();
}
}