You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ni...@apache.org on 2013/05/28 10:54:52 UTC

svn commit: r1486823 [3/3] - in /cxf/trunk/rt: ./ transports/http-netty/ transports/http-netty/netty-client/ transports/http-netty/netty-client/src/ transports/http-netty/netty-client/src/main/ transports/http-netty/netty-client/src/main/java/ transpor...

Added: cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/session/DefaultHttpSessionStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/session/DefaultHttpSessionStore.java?rev=1486823&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/session/DefaultHttpSessionStore.java (added)
+++ cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/session/DefaultHttpSessionStore.java Tue May 28 08:54:49 2013
@@ -0,0 +1,85 @@
+/**
+ * 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.cxf.transport.http.netty.server.session;
+
+
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.transport.http.netty.server.servlet.NettyHttpSession;
+
+
+public class DefaultHttpSessionStore implements HttpSessionStore {
+
+    private static final Logger LOG = LogUtils.getL7dLogger(DefaultHttpSessionStore.class);
+
+    private static final Map<String, NettyHttpSession> SESSIONS 
+        = new ConcurrentHashMap<String, NettyHttpSession>();
+
+    @Override
+    public NettyHttpSession createSession() {
+        String sessionId = this.generateNewSessionId();
+        LOG.log(Level.FINE, "Creating new session with id {}", sessionId);
+
+        NettyHttpSession session = new NettyHttpSession(sessionId);
+        SESSIONS.put(sessionId, session);
+        return session;
+    }
+
+    @Override
+    public void destroySession(String sessionId) {
+        LOG.log(Level.FINE, "Destroying session with id {}", sessionId);
+        SESSIONS.remove(sessionId);
+    }
+
+    @Override
+    public NettyHttpSession findSession(String sessionId) {
+        if (SESSIONS == null) {
+            return null;
+        }
+        return SESSIONS.get(sessionId);
+    }
+
+    protected String generateNewSessionId() {
+        return UUID.randomUUID().toString();
+    }
+
+    @Override
+    public void destroyInactiveSessions() {
+        for (Map.Entry<String, NettyHttpSession> entry : SESSIONS.entrySet()) {
+            NettyHttpSession session = entry.getValue();
+            if (session.getMaxInactiveInterval() < 0) {
+                continue;
+            }
+            
+            long currentMillis = System.currentTimeMillis();
+
+            if (currentMillis - session.getLastAccessedTime() > session
+                    .getMaxInactiveInterval() * 1000) {
+
+                destroySession(entry.getKey());
+            }
+        }
+    }
+}

Added: cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/session/HttpSessionStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/session/HttpSessionStore.java?rev=1486823&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/session/HttpSessionStore.java (added)
+++ cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/session/HttpSessionStore.java Tue May 28 08:54:49 2013
@@ -0,0 +1,34 @@
+/**
+ * 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.cxf.transport.http.netty.server.session;
+
+import org.apache.cxf.transport.http.netty.server.servlet.NettyHttpSession;
+
+public interface HttpSessionStore {
+
+    NettyHttpSession findSession(String sessionId);
+
+    NettyHttpSession createSession();
+
+    void destroySession(String sessionId);
+
+    void destroyInactiveSessions();
+
+}

Added: cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/util/Utils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/util/Utils.java?rev=1486823&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/util/Utils.java (added)
+++ cxf/trunk/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/util/Utils.java Tue May 28 08:54:49 2013
@@ -0,0 +1,207 @@
+/**
+ * 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.cxf.transport.http.netty.server.util;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.net.FileNameMap;
+import java.net.URLConnection;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.netty.handler.codec.http.Cookie;
+import org.jboss.netty.handler.codec.http.CookieDecoder;
+import org.jboss.netty.handler.codec.http.HttpRequest;
+import org.jboss.netty.handler.codec.http.HttpResponse;
+
+import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.COOKIE;
+
+
+public final class Utils {
+    private Utils() {
+        // Utils class
+    }
+
+    public static <T> Enumeration<T> emptyEnumeration() {
+        return Collections.enumeration(Collections.<T>emptySet());
+    }
+
+    public static <T> Enumeration<T> enumeration(Collection<T> collection) {
+        if (collection == null) {
+            return emptyEnumeration();
+        }
+        return Collections.enumeration(collection);
+    }
+
+    public static <T> Enumeration<T> enumerationFromKeys(Map<T, ?> map) {
+        if (map == null) {
+            return emptyEnumeration();
+        }
+        return Collections.enumeration(map.keySet());
+    }
+
+    public static <T> Enumeration<T> enumerationFromValues(Map<?, T> map) {
+        if (map == null) {
+            return emptyEnumeration();
+        }
+        return Collections.enumeration(map.values());
+    }
+
+
+    /**
+     * Parse the character encoding from the specified content type header. If
+     * the content type is null, or there is no explicit character encoding,
+     * <code>null</code> is returned.
+     *
+     * @param contentType a content type header
+     */
+    public static String getCharsetFromContentType(String contentType) {
+
+        if (contentType == null) {
+            return null;
+        }
+        int start = contentType.indexOf("charset=");
+        if (start < 0) {
+            return null;
+        }
+        String encoding = contentType.substring(start + 8);
+        int end = encoding.indexOf(';');
+        if (end >= 0) {
+            encoding = encoding.substring(0, end);
+        }
+        encoding = encoding.trim();
+        if ((encoding.length() > 2) && (encoding.startsWith("\""))
+                && (encoding.endsWith("\""))) {
+            encoding = encoding.substring(1, encoding.length() - 1);
+        }
+        return encoding.trim();
+
+    }
+
+    public static Collection<Cookie> getCookies(String name,
+                                                      HttpRequest request) {
+        String cookieString = request.getHeader(COOKIE);
+        if (cookieString != null) {
+            List<Cookie> foundCookie = new ArrayList<Cookie>();
+            CookieDecoder cookieDecoder = new CookieDecoder();
+            Set<Cookie> cookies = cookieDecoder.decode(cookieString);
+            for (Cookie cookie : cookies) {
+                if (cookie.getName().equals(name)) {
+                    foundCookie.add(cookie);
+                }
+            }
+
+            return foundCookie;
+        }
+        return null;
+    }
+
+    public static Collection<Cookie> getCookies(String name,
+                                                HttpResponse response) {
+        String cookieString = response.getHeader(COOKIE);
+        if (cookieString != null) {
+            List<Cookie> foundCookie = new ArrayList<Cookie>();
+            CookieDecoder cookieDecoder = new CookieDecoder();
+            Set<Cookie> cookies = cookieDecoder.decode(cookieString);
+            for (Cookie cookie : cookies) {
+                if (cookie.getName().equals(name)) {
+                    foundCookie.add(cookie);
+                }
+            }
+
+            return foundCookie;
+        }
+        return null;
+    }
+
+    public static String getMimeType(String fileUrl) {
+        FileNameMap fileNameMap = URLConnection.getFileNameMap();
+        return fileNameMap.getContentTypeFor(fileUrl);
+    }
+
+    public static String sanitizeUri(String uri) {
+        // Decode the path.
+        try {
+            uri = URLDecoder.decode(uri, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            try {
+                uri = URLDecoder.decode(uri, "ISO-8859-1");
+            } catch (UnsupportedEncodingException e1) {
+                throw new Error();
+            }
+        }
+
+        // Convert file separators.
+        uri = uri.replace('/', File.separatorChar);
+
+        // Simplistic dumb security check.
+        // You will have to do something serious in the production environment.
+        if (uri.contains(File.separator + ".")
+                || uri.contains("." + File.separator) || uri.startsWith(".")
+                || uri.endsWith(".")) {
+            return null;
+        }
+
+        return uri;
+    }
+
+    public static Collection<Locale> parseAcceptLanguageHeader(
+            String acceptLanguageHeader) {
+
+        if (acceptLanguageHeader == null) {
+            return null;
+        }
+
+        List<Locale> locales = new ArrayList<Locale>();
+
+        for (String str : acceptLanguageHeader.split(",")) {
+            String[] arr = str.trim().replace("-", "_").split(";");
+
+            // Parse the locale
+            Locale locale = null;
+            String[] l = arr[0].split("_");
+            switch (l.length) {
+            case 2:
+                locale = new Locale(l[0], l[1]);
+                break;
+            case 3:
+                locale = new Locale(l[0], l[1], l[2]);
+                break;
+            default:
+                locale = new Locale(l[0]);
+                break;
+            }
+
+            locales.add(locale);
+        }
+
+        return locales;
+
+    }
+
+
+}

Added: cxf/trunk/rt/transports/http-netty/netty-server/src/main/resources/META-INF/cxf/bus-extensions.txt
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http-netty/netty-server/src/main/resources/META-INF/cxf/bus-extensions.txt?rev=1486823&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http-netty/netty-server/src/main/resources/META-INF/cxf/bus-extensions.txt (added)
+++ cxf/trunk/rt/transports/http-netty/netty-server/src/main/resources/META-INF/cxf/bus-extensions.txt Tue May 28 08:54:49 2013
@@ -0,0 +1,2 @@
+org.apache.cxf.transport.http.netty.server.NettyHttpDestinationFactory::true
+org.apache.cxf.transport.http.netty.server.NettyHttpServerEngineFactory::true

Added: cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpDestinationTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpDestinationTest.java?rev=1486823&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpDestinationTest.java (added)
+++ cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpDestinationTest.java Tue May 28 08:54:49 2013
@@ -0,0 +1,976 @@
+/**
+ * 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.cxf.transport.http.netty.server;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusException;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.extension.ExtensionManagerBus;
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.configuration.security.AuthorizationPolicy;
+import org.apache.cxf.continuations.SuspendedInvocationException;
+import org.apache.cxf.endpoint.EndpointResolverRegistry;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.io.AbstractWrappedOutputStream;
+import org.apache.cxf.message.ExchangeImpl;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.policy.PolicyDataEngine;
+import org.apache.cxf.security.transport.TLSSessionInfo;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.service.model.ServiceInfo;
+import org.apache.cxf.transport.Conduit;
+import org.apache.cxf.transport.ConduitInitiator;
+import org.apache.cxf.transport.ConduitInitiatorManager;
+import org.apache.cxf.transport.Destination;
+import org.apache.cxf.transport.MessageObserver;
+import org.apache.cxf.transport.http.AbstractHTTPDestination;
+import org.apache.cxf.transport.http.ContinuationProviderFactory;
+import org.apache.cxf.transport.http.DestinationRegistry;
+import org.apache.cxf.transport.http.HTTPTransportFactory;
+import org.apache.cxf.transport.http.netty.server.util.Utils;
+import org.apache.cxf.transports.http.QueryHandler;
+import org.apache.cxf.transports.http.QueryHandlerRegistry;
+import org.apache.cxf.transports.http.StemMatchingQueryHandler;
+import org.apache.cxf.transports.http.configuration.HTTPServerPolicy;
+import org.apache.cxf.ws.addressing.AddressingProperties;
+import org.apache.cxf.ws.addressing.EndpointReferenceType;
+import org.apache.cxf.ws.addressing.JAXWSAConstants;
+import org.apache.cxf.wsdl.EndpointReferenceUtils;
+import org.easymock.EasyMock;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class NettyHttpDestinationTest extends Assert {
+    protected static final String AUTH_HEADER = "Authorization";
+    protected static final String USER = "copernicus";
+    protected static final String PASSWD = "epicycles";
+    protected static final String BASIC_AUTH =
+        "Basic " + Base64Utility.encode((USER + ":" + PASSWD).getBytes());   
+
+    private static final String NOWHERE = "http://nada.nothing.nowhere.null/";
+    private static final String PAYLOAD = "message payload";
+    private static final String CHALLENGE_HEADER = "WWW-Authenticate";
+    private static final String BASIC_CHALLENGE = "Basic realm=terra";
+    private static final String DIGEST_CHALLENGE = "Digest realm=luna";
+    private static final String CUSTOM_CHALLENGE = "Custom realm=sol";
+    private Bus bus;
+    private Bus threadDefaultBus;
+    private Conduit decoupledBackChannel;
+    private EndpointInfo endpointInfo;
+    private EndpointReferenceType address;
+    private NettyHttpServerEngine engine;
+    private HTTPServerPolicy policy;
+    private NettyHttpDestination destination;
+    private HttpServletRequest request;
+    private HttpServletResponse response;
+    private Message inMessage;
+    private Message outMessage;
+    private MessageObserver observer;
+    private ServletInputStream is;
+    private ServletOutputStream os;
+    private QueryHandler wsdlQueryHandler;
+    private QueryHandlerRegistry  queryHandlerRegistry;
+    private List<QueryHandler> queryHandlerList;
+    private HTTPTransportFactory transportFactory; 
+
+    /**
+     * This class replaces the engine in the Netty Http Destination.
+     */
+    private class EasyMockJettyHTTPDestination
+        extends NettyHttpDestination {
+
+        public EasyMockJettyHTTPDestination(Bus bus,
+                                            DestinationRegistry registry,
+                                            EndpointInfo endpointInfo,
+                                            NettyHttpServerEngineFactory serverEngineFactory,
+                                            NettyHttpServerEngine easyMockEngine) throws IOException {
+            super(bus, registry, endpointInfo, serverEngineFactory);
+            engine = easyMockEngine;
+        }
+        
+        @Override
+        public void retrieveEngine() {
+            // Leave engine alone.
+        }
+    }
+    @After
+    public void tearDown() {
+       
+        bus = null;
+        transportFactory = null;
+        decoupledBackChannel = null;
+        address = null;
+        engine = null;
+        request = null;
+        response = null;
+        inMessage = null;
+        outMessage = null;
+        is = null;
+        os = null;
+        destination = null;
+        BusFactory.setDefaultBus(null); 
+    }
+    
+    @Test
+    public void testGetAddress() throws Exception {
+        destination = setUpDestination();
+        EndpointReferenceType ref = destination.getAddress();
+        assertNotNull("unexpected null address", ref);
+        assertEquals("unexpected address",
+                     EndpointReferenceUtils.getAddress(ref),
+                     StringUtils.addDefaultPortIfMissing(EndpointReferenceUtils.getAddress(address)));
+        assertEquals("unexpected service name local part",
+                     EndpointReferenceUtils.getServiceName(ref, bus).getLocalPart(),
+                     "Service");
+        assertEquals("unexpected portName",
+                     EndpointReferenceUtils.getPortName(ref),
+                     "Port");
+    }
+    
+    @Test
+    public void testRandomPortAllocation() throws Exception {
+        transportFactory = new HTTPTransportFactory();
+        transportFactory.setBus(BusFactory.getDefaultBus());
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.setName(new QName("bla", "Service"));
+        EndpointInfo ei = new EndpointInfo(serviceInfo, "");
+        ei.setName(new QName("bla", "Port"));
+        
+        Destination d1 = transportFactory.getDestination(ei);
+        URL url = new URL(d1.getAddress().getAddress().getValue());
+        assertTrue("No random port has been allocated", 
+                   url.getPort() > 0);
+        
+    }
+    
+    @Test
+    public void testSuspendedException() throws Exception {
+        destination = setUpDestination(false, false);
+        setUpDoService(false);
+        final RuntimeException ex = new RuntimeException();
+        observer = new MessageObserver() {
+            public void onMessage(Message m) {
+                throw new SuspendedInvocationException(ex);
+            }
+        };
+        destination.setMessageObserver(observer);
+        try {
+            destination.doService(request, response);
+            fail("Suspended invocation swallowed");
+        } catch (RuntimeException runtimeEx) {
+            assertSame("Original exception is not preserved", ex, runtimeEx);
+        }
+    }
+    
+    
+    @Test
+    public void testContinuationsIgnored() throws Exception {
+        
+        HttpServletRequest httpRequest = EasyMock.createMock(HttpServletRequest.class);
+        
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.setName(new QName("bla", "Service"));
+        EndpointInfo ei = new EndpointInfo(serviceInfo, "");
+        ei.setName(new QName("bla", "Port"));
+
+        // Just create a fake engine
+        final NettyHttpServerEngine httpEngine = new NettyHttpServerEngine("localhost", 8080);
+        //httpEngine.setContinuationsEnabled(false);
+        NettyHttpServerEngineFactory factory = new NettyHttpServerEngineFactory() {
+            @Override
+            public NettyHttpServerEngine retrieveNettyHttpServerEngine(int port) {
+                return httpEngine;
+            }
+        };
+        transportFactory = new HTTPTransportFactory();
+        transportFactory.setBus(new ExtensionManagerBus());
+        transportFactory.getBus().setExtension(
+            factory, NettyHttpServerEngineFactory.class);
+        
+        TestJettyDestination testDestination = 
+            new TestJettyDestination(transportFactory.getBus(), 
+                                     transportFactory.getRegistry(), 
+                                     ei,
+                                     factory);
+        testDestination.finalizeConfig();
+        Message mi = testDestination.retrieveFromContinuation(httpRequest);
+        assertNull("Continuations must be ignored", mi);
+    }
+    
+    @Test
+    public void testGetMultiple() throws Exception {
+        transportFactory = new HTTPTransportFactory();
+        transportFactory.setBus(BusFactory.getDefaultBus(true));
+        
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.setName(new QName("bla", "Service"));        
+        EndpointInfo ei = new EndpointInfo(serviceInfo, "");
+        ei.setName(new QName("bla", "Port"));
+        ei.setAddress("http://foo");
+        Destination d1 = transportFactory.getDestination(ei);
+        
+        Destination d2 = transportFactory.getDestination(ei);
+        
+        // Second get should not generate a new destination. It should just retrieve the existing one
+        assertEquals(d1, d2);
+        
+        d2.shutdown();
+        
+        Destination d3 = transportFactory.getDestination(ei);
+        // Now a new destination should have been created
+        assertNotSame(d1, d3);
+    }
+    
+    
+    @Test
+    public void testRemoveServant() throws Exception {
+        destination = setUpDestination();
+        setUpRemoveServant();
+        destination.setMessageObserver(null);
+    }
+
+    @Test
+    public void testDoServiceRedirectURL() throws Exception {
+        destination = setUpDestination(false, false);
+        setUpDoService(true);
+        destination.doService(request, response);
+        
+    }
+
+    @Test
+    public void testDoService() throws Exception {
+        Bus defaultBus = new ExtensionManagerBus();
+        assertSame("Default thread bus has not been set",
+                   defaultBus, BusFactory.getThreadDefaultBus()); 
+        destination = setUpDestination(false, false);
+        setUpDoService(false);
+        assertSame("Default thread bus has been unexpectedly reset",
+                   defaultBus, BusFactory.getThreadDefaultBus());
+        destination.doService(request, response);
+        verifyDoService();
+        assertSame("Default thread bus has not been reset",
+                    defaultBus, BusFactory.getThreadDefaultBus());
+    }
+    
+    @Test
+    public void testDoServiceWithHttpGET() throws Exception {
+        destination = setUpDestination(false, false);
+        setUpDoService(false,
+                       false,
+                       false,
+                       "GET",
+                       "?customerId=abc&cutomerAdd=def",
+                       200);
+        destination.doService(request, response);
+        
+        assertNotNull("unexpected null message", inMessage);
+        assertEquals("unexpected method",
+                     inMessage.get(Message.HTTP_REQUEST_METHOD),
+                     "GET");
+        assertEquals("unexpected path",
+                     inMessage.get(Message.PATH_INFO),
+                     "/bar/foo");
+        assertEquals("unexpected query",
+                     inMessage.get(Message.QUERY_STRING),
+                     "?customerId=abc&cutomerAdd=def");
+
+    }
+    
+    @Test
+    public void testDoServiceWithHttpGETandStemMatchingQueryWSDL() throws Exception {
+        destination = setUpDestination(false, true);
+        setUpQueryHandler(true);
+        setUpDoService(false,
+                       false,
+                       false,
+                       "GET",
+                       "?wsdl",
+                       200);
+        
+        destination.doService(request, response);
+        assertNotNull("unexpected null response", response);
+        
+        
+    }
+    
+    @Test
+    public void testDoServiceWithHttpGETandNonStemMatchingQueryWSDL() throws Exception {
+        destination = setUpDestination(false, true);
+        setUpQueryHandler(false);
+        setUpDoService(false,
+                       false,
+                       false,
+                       "GET",
+                       "?wsdl",
+                       200);
+        
+        destination.doService(request, response);
+        assertNotNull("unexpected null response", response);
+        
+        
+    }
+
+    @Test
+    public void testGetAnonBackChannel() throws Exception {
+        destination = setUpDestination(false, false);
+        setUpDoService(false);
+        destination.doService(request, response);
+        setUpInMessage();
+        Conduit backChannel = destination.getBackChannel(inMessage);
+        
+        assertNotNull("expected back channel", backChannel);
+        assertEquals("unexpected target",
+                     EndpointReferenceUtils.ANONYMOUS_ADDRESS,
+                     backChannel.getTarget().getAddress().getValue());
+    }
+    
+    @Test
+    public void testGetBackChannelSend() throws Exception {
+        destination = setUpDestination(false, false);
+        setUpDoService(false, true);
+        destination.doService(request, response);
+        setUpInMessage();
+        Conduit backChannel =
+            destination.getBackChannel(inMessage);
+        outMessage = setUpOutMessage();
+        backChannel.prepare(outMessage);
+        verifyBackChannelSend(backChannel, outMessage, 200);
+    }
+
+    @Test
+    public void testGetBackChannelSendFault() throws Exception {
+        destination = setUpDestination(false, false);
+        setUpDoService(false, true, 500);
+        destination.doService(request, response);
+        setUpInMessage();
+        Conduit backChannel =
+            destination.getBackChannel(inMessage);
+        outMessage = setUpOutMessage();
+        backChannel.prepare(outMessage);
+        verifyBackChannelSend(backChannel, outMessage, 500);
+    }
+    
+    @Test
+    public void testGetBackChannelSendOneway() throws Exception {
+        destination = setUpDestination(false, false);
+        setUpDoService(false, true, 500);
+        destination.doService(request, response);
+        setUpInMessage();
+        Conduit backChannel =
+            destination.getBackChannel(inMessage);
+        outMessage = setUpOutMessage();
+        backChannel.prepare(outMessage);
+        verifyBackChannelSend(backChannel, outMessage, 500, true);
+    }
+
+    @Test
+    public void testGetBackChannelSendDecoupled() throws Exception {
+        destination = setUpDestination(false, false);
+        setUpDoService(false, true, true, 202);
+        destination.doService(request, response);
+        setUpInMessage();
+        
+        Message partialResponse = setUpOutMessage();
+        partialResponse.put(Message.PARTIAL_RESPONSE_MESSAGE, Boolean.TRUE);
+        Conduit partialBackChannel =
+            destination.getBackChannel(inMessage);
+        partialBackChannel.prepare(partialResponse);
+        verifyBackChannelSend(partialBackChannel, partialResponse, 202);
+
+        outMessage = setUpOutMessage();
+        Conduit fullBackChannel =
+            destination.getBackChannel(inMessage);
+
+        fullBackChannel.prepare(outMessage);
+    }
+    
+    @Test
+    public void testServerPolicyInServiceModel()
+        throws Exception {
+        policy = new HTTPServerPolicy();
+        address = getEPR("bar/foo");
+        bus = new ExtensionManagerBus();
+        
+        transportFactory = new HTTPTransportFactory();
+        transportFactory.setBus(bus);
+        
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.setName(new QName("bla", "Service"));        
+        endpointInfo = new EndpointInfo(serviceInfo, "");
+        endpointInfo.setName(new QName("bla", "Port"));
+        endpointInfo.addExtensor(policy);
+        
+        engine = EasyMock.createMock(NettyHttpServerEngine.class);
+        EasyMock.replay();
+        endpointInfo.setAddress(NOWHERE + "bar/foo");
+        
+        NettyHttpDestination dest =
+            new EasyMockJettyHTTPDestination(
+                    bus, transportFactory.getRegistry(), endpointInfo, null, engine);
+        assertEquals(policy, dest.getServer());
+    }
+        
+    @Test
+    public void testMultiplexGetAddressWithId() throws Exception {
+        destination = setUpDestination();
+        final String id = "ID2";
+        EndpointReferenceType refWithId = destination.getAddressWithId(id);
+        assertNotNull(refWithId);
+        assertNotNull(refWithId.getReferenceParameters());
+        assertNotNull(refWithId.getReferenceParameters().getAny());
+        assertTrue("it is an element", 
+                   refWithId.getReferenceParameters().getAny().get(0) instanceof JAXBElement);
+        JAXBElement<?> el = (JAXBElement<?>) refWithId.getReferenceParameters().getAny().get(0);
+        assertEquals("match our id", el.getValue(), id);
+    }
+    
+    @Test
+    public void testMultiplexGetAddressWithIdForAddress() throws Exception {
+        destination = setUpDestination();
+        destination.setMultiplexWithAddress(true);
+        
+        final String id = "ID3";
+        EndpointReferenceType refWithId = destination.getAddressWithId(id);
+        assertNotNull(refWithId);
+        assertNull(refWithId.getReferenceParameters());
+        assertTrue("match our id", EndpointReferenceUtils.getAddress(refWithId).indexOf(id) != -1);
+    }
+    
+    @Test
+    public void testMultiplexGetIdForAddress() throws Exception {
+        destination = setUpDestination();
+        destination.setMultiplexWithAddress(true);
+        
+        final String id = "ID3";
+        EndpointReferenceType refWithId = destination.getAddressWithId(id);
+        String pathInfo = EndpointReferenceUtils.getAddress(refWithId);
+        
+        Map<String, Object> context = new HashMap<String, Object>();
+        assertNull("fails with no context", destination.getId(context));
+        
+        context.put(Message.PATH_INFO, pathInfo);
+        String result = destination.getId(context);
+        assertNotNull(result);
+        assertEquals("match our id", result, id);
+    }
+    
+    @Test
+    public void testMultiplexGetId() throws Exception {
+        destination = setUpDestination();
+        
+        final String id = "ID3";
+        EndpointReferenceType refWithId = destination.getAddressWithId(id);
+        
+        Map<String, Object> context = new HashMap<String, Object>();
+        assertNull("fails with no context", destination.getId(context));
+        
+        AddressingProperties maps = EasyMock.createMock(AddressingProperties.class);
+        maps.getToEndpointReference();
+        EasyMock.expectLastCall().andReturn(refWithId);
+        EasyMock.replay(maps);      
+        context.put(JAXWSAConstants.SERVER_ADDRESSING_PROPERTIES_INBOUND, maps);
+        String result = destination.getId(context);
+        assertNotNull(result);
+        assertEquals("match our id", result, id);
+    }
+    
+    private NettyHttpDestination setUpDestination()
+        throws Exception {
+        return setUpDestination(false, false);
+    };
+    
+    private NettyHttpDestination setUpDestination(
+            boolean contextMatchOnStem, boolean mockedBus)
+        throws Exception {
+        policy = new HTTPServerPolicy();
+        address = getEPR("bar/foo");
+        
+
+        transportFactory = new HTTPTransportFactory();
+
+        final ConduitInitiator ci = new ConduitInitiator() {
+            public Conduit getConduit(EndpointInfo targetInfo) throws IOException {
+                return decoupledBackChannel;
+            }
+
+            public Conduit getConduit(EndpointInfo localInfo, EndpointReferenceType target)
+                throws IOException {
+                return decoupledBackChannel;
+            }
+
+            public List<String> getTransportIds() {
+                return null;
+            }
+
+            public Set<String> getUriPrefixes() {
+                return new HashSet<String>(Collections.singletonList("http"));
+            }
+            
+        };
+        ConduitInitiatorManager mgr = new ConduitInitiatorManager() {
+            public void deregisterConduitInitiator(String name) {
+            }
+
+            public ConduitInitiator getConduitInitiator(String name) throws BusException {
+                return null;
+            }
+
+            public ConduitInitiator getConduitInitiatorForUri(String uri) {
+                return ci;
+            }
+
+            public void registerConduitInitiator(String name, ConduitInitiator factory) {
+            }
+        };
+        
+        if (!mockedBus) {
+            bus = new ExtensionManagerBus();
+            bus.setExtension(mgr, ConduitInitiatorManager.class);
+        } else {
+            bus = EasyMock.createMock(Bus.class);
+            bus.getExtension(EndpointResolverRegistry.class);
+            EasyMock.expectLastCall().andReturn(null);
+            bus.getExtension(ContinuationProviderFactory.class);
+            EasyMock.expectLastCall().andReturn(null).anyTimes();
+            bus.getExtension(PolicyDataEngine.class);
+            EasyMock.expectLastCall().andReturn(null).anyTimes();
+            bus.hasExtensionByName("org.apache.cxf.ws.policy.PolicyEngine");
+            EasyMock.expectLastCall().andReturn(false);
+            bus.getExtension(ClassLoader.class);
+            EasyMock.expectLastCall().andReturn(this.getClass().getClassLoader());
+            EasyMock.replay(bus);
+        }
+        
+        
+        engine = EasyMock.createNiceMock(NettyHttpServerEngine.class);
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.setName(new QName("bla", "Service"));        
+        endpointInfo = new EndpointInfo(serviceInfo, "");
+        endpointInfo.setName(new QName("bla", "Port"));
+        endpointInfo.setAddress(NOWHERE + "bar/foo");
+       
+        endpointInfo.addExtensor(policy);
+        engine.addServant(EasyMock.eq(new URL(NOWHERE + "bar/foo")),
+                          EasyMock.isA(NettyHttpHandler.class));
+        EasyMock.expectLastCall();
+
+        EasyMock.replay(engine);
+        
+        NettyHttpDestination dest = new EasyMockJettyHTTPDestination(bus,
+                                                             transportFactory.getRegistry(),
+                                                             endpointInfo,
+                                                             null,
+                                                             engine);
+        dest.retrieveEngine();
+        policy = dest.getServer();
+        observer = new MessageObserver() {
+            public void onMessage(Message m) {
+                inMessage = m;
+                threadDefaultBus = BusFactory.getThreadDefaultBus();
+            }
+        };
+        dest.setMessageObserver(observer);
+        return dest;
+    }
+    
+    private void setUpQueryHandler(boolean stemMatching) {
+        wsdlQueryHandler = stemMatching
+                           ? EasyMock.createMock(StemMatchingQueryHandler.class)
+                           : EasyMock.createMock(QueryHandler.class);
+
+    }
+    
+    private void setUpRemoveServant() throws Exception {
+        EasyMock.reset(engine);
+        engine.removeServant(EasyMock.eq(new URL(NOWHERE + "bar/foo")));
+        EasyMock.expectLastCall();
+        EasyMock.replay(engine);
+    }
+    
+    private void setUpDoService(boolean setRedirectURL) throws Exception {
+        setUpDoService(setRedirectURL, false);
+    }
+
+    private void setUpDoService(boolean setRedirectURL,
+                                boolean sendResponse) throws Exception {
+        setUpDoService(setRedirectURL,
+                       sendResponse,
+                       false);
+    }      
+
+    private void setUpDoService(boolean setRedirectURL,
+                                boolean sendResponse, int status) throws Exception {
+        String method = "POST";
+        String query = "?name";
+        setUpDoService(setRedirectURL, sendResponse, false, method, query, status);
+    }
+    
+    private void setUpDoService(boolean setRedirectURL,
+                                boolean sendResponse, boolean decoupled, int status) throws Exception {
+        String method = "POST";
+        String query = "?name";
+        setUpDoService(setRedirectURL, sendResponse, decoupled, method, query, status);
+    }
+    
+    private void setUpDoService(boolean setRedirectURL,
+            boolean sendResponse,
+            boolean decoupled) throws Exception {
+        String method = "POST";
+        String query = "?name";
+        setUpDoService(setRedirectURL, sendResponse, decoupled, method, query, 200);
+    }
+
+    private void setUpDoService(boolean setRedirectURL,
+                                boolean sendResponse,
+                                boolean decoupled,
+                                String method,
+                                String query,
+                                int status
+                                ) throws Exception {
+       
+        is = EasyMock.createMock(ServletInputStream.class);
+        os = EasyMock.createMock(ServletOutputStream.class);
+        request = EasyMock.createMock(HttpServletRequest.class);
+        response = EasyMock.createMock(HttpServletResponse.class);
+        request.getMethod();
+        EasyMock.expectLastCall().andReturn(method).atLeastOnce();
+        request.getUserPrincipal();
+        EasyMock.expectLastCall().andReturn(null).anyTimes();
+        
+        
+        if (setRedirectURL) {
+            policy.setRedirectURL(NOWHERE + "foo/bar");
+            response.sendRedirect(EasyMock.eq(NOWHERE + "foo/bar"));
+            EasyMock.expectLastCall();
+            response.flushBuffer();
+            EasyMock.expectLastCall();
+        } else { 
+            //getQueryString for if statement
+            request.getQueryString();
+            EasyMock.expectLastCall().andReturn(query);      
+            
+            if ("GET".equals(method) && "?wsdl".equals(query)) {
+                verifyGetWSDLQuery();                
+            } else { // test for the post
+                EasyMock.expect(request.getAttribute(AbstractHTTPDestination.CXF_CONTINUATION_MESSAGE))
+                    .andReturn(null);
+                
+                //EasyMock.expect(request.getMethod()).andReturn(method);            
+                EasyMock.expect(request.getInputStream()).andReturn(is);
+                EasyMock.expect(request.getContextPath()).andReturn("/bar");
+                EasyMock.expect(request.getServletPath()).andReturn("");
+                EasyMock.expect(request.getPathInfo()).andReturn("/foo").times(2);
+                EasyMock.expect(request.getRequestURI()).andReturn("/foo");
+                EasyMock.expect(request.getRequestURL())
+                    .andReturn(new StringBuffer("http://localhost/foo")).anyTimes();
+                EasyMock.expect(request.getCharacterEncoding()).andReturn("UTF-8");
+                EasyMock.expect(request.getQueryString()).andReturn(query).times(2);    
+                EasyMock.expect(request.getHeader("Accept")).andReturn("*/*");  
+                EasyMock.expect(request.getContentType()).andReturn("text/xml charset=utf8").times(2);
+                EasyMock.expect(request.getAttribute("org.eclipse.jetty.ajax.Continuation")).andReturn(null);
+
+                List<String> contentType = new ArrayList<String>();
+                contentType.add("text/xml");
+                contentType.add("charset=utf8");
+                List<String> authHeader = new ArrayList<String>();
+                authHeader.add(BASIC_AUTH);
+                List<String> headerNames = new ArrayList<String>();
+                headerNames.add("content-type");
+                headerNames.add(AUTH_HEADER);
+                
+                EasyMock.expect(request.getHeaderNames()).andReturn(Utils.enumeration(headerNames));
+                request.getHeaders("content-type");
+                EasyMock.expectLastCall().andReturn(Utils.enumeration(contentType));
+                request.getHeaders(NettyHttpDestinationTest.AUTH_HEADER);
+                EasyMock.expectLastCall().andReturn(Utils.enumeration(authHeader));
+                 
+                EasyMock.expect(request.getInputStream()).andReturn(is);
+
+                response.flushBuffer();
+                EasyMock.expectLastCall();
+                if (sendResponse) {
+                    response.setStatus(status);
+                    EasyMock.expectLastCall();
+                    response.setContentType("text/xml charset=utf8");
+                    EasyMock.expectLastCall();
+                    response.addHeader(EasyMock.isA(String.class), EasyMock.isA(String.class));
+                    EasyMock.expectLastCall().anyTimes();
+                    response.setContentLength(0);
+                    EasyMock.expectLastCall().anyTimes();
+                    response.getOutputStream();
+                    EasyMock.expectLastCall().andReturn(os);
+                    response.flushBuffer();
+                    EasyMock.expectLastCall();                
+                }
+                request.getAttribute("javax.servlet.request.cipher_suite");
+                EasyMock.expectLastCall().andReturn("anythingwilldoreally");
+                request.getAttribute("javax.net.ssl.session");
+                EasyMock.expectLastCall().andReturn(null);
+                request.getAttribute("javax.servlet.request.X509Certificate");
+                EasyMock.expectLastCall().andReturn(null);
+            }
+        }
+        
+        if (decoupled) {
+            setupDecoupledBackChannel();
+        }
+        EasyMock.replay(response);
+        EasyMock.replay(request);
+    }
+    
+    private void setupDecoupledBackChannel() throws IOException {
+        decoupledBackChannel = EasyMock.createMock(Conduit.class);
+        decoupledBackChannel.setMessageObserver(EasyMock.isA(MessageObserver.class));           
+        decoupledBackChannel.prepare(EasyMock.isA(Message.class));
+        EasyMock.expectLastCall();
+        EasyMock.replay(decoupledBackChannel);
+    }
+    
+    private void setUpInMessage() {
+        inMessage.setExchange(new ExchangeImpl());
+    }
+    
+    private Message setUpOutMessage() {
+        Message outMsg = new MessageImpl();
+        outMsg.putAll(inMessage);
+        outMsg.setExchange(new ExchangeImpl());
+        outMsg.put(Message.PROTOCOL_HEADERS,
+                   new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER));
+        return outMsg;
+    }
+    
+    private void setUpResponseHeaders(Message outMsg) {
+        Map<String, List<String>> responseHeaders =
+            CastUtils.cast((Map<?, ?>)outMsg.get(Message.PROTOCOL_HEADERS));
+        assertNotNull("expected response headers", responseHeaders);
+        List<String> challenges = new ArrayList<String>();
+        challenges.add(BASIC_CHALLENGE);
+        challenges.add(DIGEST_CHALLENGE);
+        challenges.add(CUSTOM_CHALLENGE);
+        responseHeaders.put(CHALLENGE_HEADER, challenges);
+    }
+    
+    private void verifyGetWSDLQuery() throws Exception {
+        queryHandlerRegistry = EasyMock.createMock(QueryHandlerRegistry.class);
+        queryHandlerList = new ArrayList<QueryHandler>();
+        queryHandlerList.add(wsdlQueryHandler);
+        EasyMock.reset(bus);        
+        bus.getExtension(QueryHandlerRegistry.class);
+        EasyMock.expectLastCall().andReturn(queryHandlerRegistry);
+        queryHandlerRegistry.getHandlers();
+        EasyMock.expectLastCall().andReturn(queryHandlerList);       
+        request.getRequestURL();
+        EasyMock.expectLastCall().andReturn(new StringBuffer("http://localhost/bar/foo")).times(2);
+        request.getPathInfo();
+        EasyMock.expectLastCall().andReturn("/bar/foo");
+        request.getCharacterEncoding();
+        EasyMock.expectLastCall().andReturn("UTF-8");
+        request.getQueryString();
+        EasyMock.expectLastCall().andReturn("wsdl");    
+        response.setContentType("text/xml");
+        EasyMock.expectLastCall();        
+        response.getOutputStream();
+        EasyMock.expectLastCall().andReturn(os).anyTimes();
+
+        if (wsdlQueryHandler instanceof StemMatchingQueryHandler) {
+            ((StemMatchingQueryHandler)wsdlQueryHandler).isRecognizedQuery(
+                "http://localhost/bar/foo?wsdl", 
+                "/bar/foo",
+                endpointInfo,
+                false);
+        } else {
+            wsdlQueryHandler.isRecognizedQuery("http://localhost/bar/foo?wsdl",
+                                               "/bar/foo",
+                                               endpointInfo);
+        }
+        EasyMock.expectLastCall().andReturn(true);   
+        wsdlQueryHandler.getResponseContentType("http://localhost/bar/foo?wsdl", "/bar/foo");
+        EasyMock.expectLastCall().andReturn("text/xml");
+        wsdlQueryHandler.writeResponse(EasyMock.eq("http://localhost/bar/foo?wsdl"),
+                                       EasyMock.eq("/bar/foo"), 
+                                       EasyMock.eq(endpointInfo),
+                                       (OutputStream)EasyMock.anyObject());
+        EasyMock.expectLastCall().once();
+        EasyMock.replay(bus);
+        EasyMock.replay(queryHandlerRegistry);
+        EasyMock.replay(wsdlQueryHandler);
+    }
+
+    private void verifyDoService() throws Exception {
+        assertSame("Default thread bus has not been set for request",
+                    bus, threadDefaultBus);
+        assertNotNull("unexpected null message", inMessage);
+        assertSame("unexpected HTTP request",
+                   inMessage.get(NettyHttpDestination.HTTP_REQUEST),
+                   request);
+        assertSame("unexpected HTTP response",
+                   inMessage.get(NettyHttpDestination.HTTP_RESPONSE),
+                   response);
+        assertEquals("unexpected method",
+                     inMessage.get(Message.HTTP_REQUEST_METHOD),
+                     "POST");
+        assertEquals("unexpected path",
+                     inMessage.get(Message.PATH_INFO),
+                     "/bar/foo");
+        assertEquals("unexpected query",
+                     inMessage.get(Message.QUERY_STRING),
+                     "?name");        
+        assertNotNull("unexpected query",
+                   inMessage.get(TLSSessionInfo.class));
+        verifyRequestHeaders();
+                
+    }
+
+    private void verifyRequestHeaders() throws Exception {
+        Map<String, List<String>> requestHeaders =
+            CastUtils.cast((Map<?, ?>)inMessage.get(Message.PROTOCOL_HEADERS));
+        assertNotNull("expected request headers",
+                      requestHeaders);        
+        List<String> values = requestHeaders.get("content-type");
+        assertNotNull("expected field", values);
+        assertEquals("unexpected values", 2, values.size());
+        assertTrue("expected value", values.contains("text/xml"));
+        assertTrue("expected value", values.contains("charset=utf8"));
+        values = requestHeaders.get(AUTH_HEADER);
+        assertNotNull("expected field", values);
+        assertEquals("unexpected values", 1, values.size());
+        assertTrue("expected value", values.contains(BASIC_AUTH));
+        
+        AuthorizationPolicy authpolicy =
+            inMessage.get(AuthorizationPolicy.class);
+        assertNotNull("Expected some auth tokens", policy);
+        assertEquals("expected user",
+                     USER,
+                     authpolicy.getUserName());
+        assertEquals("expected passwd",
+                     PASSWD,
+                     authpolicy.getPassword());
+    }
+    
+    private void verifyResponseHeaders(Message outMsg) throws Exception {
+        Map<String, List<String>> responseHeaders =
+            CastUtils.cast((Map<?, ?>)outMsg.get(Message.PROTOCOL_HEADERS));
+        assertNotNull("expected response headers",
+                      responseHeaders);
+        //REVISIT CHALLENGE_HEADER's mean
+        /*assertEquals("expected addField",
+                     3,
+                     response.getAddFieldCallCount());
+        Enumeration e = response.getFieldValues(CHALLENGE_HEADER);
+        List<String> challenges = new ArrayList<String>();
+        while (e.hasMoreElements()) {
+            challenges.add((String)e.nextElement());
+        }
+        assertTrue("expected challenge",
+                   challenges.contains(BASIC_CHALLENGE));
+        assertTrue("expected challenge",
+                   challenges.contains(DIGEST_CHALLENGE));
+        assertTrue("expected challenge",
+                   challenges.contains(CUSTOM_CHALLENGE));*/
+    }
+    
+    private void verifyBackChannelSend(Conduit backChannel,
+                                       Message outMsg,
+                                       int status) throws Exception {
+        verifyBackChannelSend(backChannel, outMsg, status, false);
+    }
+    
+    private void verifyBackChannelSend(Conduit backChannel,
+                                       Message outMsg,
+                                       int status,
+                                       boolean oneway) throws Exception {
+        outMsg.getExchange().setOneWay(oneway);
+
+        assertTrue("unexpected back channel type",
+                   backChannel instanceof NettyHttpDestination.BackChannelConduit);
+        assertTrue("unexpected content formats",
+                   outMsg.getContentFormats().contains(OutputStream.class));
+        OutputStream responseOS = outMsg.getContent(OutputStream.class);
+        assertNotNull("expected output stream", responseOS);
+        assertTrue("unexpected output stream type",
+                   responseOS instanceof AbstractWrappedOutputStream);
+               
+        outMsg.put(Message.RESPONSE_CODE, status);          
+        responseOS.write(PAYLOAD.getBytes());
+        
+        setUpResponseHeaders(outMsg);
+        
+        responseOS.flush();
+        // we don't need to check the status here
+        /*if (status == 500) {
+            assertEquals("unexpected status message",
+                         "Internal Server Error",
+                         response.getReason());
+        }*/
+        verifyResponseHeaders(outMsg);     
+        
+        if (oneway) {
+            assertNull("unexpected HTTP response",
+                       outMsg.get(NettyHttpDestination.HTTP_RESPONSE));
+        } else {
+            assertNotNull("expected HTTP response",
+                           outMsg.get(NettyHttpDestination.HTTP_RESPONSE));
+            responseOS.close();            
+        }
+    }
+    
+    static EndpointReferenceType getEPR(String s) {
+        return EndpointReferenceUtils.getEndpointReference(NOWHERE + s);
+    }
+    
+    private static class TestJettyDestination extends NettyHttpDestination {
+        public TestJettyDestination(Bus bus,
+                                    DestinationRegistry registry,
+                                    EndpointInfo endpointInfo,
+                                    NettyHttpServerEngineFactory serverEngineFactory) throws IOException {
+            super(bus, registry, endpointInfo, serverEngineFactory);
+        }
+        
+        @Override
+        public Message retrieveFromContinuation(HttpServletRequest request) {
+            return super.retrieveFromContinuation(request);
+        }
+        
+        
+    }
+}

Added: cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactoryTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactoryTest.java?rev=1486823&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactoryTest.java (added)
+++ cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactoryTest.java Tue May 28 08:54:49 2013
@@ -0,0 +1,84 @@
+/**
+ * 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.cxf.transport.http.netty.server;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.transport.DestinationFactory;
+import org.apache.cxf.transport.DestinationFactoryManager;
+import org.apache.cxf.transport.http.HTTPTransportFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+
+public class NettyHttpServerEngineFactoryTest
+        extends Assert {
+    Bus bus;
+    
+    @BeforeClass
+    public static void classUp() {
+        // Get rid of any notion of a default bus set by other 
+        // rogue tests.
+        BusFactory.setDefaultBus(null);
+    }
+    
+    @AfterClass
+    public static void classDown() {
+        // Clean up.
+        BusFactory.setDefaultBus(null);
+    }
+    
+    @After
+    public void tearDown() {
+        if (bus != null) {
+            bus.shutdown(false);
+            bus = null;
+        }
+    }
+
+    @Test
+    public void testTransportFactoryHasEngineFactory() throws Exception {
+        bus = BusFactory.getDefaultBus(true);
+        
+        assertNotNull("Cannot get bus", bus);
+        
+        // Make sure we got the Transport Factory.
+        DestinationFactoryManager destFM = 
+            bus.getExtension(DestinationFactoryManager.class);
+        assertNotNull("Cannot get DestinationFactoryManager", destFM);
+        DestinationFactory destF = 
+            destFM.getDestinationFactory(
+                    "http://cxf.apache.org/transports/http");
+        assertNotNull("No DestinationFactory", destF);
+        assertTrue(HTTPTransportFactory.class.isInstance(destF));
+
+
+        NettyHttpServerEngineFactory factory =
+            bus.getExtension(NettyHttpServerEngineFactory.class);
+        assertNotNull("EngineFactory is not configured.", factory);
+    }
+    
+
+
+}

Added: cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineTest.java?rev=1486823&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineTest.java (added)
+++ cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineTest.java Tue May 28 08:54:49 2013
@@ -0,0 +1,152 @@
+/**
+ * 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.cxf.transport.http.netty.server;
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import org.apache.cxf.Bus;
+import org.apache.cxf.configuration.Configurer;
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.testutil.common.TestUtil;
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+
+public class NettyHttpServerEngineTest extends Assert {
+    private static final int PORT1 
+        = Integer.valueOf(TestUtil.getPortNumber(NettyHttpServerEngineTest.class, 1));
+    private static final int PORT3 
+        = Integer.valueOf(TestUtil.getPortNumber(NettyHttpServerEngineTest.class, 3));
+    
+
+    private Bus bus;
+    private IMocksControl control;
+    private NettyHttpServerEngineFactory factory;
+
+    @Before
+    public void setUp() throws Exception {
+        control = EasyMock.createNiceControl();
+        bus = control.createMock(Bus.class);
+        
+        Configurer configurer = control.createMock(Configurer.class);
+        bus.getExtension(Configurer.class);
+        EasyMock.expectLastCall().andReturn(configurer).anyTimes();
+        
+        control.replay();
+
+        factory = new NettyHttpServerEngineFactory();
+        factory.setBus(bus);
+
+    }
+
+    @Test
+    public void testEngineRetrieval() throws Exception {
+        NettyHttpServerEngine engine =
+            factory.createNettyHttpServerEngine(PORT1, "http");
+
+        assertTrue(
+            "Engine references for the same port should point to the same instance",
+            engine == factory.retrieveNettyHttpServerEngine(PORT1));
+
+        NettyHttpServerEngineFactory.destroyForPort(PORT1);
+    }
+
+    @Test
+    public void testaddServants() throws Exception {
+        String urlStr = "http://localhost:" + PORT1 + "/hello/test";
+        String urlStr2 = "http://localhost:" + PORT1 + "/hello233/test";
+        NettyHttpServerEngine engine =
+            factory.createNettyHttpServerEngine(PORT1, "http");
+
+        NettyHttpTestHandler handler1 = new NettyHttpTestHandler("string1", true);
+        NettyHttpTestHandler handler2 = new NettyHttpTestHandler("string2", true);
+        engine.addServant(new URL(urlStr), handler1);
+        //assertEquals("Get the wrong maxIdleTime.", 30000, engine.getConnector().getMaxIdleTime());
+        
+        String response = null;
+        response = getResponse(urlStr);
+        assertEquals("The jetty http handler did not take effect", response, "string1");
+
+        engine.addServant(new URL(urlStr), handler2);
+        response = getResponse(urlStr);
+        assertEquals("The jetty http handler did not take effect", response, "string1string2");
+        engine.addServant(new URL(urlStr2), handler2);
+
+        
+        engine.removeServant(new URL(urlStr));
+        response = getResponse(urlStr2);
+        assertEquals("The jetty http handler did not take effect", response, "string2");
+        engine.shutdown();
+        // set the get request
+        NettyHttpServerEngineFactory.destroyForPort(PORT1);
+
+    }
+
+    @Test
+    public void testNettyHttpHandler() throws Exception {
+        String urlStr1 = "http://localhost:" + PORT3 + "/hello/test";
+        String urlStr2 = "http://localhost:" + PORT3 + "/hello/test2";
+        NettyHttpServerEngine engine =
+            factory.createNettyHttpServerEngine(PORT3, "http");
+
+        NettyHttpTestHandler handler1 = new NettyHttpTestHandler("test", false);
+        NettyHttpTestHandler handler2 = new NettyHttpTestHandler("test2", false);
+        engine.addServant(new URL(urlStr1), handler1);
+        engine.addServant(new URL(urlStr2), handler2);
+
+
+        String response = null;
+        try {
+            response = getResponse(urlStr1 + "/test");
+        } catch (Exception ex) {
+            fail("Can't get the reponse from the server " + ex);
+        }
+        assertEquals("the jetty http handler did not take effect", response, "test");
+
+        try {
+            response = getResponse(urlStr2 + "/test");
+        } catch (Exception ex) {
+            fail("Can't get the reponse from the server " + ex);
+        }
+        assertEquals("the jetty http handler did not take effect", response, "test2");
+
+        NettyHttpServerEngineFactory.destroyForPort(PORT3);
+    }
+
+    private String getResponse(String target) throws Exception {
+        URL url = new URL(target);
+
+        URLConnection connection = url.openConnection();
+
+        assertTrue(connection instanceof HttpURLConnection);
+        connection.connect();
+        InputStream in = connection.getInputStream();
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        IOUtils.copy(in, buffer);
+        return buffer.toString();
+    }
+}

Added: cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpTestHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpTestHandler.java?rev=1486823&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpTestHandler.java (added)
+++ cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/NettyHttpTestHandler.java Tue May 28 08:54:49 2013
@@ -0,0 +1,59 @@
+/**
+ * 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.cxf.transport.http.netty.server;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+public class NettyHttpTestHandler extends NettyHttpHandler {
+    private boolean contextMatchExact;
+    private String response;
+
+    public NettyHttpTestHandler(String s, boolean cmExact) {
+        super(null, cmExact);
+        contextMatchExact = cmExact;
+        response = s;
+    }
+
+    @Override
+    public void handle(String target,
+                       HttpServletRequest request,
+                       HttpServletResponse resp) throws IOException, ServletException {
+
+        if (contextMatchExact) {
+            // just return the response for testing
+            resp.getOutputStream().write(response.getBytes());
+            resp.flushBuffer();
+
+        } else {
+            if (target.equals(getName()) || checkContextPath(target)) {
+                resp.getOutputStream().write(response.getBytes());
+                resp.flushBuffer();
+            }
+        }
+    }
+
+
+
+}

Added: cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/integration/NettyServerTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/integration/NettyServerTest.java?rev=1486823&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/integration/NettyServerTest.java (added)
+++ cxf/trunk/rt/transports/http-netty/netty-server/src/test/java/org/apache/cxf/transport/http/netty/server/integration/NettyServerTest.java Tue May 28 08:54:49 2013
@@ -0,0 +1,75 @@
+/**
+ * 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.cxf.transport.http.netty.server.integration;
+
+
+import java.net.URL;
+import javax.xml.ws.Endpoint;
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.hello_world_soap_http.Greeter;
+import org.apache.hello_world_soap_http.SOAPService;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class NettyServerTest extends AbstractBusClientServerTestBase {
+    public static final String PORT = allocatePort(NettyServerTest.class);
+
+    static Endpoint ep;
+
+    static Greeter g;
+
+    @BeforeClass
+    public static void start() throws Exception {
+        Bus b = createStaticBus();
+        BusFactory.setThreadDefaultBus(b);
+        ep = Endpoint.publish("http://localhost:" + PORT + "/SoapContext/SoapPort",
+                new org.apache.hello_world_soap_http.GreeterImpl());
+
+        URL wsdl = NettyServerTest.class.getResource("/wsdl/hello_world.wsdl");
+        assertNotNull("WSDL is null", wsdl);
+
+        SOAPService service = new SOAPService(wsdl);
+        assertNotNull("Service is null", service);
+
+        g = service.getSoapPort();
+        assertNotNull("Port is null", g);
+    }
+
+    @AfterClass
+    public static void stop() throws Exception {
+        if (g != null) {
+            ((java.io.Closeable)g).close();
+        }
+        if (ep != null) {
+            ep.stop();
+        }
+        ep = null;
+    }
+
+    @Test
+    public void testInvocation() throws Exception {
+        updateAddressPort(g, PORT);
+        String response = g.greetMe("test");
+        assertEquals("Get a wrong response", "Hello test", response);
+    }
+
+}