package org.limewire.ui.support; import java.io.IOException; import java.util.Arrays; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.params.HttpClientParams; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.HttpConnectionParams; import org.apache.http.util.EntityUtils; import org.limewire.core.api.support.LocalClientInfo; import org.limewire.http.httpclient.LimeHttpClient; import org.limewire.http.httpclient.SimpleLimeHttpClient; import com.google.inject.Inject; import com.google.inject.Provider; import com.limegroup.gnutella.util.LimeWireUtils; /** * This class handles accessing the servlet, sending it data about the client * configuration, and obtaining information about the next time this or any * bug can be sent. */ //2345678|012345678|012345678|012345678|012345678|012345678|012345678|012345678| final class ServletAccessor { private static final Log LOG = LogFactory.getLog(ServletAccessor.class); @Inject private static volatile Provider<LimeHttpClient> limeHttpClient; /** * Constant number of milliseconds to wait before timing out the * connection to the servlet. */ private static final int CONNECT_TIMEOUT = 10 * 1000; // 10 seconds. /** * Constant for the servlet url. */ private static final String DEFAULT_SERVLET_URL = "http://bugreports.limewire.com/bugs/servlet/BugHandler"; private final String SERVLET_URL; /** Whether or not HttpClient can use NIO */ private final boolean ALLOW_NIO; /** Constructs an accessor that can use NIO */ ServletAccessor() { this(true); } /** Constructs an accessor that may or may not use NIO. Use true if it can. */ ServletAccessor(boolean allowNIO) { this(allowNIO, DEFAULT_SERVLET_URL); } /** Constructs an accessor that may or may not use NIO. Use true if it can. * Also takes a URL value as a parameter to be assigned to SERVLET_URL */ ServletAccessor(boolean allowNIO, String servlet_url) { this.ALLOW_NIO = allowNIO; SERVLET_URL = servlet_url; } /** * Contacts the application servlet and sends it the information * contained in the <tt>LocalClientInfo</tt> object. This method * also builds a <tt>RemoteClientInfo</tt> object from the information * obtained from the servlet. * * @return a <tt>RemoteClientInfo</tt> object that encapsulates the * data about when to next send a bug. * @param localInfo is an object encapsulating information about the * local machine to send to the remote server */ synchronized RemoteClientInfo getRemoteBugInfo(LocalClientInfo localInfo) { RemoteClientInfo remoteInfo = new RemoteClientInfo(); HttpResponse response = null; LimeHttpClient client = ALLOW_NIO && limeHttpClient != null ? limeHttpClient.get() : new SimpleLimeHttpClient(); try { NameValuePair[] params = getNameValuePairs(localInfo.getPostRequestParams()); HttpPost post = new HttpPost(SERVLET_URL); post.addHeader("Cache-Control", "no-cache"); post.addHeader("User-Agent", LimeWireUtils.getHttpServer()); post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); post.setEntity(new UrlEncodedFormEntity(Arrays.asList(params), "UTF-8")); HttpConnectionParams.setConnectionTimeout(client.getParams(), CONNECT_TIMEOUT); HttpClientParams.setRedirecting(client.getParams(), false); response = client.execute(post); String result; if (response.getEntity() != null) { result = EntityUtils.toString(response.getEntity()); } else { result = null; } String body = result; if (LOG.isDebugEnabled()) LOG.debug("Got response: " + response); // process results if valid status code if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) remoteInfo.addRemoteInfo(body); // otherwise mark as server down. else { if (LOG.isWarnEnabled()) LOG.warn("Servlet connect failed, code: " + response.getStatusLine().getStatusCode()); remoteInfo.connectFailed(); } } catch(IOException e) { fail(remoteInfo, e); } finally { client.releaseConnection(response); } return remoteInfo; } private void fail(RemoteClientInfo remoteInfo, Throwable e) { LOG.error("Error connecting to bug servlet", e); remoteInfo.connectFailed(); } /** * Converts the specified array of map entries into an array of * NameValuePair objects. */ private NameValuePair[] getNameValuePairs(Map.Entry[] entries) { // Create result. NameValuePair[] pairs = new NameValuePair[entries.length]; // Convert each Map.Entry into a NameValuePair. for (int i = 0; i < entries.length; i++) { Map.Entry entry = entries[i]; pairs[i] = new BasicNameValuePair(String.valueOf(entry.getKey()), String.valueOf(entry.getValue())); } return pairs; } }