You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@synapse.apache.org by ve...@apache.org on 2008/06/12 23:43:01 UTC
svn commit: r667244 - in
/synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport:
./ nhttp/ vfs/
Author: veithen
Date: Thu Jun 12 14:43:00 2008
New Revision: 667244
URL: http://svn.apache.org/viewvc?rev=667244&view=rev
Log:
Added a generic test case for transport listeners (TransportListenerTestTemplate) as well as implementations of this test case for the VFS and HTTP NIO transports. This resolves part of SYNAPSE-350.
Added:
synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/DefaultOperationDispatcher.java
synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/MockMessageReceiver.java
synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/TransportListenerTestTemplate.java
synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/nhttp/
synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/nhttp/HttpCoreNIOListenerTest.java
synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/vfs/VFSTransportListenerTest.java
Added: synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/DefaultOperationDispatcher.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/DefaultOperationDispatcher.java?rev=667244&view=auto
==============================================================================
--- synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/DefaultOperationDispatcher.java (added)
+++ synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/DefaultOperationDispatcher.java Thu Jun 12 14:43:00 2008
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.synapse.transport;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.description.AxisOperation;
+import org.apache.axis2.description.AxisService;
+import org.apache.axis2.description.HandlerDescription;
+import org.apache.axis2.engine.AbstractDispatcher;
+
+/**
+ * Dispatcher that falls back to a default operation. This class is useful
+ * to implement "catch all" services that accept any kind of message.
+ * It is similar to {@link org.apache.synapse.core.axis2.SynapseDispatcher}.
+ */
+public class DefaultOperationDispatcher extends AbstractDispatcher {
+ public static final QName DEFAULT_OPERATION_NAME = new QName("__default__");
+
+ @Override
+ public void initDispatcher() {
+ super.init(new HandlerDescription("DefaultOperationDispatcher"));
+ }
+
+ @Override
+ public AxisService findService(MessageContext messageContext)
+ throws AxisFault {
+ return null;
+ }
+
+ @Override
+ public AxisOperation findOperation(AxisService service,
+ MessageContext messageContext) throws AxisFault {
+ return service.getOperation(DEFAULT_OPERATION_NAME);
+ }
+}
Added: synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/MockMessageReceiver.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/MockMessageReceiver.java?rev=667244&view=auto
==============================================================================
--- synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/MockMessageReceiver.java (added)
+++ synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/MockMessageReceiver.java Thu Jun 12 14:43:00 2008
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.synapse.transport;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.axiom.soap.SOAPEnvelope;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.engine.MessageReceiver;
+
+/**
+ * A mock message receiver that puts the SOAP envelope in a queue.
+ */
+public class MockMessageReceiver implements MessageReceiver {
+ private final BlockingQueue<SOAPEnvelope> queue = new LinkedBlockingQueue<SOAPEnvelope>();
+
+ public void receive(MessageContext messageCtx) throws AxisFault {
+ queue.add(messageCtx.getEnvelope());
+ }
+
+ public SOAPEnvelope waitForMessage(long timeout, TimeUnit unit) throws InterruptedException {
+ return queue.poll(timeout, unit);
+ }
+}
Added: synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/TransportListenerTestTemplate.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/TransportListenerTestTemplate.java?rev=667244&view=auto
==============================================================================
--- synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/TransportListenerTestTemplate.java (added)
+++ synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/TransportListenerTestTemplate.java Thu Jun 12 14:43:00 2008
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.synapse.transport;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import javax.activation.DataHandler;
+import javax.xml.namespace.QName;
+
+import junit.framework.TestCase;
+
+import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMNode;
+import org.apache.axiom.om.OMOutputFormat;
+import org.apache.axiom.om.OMText;
+import org.apache.axiom.soap.SOAPBody;
+import org.apache.axiom.soap.SOAPEnvelope;
+import org.apache.axiom.soap.SOAPFactory;
+import org.apache.axis2.addressing.EndpointReference;
+import org.apache.axis2.description.AxisOperation;
+import org.apache.axis2.description.AxisService;
+import org.apache.axis2.description.InOnlyAxisOperation;
+import org.apache.axis2.description.Parameter;
+import org.apache.axis2.description.TransportInDescription;
+import org.apache.axis2.engine.AxisConfiguration;
+import org.apache.axis2.engine.DispatchPhase;
+import org.apache.synapse.transport.base.BaseConstants;
+
+/**
+ * Base class for standard transport listener tests.
+ * This test case verifies that the transport listener is able to process various
+ * types of messages and to hand them over to the Axis2 engine. Subclasses only
+ * need to provide
+ * <ul>
+ * <li>the {@link TransportInDescription} object for the transport;</li>
+ * <li>the parameters necessary to configure a service to receive messages of
+ * a given content type through the transport;</li>
+ * <li>the logic to send a message with a given content type to the listener.</li>
+ * </ul>
+ * The test sets up a server environment and intercepts the received messages by
+ * configuring a service with a custom message receiver.
+ */
+public abstract class TransportListenerTestTemplate extends TestCase {
+ private static final String testString = "\u00e0 peine arriv\u00e9s nous entr\u00e2mes dans sa chambre";
+
+ private SOAPEnvelope runTest(String contentType, byte[] content) throws Exception {
+ UtilsTransportServer server = new UtilsTransportServer();
+
+ TransportInDescription trpInDesc = createTransportInDescription();
+ server.addTransport(trpInDesc);
+
+ AxisConfiguration axisConfiguration = server.getAxisConfiguration();
+
+ // Add a DefaultOperationDispatcher to the InFlow phase. This is necessary because
+ // we want to receive all messages through the same operation.
+ DispatchPhase dispatchPhase = null;
+ for (Object phase : axisConfiguration.getInFlowPhases()) {
+ if (phase instanceof DispatchPhase) {
+ dispatchPhase = (DispatchPhase)phase;
+ break;
+ }
+ }
+ dispatchPhase.addHandler(new DefaultOperationDispatcher());
+
+ // Set up a test service with a default operation backed by a mock message
+ // receiver. The service is configured using the parameters specified by the
+ // implementation.
+ AxisService service = new AxisService("TestService");
+ AxisOperation operation = new InOnlyAxisOperation(DefaultOperationDispatcher.DEFAULT_OPERATION_NAME);
+ MockMessageReceiver messageReceiver = new MockMessageReceiver();
+ operation.setMessageReceiver(messageReceiver);
+ service.addOperation(operation);
+ List<Parameter> parameters = getServiceParameters(contentType);
+ if (parameters != null) {
+ for (Parameter parameter : parameters) {
+ service.addParameter(parameter);
+ }
+ }
+ axisConfiguration.addService(service);
+
+ // Run the test.
+ beforeStartup();
+ server.start();
+ Thread.sleep(100); // TODO: this is required for the NIO transport; check whether this is a bug
+ try {
+ EndpointReference[] endpointReferences
+ = trpInDesc.getReceiver().getEPRsForService(service.getName(), "localhost");
+ sendMessage(endpointReferences != null && endpointReferences.length > 0
+ ? endpointReferences[0].getAddress() : null,
+ contentType, content);
+ SOAPEnvelope envelope = messageReceiver.waitForMessage(8, TimeUnit.SECONDS);
+ if (envelope == null) {
+ fail("Failed to get message");
+ }
+ return envelope;
+ }
+ finally {
+ server.stop();
+ Thread.sleep(100); // TODO: this is required for the NIO transport; check whether this is a bug
+ }
+ }
+
+ private void testSOAP11(String text, String charset) throws Exception {
+ SOAPFactory factory = OMAbstractFactory.getSOAP11Factory();
+ SOAPEnvelope orgEnvelope = factory.createSOAPEnvelope();
+ SOAPBody orgBody = factory.createSOAPBody();
+ OMElement orgElement = factory.createOMElement(new QName("root"));
+ orgElement.setText(text);
+ orgBody.addChild(orgElement);
+ orgEnvelope.addChild(orgBody);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ OMOutputFormat outputFormat = new OMOutputFormat();
+ outputFormat.setCharSetEncoding(charset);
+ outputFormat.setIgnoreXMLDeclaration(true);
+ orgEnvelope.serializeAndConsume(baos, outputFormat);
+ SOAPEnvelope envelope = runTest("text/xml; charset=\"" + charset + "\"", baos.toByteArray());
+ OMElement element = envelope.getBody().getFirstElement();
+ assertEquals(orgElement.getQName(), element.getQName());
+ assertEquals(text, element.getText());
+ }
+
+ public void testSOAP11ASCII() throws Exception {
+ testSOAP11("test string", "us-ascii");
+ }
+
+ public void testSOAP11UTF8() throws Exception {
+ testSOAP11(testString, "UTF-8");
+ }
+
+ public void testSOAP11Latin1() throws Exception {
+ testSOAP11(testString, "ISO-8859-1");
+ }
+
+ private void testTextPlain(String text, String charset) throws Exception {
+ SOAPEnvelope envelope = runTest("text/plain; charset=" + charset, text.getBytes(charset));
+ OMElement wrapper = envelope.getBody().getFirstElement();
+ assertEquals(BaseConstants.DEFAULT_TEXT_WRAPPER, wrapper.getQName());
+ assertEquals(text, wrapper.getText());
+ }
+
+ public void testTextPlainASCII() throws Exception {
+ testTextPlain("test string", "us-ascii");
+ }
+
+ public void testTextPlainUTF8() throws Exception {
+ testTextPlain(testString, "UTF-8");
+ }
+
+ public void testTextPlainLatin1() throws Exception {
+ testTextPlain(testString, "ISO-8859-1");
+ }
+
+ public void testBinary() throws Exception {
+ Random random = new Random();
+ byte[] content = new byte[8192];
+ random.nextBytes(content);
+ SOAPEnvelope envelope = runTest("application/octet-stream", content);
+ OMElement wrapper = envelope.getBody().getFirstElement();
+ assertEquals(BaseConstants.DEFAULT_BINARY_WRAPPER, wrapper.getQName());
+ OMNode child = wrapper.getFirstOMChild();
+ assertTrue(child instanceof OMText);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ((DataHandler)((OMText)child).getDataHandler()).writeTo(baos);
+ assertTrue(Arrays.equals(content, baos.toByteArray()));
+ }
+
+ /**
+ * Create a TransportInDescription for the transport under test.
+ *
+ * @return the transport description
+ */
+ protected abstract TransportInDescription createTransportInDescription();
+
+ /**
+ * Carry out initialization before server startup. This method is called
+ * immediately before the test server is started and can be used by subclasses
+ * to set up the test environment.
+ *
+ * @throws Exception
+ */
+ protected void beforeStartup() throws Exception {
+ }
+
+ /**
+ * Get the parameters necessary to configure a service to receive messages of
+ * a given content type through the transport under test.
+ *
+ * @param contentType the content type
+ * @return a list of service parameters
+ * @throws Exception
+ */
+ protected List<Parameter> getServiceParameters(String contentType) throws Exception {
+ return null;
+ }
+
+ /**
+ * Send a message to the transport listener. It is not recommended to use the
+ * corresponding transport sender to achieve this. Instead the implementation
+ * should use protocol specific libraries or APIs.
+ *
+ * @param endpointReference the endpoint reference of the service
+ * @param contentType the content type of the message
+ * @param content the content of the message
+ * @throws Exception
+ */
+ protected abstract void sendMessage(String endpointReference, String contentType, byte[] content) throws Exception;
+}
Added: synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/nhttp/HttpCoreNIOListenerTest.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/nhttp/HttpCoreNIOListenerTest.java?rev=667244&view=auto
==============================================================================
--- synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/nhttp/HttpCoreNIOListenerTest.java (added)
+++ synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/nhttp/HttpCoreNIOListenerTest.java Thu Jun 12 14:43:00 2008
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.synapse.transport.nhttp;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+import org.apache.axis2.description.TransportInDescription;
+import org.apache.commons.io.IOUtils;
+import org.apache.synapse.transport.TransportListenerTestTemplate;
+
+public class HttpCoreNIOListenerTest extends TransportListenerTestTemplate {
+ @Override
+ protected TransportInDescription createTransportInDescription() {
+ TransportInDescription trpInDesc = new TransportInDescription("http");
+ trpInDesc.setReceiver(new HttpCoreNIOListener());
+ return trpInDesc;
+ }
+
+ @Override
+ protected void sendMessage(String endpointReference, String contentType, byte[] content) throws Exception {
+ URLConnection connection = new URL(endpointReference).openConnection();
+ connection.setDoOutput(true);
+ connection.setDoInput(true);
+ connection.setRequestProperty("Content-Type", contentType);
+ OutputStream out = connection.getOutputStream();
+ out.write(content);
+ out.close();
+ InputStream in = connection.getInputStream();
+ IOUtils.copy(in, System.out);
+ in.close();
+ }
+}
Added: synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/vfs/VFSTransportListenerTest.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/vfs/VFSTransportListenerTest.java?rev=667244&view=auto
==============================================================================
--- synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/vfs/VFSTransportListenerTest.java (added)
+++ synapse/trunk/java/modules/transports/src/test/java/org/apache/synapse/transport/vfs/VFSTransportListenerTest.java Thu Jun 12 14:43:00 2008
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.synapse.transport.vfs;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.axis2.description.Parameter;
+import org.apache.axis2.description.TransportInDescription;
+import org.apache.synapse.transport.TransportListenerTestTemplate;
+
+/**
+ * TransportListenerTestTemplate implementation for the VFS transport.
+ */
+public class VFSTransportListenerTest extends TransportListenerTestTemplate {
+ private final File requestFile = new File("target/vfs3/req/in").getAbsoluteFile();
+
+ @Override
+ protected TransportInDescription createTransportInDescription() {
+ TransportInDescription trpInDesc =
+ new TransportInDescription(VFSTransportListener.TRANSPORT_NAME);
+ trpInDesc.setReceiver(new VFSTransportListener());
+ return trpInDesc;
+ }
+
+ @Override
+ protected void beforeStartup() throws Exception {
+ requestFile.getParentFile().mkdirs();
+ requestFile.delete();
+ }
+
+ @Override
+ protected List<Parameter> getServiceParameters(String contentType) throws Exception {
+ List<Parameter> parameters = new ArrayList<Parameter>();
+ parameters.add(new Parameter("transport.vfs.FileURI", "vfs:" + requestFile.toURL()));
+ parameters.add(new Parameter("transport.vfs.ContentType", contentType));
+ parameters.add(new Parameter("transport.PollInterval", "1"));
+ parameters.add(new Parameter("transport.vfs.ActionAfterProcess", "DELETE"));
+ return parameters;
+ }
+
+ @Override
+ protected void sendMessage(String endpointReference, String contentType, byte[] content) throws Exception {
+ OutputStream out = new FileOutputStream("target/vfs3/req/in");
+ out.write(content);
+ out.close();
+ }
+}