/* ******************************************************************************
* Copyright (c) 2006-2016 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
/**
*
*/
package org.xmind.core.net.http;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.xmind.core.net.Field;
import org.xmind.core.net.FieldSet;
import org.xmind.core.net.internal.Activator;
import org.xmind.core.net.internal.EncodingUtils;
import org.xmind.core.net.internal.FixedLengthInputStream;
import org.xmind.core.net.internal.LoggingOutputStream;
import org.xmind.core.net.internal.MonitoredInputStream;
import org.xmind.core.net.internal.MonitoredOutputStream;
import org.xmind.core.net.internal.TeeInputStream;
import org.xmind.core.net.internal.TeeOutputStream;
/**
* @author Frank Shaka
* @since 3.6.50
*/
public class HttpRequest {
public static final int DEFAULT_PORT = -1;
public static final String GET = "GET"; //$NON-NLS-1$
public static final String POST = "POST"; //$NON-NLS-1$
public static final String PUT = "PUT"; //$NON-NLS-1$
public static final String DELETE = "DELETE"; //$NON-NLS-1$
public static final int HTTP_PREPARING = 0;
public static final int HTTP_CONNECTING = 1;
public static final int HTTP_SENDING = 2;
public static final int HTTP_WAITING = 3;
public static final int HTTP_RECEIVING = 4;
public static final int HTTP_ERROR = 999;
/* 2XX: generally "OK" */
/**
* HTTP Status-Code 200: OK.
*/
public static final int HTTP_OK = HttpURLConnection.HTTP_OK;
/**
* HTTP Status-Code 201: Created.
*/
public static final int HTTP_CREATED = HttpURLConnection.HTTP_CREATED;
/**
* HTTP Status-Code 202: Accepted.
*/
public static final int HTTP_ACCEPTED = HttpURLConnection.HTTP_ACCEPTED;
/**
* HTTP Status-Code 203: Non-Authoritative Information.
*/
public static final int HTTP_NOT_AUTHORITATIVE = HttpURLConnection.HTTP_NOT_AUTHORITATIVE;
/**
* HTTP Status-Code 204: No Content.
*/
public static final int HTTP_NO_CONTENT = HttpURLConnection.HTTP_NO_CONTENT;
/**
* HTTP Status-Code 205: Reset Content.
*/
public static final int HTTP_RESET = HttpURLConnection.HTTP_RESET;
/**
* HTTP Status-Code 206: Partial Content.
*/
public static final int HTTP_PARTIAL = HttpURLConnection.HTTP_PARTIAL;
/* 3XX: relocation/redirect */
/**
* HTTP Status-Code 300: Multiple Choices.
*/
public static final int HTTP_MULT_CHOICE = HttpURLConnection.HTTP_MULT_CHOICE;
/**
* HTTP Status-Code 301: Moved Permanently.
*/
public static final int HTTP_MOVED_PERM = HttpURLConnection.HTTP_MOVED_PERM;
/**
* HTTP Status-Code 302: Temporary Redirect.
*/
public static final int HTTP_MOVED_TEMP = HttpURLConnection.HTTP_MOVED_TEMP;
/**
* HTTP Status-Code 303: See Other.
*/
public static final int HTTP_SEE_OTHER = HttpURLConnection.HTTP_SEE_OTHER;
/**
* HTTP Status-Code 304: Not Modified.
*/
public static final int HTTP_NOT_MODIFIED = HttpURLConnection.HTTP_NOT_MODIFIED;
/**
* HTTP Status-Code 305: Use Proxy.
*/
public static final int HTTP_USE_PROXY = HttpURLConnection.HTTP_USE_PROXY;
/* 4XX: client error */
/**
* HTTP Status-Code 400: Bad Request.
*/
public static final int HTTP_BAD_REQUEST = HttpURLConnection.HTTP_BAD_REQUEST;
/**
* HTTP Status-Code 401: Unauthorized.
*/
public static final int HTTP_UNAUTHORIZED = HttpURLConnection.HTTP_UNAUTHORIZED;
/**
* HTTP Status-Code 402: Payment Required.
*/
public static final int HTTP_PAYMENT_REQUIRED = HttpURLConnection.HTTP_PAYMENT_REQUIRED;
/**
* HTTP Status-Code 403: Forbidden.
*/
public static final int HTTP_FORBIDDEN = HttpURLConnection.HTTP_FORBIDDEN;
/**
* HTTP Status-Code 404: Not Found.
*/
public static final int HTTP_NOT_FOUND = HttpURLConnection.HTTP_NOT_FOUND;
/**
* HTTP Status-Code 405: Method Not Allowed.
*/
public static final int HTTP_BAD_METHOD = HttpURLConnection.HTTP_BAD_METHOD;
/**
* HTTP Status-Code 406: Not Acceptable.
*/
public static final int HTTP_NOT_ACCEPTABLE = HttpURLConnection.HTTP_NOT_ACCEPTABLE;
/**
* HTTP Status-Code 407: Proxy Authentication Required.
*/
public static final int HTTP_PROXY_AUTH = HttpURLConnection.HTTP_PROXY_AUTH;
/**
* HTTP Status-Code 408: Request Time-Out.
*/
public static final int HTTP_CLIENT_TIMEOUT = HttpURLConnection.HTTP_CLIENT_TIMEOUT;
/**
* HTTP Status-Code 409: Conflict.
*/
public static final int HTTP_CONFLICT = HttpURLConnection.HTTP_CONFLICT;
/**
* HTTP Status-Code 410: Gone.
*/
public static final int HTTP_GONE = HttpURLConnection.HTTP_GONE;
/**
* HTTP Status-Code 411: Length Required.
*/
public static final int HTTP_LENGTH_REQUIRED = HttpURLConnection.HTTP_LENGTH_REQUIRED;
/**
* HTTP Status-Code 412: Precondition Failed.
*/
public static final int HTTP_PRECON_FAILED = HttpURLConnection.HTTP_PRECON_FAILED;
/**
* HTTP Status-Code 413: Request HttpEntity Too Large.
*/
public static final int HTTP_ENTITY_TOO_LARGE = HttpURLConnection.HTTP_ENTITY_TOO_LARGE;
/**
* HTTP Status-Code 414: Request-URI Too Large.
*/
public static final int HTTP_REQ_TOO_LONG = HttpURLConnection.HTTP_REQ_TOO_LONG;
/**
* HTTP Status-Code 415: Unsupported Media Type.
*/
public static final int HTTP_UNSUPPORTED_TYPE = HttpURLConnection.HTTP_UNSUPPORTED_TYPE;
/* 5XX: server error */
/**
* HTTP Status-Code 500: Internal Server Error.
*/
public static final int HTTP_INTERNAL_ERROR = HttpURLConnection.HTTP_INTERNAL_ERROR;
/**
* HTTP Status-Code 501: Not Implemented.
*/
public static final int HTTP_NOT_IMPLEMENTED = HttpURLConnection.HTTP_NOT_IMPLEMENTED;
/**
* HTTP Status-Code 502: Bad Gateway.
*/
public static final int HTTP_BAD_GATEWAY = HttpURLConnection.HTTP_BAD_GATEWAY;
/**
* HTTP Status-Code 503: Service Unavailable.
*/
public static final int HTTP_UNAVAILABLE = HttpURLConnection.HTTP_UNAVAILABLE;
/**
* HTTP Status-Code 504: Gateway Timeout.
*/
public static final int HTTP_GATEWAY_TIMEOUT = HttpURLConnection.HTTP_GATEWAY_TIMEOUT;
/**
* HTTP Status-Code 505: HTTP Version Not Supported.
*/
public static final int HTTP_VERSION = HttpURLConnection.HTTP_VERSION;
/**
* Property name for connect timeout. Value should be a positive integer.
*/
public static final String SETTING_CONNECT_TIMEOUT = "connectTimeout"; //$NON-NLS-1$
/**
* Property name for read timeout. Value should be a positive integer.
*/
public static final String SETTING_READ_TIMEOUT = "readTimeout"; //$NON-NLS-1$
private static Set<String> VALID_METHODS = new HashSet<String>(
Arrays.asList(GET, PUT, POST, DELETE));
private URL url;
private String method;
private FieldSet requestHeaders;
private HttpEntity requestEntity;
private FieldSet settings;
private IResponseHandler responseHandler;
private int statusCode;
private String statusMessage;
private FieldSet responseHeaders;
private boolean debugging;
private PrintStream logStream;
private byte[] responseBuffer;
public HttpRequest(URL url, String method, FieldSet headers,
HttpEntity entity, FieldSet settings,
IResponseHandler responseHandler) {
Assert.isLegal(url != null);
Assert.isLegal(method != null && VALID_METHODS.contains(method));
this.url = url;
this.method = method;
this.requestHeaders = new FieldSet(headers);
this.requestEntity = entity;
this.settings = new FieldSet(settings);
this.responseHandler = responseHandler;
this.statusCode = HTTP_PREPARING;
this.statusMessage = null;
this.responseHeaders = new FieldSet();
boolean forceDebugging = Activator
.isDebugging(Activator.OPTION_HTTP_REQEUSTS);
this.debugging = forceDebugging
|| System.getProperty(Activator.CONFIG_DEBUG_HTTP_REQUESTS,
null) != null;
this.logStream = forceDebugging ? System.out : null;
this.responseBuffer = null;
}
public HttpRequest(boolean https, String host, int port, String path,
FieldSet queries, String ref, String method, FieldSet headers,
HttpEntity entity, FieldSet settings,
IResponseHandler responseHandler) {
this(makeURL(https, host, port, path, queries, ref), method, headers,
entity, settings, responseHandler);
}
/**
* @return the url
*/
public URL getURL() {
return url;
}
public String getMethod() {
return method;
}
/**
* @return the requestEntity
*/
public HttpEntity getRequestEntity() {
return requestEntity;
}
/**
* @return the requestHeaders
*/
public FieldSet getRequestHeaders() {
return new FieldSet(requestHeaders);
}
public int getStatusCode() {
return statusCode;
}
public String getStatusMessage() {
return statusMessage;
}
/**
* @return the responseHandler
*/
public IResponseHandler getResponseHandler() {
return responseHandler;
}
public String getResponseAsString() {
if (responseBuffer == null)
return null;
return EncodingUtils.toDefaultString(responseBuffer);
}
public JSONObject getResponseAsJSON() {
if (responseBuffer == null)
return null;
ByteArrayInputStream input = new ByteArrayInputStream(responseBuffer);
try {
return new JSONObject(new JSONTokener(input));
} catch (JSONException e) {
// not a valid JSON object
return null;
} finally {
try {
input.close();
} catch (IOException e) {
}
}
}
/**
* @return the responseHeaders
*/
public FieldSet getResponseHeaders() {
return new FieldSet(responseHeaders);
}
public String getResponseHeader(String name) {
return responseHeaders.getString(name);
}
public void execute(IProgressMonitor monitor)
throws HttpException, InterruptedException {
final SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
if (subMonitor.isCanceled())
return;
final boolean[] finished = new boolean[1];
final Throwable[] exception = new Throwable[1];
final HttpURLConnection[] connection = new HttpURLConnection[1];
log("Preparing...."); //$NON-NLS-1$
finished[0] = false;
Thread thread = new Thread(new Runnable() {
public void run() {
try {
doExecute(subMonitor, connection);
} catch (InterruptedException e) {
subMonitor.setCanceled(true);
} catch (Throwable e) {
exception[0] = e;
} finally {
finished[0] = true;
}
}
}, "HttpRequestSession-" + method + "-" + url.toExternalForm()); //$NON-NLS-1$ //$NON-NLS-2$
thread.setDaemon(true);
thread.setPriority((Thread.MIN_PRIORITY + Thread.NORM_PRIORITY) / 2);
thread.start();
try {
while (!finished[0] && !subMonitor.isCanceled()) {
Thread.sleep(1);
}
} finally {
if (thread != null) {
thread.interrupt();
}
if (connection[0] != null) {
connection[0].disconnect();
}
}
if (subMonitor.isCanceled()) {
log("Canceled."); //$NON-NLS-1$
throw new InterruptedException();
}
if (exception[0] != null) {
Throwable e = exception[0];
log("Error: {0}", e); //$NON-NLS-1$
if (e instanceof HttpException)
throw (HttpException) e;
throw new HttpException(this, e);
}
if (getStatusCode() >= 400)
throw new HttpException(this, null);
}
private void doExecute(IProgressMonitor monitor,
HttpURLConnection[] _connection)
throws InterruptedException, IOException {
if (monitor.isCanceled())
return;
log("Connecting to {0}....", url.getAuthority()); //$NON-NLS-1$
setStatusCode(HTTP_CONNECTING, "Connecting"); //$NON-NLS-1$
if (monitor.isCanceled())
throw new OperationCanceledException();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
_connection[0] = connection;
if (monitor.isCanceled())
throw new InterruptedException();
assc(connection);
if (monitor.isCanceled())
throw new InterruptedException();
int connectTimeout = settings.getInt(SETTING_CONNECT_TIMEOUT, -1);
if (connectTimeout >= 0) {
connection.setConnectTimeout(connectTimeout);
}
int readTimeout = settings.getInt(SETTING_READ_TIMEOUT, -1);
if (readTimeout >= 0) {
connection.setReadTimeout(readTimeout);
}
log("Sending...."); //$NON-NLS-1$
setStatusCode(HTTP_SENDING, "Sending"); //$NON-NLS-1$
if (monitor.isCanceled())
throw new InterruptedException();
try {
connection.setDoOutput(requestEntity != null);
if (monitor.isCanceled())
throw new InterruptedException();
connection.setRequestMethod(method);
if (monitor.isCanceled())
throw new InterruptedException();
writeHeaders(connection);
if (monitor.isCanceled())
throw new InterruptedException();
writeBody(monitor, connection);
if (monitor.isCanceled())
throw new InterruptedException();
log("Waiting..."); //$NON-NLS-1$
setStatusCode(HTTP_WAITING, "Waiting"); //$NON-NLS-1$
if (monitor.isCanceled())
throw new InterruptedException();
readResponse(monitor, connection, connection.getInputStream(),
connection.getResponseCode(),
connection.getResponseMessage());
if (monitor.isCanceled())
throw new InterruptedException();
} catch (IOException e) {
InputStream errorStream = connection.getErrorStream();
if (errorStream == null) {
e.printStackTrace();
log("Error stream is NULL, response state: {0} {1}", //$NON-NLS-1$
connection.getResponseCode(),
connection.getResponseMessage());
throw new InterruptedException();
} else {
readResponse(monitor, connection, errorStream,
connection.getResponseCode(),
connection.getResponseMessage());
}
if (monitor.isCanceled())
throw new InterruptedException();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
private void setStatusCode(int newStatus, String statusMessage) {
this.statusCode = newStatus;
this.statusMessage = statusMessage;
}
private void writeHeaders(URLConnection connection) {
List<Field> writtenHeaders = new ArrayList<Field>();
Object userAgent = null;
for (Field header : requestHeaders) {
writeHeader(connection, header.name, header.getValue(),
writtenHeaders);
if ("User-Agent".equalsIgnoreCase(header.name)) { //$NON-NLS-1$
userAgent = header.value;
}
}
if (userAgent == null || "".equals(userAgent)) { //$NON-NLS-1$
writeHeader(connection, "User-Agent", getDefaultUserAgent(), //$NON-NLS-1$
writtenHeaders);
}
if (requestEntity != null) {
writeHeader(connection, "Content-Type", //$NON-NLS-1$
requestEntity.getContentType(), writtenHeaders);
writeHeader(connection, "Content-Length", //$NON-NLS-1$
String.valueOf(requestEntity.getContentLength()),
writtenHeaders);
}
log("> {0} {1} HTTP/1.1", method, url.getPath()); //$NON-NLS-1$
if (debugging) {
for (Field header : writtenHeaders) {
log("> {0}: {1}", header.name, //$NON-NLS-1$
header.value);
}
}
}
private void writeHeader(URLConnection connection, String key, String value,
List<Field> headers) {
connection.setRequestProperty(key, value);
headers.add(new Field(key, value));
}
private static String getDefaultUserAgent() {
String buildId = System.getProperty("org.xmind.product.buildid", //$NON-NLS-1$
null);
if (buildId == null || "".equals(buildId)) { //$NON-NLS-1$
Activator p = Activator.getDefault();
if (p != null) {
buildId = p.getBundle().getVersion().toString();
} else {
buildId = "unknown"; //$NON-NLS-1$
}
}
String os = System.getProperty("osgi.os", "OS"); //$NON-NLS-1$ //$NON-NLS-2$
String arch = System.getProperty("osgi.arch", "ARCH"); //$NON-NLS-1$ //$NON-NLS-2$
String ws = System.getProperty("osgi.ws", "WS"); //$NON-NLS-1$ //$NON-NLS-2$
String nl = System.getProperty("osgi.nl", "NL"); //$NON-NLS-1$ //$NON-NLS-2$
String osName = System.getProperty("os.name", "OS_NAME"); //$NON-NLS-1$ //$NON-NLS-2$
String osArch = System.getProperty("os.arch", "OS_ARCH"); //$NON-NLS-1$ //$NON-NLS-2$
String osVersion = System.getProperty("os.version", "OS_VERSION"); //$NON-NLS-1$ //$NON-NLS-2$
String javaVersion = System.getProperty("java.version", "JAVA_VERSION"); //$NON-NLS-1$ //$NON-NLS-2$
return String.format(
"XMind/%s (%s.%s.%s; %s Arch/%s Version/%s; %s) Java/%s", //$NON-NLS-1$
buildId, ws, os, arch, osName, osArch, osVersion, nl,
javaVersion);
}
private void writeBody(IProgressMonitor monitor, URLConnection connection)
throws InterruptedException, IOException {
if (requestEntity == null)
return;
OutputStream output = new MonitoredOutputStream(
connection.getOutputStream(), monitor);
if (debugging && logStream != null) {
output = new TeeOutputStream(output,
new LoggingOutputStream(logStream));
}
try {
requestEntity.writeTo(output);
} catch (OperationCanceledException e) {
throw new InterruptedIOException();
}
if (debugging && logStream != null) {
logStream.println();
}
if (monitor.isCanceled())
throw new InterruptedException();
output.flush();
}
private void readResponse(IProgressMonitor monitor,
URLConnection connection, InputStream readStream, int responseCode,
String responseMessage) throws InterruptedException, IOException {
if (responseCode < 0) {
responseCode = HTTP_ERROR;
log("Unknown error, maybe not a valid HTTP response."); //$NON-NLS-1$
setStatusCode(responseCode, responseMessage);
return;
}
log("< HTTP/1.1 {0} {1}", responseCode, responseMessage); //$NON-NLS-1$
setStatusCode(responseCode, responseMessage);
if (monitor.isCanceled())
throw new InterruptedException();
readResponseHeaders(connection);
if (monitor.isCanceled())
throw new InterruptedException();
final long totalBytes = getResponseLength(readStream);
if (monitor.isCanceled())
throw new InterruptedException();
log("Receiving {0} bytes...", totalBytes); //$NON-NLS-1$
if (totalBytes > 0) {
if (readStream == null)
throw new IOException(
"No input stream available to read response from"); //$NON-NLS-1$
readStream = new FixedLengthInputStream(readStream, this,
totalBytes);
}
if (readStream != null) {
if (debugging && logStream != null) {
readStream = new TeeInputStream(readStream,
new LoggingOutputStream(logStream));
}
ByteArrayOutputStream bufferStream = new ByteArrayOutputStream(
(int) totalBytes);
readStream = new TeeInputStream(readStream, bufferStream);
readStream = new MonitoredInputStream(readStream, monitor);
if (responseHandler != null) {
final HttpEntity responseEntity = new StreamedEntity(readStream,
totalBytes);
try {
responseHandler.handleResponseEntity(monitor, this,
responseEntity);
} catch (OperationCanceledException e) {
throw new InterruptedException();
}
}
/// read until the end of stream to receive all response content
/// TODO potential dead lock?
byte[] temp = new byte[1024];
while (readStream.read(temp) != -1) {
/// do nothing and wait until the stream is consumed
}
responseBuffer = bufferStream.toByteArray();
}
if (debugging && logStream != null) {
logStream.println();
}
log("Handled."); //$NON-NLS-1$
}
private long getResponseLength(InputStream readStream) throws IOException {
long totalBytes = -1;
String length = getResponseHeader("Content-Length"); //$NON-NLS-1$
if (length != null) {
try {
totalBytes = Long.parseLong(length, 10);
} catch (NumberFormatException e) {
}
}
if (totalBytes < 0 && readStream != null) {
totalBytes = readStream.available();
}
return totalBytes;
}
/**
* @param connection
*/
private void readResponseHeaders(URLConnection connection) {
// Skip status line:
connection.getHeaderField(0);
// Start from 2nd header line:
int i = 1;
String key, value;
while ((key = connection.getHeaderFieldKey(i)) != null) {
value = connection.getHeaderField(i);
responseHeaders.add(key, value);
log("< {0}: {1}", key, value); //$NON-NLS-1$
i++;
}
}
public HttpRequest debug(PrintStream logStream) {
this.debugging = true;
this.logStream = logStream;
return this;
}
private void log(String format, Object... values) {
if (!debugging)
return;
String prefix;
if (format.startsWith(">") || format.startsWith("<")) { //$NON-NLS-1$ //$NON-NLS-2$
prefix = ""; //$NON-NLS-1$
} else {
prefix = "* "; //$NON-NLS-1$
}
String message = prefix + MessageFormat.format(format, values);
if (logStream != null) {
logStream.println(message);
} else {
Activator.log(message);
}
}
private void assc(HttpURLConnection connection) {
if (!Activator.isDebugging(Activator.OPTION_HTTP_ASSC))
return;
try {
TrustModifier.relaxHostChecking(connection);
} catch (Exception e) {
if (logStream != null) {
e.printStackTrace(logStream);
} else {
Activator.log(e);
}
}
}
/**
* A solution to accept self-signed SSL certificates.
* <p>
* Source came from Craig Flichel's post <a href=
* "http://www.javacodegeeks.com/2011/12/ignoring-self-signed-certificates-in.html"
* >Ignoring Self-Signed Certificates in Java</a> on Dec 1, 2011.
* </p>
*
* @author Craig Flichel
*/
private static class TrustModifier {
private static final TrustingHostnameVerifier TRUSTING_HOSTNAME_VERIFIER = new TrustingHostnameVerifier();
private static SSLSocketFactory factory;
/**
* Call this with any HttpURLConnection, and it will modify the trust
* settings if it is an HTTPS connection.
*/
public static void relaxHostChecking(HttpURLConnection conn)
throws KeyManagementException, NoSuchAlgorithmException,
KeyStoreException {
if (conn instanceof HttpsURLConnection) {
HttpsURLConnection httpsConnection = (HttpsURLConnection) conn;
SSLSocketFactory factory = prepFactory(httpsConnection);
httpsConnection.setSSLSocketFactory(factory);
httpsConnection.setHostnameVerifier(TRUSTING_HOSTNAME_VERIFIER);
}
}
static synchronized SSLSocketFactory prepFactory(
HttpsURLConnection httpsConnection)
throws NoSuchAlgorithmException, KeyStoreException,
KeyManagementException {
if (factory == null) {
SSLContext ctx = SSLContext.getInstance("TLS"); //$NON-NLS-1$
ctx.init(null, new TrustManager[] { new AlwaysTrustManager() },
null);
factory = ctx.getSocketFactory();
}
return factory;
}
private static final class TrustingHostnameVerifier
implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
private static class AlwaysTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
}
private static final String PROTOCOL_HTTP = "http"; //$NON-NLS-1$
private static final String PROTOCOL_HTTPS = "https"; //$NON-NLS-1$
private static URL makeURL(boolean https, String host, int port,
String path, FieldSet queries, String ref) {
String protocol = https ? PROTOCOL_HTTPS : PROTOCOL_HTTP;
String file = (path == null) ? "/" : path; //$NON-NLS-1$
if (queries != null) {
file = file + "?" + new FormEntity(queries).toString(); //$NON-NLS-1$
}
if (ref != null) {
file = file + "#" + ref; //$NON-NLS-1$
}
URL url;
try {
url = new URL(protocol, host, port, file);
} catch (MalformedURLException e) {
throw new AssertionError("Failed creating HTTP URL from components", //$NON-NLS-1$
e);
}
return url;
}
}