View Javadoc

1   /*
2    * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.opensaml.ws.soap.client;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.io.OutputStream;
22  import java.io.PipedInputStream;
23  import java.io.PipedOutputStream;
24  import java.net.URI;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import org.apache.commons.httpclient.HttpClient;
29  import org.apache.commons.httpclient.HttpVersion;
30  import org.apache.commons.httpclient.NameValuePair;
31  import org.apache.commons.httpclient.URIException;
32  import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
33  import org.apache.commons.httpclient.methods.PostMethod;
34  import org.opensaml.ws.message.MessageContext;
35  import org.opensaml.ws.message.decoder.MessageDecoder;
36  import org.opensaml.ws.message.decoder.MessageDecodingException;
37  import org.opensaml.ws.message.encoder.MessageEncoder;
38  import org.opensaml.ws.message.encoder.MessageEncodingException;
39  import org.opensaml.ws.transport.TransportException;
40  import org.opensaml.ws.transport.http.HTTPInTransport;
41  import org.opensaml.ws.transport.http.HTTPOutTransport;
42  import org.opensaml.xml.security.SecurityException;
43  import org.opensaml.xml.security.credential.Credential;
44  import org.slf4j.Logger;
45  import org.slf4j.LoggerFactory;
46  
47  /**
48   * SOAP transport using HTTP.
49   */
50  public class HTTPSOAPTransport implements ClientTransport {
51  
52      /** Class logger. */
53      private final Logger log = LoggerFactory.getLogger(HTTPSOAPTransport.class);
54  
55      /** HTTP client used to connect to peers. */
56      private HttpClient httpClient;
57  
58      /** Encoder used to encode message to the outbound transport. */
59      private MessageEncoder messageEncoder;
60  
61      /** Decoder used to decode message from inbound transport. */
62      private MessageDecoder messageDecoder;
63  
64      /**
65       * Constructor.
66       * 
67       * @param client client used to communicate with peer.
68       * @param encoder encoder used to encode messages onto the outgoing transport
69       * @param decoder decoder used to decode messages from inbound transport
70       */
71      public HTTPSOAPTransport(HttpClient client, MessageEncoder encoder, MessageDecoder decoder) {
72          httpClient = client;
73          messageEncoder = encoder;
74          messageDecoder = decoder;
75      }
76  
77      /** {@inheritDoc} */
78      public void send(URI endpointURI, MessageContext messageContext) throws TransportException {
79          try {
80              PostMethod postMethod = new PostMethod(endpointURI.toASCIIString());
81              PostMethodHttpOutTransport outTransport = new PostMethodHttpOutTransport(postMethod);
82              messageContext.setOutboundMessageTransport(outTransport);
83              messageEncoder.encode(messageContext);
84  
85              httpClient.executeMethod(postMethod);
86  
87              PostMethodHttpInTransport inTransport = new PostMethodHttpInTransport(postMethod);
88              messageContext.setInboundMessageTransport(inTransport);
89              messageDecoder.decode(messageContext);
90          } catch (IOException e) {
91              throw new TransportException("Unable to establish connection to peer", e);
92          } catch (MessageEncodingException e) {
93              throw new TransportException("Unable to encode message onto outbound transport", e);
94          } catch (MessageDecodingException e) {
95              throw new TransportException("Unable to decode message from inbound transport", e);
96          } catch (SecurityException e){
97              throw new TransportException("Inbound transport and response did not meet security policy requirements", e);
98          }
99      }
100 
101     /**
102      * Adapts an Apache Commons HTTPClient {@link PostMethod} into an {@link HTTPOutTransport}.
103      */
104     protected class PostMethodHttpOutTransport implements HTTPOutTransport {
105 
106         /** Post method used to send the request. */
107         private PostMethod postMethod;
108 
109         /** Whether the transport is authenticated. */
110         private boolean transportAuthenticated;
111 
112         /** Whether the transport is confidential. */
113         private boolean transportConfidential;
114         
115         /** Whether the transport provides integrity protection. */
116         private boolean transportIntegrityProtected;
117 
118         /**
119          * Constructor.
120          * 
121          * @param method post method used to send the request
122          */
123         public PostMethodHttpOutTransport(PostMethod method) {
124             postMethod = method;
125         }
126 
127         /**
128          * {@inheritDoc}
129          * 
130          * This method is not supported for this transport implementation.
131          */
132         public void sendRedirect(String location) {
133 
134         }
135 
136         /** {@inheritDoc} */
137         public void setHeader(String name, String value) {
138             postMethod.addRequestHeader(name, value);
139         }
140 
141         /**
142          * {@inheritDoc}
143          * 
144          * This method is not supported for this transport implementation.
145          */
146         public void addParameter(String name, String value) {
147 
148         }
149 
150         /**
151          * {@inheritDoc}
152          * 
153          * This method is not supported for this transport implementation.
154          */
155         public void setStatusCode(int code) {
156 
157         }
158 
159         /**
160          * {@inheritDoc}
161          * 
162          * This method is not supported for this transport implementation.
163          */
164         public void setVersion(HTTP_VERSION version) {
165 
166         }
167 
168         /**
169          * {@inheritDoc}
170          * 
171          * This method is not supported for this transport implementation.
172          */
173         public OutputStream getOutgoingStream() {
174             try {
175                 PipedInputStream requestInputStream = new PipedInputStream();
176                 PipedOutputStream pipedOutput = new PipedOutputStream(requestInputStream);
177                 requestInputStream.connect(pipedOutput);
178 
179                 InputStreamRequestEntity requestEntity = new InputStreamRequestEntity(requestInputStream);
180                 postMethod.setRequestEntity(requestEntity);
181 
182                 return pipedOutput;
183             } catch (IOException e) {
184                 log.error("Error constructing output stream to POST method body", e);
185                 return null;
186             }
187         }
188 
189         /**
190          * {@inheritDoc}
191          * 
192          * This method is not supported for this transport implementation.
193          */
194         public void setAttribute(String name, Object value) {
195 
196         }
197 
198         /**
199          * {@inheritDoc}
200          * 
201          * This method is not supported for this transport implementation.
202          * 
203          */
204         public void setCharacterEncoding(String encoding) {
205 
206         }
207 
208         /**
209          * {@inheritDoc}
210          * 
211          * This method is not supported for this transport implementation.
212          */
213         public Object getAttribute(String name) {
214             return null;
215         }
216 
217         /**
218          * {@inheritDoc}
219          * 
220          * This method is not supported for this transport implementation.
221          */
222         public String getCharacterEncoding() {
223             return postMethod.getRequestCharSet();
224         }
225 
226         /**
227          * {@inheritDoc}
228          * 
229          * This method is not supported for this transport implementation.
230          */
231         public Credential getLocalCredential() {
232             return null;
233         }
234 
235         /**
236          * {@inheritDoc}
237          * 
238          * This method is not supported for this transport implementation.
239          */
240         public Credential getPeerCredential() {
241             return null;
242         }
243 
244         /** {@inheritDoc} */
245         public boolean isAuthenticated() {
246             return transportAuthenticated;
247         }
248 
249         /** {@inheritDoc} */
250         public boolean isConfidential() {
251             return transportConfidential;
252         }
253 
254         /**
255          * {@inheritDoc}
256          * 
257          * This method is not supported for this transport implementation.
258          */
259         public void setAuthenticated(boolean isAuthenticated) {
260             transportAuthenticated = isAuthenticated;
261         }
262 
263         /** {@inheritDoc} */
264         public void setConfidential(boolean isConfidential) {
265             transportConfidential = isConfidential;
266         }
267 
268         /** {@inheritDoc} */
269         public String getHTTPMethod() {
270             return postMethod.getName();
271         }
272 
273         /** {@inheritDoc} */
274         public String getHeaderValue(String name) {
275             return postMethod.getRequestHeader(name).getValue();
276         }
277 
278         /** {@inheritDoc} */
279         public String getParameterValue(String name) {
280             return postMethod.getParameter(name).getValue();
281         }
282         
283         /** {@inheritDoc} */
284         public List<String> getParameterValues(String name) {
285             ArrayList<String> valueList = new ArrayList<String>();
286             NameValuePair[] parameters = postMethod.getParameters();
287             if(parameters != null){
288                 for(NameValuePair parameter : parameters){
289                     if(parameter.getName().equals(name)){
290                         valueList.add(parameter.getValue());
291                     }
292                 }
293             }
294 
295             return valueList;
296         }
297 
298         /**
299          * {@inheritDoc}
300          * 
301          * This method is not supported for this transport implementation.
302          */
303         public int getStatusCode() {
304             return -1;
305         }
306 
307         /**
308          * {@inheritDoc}
309          */
310         public HTTP_VERSION getVersion() {
311             HttpVersion httpVersion = postMethod.getEffectiveVersion();
312             if (httpVersion == HttpVersion.HTTP_1_0) {
313                 return HTTP_VERSION.HTTP1_0;
314             } else if (httpVersion == HttpVersion.HTTP_1_1) {
315                 return HTTP_VERSION.HTTP1_1;
316             }
317             return null;
318         }
319         
320         /** {@inheritDoc} */
321         public boolean isIntegrityProtected() {
322             return transportIntegrityProtected;
323         }
324         
325         /** {@inheritDoc} */
326         public void setIntegrityProtected(boolean isIntegrityProtected) {
327             transportIntegrityProtected = isIntegrityProtected;
328         }
329     }
330 
331     /**
332      * Adapts an Apache Commons HTTPClient {@link PostMethod} into an {@link HTTPInTransport}.
333      */
334     protected class PostMethodHttpInTransport implements HTTPInTransport {
335 
336         /** Adapted POST method. */
337         private PostMethod postMethod;
338 
339         /** Whether the transport is authenticated. */
340         private boolean transportAuthenticated;
341 
342         /** Whether the transport is confidential. */
343         private boolean transportConfidential;
344         
345         /** Whether the transport provides integrity protection. */
346         private boolean transportIntegrityProtected;
347 
348         /**
349          * Constructor.
350          * 
351          * @param method post method to be adapted
352          */
353         public PostMethodHttpInTransport(PostMethod method) {
354             postMethod = method;
355         }
356 
357         /** {@inheritDoc} */
358         public String getPeerAddress() {
359             // TODO Auto-generated method stub
360             return null;
361         }
362 
363         /**
364          * {@inheritDoc}
365          * 
366          * This method is not supported for this transport implementation.
367          */
368         public String getPeerDomainName() {
369             try {
370                 return postMethod.getURI().getHost();
371             } catch (URIException e) {
372                 log.error("Unable to recover host from request URI", e);
373                 return null;
374             }
375         }
376 
377         /** {@inheritDoc} */
378         public InputStream getIncomingStream() {
379             try {
380                 return postMethod.getResponseBodyAsStream();
381             } catch (IOException e) {
382                 log.error("Unable to retrieve response stream", e);
383                 return null;
384             }
385         }
386 
387         /**
388          * {@inheritDoc}
389          * 
390          * This method is not supported for this transport implementation.
391          */
392         public Object getAttribute(String name) {
393             return null;
394         }
395 
396         /** {@inheritDoc} */
397         public String getCharacterEncoding() {
398             return postMethod.getResponseCharSet();
399         }
400 
401         /**
402          * {@inheritDoc}
403          * 
404          * This method is not supported for this transport implementation.
405          */
406         public Credential getLocalCredential() {
407             // TODO Auto-generated method stub
408             return null;
409         }
410 
411         /**
412          * {@inheritDoc}
413          * 
414          * This method is not supported for this transport implementation.
415          */
416         public Credential getPeerCredential() {
417             // TODO Auto-generated method stub
418             return null;
419         }
420 
421         /** {@inheritDoc} */
422         public boolean isAuthenticated() {
423             return transportAuthenticated;
424         }
425 
426         /**
427          * {@inheritDoc}
428          * 
429          * This method is not supported for this transport implementation.
430          */
431         public boolean isConfidential() {
432             return transportConfidential;
433         }
434 
435         /** {@inheritDoc} */
436         public void setAuthenticated(boolean isAuthenticated) {
437             transportAuthenticated = isAuthenticated;
438         }
439 
440         /** {@inheritDoc} */
441         public void setConfidential(boolean isConfidential) {
442             transportConfidential = isConfidential;
443         }
444 
445         /** {@inheritDoc} */
446         public String getHTTPMethod() {
447             return postMethod.getName();
448         }
449 
450         /** {@inheritDoc} */
451         public String getHeaderValue(String name) {
452             return postMethod.getResponseHeader(name).getValue();
453         }
454 
455         /**
456          * {@inheritDoc}
457          * 
458          * This method is not supported for this transport implementation.
459          */
460         public String getParameterValue(String name) {
461             return null;
462         }
463         
464         /** {@inheritDoc} */
465         public List<String> getParameterValues(String name) {
466             return null;
467         }
468 
469         /** {@inheritDoc} */
470         public int getStatusCode() {
471             return postMethod.getStatusCode();
472         }
473 
474         /**
475          * {@inheritDoc}
476          */
477         public HTTP_VERSION getVersion() {
478             HttpVersion httpVersion = postMethod.getEffectiveVersion();
479             if (httpVersion == HttpVersion.HTTP_1_0) {
480                 return HTTP_VERSION.HTTP1_0;
481             } else if (httpVersion == HttpVersion.HTTP_1_1) {
482                 return HTTP_VERSION.HTTP1_1;
483             }
484             return null;
485         }
486         
487         /** {@inheritDoc} */
488         public boolean isIntegrityProtected() {
489             return transportIntegrityProtected;
490         }
491         
492         /** {@inheritDoc} */
493         public void setIntegrityProtected(boolean isIntegrityProtected) {
494             transportIntegrityProtected = isIntegrityProtected;
495         }
496     }
497 }