001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.transport.http;
019:
020: import java.io.OutputStream;
021: import java.net.HttpURLConnection;
022: import java.net.URL;
023: import java.util.ArrayList;
024: import java.util.HashMap;
025: import java.util.List;
026: import java.util.Map;
027:
028: import org.apache.cxf.Bus;
029: import org.apache.cxf.bus.CXFBusImpl;
030: import org.apache.cxf.common.util.Base64Utility;
031: import org.apache.cxf.configuration.security.AuthorizationPolicy;
032: import org.apache.cxf.helpers.CastUtils;
033: import org.apache.cxf.message.Message;
034: import org.apache.cxf.message.MessageImpl;
035: import org.apache.cxf.service.model.EndpointInfo;
036: import org.apache.cxf.transport.Destination;
037: import org.apache.cxf.transport.DestinationFactory;
038: import org.apache.cxf.transport.DestinationFactoryManager;
039: import org.apache.cxf.transport.MessageObserver;
040: import org.apache.cxf.ws.addressing.EndpointReferenceType;
041: import org.apache.cxf.wsdl.EndpointReferenceUtils;
042: import org.easymock.classextension.EasyMock;
043: import org.easymock.classextension.IMocksControl;
044: import org.junit.After;
045: import org.junit.Assert;
046: import org.junit.Before;
047: import org.junit.Test;
048:
049: import static org.apache.cxf.message.Message.DECOUPLED_CHANNEL_MESSAGE;
050:
051: public class HTTPConduitTest extends Assert {
052: private Message inMessage;
053: private IMocksControl control;
054:
055: @Before
056: public void setUp() throws Exception {
057: }
058:
059: @After
060: public void tearDown() {
061: }
062:
063: /**
064: * Generates a new message.
065: */
066: private Message getNewMessage() {
067: Message message = new MessageImpl();
068: Map<String, List<String>> headers = new HashMap<String, List<String>>();
069: List<String> contentTypes = new ArrayList<String>();
070: contentTypes.add("text/xml");
071: contentTypes.add("charset=utf8");
072: headers.put("content-type", contentTypes);
073: message.put(Message.PROTOCOL_HEADERS, headers);
074: return message;
075: }
076:
077: /**
078: * This test class is a Basic Auth Supplier with a
079: * preemptive UserPass.
080: */
081: class BasicAuthSupplier extends HttpBasicAuthSupplier {
082: public UserPass getPreemptiveUserPass(String conduitName,
083: URL url, Message m) {
084: return createUserPass("Gandalf", "staff");
085: }
086:
087: public UserPass getUserPassForRealm(String conduitName,
088: URL url, Message m, String r) {
089: return null;
090: }
091: }
092:
093: /**
094: * This test verfies that the "getTarget() call returns the correct
095: * EndpointReferenceType for the given endpoint address.
096: */
097: @Test
098: public void testGetTarget() throws Exception {
099: Bus bus = new CXFBusImpl();
100: EndpointInfo ei = new EndpointInfo();
101: ei.setAddress("http://nowhere.com/bar/foo");
102: HTTPConduit conduit = new HTTPConduit(bus, ei, null);
103: conduit.finalizeConfig();
104:
105: EndpointReferenceType target = EndpointReferenceUtils
106: .getEndpointReference("http://nowhere.com/bar/foo");
107:
108: // Test call
109: EndpointReferenceType ref = conduit.getTarget();
110:
111: assertNotNull("unexpected null target", ref);
112: assertEquals("unexpected target", EndpointReferenceUtils
113: .getAddress(ref), EndpointReferenceUtils
114: .getAddress(target));
115:
116: assertEquals("unexpected address", conduit.getAddress(),
117: "http://nowhere.com/bar/foo");
118: assertNull("unexpected upfront URL", conduit.getURL(false));
119: assertEquals("unexpected on-demand URL", conduit.getURL()
120: .getPath(), "/bar/foo");
121: }
122:
123: /**
124: * Verfies one of the tenents of our interface -- the Conduit sets up
125: * an OutputStream on the message after a "prepare".
126: */
127: @Test
128: public void testConduitOutputStream() throws Exception {
129: Bus bus = new CXFBusImpl();
130: EndpointInfo ei = new EndpointInfo();
131: ei.setAddress("http://nowhere.com/bar/foo");
132: HTTPConduit conduit = new HTTPConduit(bus, ei, null);
133: conduit.finalizeConfig();
134:
135: Message message = getNewMessage();
136:
137: // Test call
138: conduit.prepare(message);
139:
140: assertNotNull("Conduit should always set output stream.",
141: message.getContent(OutputStream.class));
142: }
143:
144: /**
145: * This test verifies the precidence of Authorization Information.
146: * Setting authorization information on the Message takes precidence
147: * over a Basic Auth Supplier with preemptive UserPass, and that
148: * followed by setting it directly on the Conduit.
149: */
150: @Test
151: public void testAuthPolicyPrecidence() throws Exception {
152: Bus bus = new CXFBusImpl();
153: EndpointInfo ei = new EndpointInfo();
154: ei.setAddress("http://nowhere.com/bar/foo");
155: HTTPConduit conduit = new HTTPConduit(bus, ei, null);
156: conduit.finalizeConfig();
157:
158: conduit.getAuthorization().setUserName("Satan");
159: conduit.getAuthorization().setPassword("hell");
160: Message message = getNewMessage();
161:
162: // Test call
163: conduit.prepare(message);
164:
165: Map<String, List<String>> headers = CastUtils
166: .cast((Map<?, ?>) message.get(Message.PROTOCOL_HEADERS));
167:
168: assertNotNull("Authorization Header should exist", headers
169: .get("Authorization"));
170:
171: assertEquals("Unexpected Authorization Token", "Basic "
172: + Base64Utility.encode("Satan:hell".getBytes()),
173: headers.get("Authorization").get(0));
174:
175: // Setting a Basic Auth User Pass should override
176: conduit.setBasicAuthSupplier(new BasicAuthSupplier());
177: message = getNewMessage();
178:
179: // Test Call
180: conduit.prepare(message);
181:
182: headers = CastUtils.cast((Map<?, ?>) message
183: .get(Message.PROTOCOL_HEADERS));
184:
185: assertEquals("Unexpected Authorization Token", "Basic "
186: + Base64Utility.encode("Gandalf:staff".getBytes()),
187: headers.get("Authorization").get(0));
188:
189: // Setting authorization policy on the message should override all.
190: AuthorizationPolicy authPolicy = new AuthorizationPolicy();
191: authPolicy.setUserName("Hello");
192: authPolicy.setPassword("world");
193: message = getNewMessage();
194: message.put(AuthorizationPolicy.class, authPolicy);
195:
196: conduit.prepare(message);
197:
198: headers = CastUtils.cast((Map<?, ?>) message
199: .get(Message.PROTOCOL_HEADERS));
200:
201: assertEquals("Unexpected Authorization Token", "Basic "
202: + Base64Utility.encode("Hello:world".getBytes()),
203: headers.get("Authorization").get(0));
204: }
205:
206: public void testDecoupledEndpoint() throws Exception {
207: control = EasyMock.createNiceControl();
208:
209: Bus bus = new CXFBusImpl();
210:
211: URL decoupledURL = new URL("http://nowhere.com/response");
212: DestinationFactoryManager mgr = control
213: .createMock(DestinationFactoryManager.class);
214: DestinationFactory factory = control
215: .createMock(DestinationFactory.class);
216: Destination destination = control.createMock(Destination.class);
217:
218: bus.setExtension(mgr, DestinationFactoryManager.class);
219: mgr.getDestinationFactoryForUri(decoupledURL.toString());
220: EasyMock.expectLastCall().andReturn(factory);
221: factory.getDestination(EasyMock.isA(EndpointInfo.class));
222: EasyMock.expectLastCall().andReturn(destination);
223: destination.setMessageObserver(EasyMock
224: .isA(HTTPConduit.InterposedMessageObserver.class));
225:
226: control.replay();
227:
228: EndpointInfo ei = new EndpointInfo();
229: ei.setAddress("http://nowhere.com/bar/foo");
230: HTTPConduit conduit = new HTTPConduit(bus, ei, null);
231: conduit.finalizeConfig();
232:
233: // Test call
234: conduit.getClient().setDecoupledEndpoint(
235: decoupledURL.toString());
236:
237: assertNotNull("expected back channel", conduit.getBackChannel());
238:
239: MessageObserver observer = new MessageObserver() {
240: public void onMessage(Message m) {
241: inMessage = m;
242: }
243: };
244:
245: // Test call
246: conduit.setMessageObserver(observer);
247:
248: Message incoming = new MessageImpl();
249: conduit.getDecoupledObserver().onMessage(incoming);
250:
251: assertSame("expected pass thru onMessage() notification",
252: inMessage, incoming);
253: assertEquals("unexpected response code",
254: HttpURLConnection.HTTP_OK, inMessage
255: .get(Message.RESPONSE_CODE));
256: assertEquals("expected DECOUPLED_CHANNEL_MESSAGE flag set",
257: Boolean.TRUE, inMessage.get(DECOUPLED_CHANNEL_MESSAGE));
258: assertEquals("unexpected HTTP_REQUEST set", false, inMessage
259: .containsKey(AbstractHTTPDestination.HTTP_REQUEST));
260: assertEquals("unexpected HTTP_RESPONSE set", false, inMessage
261: .containsKey(AbstractHTTPDestination.HTTP_RESPONSE));
262: assertEquals(
263: "unexpected Message.ASYNC_POST_RESPONSE_DISPATCH set",
264: false,
265: inMessage
266: .containsKey(Message.ASYNC_POST_RESPONSE_DISPATCH));
267:
268: // avoid intermittent spurious failures on EasyMock detecting finalize
269: // calls by mocking up only class data members (no local variables)
270: // and explicitly making available for GC post-verify
271: finalVerify();
272: inMessage = null;
273: }
274:
275: private void finalVerify() {
276: if (control != null) {
277: control.verify();
278: control = null;
279: }
280: }
281:
282: }
|