View Javadoc
1   /*
2    * Copyright (c) 2002-2021, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.util.httpaccess;
35  
36  import java.io.BufferedOutputStream;
37  import java.io.ByteArrayOutputStream;
38  import java.io.File;
39  import java.io.FileOutputStream;
40  import java.io.IOException;
41  import java.io.OutputStream;
42  import java.net.URI;
43  import java.net.URISyntaxException;
44  import java.nio.charset.Charset;
45  import java.util.ArrayList;
46  import java.util.Arrays;
47  import java.util.List;
48  import java.util.Map;
49  import java.util.Map.Entry;
50  import java.util.regex.Matcher;
51  import java.util.regex.Pattern;
52  
53  import org.apache.commons.fileupload.FileItem;
54  import org.apache.commons.lang3.StringUtils;
55  import org.apache.hc.client5.http.classic.methods.HttpDelete;
56  import org.apache.hc.client5.http.classic.methods.HttpGet;
57  import org.apache.hc.client5.http.classic.methods.HttpPost;
58  import org.apache.hc.client5.http.classic.methods.HttpPut;
59  import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
60  import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
61  import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
62  import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
63  import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
64  import org.apache.hc.core5.http.ContentType;
65  import org.apache.hc.core5.http.Header;
66  import org.apache.hc.core5.http.HttpEntity;
67  import org.apache.hc.core5.http.NameValuePair;
68  import org.apache.hc.core5.http.ParseException;
69  import org.apache.hc.core5.http.ProtocolException;
70  import org.apache.hc.core5.http.io.entity.EntityUtils;
71  import org.apache.hc.core5.http.io.entity.StringEntity;
72  import org.apache.hc.core5.http.message.BasicNameValuePair;
73  import org.apache.hc.core5.net.URIBuilder;
74  
75  import fr.paris.lutece.portal.service.util.AppLogService;
76  import fr.paris.lutece.util.signrequest.AuthenticateRequestInformations;
77  import fr.paris.lutece.util.signrequest.RequestAuthenticator;
78  
79  
80  /**
81   * Http net Object Accessor.
82   */
83  public class HttpAccess
84  {
85      // proxy authentication settings
86  
87      /** The Constant PATTERN_FILENAME. */
88      private static final String PATTERN_FILENAME = ".*filename=\"([^\"]+)";
89  
90      /** The Constant DEFAULT_MIME_TYPE. */
91      private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
92  
93      /** The Constant DEFAULT_JSON_MIME_TYPE. */
94      private static final String DEFAULT_JSON_MIME_TYPE = "application/json";
95  
96      /** The Constant SEPARATOR_CONTENT_TYPE. */
97      private static final String SEPARATOR_CONTENT_TYPE = ";";
98  
99      /** The Constant PROPERTY_HEADER_CONTENT_DISPOSITION. */
100     private static final String PROPERTY_HEADER_CONTENT_DISPOSITION = "Content-Disposition";
101 
102     /** The Constant PROPERTY_HEADER_CONTENT_LENGTH. */
103     private static final String PROPERTY_HEADER_CONTENT_LENGTH = "Content-Length";
104 
105     /** The Constant PROPERTY_HEADER_CONTENT_TYPE. */
106     private static final String PROPERTY_HEADER_CONTENT_TYPE = "Content-Type";
107 
108   
109     /** The Constant PROPERTY_HTTP_REQUEST_POST. */
110     private static final String PROPERTY_HTTP_REQUEST_POST = "POST";
111 
112     /** The Constant PROPERTY_HTTP_REQUEST_PUT. */
113     private static final String PROPERTY_HTTP_REQUEST_PUT = "PUT";
114     
115     /** The Constant PROPERTY_HTTP_REQUEST_DELETE. */
116     private static final String PROPERTY_HTTP_REQUEST_DELETE = "DELETE";
117 
118 
119     /** The Constant DEFAULT_CHARSET. */
120     private static final String DEFAULT_CHARSET = "UTF-8";
121 
122     /** The response validator. */
123     private ResponseStatusValidator _responseValidator;
124     
125     /** The access service. */
126     private HttpAccessService _accessService;
127 
128     /**
129      * Instantiates a new http access.
130      */
131     public HttpAccess( )
132     {
133         _accessService = HttpAccessService.getInstance( );
134         _responseValidator = HttpAccessService.getInstance( );
135     }
136 
137     /**
138      * Instantiates a new http access.
139      *
140      * @param validator the validator
141      */
142     public HttpAccess( ResponseStatusValidator validator )
143     {
144         _accessService = HttpAccessService.getInstance( );
145         _responseValidator = validator;
146     }
147     
148     
149     /**
150      * Instantiates a new http access.
151      *
152      * @param accessService the access service
153      * @param validator the validator
154      */
155     public HttpAccess(  HttpAccessService accessService,ResponseStatusValidator validator)
156     {
157         _accessService = accessService;
158         _responseValidator =validator;
159     }
160     
161     /**
162      * Instantiates a new http access.
163      *
164      * @param accessService the access service
165      */
166     public HttpAccess(  HttpAccessService accessService)
167     {
168         _accessService = accessService;
169         _responseValidator =HttpAccessService.getInstance( );
170     }
171     
172     
173 
174 
175     /**
176      * Send a GET HTTP request to an Url and return the response content.
177      * 
178      * @param strUrl
179      *            The Url to access
180      * @return The response content of the Get request to the given Url
181      * @throws HttpAccessException
182      *             if there is a problem to access to the given Url
183      */
184     public String doGet( String strUrl ) throws HttpAccessException
185     {
186         return doGet( strUrl, null, null );
187     }
188 
189     /**
190      * Send a GET HTTP request to an Url and return the response content.
191      * 
192      * @param strUrl
193      *            The Url to access
194      * @param authenticator
195      *            The {@link RequestAuthenticator}
196      * @param listElements
197      *            to include in the signature
198      * @return The response content of the Get request to the given Url
199      * @throws HttpAccessException
200      *             if there is a problem to access to the given Url
201      */
202     public String doGet( String strUrl, RequestAuthenticator authenticator, List<String> listElements ) throws HttpAccessException
203     {
204         return doGet( strUrl, authenticator, listElements, null );
205     }
206 
207     /**
208      * Send a GET HTTP request to an Url and return the response content.
209      *
210      * @param strUrl
211      *            The Url to access
212      * @param authenticator
213      *            The {@link RequestAuthenticator}
214      * @param listElements
215      *            to include in the signature
216      * @param headers
217      *            the headers
218      * @return The response content of the Get request to the given Url
219      * @throws HttpAccessException
220      *             if there is a problem to access to the given Url
221      */
222     public String doGet( String strUrl, RequestAuthenticator authenticator, List<String> listElements, Map<String, String> headers ) throws HttpAccessException
223     {
224         return doGet( strUrl, authenticator, listElements, headers, null );
225     }
226 
227     /**
228      * Send a GET HTTP request to an Url and return the response content.
229      * 
230      * @param strUrl
231      *            The Url to access
232      * @param authenticator
233      *            The {@link RequestAuthenticator}
234      * @param listElements
235      *            to include in the signature
236      * @param headersRequest
237      *            Map of headers request parameters
238      * @param headersResponse
239      *            Map to contain response headers
240      * @return The response content of the Get request to the given Url
241      * @throws HttpAccessException
242      *             if there is a problem to access to the given Url
243      */
244     public String doGet( String strUrl, RequestAuthenticator authenticator, List<String> listElements, Map<String, String> headersRequest,
245             Map<String, String> headersResponse ) throws HttpAccessException
246     {
247 		String strResponseBody = StringUtils.EMPTY;
248 		
249 		 HttpUriRequestBase httpGet = new HttpGet(strUrl);
250 		 addSecurityInformations(httpGet, strUrl, authenticator, listElements);
251 
252 		 
253 		if (headersRequest != null) {
254 			headersRequest.forEach((k, v) -> httpGet.addHeader(k, v));
255 		}
256 		
257 		
258 		strResponseBody=getResponseBody(httpGet, strUrl, headersResponse);
259 		
260 
261 		return strResponseBody;
262     }
263 
264     /**
265      * Send a POST HTTP request to an url and return the response content.
266      *
267      * @param strUrl
268      *            the url to access
269      * @param params
270      *            the list of parameters to post
271      * @return The response content of the Post request to the given Url
272      * @throws HttpAccessException
273      *             if there is a problem to access to the given Url
274      */
275     public String doPost( String strUrl, Map<String, String> params ) throws HttpAccessException
276     {
277         return doPost( strUrl, params, null, null );
278     }
279 
280     /**
281      * Send a POST HTTP request to an url and return the response content.
282      *
283      * @param strUrl
284      *            the url to access
285      * @param params
286      *            the list of parameters to post
287      * @param authenticator
288      *            The {@link RequestAuthenticator}
289      * @param listElements
290      *            to include in the signature
291      * @return The response content of the Post request to the given Url
292      * @throws HttpAccessException
293      *             if there is a problem to access to the given Url
294      */
295     public String doPost( String strUrl, Map<String, String> params, RequestAuthenticator authenticator, List<String> listElements ) throws HttpAccessException
296     {
297         return doPost( strUrl, params, authenticator, listElements, null );
298     }
299 
300     /**
301      * Send a POST HTTP request to an url and return the response content.
302      *
303      * @param strUrl
304      *            the url to access
305      * @param params
306      *            the list of parameters to post
307      * @param authenticator
308      *            The {@link RequestAuthenticator}
309      * @param listElements
310      *            to include in the signature
311      * @param headersRequest
312      *            Map of headers request parameters
313      * @return The response content of the Post request to the given Url
314      * @throws HttpAccessException
315      *             if there is a problem to access to the given Url
316      */
317     public String doPost( String strUrl, Map<String, String> params, RequestAuthenticator authenticator, List<String> listElements,
318             Map<String, String> headersRequest ) throws HttpAccessException
319     {
320         return doPost( strUrl, params, authenticator, listElements, headersRequest, null );
321     }
322 
323     /**
324      * Send a POST HTTP request to an url and return the response content.
325      *
326      * @param strUrl
327      *            the url to access
328      * @param params
329      *            the list of parameters to post
330      * @param authenticator
331      *            The {@link RequestAuthenticator}
332      * @param listElements
333      *            to include in the signature
334      * @param headersRequest
335      *            Map of headers request parameters
336      * @param headersResponse
337      *            Map to contain response headers
338      * @return The response content of the Post request to the given Url
339      * @throws HttpAccessException
340      *             if there is a problem to access to the given Url
341      */
342     public String doPost( String strUrl, Map<String, String> params, RequestAuthenticator authenticator, List<String> listElements,
343             Map<String, String> headersRequest, Map<String, String> headersResponse ) throws HttpAccessException
344     {
345           
346         HttpUriRequestBase httpPost = new HttpPost(strUrl);
347      
348         return doSendFormEntity(httpPost, strUrl, params, authenticator, listElements, headersRequest, headersResponse);
349         
350         
351     }
352 
353     /**
354      * Do request enclosing method.
355      *
356      * @param strUrl
357      *            the str url
358      * @param strMethod
359      *            the str method
360      * @param strContent
361      *            the str content
362      * @param contentType
363      *            the content type
364      * @param charset
365      *            the charset
366      * @param authenticator
367      *            the authenticator
368      * @param listElements
369      *            the list elements
370      * @param headersRequest
371      *            the headers request
372      * @param headersResponse
373      *            the headers response
374      * @return the string
375      * @throws HttpAccessException
376      *             the http access exception
377      */
378     public String doRequestEnclosingMethod( String strUrl, String strMethod, String strContent, String contentType, String charset,
379             RequestAuthenticator authenticator, List<String> listElements, Map<String, String> headersRequest, Map<String, String> headersResponse )
380             throws HttpAccessException
381     {
382         String strResponseBody = StringUtils.EMPTY;
383         HttpUriRequestBase httpRequest;
384 
385         switch( strMethod )
386         {
387             case PROPERTY_HTTP_REQUEST_PUT:
388             
389             	httpRequest=new HttpPut(strUrl);
390                 break;
391 
392             case PROPERTY_HTTP_REQUEST_POST:
393             	httpRequest = new HttpPost(strUrl);
394                 break;
395 
396             case PROPERTY_HTTP_REQUEST_DELETE:
397             	httpRequest = new HttpDelete(strUrl);
398             	break;
399             default:
400             	httpRequest =  new HttpPost(strUrl);
401                 break;
402         }
403        
404 
405         
406         if (headersRequest != null) {
407 			headersRequest.forEach((k, v) -> httpRequest.addHeader(k, v));
408 		}
409         addSecurityInformations(httpRequest, strUrl, authenticator, listElements);
410         httpRequest.setEntity(new StringEntity(strContent, ContentType.APPLICATION_JSON, charset, false));
411         
412 		   strResponseBody=getResponseBody(httpRequest, strUrl, headersResponse);
413 			
414 
415         return strResponseBody;
416     }
417 
418     /**
419      * Do post json.
420      *
421      * @param strUrl
422      *            the str url
423      * @param strJSON
424      *            the str json
425      * @param authenticator
426      *            the authenticator
427      * @param listElements
428      *            the list elements
429      * @param headersRequest
430      *            the headers request
431      * @param headersResponse
432      *            the headers response
433      * @return the string
434      * @throws HttpAccessException
435      *             the http access exception
436      */
437     public String doPostJSON( String strUrl, String strJSON, RequestAuthenticator authenticator, List<String> listElements, Map<String, String> headersRequest,
438             Map<String, String> headersResponse ) throws HttpAccessException
439     {
440         return doRequestEnclosingMethod( strUrl, PROPERTY_HTTP_REQUEST_POST, strJSON, DEFAULT_JSON_MIME_TYPE, !StringUtils.isEmpty( _accessService.getHttpClientConfiguration().getContentCharset())? _accessService.getHttpClientConfiguration().getContentCharset():DEFAULT_CHARSET, authenticator, listElements,
441                 headersRequest, headersResponse );
442     }
443 
444     /**
445      * Do post json.
446      *
447      * @param strUrl
448      *            the str url
449      * @param strJSON
450      *            the str json
451      * @param headersRequest
452      *            the headers request
453      * @param headersResponse
454      *            the headers response
455      * @return the string
456      * @throws HttpAccessException
457      *             the http access exception
458      */
459     public String doPostJSON( String strUrl, String strJSON, Map<String, String> headersRequest, Map<String, String> headersResponse )
460             throws HttpAccessException
461     {
462         return doRequestEnclosingMethod( strUrl, PROPERTY_HTTP_REQUEST_POST, strJSON, DEFAULT_JSON_MIME_TYPE, !StringUtils.isEmpty( _accessService.getHttpClientConfiguration().getContentCharset())? _accessService.getHttpClientConfiguration().getContentCharset():DEFAULT_CHARSET, null, null, headersRequest,
463                 headersResponse );
464     }
465 
466     /**
467      * Do put json.
468      *
469      * @param strUrl
470      *            the str url
471      * @param strJSON
472      *            the str json
473      * @param authenticator
474      *            the authenticator
475      * @param listElements
476      *            the list elements
477      * @param headersRequest
478      *            the headers request
479      * @param headersResponse
480      *            the headers response
481      * @return the string
482      * @throws HttpAccessException
483      *             the http access exception
484      */
485     public String doPutJSON( String strUrl, String strJSON, RequestAuthenticator authenticator, List<String> listElements, Map<String, String> headersRequest,
486             Map<String, String> headersResponse ) throws HttpAccessException
487     {
488         return doRequestEnclosingMethod( strUrl, PROPERTY_HTTP_REQUEST_PUT, strJSON, DEFAULT_JSON_MIME_TYPE, !StringUtils.isEmpty( _accessService.getHttpClientConfiguration().getContentCharset())? _accessService.getHttpClientConfiguration().getContentCharset():DEFAULT_CHARSET, authenticator, listElements,
489                 headersRequest, headersResponse );
490     }
491 
492     /**
493      * Do put json.
494      *
495      * @param strUrl
496      *            the str url
497      * @param strJSON
498      *            the str json
499      * @param headersRequest
500      *            the headers request
501      * @param headersResponse
502      *            the headers response
503      * @return the string
504      * @throws HttpAccessException
505      *             the http access exception
506      */
507     public String doPutJSON( String strUrl, String strJSON, Map<String, String> headersRequest, Map<String, String> headersResponse ) throws HttpAccessException
508     {
509         return doRequestEnclosingMethod( strUrl, PROPERTY_HTTP_REQUEST_PUT, strJSON, DEFAULT_JSON_MIME_TYPE, !StringUtils.isEmpty( _accessService.getHttpClientConfiguration().getContentCharset())? _accessService.getHttpClientConfiguration().getContentCharset():DEFAULT_CHARSET, null, null, headersRequest,
510                 headersResponse );
511     }
512 
513     /**
514      * Send a POST HTTP request to an url and return the response content.
515      *
516      * @param strUrl
517      *            the url to access
518      * @param params
519      *            the list of parameters to post
520      * @return The response content of the Post request to the given Url
521      * @throws HttpAccessException
522      *             if there is a problem to access to the given Url
523      */
524     public String doPostMultiValues( String strUrl, Map<String, List<String>> params ) throws HttpAccessException
525     {
526         return doPostMultiValues( strUrl, params, null, null );
527     }
528 
529     /**
530      * Send a POST HTTP request to an url and return the response content.
531      *
532      * @param strUrl
533      *            the url to access
534      * @param params
535      *            the list of parameters to post
536      * @param authenticator
537      *            The {@link RequestAuthenticator}
538      * @param listElements
539      *            to include in the signature
540      * @return The response content of the Post request to the given Url
541      * @throws HttpAccessException
542      *             if there is a problem to access to the given Url
543      */
544     public String doPostMultiValues( String strUrl, Map<String, List<String>> params, RequestAuthenticator authenticator, List<String> listElements )
545             throws HttpAccessException
546     {
547         return doPostMultiValues( strUrl, params, authenticator, listElements, null );
548     }
549 
550     /**
551      * Send a POST HTTP request to an url and return the response content.
552      *
553      * @param strUrl
554      *            the url to access
555      * @param params
556      *            the list of parameters to post
557      * @param authenticator
558      *            The {@link RequestAuthenticator}
559      * @param listElements
560      *            to include in the signature
561      * @param headersRequest
562      *            Map of headers request parameters
563      * @return The response content of the Post request to the given Url
564      * @throws HttpAccessException
565      *             if there is a problem to access to the given Url
566      */
567     public String doPostMultiValues( String strUrl, Map<String, List<String>> params, RequestAuthenticator authenticator, List<String> listElements,
568             Map<String, String> headersRequest ) throws HttpAccessException
569     {  
570    
571     	return doPostMultiValues(strUrl, params, authenticator, listElements, headersRequest, null);
572     }
573 
574     /**
575      * Send a POST HTTP request to an url and return the response content.
576      *
577      * @param strUrl
578      *            the url to access
579      * @param params
580      *            the list of parameters to post
581      * @param authenticator
582      *            The {@link RequestAuthenticator}
583      * @param listElements
584      *            to include in the signature
585      * @param headersRequest
586      *            Map of headers request parameters
587      * @param headersResponse
588      *            Map to contain response headers
589      * @return The response content of the Post request to the given Url
590      * @throws HttpAccessException
591      *             if there is a problem to access to the given Url
592      */
593     public String doPostMultiValues( String strUrl, Map<String, List<String>> params, RequestAuthenticator authenticator, List<String> listElements,
594             Map<String, String> headersRequest, Map<String, String> headersResponse ) throws HttpAccessException
595     {
596     	
597     	
598     	String strResponseBody = StringUtils.EMPTY;
599     	HttpUriRequestBase httpPost = new HttpPost(strUrl);
600         
601         
602     	List<NameValuePair> nvps = new ArrayList<>();
603         
604 
605     	if (headersRequest != null) {
606     		headersRequest.forEach((k, v) -> httpPost.addHeader(k, v));
607     	}
608 
609     	
610     	 if ( params != null ){
611     		 	params.forEach((k, v) -> v.stream().forEach(y-> nvps.add(new BasicNameValuePair(k, y))));
612           }
613 
614     	
615     	addSecurityInformations(httpPost, strUrl, authenticator, listElements);
616     	httpPost.setEntity(new UrlEncodedFormEntity(nvps, !StringUtils.isEmpty(   _accessService.getHttpClientConfiguration().getContentCharset())? Charset.forName(_accessService.getHttpClientConfiguration().getContentCharset()):Charset.forName(DEFAULT_CHARSET)));
617 
618 		strResponseBody=getResponseBody(httpPost, strUrl, headersResponse);
619 		
620         return strResponseBody;
621     }
622 
623     /**
624      * Send a POST HTTP request to an url and return the response content.
625      *
626      * @param strUrl
627      *            the url to access
628      * @param params
629      *            the list of parameters to post
630      * @param fileItems
631      *            The list of file items
632      * @return The response content of the Post request to the given Url
633      * @throws HttpAccessException
634      *             if there is a problem to access to the given Url
635      */
636     public String doPostMultiPart( String strUrl, Map<String, List<String>> params, Map<String, FileItem> fileItems ) throws HttpAccessException
637     {
638         return doPostMultiPart( strUrl, params, fileItems, null, null );
639     }
640 
641     /**
642      * Send a POST HTTP request to an url and return the response content.
643      *
644      * @param strUrl
645      *            the url to access
646      * @param params
647      *            the list of parameters to post
648      * @param fileItems
649      *            The list of file items
650      * @param authenticator
651      *            The {@link RequestAuthenticator}
652      * @param listElements
653      *            to include in the signature
654      * @return The response content of the Post request to the given Url
655      * @throws HttpAccessException
656      *             if there is a problem to access to the given Url
657      */
658     public String doPostMultiPart( String strUrl, Map<String, List<String>> params, Map<String, FileItem> fileItems, RequestAuthenticator authenticator,
659             List<String> listElements ) throws HttpAccessException
660     {
661         return doPostMultiPart( strUrl, params, fileItems, authenticator, listElements, null );
662     }
663 
664     /**
665      * Send a POST HTTP request to an url and return the response content.
666      *
667      * @param strUrl
668      *            the url to access
669      * @param params
670      *            the list of parameters to post
671      * @param fileItems
672      *            The list of file items
673      * @param authenticator
674      *            The {@link RequestAuthenticator}
675      * @param listElements
676      *            to include in the signature
677      * @param headersRequest
678      *            Map of headers request parameters
679      * @return The response content of the Post request to the given Url
680      * @throws HttpAccessException
681      *             if there is a problem to access to the given Url
682      */
683     public String doPostMultiPart( String strUrl, Map<String, List<String>> params, Map<String, FileItem> fileItems, RequestAuthenticator authenticator,
684             List<String> listElements, Map<String, String> headersRequest ) throws HttpAccessException
685     {
686         return doPostMultiPart( strUrl, params, fileItems, authenticator, listElements, headersRequest, null );
687     }
688 
689     /**
690      * Send a POST HTTP request to an url and return the response content.
691      *
692      * @param strUrl
693      *            the url to access
694      * @param params
695      *            the list of parameters to post
696      * @param fileItems
697      *            The list of file items
698      * @param authenticator
699      *            The {@link RequestAuthenticator}
700      * @param listElements
701      *            to include in the signature
702      * @param headersRequest
703      *            Map of headers request parameters
704      * @param headersResponse
705      *            Map to contain response headers
706      * @return The response content of the Post request to the given Url
707      * @throws HttpAccessException
708      *             if there is a problem to access to the given Url
709      */
710     public String doPostMultiPart( String strUrl, Map<String, List<String>> params, Map<String, FileItem> fileItems, RequestAuthenticator authenticator,
711             List<String> listElements, Map<String, String> headersRequest, Map<String, String> headersResponse ) throws HttpAccessException
712     {
713         String strResponseBody = StringUtils.EMPTY;
714         HttpUriRequestBase httpPost = new HttpPost(strUrl);
715 
716         if (headersRequest != null) {
717 			headersRequest.forEach((k, v) -> httpPost.addHeader(k, v));
718 		}
719 
720         ArrayList<File> listFiles = new ArrayList<File>( );
721         
722         MultipartEntityBuilder builder = MultipartEntityBuilder.create();
723 
724        
725             if ( ( fileItems != null ) && !fileItems.isEmpty( ) )
726             {
727                 // Store the Files
728                 for ( Entry<String, FileItem> paramFileItem : fileItems.entrySet( ) )
729                 {
730                     FileItem fileItem = paramFileItem.getValue( );
731 
732                     if ( fileItem != null )
733                     {
734                         try
735                         {
736                             String strContentType = null;
737                             String strCharset = null;
738                             if ( StringUtils.isNotBlank( fileItem.getContentType( ) ) )
739                             {
740                                 String [ ] splitContentType = StringUtils.split( fileItem.getContentType( ), SEPARATOR_CONTENT_TYPE );
741                                 if ( splitContentType.length > 0 && StringUtils.isNotBlank( splitContentType [0] ) )
742                                 {
743                                     strContentType = splitContentType [0];
744                                 }
745                                 if ( splitContentType.length > 1 && StringUtils.isNotBlank( splitContentType [1] ) &&   splitContentType [1] .toUpperCase().contains("CHARSET") )
746                                 {
747                                 	
748                                 	String [ ] splitCharset =splitContentType [1].split("=");
749                                 	if(splitCharset.length>1)
750                                 	{
751                                 		strCharset = splitCharset [1];
752                                 	}
753                                     
754            
755                                     
756                                 }
757                             }
758 
759                             if ( fileItem.isInMemory( ) )
760                             {
761                      
762                                ContentType contentType= !StringUtils.isEmpty(strContentType)?ContentType.create(strContentType,!StringUtils.isEmpty(strCharset)?Charset.forName(strCharset):Charset.forName(DEFAULT_CHARSET)):ContentType.DEFAULT_BINARY;
763                                  
764                             	builder.addBinaryBody(paramFileItem.getKey( ), fileItem.get( ),contentType,fileItem.getName());
765                             	
766                             	
767                             }
768                             else
769                             {
770                                 File file = File.createTempFile( "httpaccess-multipart-", null );
771                                 // Store files for deletion after the request completed
772                                 listFiles.add( file );
773                                 fileItem.write( file );
774                                 ContentType contentType= !StringUtils.isEmpty(strContentType)?ContentType.create(strContentType,!StringUtils.isEmpty(strCharset)?Charset.forName(strCharset):Charset.forName(DEFAULT_CHARSET)):ContentType.DEFAULT_BINARY;
775                                 
776                                 builder.addBinaryBody(paramFileItem.getKey( ), file,contentType ,fileItem.getName());
777                          
778                              
779                             }
780                            
781 
782                           
783                         }
784                         catch( Exception e )
785                         {
786                             String strError = "HttpAccess - Error writing file '" + fileItem.getName( ) + "' : ";
787                             AppLogService.error( strError + e.getMessage( ), e );
788                             throw new HttpAccessException( strError + e.getMessage( ), e );
789                         }
790                     }
791                 }
792             }
793             if ( ( params != null ) && !params.isEmpty( ) )
794             {
795             	
796             	 ContentType contentType= ContentType.create("text/plain",!StringUtils.isEmpty(   _accessService.getHttpClientConfiguration().getContentCharset())? Charset.forName(_accessService.getHttpClientConfiguration().getContentCharset()):Charset.forName(DEFAULT_CHARSET));
797                 // Additionnal parameters
798                 params.forEach((k, v) -> { v.stream().forEach(  y -> { builder.addTextBody(k,y,contentType);});});
799                
800             }
801             
802             addSecurityInformations(httpPost, strUrl, authenticator, listElements);
803             builder.setCharset(  !StringUtils.isEmpty(   _accessService.getHttpClientConfiguration().getContentCharset())? Charset.forName(_accessService.getHttpClientConfiguration().getContentCharset()):Charset.forName(DEFAULT_CHARSET));
804         	HttpEntity entityForm = builder.build();
805         	httpPost.setEntity(entityForm);
806         	
807         	strResponseBody=getResponseBody(httpPost, strUrl, headersResponse);
808 
809        
810         
811         return strResponseBody;
812     }
813 
814     /**
815      * Send a PUT HTTP request to an url and return the response content.
816      *
817      * @param strUrl
818      *            the url to access
819      * @param authenticator
820      *            The {@link RequestAuthenticator}
821      * @param listElements
822      *            to include in the signature
823      * @param params
824      *            the params
825      * @param headersRequest
826      *            Map of headers request parameters
827      * @param headersResponse
828      *            Map to contain response headers
829      * @return The response content of the Post request to the given Url
830      * @throws HttpAccessException
831      *             if there is a problem to access to the given Url
832      */
833     public String doPut( String strUrl, RequestAuthenticator authenticator, List<String> listElements, Map<String, String> params,
834             Map<String, String> headersRequest, Map<String, String> headersResponse ) throws HttpAccessException
835     {
836        
837         HttpPut httpPut = new HttpPut(strUrl);
838         return doSendFormEntity(httpPut, strUrl, params, authenticator, listElements, headersRequest, headersResponse);
839     }
840     
841     
842     
843     
844     /**
845      * Send a POST or PUT HTTP request to an url and return the response content.
846      *
847      * @param httprequestBase the httprequest base
848      * @param strUrl            the url to access
849      * @param params            the list of parameters to post
850      * @param authenticator            The {@link RequestAuthenticator}
851      * @param listElements            to include in the signature
852      * @param headersRequest            Map of headers request parameters
853      * @param headersResponse            Map to contain response headers
854      * @return The response content of the Post request to the given Url
855      * @throws HttpAccessException             if there is a problem to access to the given Url
856      */
857     private String doSendFormEntity( HttpUriRequestBase httprequestBase,String strUrl, Map<String, String> params, RequestAuthenticator authenticator, List<String> listElements,
858             Map<String, String> headersRequest, Map<String, String> headersResponse ) throws HttpAccessException
859     {
860         String strResponseBody = StringUtils.EMPTY;
861         
862     	List<NameValuePair> nvps = new ArrayList<>();
863 
864 		if (headersRequest != null) {
865 			headersRequest.forEach((k, v) -> httprequestBase.addHeader(k, v));
866 		}
867 		if (params != null) {
868 			params.forEach((k, v) -> nvps.add(new BasicNameValuePair(k, v)));
869 		}
870 		
871 		addSecurityInformations(httprequestBase, strUrl, authenticator, listElements);
872 		httprequestBase.setEntity(new UrlEncodedFormEntity(nvps, !StringUtils.isEmpty(   _accessService.getHttpClientConfiguration().getContentCharset())? Charset.forName(_accessService.getHttpClientConfiguration().getContentCharset()):Charset.forName(DEFAULT_CHARSET)));
873 
874 		strResponseBody=getResponseBody(httprequestBase, strUrl, headersResponse);
875 		
876 
877         return strResponseBody;
878     }
879 
880     
881     
882     
883 
884     /**
885      * Send a DELETE HTTP request to an url and return the response content.
886      *
887      * @param strUrl
888      *            the url to access
889      * @param authenticator
890      *            The {@link RequestAuthenticator}
891      * @param listElements
892      *            to include in the signature
893      * @param headersRequest
894      *            Map of headers request parameters
895      * @param headersResponse
896      *            Map to contain response headers
897      * @return The response content of the Post request to the given Url
898      * @throws HttpAccessException
899      *             if there is a problem to access to the given Url
900      */
901     public String doDelete( String strUrl, RequestAuthenticator authenticator, List<String> listElements, Map<String, String> headersRequest,
902             Map<String, String> headersResponse ) throws HttpAccessException
903     {
904     	String strResponseBody = StringUtils.EMPTY;
905 		
906 		 HttpUriRequestBase httpDelete = new HttpDelete(strUrl);
907 		 addSecurityInformations(httpDelete, strUrl, authenticator, listElements);
908 
909 		 
910 		if (headersRequest != null) {
911 			headersRequest.forEach((k, v) -> httpDelete.addHeader(k, v));
912 		}
913 		
914 		
915 		strResponseBody=getResponseBody(httpDelete, strUrl, headersResponse);
916 		
917 
918 		return strResponseBody;
919     }
920 
921     /**
922      * Send a DELETE HTTP request to an url and return the response content.
923      *
924      * @param strUrl
925      *            the url to access
926      * @param strJson
927      *            the json to send in body
928      * @param authenticator
929      *            The {@link RequestAuthenticator}
930      * @param listElements
931      *            to include in the signature
932      * @param headersRequest
933      *            Map of headers request parameters
934      * @param headersResponse
935      *            Map to contain response headers
936      * @return The response content of the Post request to the given Url
937      * @throws HttpAccessException
938      *             if there is a problem to access to the given Url
939      */
940     public String doDeleteJSON( String strUrl, String strJSON, RequestAuthenticator authenticator, List<String> listElements, Map<String, String> headersRequest,
941             Map<String, String> headersResponse ) throws HttpAccessException
942     {
943     	return doRequestEnclosingMethod( strUrl, PROPERTY_HTTP_REQUEST_DELETE, strJSON, DEFAULT_JSON_MIME_TYPE, !StringUtils.isEmpty( _accessService.getHttpClientConfiguration().getContentCharset())? _accessService.getHttpClientConfiguration().getContentCharset():DEFAULT_CHARSET, authenticator, listElements,
944                 headersRequest, headersResponse );
945     }
946     
947     /**
948      * Send a GET HTTP request to an Url and return the response content.
949      * 
950      * @param strUrl
951      *            The Url to access
952      * @param strFilePath
953      *            the file path
954      * @throws HttpAccessException
955      *             if there is a problem to access to the given Url
956      */
957     public void downloadFile( String strUrl, String strFilePath ) throws HttpAccessException
958     {
959         BufferedOutputStream bos = null;
960 
961         try
962         {
963             FileOutputStream fos = new FileOutputStream( strFilePath );
964             bos = new BufferedOutputStream( fos );
965             downloadFile( strUrl, bos );
966 
967         }
968         catch( IOException e )
969         {
970             throwHttpAccessException( strUrl, e );
971         }
972         finally
973         {
974             try
975             {
976                 if ( bos != null )
977                 {
978                     bos.close( );
979                 }
980             }
981             catch( IOException e )
982             {
983                 AppLogService.error( "HttpAccess - Error closing stream : " + e.getMessage( ), e );
984                 throw new HttpAccessException( e.getMessage( ), e );
985             }
986 
987         }
988     }
989 
990     /**
991      * Send a GET HTTP request to an Url and return the response content in the ouput stream.
992      * 
993      * @param strUrl
994      *            The Url to access
995      * @param outputStream
996      *            write in the outpustrean the contents of the file
997      * @throws HttpAccessException
998      *             if there is a problem to access to the given Url
999      */
1000     public void downloadFile( String strUrl, OutputStream outputStream ) throws HttpAccessException
1001     {
1002     	HttpGet httpGet = new HttpGet(strUrl);
1003     	
1004     	try  {
1005     		
1006     		CloseableHttpClient httpClient = _accessService.getHttpClient(httpGet.getUri().getHost());
1007 			try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
1008 
1009 				int nResponse = response.getCode();
1010 				validateResponseStatus(nResponse, httpGet.getMethod(), response, strUrl);
1011 				
1012 				HttpEntity entity = response.getEntity();
1013 				
1014 				
1015 				if(entity!=null)
1016 				{
1017 					entity.writeTo(outputStream);				   
1018 			         	
1019 				}
1020 				
1021 				 
1022 		        }
1023     		}
1024     		catch (IOException | ParseException | URISyntaxException e) {
1025 			throwHttpAccessException(strUrl, e);
1026     		}
1027 		        finally
1028 		        {
1029 		            try
1030 		            {
1031 		                if ( outputStream != null )
1032 		                {
1033 		                	outputStream.close( );
1034 		                }
1035 
1036 		            }
1037 		            catch( IOException e )
1038 		            {
1039 		                AppLogService.error( "HttpAccess - Error closing stream : " + e.getMessage( ), e );
1040 		                throw new HttpAccessException( e.getMessage( ), e );
1041 		            }
1042 
1043 		          
1044 		        }
1045 				
1046 			
1047 			}
1048 
1049     /**
1050      * Send a GET HTTP request to an Url and return the response content.
1051      * 
1052      * @param strUrl
1053      *            The Url to access
1054      * @return the file name
1055      * @throws HttpAccessException
1056      *             if there is a problem to access to the given Url
1057      */
1058     public String getFileName( String strUrl ) throws HttpAccessException
1059     {
1060           String strFileName = null;
1061         
1062           HttpGet httpGet = new HttpGet(strUrl);
1063     	
1064     	
1065     	try  {
1066     		CloseableHttpClient httpClient = _accessService.getHttpClient(httpGet.getUri().getHost());
1067 			try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
1068 				
1069 				int nResponse = response.getCode();
1070 				validateResponseStatus(nResponse, httpGet.getMethod(), response, strUrl);
1071 				
1072 				
1073 				Header  headerContentDisposition= response.getHeader(PROPERTY_HEADER_CONTENT_DISPOSITION);
1074 				  if ( headerContentDisposition != null )
1075 		            {
1076 		                String headerValue = headerContentDisposition.getValue( );
1077 		                Pattern p = Pattern.compile( PATTERN_FILENAME );
1078 		                Matcher matcher = p.matcher( headerValue );
1079 
1080 		                if ( matcher.matches( ) )
1081 		                {
1082 		                    strFileName = matcher.group( 1 );
1083 		                }
1084 		            }
1085 		            else
1086 		            {
1087 		                String [ ] tab = strUrl.split( "/" );
1088 		                strFileName = tab [tab.length - 1];
1089 		            }
1090 				
1091 				 
1092 	       
1093 		}
1094     	}
1095 		catch (IOException | URISyntaxException|ProtocolException  e) {
1096 		throwHttpAccessException(strUrl, e);
1097 		}
1098 				
1099 			
1100         
1101     	return strFileName;
1102         
1103         
1104       
1105     }
1106 
1107     /**
1108      * Send a GET HTTP request to an Url and return the response content.
1109      * 
1110      * @param strUrl
1111      *            The Url to access
1112      * @return a {@link FileItem}
1113      * @throws HttpAccessException
1114      *             if there is a problem to access to the given Url
1115      */
1116     public FileItem downloadFile( String strUrl ) throws HttpAccessException
1117     {
1118     	 MemoryFileItem fileItem = null;
1119          HttpGet httpGet = new HttpGet(strUrl);
1120    	
1121          try {
1122         	 
1123         	 CloseableHttpClient httpClient = _accessService.getHttpClient(httpGet.getUri().getHost());
1124 			try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
1125 				
1126 				int nResponse = response.getCode();
1127 				validateResponseStatus(nResponse, httpGet.getMethod(), response, strUrl);
1128             // Get the file name
1129             String strFileName = StringUtils.EMPTY;
1130            
1131             Header  headerContentDisposition= response.getHeader(PROPERTY_HEADER_CONTENT_DISPOSITION);
1132 			  if ( headerContentDisposition != null )
1133 	            {
1134 	                String headerValue = headerContentDisposition.getValue( );
1135 	                Pattern p = Pattern.compile( PATTERN_FILENAME );
1136 	                Matcher matcher = p.matcher( headerValue );
1137 
1138 	                if ( matcher.matches( ) )
1139 	                {
1140 	                    strFileName = matcher.group( 1 );
1141 	                }
1142 	            }
1143 	            else
1144 	            {
1145 	                String [ ] tab = strUrl.split( "/" );
1146 	                strFileName = tab [tab.length - 1];
1147 	            }
1148 			  
1149 			  
1150             // Get the file size
1151             long lSize = 0;
1152             Header  headerContentLength= response.getHeader(PROPERTY_HEADER_CONTENT_LENGTH);
1153             if ( headerContentLength != null )
1154             {
1155                 lSize = Long.parseLong( headerContentLength.getValue());
1156             }
1157 
1158             // Get the content type of the file
1159             String strContentType = StringUtils.EMPTY;
1160 
1161             Header headerContentType = response.getHeader( PROPERTY_HEADER_CONTENT_TYPE );
1162 
1163             if ( headerContentType != null )
1164             {
1165                 strContentType = headerContentType.getValue( );
1166 
1167                 if ( StringUtils.isNotBlank( strContentType ) )
1168                 {
1169                     int nIndexOfSeparator = strContentType.indexOf( SEPARATOR_CONTENT_TYPE );
1170                     strContentType = strContentType.substring( 0, nIndexOfSeparator );
1171                 }
1172             }
1173 
1174             if ( StringUtils.isBlank( strContentType ) )
1175             {
1176                 strContentType = DEFAULT_MIME_TYPE;
1177             }
1178             
1179             
1180             HttpEntity entity = response.getEntity();
1181 			
1182 			
1183 			if(entity!=null)
1184 			{
1185 				ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
1186 				entity.writeTo(outputStream);				   
1187 			    fileItem = new MemoryFileItem(outputStream.toByteArray(), strFileName, lSize, strContentType );   	
1188 			}
1189 
1190 			
1191 			}
1192          }
1193          
1194  		catch (IOException | URISyntaxException|ProtocolException  e) {
1195  		throwHttpAccessException(strUrl, e);
1196  		}
1197 
1198         return fileItem;
1199     }
1200 
1201     /**
1202      * Validate an HTTP response status code.
1203      *
1204      * @param nResponseStatus            The response status
1205      * @param strMethodName the str method name
1206      * @param response the response
1207      * @param strUrl the str url
1208      * @throws HttpAccessException the http access exception
1209      * @throws ParseException the parse exception
1210      */
1211     private void validateResponseStatus( int nResponseStatus,String strMethodName, CloseableHttpResponse response, String strUrl ) throws HttpAccessException, ParseException
1212     {
1213         if ( !_responseValidator.validate( nResponseStatus ) )
1214         {
1215             String strError = "HttpAccess - Error executing method " + strMethodName + " at URL : " + stripPassword( strUrl ) + " - return code : " + nResponseStatus;
1216             String strResponseBody;
1217             try
1218             {
1219             	
1220             	HttpEntity entity = response.getEntity();
1221                 // Get response information
1222             	
1223                 strResponseBody = " Response Body : \n" + entity!=null?EntityUtils.toString(entity): " unable to get Response Body.";
1224 
1225             }
1226             catch( IOException ex )
1227             {
1228                 strResponseBody = " unable to get Response Body.";
1229             }
1230             strError += strResponseBody;
1231 
1232             throw new InvalidResponseStatus( strError, nResponseStatus, null );
1233         }
1234 
1235     }
1236 
1237     /**
1238      * Throws a new HttpAccess exception.
1239      *
1240      * @param strUrl            The URL concerned by the original exception
1241      * @param exception            the original exception
1242      * @throws HttpAccessException             The exception throwned
1243      */
1244     private void throwHttpAccessException( String strUrl, Exception exception ) throws HttpAccessException
1245     {
1246         String strError = "HttpAccess - Error URL : " + stripPassword( strUrl ) + "' : ";
1247         AppLogService.error( strError + exception.getMessage( ), exception );
1248         throw new HttpAccessException( strError + exception.getMessage( ), exception );
1249     }
1250 
1251     /**
1252      * Hide end of url if the keyword "password" appears in parameters.
1253      *
1254      * @param strUrl the str url
1255      * @return the url stripped
1256      */
1257     private String stripPassword( String strUrl )
1258     {
1259         if ( strUrl != null && strUrl.indexOf( "?" ) > 0 && strUrl.toLowerCase( ).indexOf( "password", strUrl.indexOf( "?" ) ) > 0 )
1260         {
1261             return strUrl.substring( 0, strUrl.toLowerCase( ).indexOf( "password", strUrl.indexOf( "?" ) ) ) + "***" ;
1262         }
1263         else
1264         {
1265             return strUrl;
1266         }
1267     }
1268     
1269     
1270     
1271     /**
1272      * Add the security information in the request
1273      *
1274      * @param httpRequest the http request
1275      * @param strTargetUrl the target url of the request
1276      * @param authenticator the authenticator
1277      * @param listElements the list of elements used by sthe authenticator
1278      */
1279     private void addSecurityInformations(HttpUriRequestBase httpRequest,String strTargetUrl,RequestAuthenticator authenticator,List<String> listElements)
1280     {
1281     	
1282     	if (authenticator != null) {
1283 			AuthenticateRequestInformations securityInformations = authenticator.getSecurityInformations(listElements);
1284 			// Add Security Parameters in the request
1285 			if (!securityInformations.getSecurityParameteres().isEmpty()) {
1286 
1287 				List<NameValuePair> nvps = new ArrayList<>();
1288 
1289 				securityInformations.getSecurityParameteres().forEach((k, v) -> nvps.add(new BasicNameValuePair(k, v)));
1290 				// Add to the request URL
1291 				try {
1292 					URI uri = new URIBuilder(new URI(strTargetUrl)).addParameters(nvps).build();
1293 					httpRequest.setUri(uri);
1294 				} catch (URISyntaxException e) {
1295 					throw new RuntimeException(e);
1296 				}
1297 
1298 			}
1299 			// Add security  Headers in the request
1300 			if (!securityInformations.getSecurityHeaders().isEmpty()) {
1301 
1302 				securityInformations.getSecurityHeaders().forEach((k, v) -> httpRequest.addHeader(k, v));
1303 			}
1304 
1305 		}	
1306     	
1307  
1308 
1309     }
1310     
1311     
1312     /**
1313      * Gets the response body.
1314      *
1315      * @param httpRequest the http request
1316      * @param strUrl the str url
1317      * @param mapResponseHeader the map response header
1318      * @return the response body
1319      * @throws HttpAccessException the http access exception
1320      */
1321     private String getResponseBody( HttpUriRequestBase httpRequest,String strUrl,Map<String,String> mapResponseHeader ) throws HttpAccessException
1322     {
1323     	String strResponseBody= StringUtils.EMPTY;
1324 		try (CloseableHttpClient httpClient = _accessService.getHttpClient(httpRequest.getUri().getHost())){
1325 		
1326 			try (CloseableHttpResponse response = httpClient.execute(httpRequest)) {
1327 
1328 				int nResponse = response.getCode();
1329 				validateResponseStatus(nResponse, httpRequest.getMethod(), response, strUrl);
1330 
1331 				if (mapResponseHeader != null && response.getHeaders() != null) {
1332 
1333 					Arrays.asList(response.getHeaders()).stream()
1334 							.forEach(x -> mapResponseHeader.put(x.getName(), x.getValue()));
1335 
1336 				}
1337 				HttpEntity entity = response.getEntity();
1338 				strResponseBody = EntityUtils.toString(entity,!StringUtils.isEmpty(   _accessService.getHttpClientConfiguration().getContentCharset())? Charset.forName(_accessService.getHttpClientConfiguration().getContentCharset()):Charset.forName(DEFAULT_CHARSET));
1339 				
1340 			}
1341 
1342 		}
1343 
1344 		catch (IOException | ParseException | URISyntaxException e) {
1345 			throwHttpAccessException(strUrl, e);
1346 		}	
1347     	
1348 		return strResponseBody;
1349     }
1350     
1351     
1352 }