Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E418CF1F2 for ; Tue, 28 May 2013 08:55:39 +0000 (UTC) Received: (qmail 72463 invoked by uid 500); 28 May 2013 08:55:35 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 71237 invoked by uid 500); 28 May 2013 08:55:19 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 71052 invoked by uid 99); 28 May 2013 08:55:17 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 28 May 2013 08:55:17 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 28 May 2013 08:55:13 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 2DBFA2388ACC; Tue, 28 May 2013 08:54:54 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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... Date: Tue, 28 May 2013 08:54:52 -0000 To: commits@cxf.apache.org From: ningjiang@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130528085454.2DBFA2388ACC@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 SESSIONS + = new ConcurrentHashMap(); + + @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 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 Enumeration emptyEnumeration() { + return Collections.enumeration(Collections.emptySet()); + } + + public static Enumeration enumeration(Collection collection) { + if (collection == null) { + return emptyEnumeration(); + } + return Collections.enumeration(collection); + } + + public static Enumeration enumerationFromKeys(Map map) { + if (map == null) { + return emptyEnumeration(); + } + return Collections.enumeration(map.keySet()); + } + + public static Enumeration enumerationFromValues(Map 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, + * null 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 getCookies(String name, + HttpRequest request) { + String cookieString = request.getHeader(COOKIE); + if (cookieString != null) { + List foundCookie = new ArrayList(); + CookieDecoder cookieDecoder = new CookieDecoder(); + Set cookies = cookieDecoder.decode(cookieString); + for (Cookie cookie : cookies) { + if (cookie.getName().equals(name)) { + foundCookie.add(cookie); + } + } + + return foundCookie; + } + return null; + } + + public static Collection getCookies(String name, + HttpResponse response) { + String cookieString = response.getHeader(COOKIE); + if (cookieString != null) { + List foundCookie = new ArrayList(); + CookieDecoder cookieDecoder = new CookieDecoder(); + Set 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 parseAcceptLanguageHeader( + String acceptLanguageHeader) { + + if (acceptLanguageHeader == null) { + return null; + } + + List locales = new ArrayList(); + + 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 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 context = new HashMap(); + 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 context = new HashMap(); + 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 getTransportIds() { + return null; + } + + public Set getUriPrefixes() { + return new HashSet(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 contentType = new ArrayList(); + contentType.add("text/xml"); + contentType.add("charset=utf8"); + List authHeader = new ArrayList(); + authHeader.add(BASIC_AUTH); + List headerNames = new ArrayList(); + 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.CASE_INSENSITIVE_ORDER)); + return outMsg; + } + + private void setUpResponseHeaders(Message outMsg) { + Map> responseHeaders = + CastUtils.cast((Map)outMsg.get(Message.PROTOCOL_HEADERS)); + assertNotNull("expected response headers", responseHeaders); + List challenges = new ArrayList(); + 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(); + 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> requestHeaders = + CastUtils.cast((Map)inMessage.get(Message.PROTOCOL_HEADERS)); + assertNotNull("expected request headers", + requestHeaders); + List 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> 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 challenges = new ArrayList(); + 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); + } + +}