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();
+    }
+}