/*
* ome.formats.importer.util.HtmlMessenger
*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2014 University of Dundee. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package ome.formats.importer.util;
import java.io.InputStreamReader;
import java.io.Reader;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
/**
* This class allows you to submit a URL and a String hash map of
* key-value pairs to be posted to the URL in question.
*
* @author Brian W. Loranger
*/
public class HtmlMessenger
{
/** proxy host. */
static final String PROXY_HOST = "http.proxyHost";
/** proxy port. */
static final String PROXY_PORT = "http.proxyPort";
/** connection_timeout **/
static final int CONN_TIMEOUT = 10000;
/** The request to post.*/
private HttpPost request;
private boolean secure;
/**
* Creates a connection.
*
* @return See above
* @throws HtmlMessengerException Thrown if an error occurred while creating the
* SSL context.
*/
private SSLConnectionSocketFactory createSSLConnection()
throws HtmlMessengerException
{
SSLContext sslcontext = SSLContexts.createSystemDefault();
final TrustManager trustEverything = new X509TrustManager() {
private final X509Certificate[]
acceptedIssuers = new X509Certificate[0];
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
@Override
public X509Certificate[] getAcceptedIssuers() {
return this.acceptedIssuers;
}
};
TrustManager[] managers = {trustEverything};
try {
sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, managers, null);
} catch (Exception e) {
new HtmlMessengerException("Cannot create security context", e);
}
return new SSLConnectionSocketFactory(sslcontext,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
}
/**
* Creates a communicator.
*
* @param secure <code>Pass</code> true if https, <code>false</code>
* otherwise.
* @return See above
* @throws HtmlMessengerException Thrown if an error occurred while creating
* the communicator.
*/
private CloseableHttpClient getCommunicationLink(boolean secure)
throws HtmlMessengerException
{
//Default connection configuration
RequestConfig.Builder builder = RequestConfig.custom();
builder.setCookieSpec(CookieSpecs.BEST_MATCH)
.setExpectContinueEnabled(true)
.setStaleConnectionCheckEnabled(true)
.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM,
AuthSchemes.DIGEST))
.setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC));
builder.setConnectTimeout(CONN_TIMEOUT);
String proxyHost = System.getProperty(PROXY_HOST);
String proxyPort = System.getProperty(PROXY_PORT);
if (StringUtils.isNotBlank(proxyHost) &&
StringUtils.isNotBlank(proxyPort)) {
builder.setProxy(new HttpHost(proxyHost,
Integer.parseInt(proxyPort)));
}
HttpClientBuilder httpBuilder = HttpClients.custom();
httpBuilder.setDefaultRequestConfig(builder.build());
if (secure)
httpBuilder.setSSLSocketFactory(createSSLConnection());
return httpBuilder.build();
}
/**
* Instantiate messenger
*
* @param url the HTTP POST URL
* @param postList variables list in post
* @throws HtmlMessengerException if the POST failed
*/
public HtmlMessenger(String url, Map<String, String> postList)
throws HtmlMessengerException
{
try
{
//Create request.
if (StringUtils.isBlank(url))
throw new HtmlMessengerException("No URL specified.");
request = new HttpPost(url);
request.addHeader("Accept", "text/plain");
request.addHeader("Content-type", "application/x-www-form-urlencoded");
List<BasicNameValuePair> p = new ArrayList<BasicNameValuePair>();
Entry<String, String> entry;
Iterator<Entry<String, String>> k = postList.entrySet().iterator();
while (k.hasNext()) {
entry = k.next();
p.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
request.setEntity(new UrlEncodedFormEntity(p));
secure = url.toLowerCase().startsWith("https");
} catch (Exception e) {
throw new HtmlMessengerException("Error creating post parameters", e);
}
}
/**
* Creates a client to communicate.
*
* @param url get a HTTP client connection
* @return if the connection is encrypted
* @throws HtmlMessengerException if connection to the URL failed
*/
public CloseableHttpClient getCommunicationLink(String url)
throws HtmlMessengerException
{
if (StringUtils.isBlank(url))
throw new HtmlMessengerException("No URL specified.");
return getCommunicationLink(url.toLowerCase().startsWith("https"));
}
/**
* Execute a post action and retrieve server reply
* This method executes the post created when this class is instantiated
*
* @return server reply
* @throws HtmlMessengerException if the HTTP POST failed
*/
public String executePost() throws HtmlMessengerException
{
String serverReply = "";
Reader reader = null;
CloseableHttpClient client = null;
try {
// Execute the POST method
client = getCommunicationLink(secure);
CloseableHttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null) {
reader = new InputStreamReader(entity.getContent());
char[] buf = new char[32678];
StringBuilder str = new StringBuilder();
for (int n; (n = reader.read(buf)) != -1;)
str.append(buf, 0, n);
serverReply = str.toString();
}
} catch( Exception e ) {
throw new HtmlMessengerException("Cannot Connect", e);
} finally {
if (client != null) {
try {
client.close();
} catch (Exception ex) {}
}
if (reader != null) {
try {
reader.close();
} catch (Exception ex) {}
}
}
return serverReply;
}
}