001/*
002 *  Copyright 2011 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.odf;
017
018import java.io.ByteArrayInputStream;
019import java.io.IOException;
020import java.io.InputStream;
021import java.io.InputStreamReader;
022import java.io.Reader;
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.HashSet;
026import java.util.List;
027import java.util.Map;
028import java.util.Set;
029
030import org.apache.avalon.framework.logger.Logger;
031import org.apache.commons.io.IOUtils;
032import org.apache.http.HttpEntity;
033import org.apache.http.NameValuePair;
034import org.apache.http.client.config.RequestConfig;
035import org.apache.http.client.entity.UrlEncodedFormEntity;
036import org.apache.http.client.methods.CloseableHttpResponse;
037import org.apache.http.client.methods.HttpPost;
038import org.apache.http.entity.InputStreamEntity;
039import org.apache.http.impl.client.CloseableHttpClient;
040import org.apache.http.impl.client.HttpClientBuilder;
041import org.apache.http.message.BasicNameValuePair;
042
043import org.ametys.core.util.StringUtils;
044import org.ametys.runtime.config.Config;
045
046/**
047 * Helper for calling WS on a remote server
048 *
049 */
050public final class CallWSHelper
051{
052    private CallWSHelper ()
053    {
054        // Empty
055    }
056    
057    /**
058     * Request the given url on remote server
059     * @param url the url to be called.
060     * @param parameters the HTTP parameters
061     * @param logger The logger for traces
062     * @return the list of server's url which failed. If empty all WS succeed. Returns <code>null</code> if a global error occurred.
063     */
064    public static Set<String> callWS (String url, Map<String, String> parameters, Logger logger)
065    {
066        Set<String> failedUrl = new HashSet<>();
067        
068        String serverConfig = Config.getInstance().getValue("odf.publish.server.url");
069        
070        Collection<String> serverUrls = StringUtils.stringToCollection(serverConfig);
071        
072        try
073        {
074            for (String serverUrl : serverUrls)
075            {
076            
077                String wsURL = serverUrl + (serverUrl.endsWith("/") ? "" : "/") + url;
078                
079                try (CloseableHttpClient httpClient = _getHttpClient())
080                {
081                    try
082                    {
083                        // Prepare a request object
084                        HttpPost postRequest = new HttpPost(wsURL);
085                        
086                        // HTTP parameters
087                        List<NameValuePair> params = new ArrayList<>();
088                        for (String paramName : parameters.keySet())
089                        {
090                            params.add(new BasicNameValuePair(paramName, parameters.get(paramName)));
091                        }
092                        postRequest.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
093                        
094                        // Execute the request
095                        try (CloseableHttpResponse httpResponse = httpClient.execute(postRequest))
096                        {
097                            if (httpResponse.getStatusLine().getStatusCode() == 200)
098                            {
099                                HttpEntity responseEntity = httpResponse.getEntity();
100                                if (responseEntity != null)
101                                {
102                                    try (Reader reader = new InputStreamReader(responseEntity.getContent(), "UTF-8"))
103                                    {
104                                        // Nothing to do
105                                    }
106                                }
107                            }
108                            else
109                            {
110                                logger.error("Unable to publish CDM-fr with request: " + wsURL + ", response: " + httpResponse.getStatusLine());
111                                failedUrl.add(serverUrl);
112                            }
113                        }
114                    }
115                    catch (Exception e)
116                    {
117                        logger.error("Unable to publish CDM-fr with request: " + wsURL, e);
118                        failedUrl.add(serverUrl);
119                    }
120                }
121            }
122        }
123        catch (IOException e)
124        {
125            logger.error("Unable to publish CDM-fr", e);
126            return null;
127        }
128        
129        return failedUrl;
130    }
131    
132    /**
133     * Request the given url on remote server
134     * @param url the url to be called.
135     * @param is The input stream for HTTP entity
136     * @param logger The logger for traces
137     * @return the list of server's url which failed. If empty all WS succeed. Returns <code>null</code> if a global error occurred.
138     */
139    public static Set<String> callWS (String url, InputStream is, Logger logger)
140    {
141        Set<String> failedUrl = new HashSet<>();
142        
143        String serverConfig = Config.getInstance().getValue("odf.publish.server.url");
144        
145        Collection<String> serverUrls = StringUtils.stringToCollection(serverConfig);
146        
147        try
148        {
149            byte[] bytes = IOUtils.toByteArray(is);
150            
151            for (String serverUrl : serverUrls)
152            {
153                String wsURL = serverUrl + (serverUrl.endsWith("/") ? "" : "/") + url;
154                
155                try (CloseableHttpClient httpclient = _getHttpClient())
156                {
157                    try
158                    {
159                        // Prepare a request object
160                        HttpPost postRequest = new HttpPost(wsURL);
161                        postRequest.addHeader("Content-Type", "text/xml");
162                        
163                        ByteArrayInputStream bIs = new ByteArrayInputStream(bytes);
164                        HttpEntity entity = new InputStreamEntity(bIs, bytes.length);
165                        postRequest.setEntity(entity);
166                        
167                        // Execute the request
168                        try (CloseableHttpResponse httpResponse = httpclient.execute(postRequest))
169                        {
170                            if (httpResponse.getStatusLine().getStatusCode() == 200)
171                            {
172                                HttpEntity responseEntity = httpResponse.getEntity();
173                                if (responseEntity != null)
174                                {
175                                    try (Reader reader = new InputStreamReader(responseEntity.getContent(), "UTF-8"))
176                                    {
177                                        // Nothing to do
178                                    }
179                                }
180                            }
181                            else
182                            {
183                                logger.error("Unable to publish CDM-fr with request: " + wsURL + ", response: " + httpResponse.getStatusLine());
184                                failedUrl.add(serverUrl);
185                            }
186                        }
187                        
188                        bIs.reset();
189                    }
190                    catch (Exception e)
191                    {
192                        logger.error("Unable to publish CDM-fr with request: " + wsURL, e);
193                        failedUrl.add(serverUrl);
194                    }
195                }
196            }
197        }
198        catch (IOException e)
199        {
200            logger.error("Unable to publish CDM-fr", e);
201            return null;
202        }
203        
204        return failedUrl;
205    }
206    
207    private static CloseableHttpClient _getHttpClient ()
208    {
209        RequestConfig requestConfig = RequestConfig.custom().build();
210        return HttpClientBuilder.create()
211                .setDefaultRequestConfig(requestConfig)
212                .useSystemProperties()
213                .build();
214    }
215}