X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fnet%2Fsf%2Fopenrocket%2Fcommunication%2FCommunication.java;fp=src%2Fnet%2Fsf%2Fopenrocket%2Fcommunication%2FCommunication.java;h=df3b0ac185178244b2040222886638c7ce9895aa;hb=b3c3c1071dfdca4c6b3eb9935dc461201abdaf60;hp=0000000000000000000000000000000000000000;hpb=fa61335265b0af5f9bc8800df953d41cde2d75f6;p=debian%2Fopenrocket diff --git a/src/net/sf/openrocket/communication/Communication.java b/src/net/sf/openrocket/communication/Communication.java new file mode 100644 index 00000000..df3b0ac1 --- /dev/null +++ b/src/net/sf/openrocket/communication/Communication.java @@ -0,0 +1,262 @@ +package net.sf.openrocket.communication; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.ArrayList; + +import net.sf.openrocket.util.ComparablePair; +import net.sf.openrocket.util.Prefs; + +public class Communication { + + private static final String BUG_REPORT_URL = + "http://openrocket.sourceforge.net/actions/reportbug"; + private static final String UPDATE_INFO_URL = + "http://openrocket.sourceforge.net/actions/updates"; + + private static final String VERSION_PARAM = "version"; + + + private static final String BUG_REPORT_PARAM = "content"; + private static final int BUG_REPORT_RESPONSE_CODE = HttpURLConnection.HTTP_ACCEPTED; + private static final int CONNECTION_TIMEOUT = 10000; // in milliseconds + + private static final int UPDATE_INFO_UPDATE_AVAILABLE = HttpURLConnection.HTTP_OK; + private static final int UPDATE_INFO_NO_UPDATE_CODE = HttpURLConnection.HTTP_NO_CONTENT; + private static final String UPDATE_INFO_CONTENT_TYPE = "text/plain"; + + + private static UpdateInfoFetcher fetcher = null; + + + /** + * Send the provided report to the OpenRocket bug report URL. If the connection + * fails or the server does not respond with the correct response code, an + * exception is thrown. + * + * @param report the report to send. + * @throws IOException if an error occurs while connecting to the server or + * the server responds with a wrong response code. + */ + public static void sendBugReport(String report) throws IOException { + URL url = new URL(BUG_REPORT_URL); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + connection.setConnectTimeout(CONNECTION_TIMEOUT); + connection.setInstanceFollowRedirects(true); + connection.setRequestMethod("POST"); + connection.setUseCaches(false); + connection.setRequestProperty("X-OpenRocket-Version", encode(Prefs.getVersion())); + + String post; + post = (VERSION_PARAM + "=" + encode(Prefs.getVersion()) + + "&" + BUG_REPORT_PARAM + "=" + encode(report)); + + OutputStreamWriter wr = null; + try { + // Send post information + connection.setDoOutput(true); + wr = new OutputStreamWriter(connection.getOutputStream(), "UTF-8"); + wr.write(post); + wr.flush(); + + if (connection.getResponseCode() != BUG_REPORT_RESPONSE_CODE) { + throw new IOException("Server responded with code " + + connection.getResponseCode() + ", expecting " + BUG_REPORT_RESPONSE_CODE); + } + } finally { + if (wr != null) + wr.close(); + connection.disconnect(); + } + } + + + + /** + * Start an asynchronous task that will fetch information about the latest + * OpenRocket version. This will overwrite any previous fetching operation. + */ + public static void startFetchUpdateInfo() { + fetcher = new UpdateInfoFetcher(); + fetcher.start(); + } + + + /** + * Check whether the update info fetching is still in progress. + * + * @return true if the communication is still in progress. + */ + public static boolean isFetchUpdateInfoRunning() { + if (fetcher == null) { + throw new IllegalStateException("startFetchUpdateInfo() has not been called"); + } + return fetcher.isAlive(); + } + + + /** + * Retrieve the result of the background update info fetcher. This method returns + * the result of the previous call to {@link #startFetchUpdateInfo()}. It must be + * called before calling this method. + *

+ * This method will return null if the info fetcher is still running or + * if it encountered a problem in communicating with the server. The difference can + * be checked using {@link #isFetchUpdateInfoRunning()}. + * + * @return the update result, or null if the fetching is still in progress + * or an error occurred while communicating with the server. + * @throws IllegalStateException if {@link #startFetchUpdateInfo()} has not been called. + */ + public static UpdateInfo getUpdateInfo() { + if (fetcher == null) { + throw new IllegalStateException("startFetchUpdateInfo() has not been called"); + } + return fetcher.info; + } + + + + /** + * Parse the data received from the server. + * + * @param r the Reader from which to read. + * @return an UpdateInfo construct, or null if the data was invalid. + * @throws IOException if an I/O exception occurs. + */ + /* package-private */ + static UpdateInfo parseUpdateInput(Reader r) throws IOException { + BufferedReader reader; + if (r instanceof BufferedReader) { + reader = (BufferedReader)r; + } else { + reader = new BufferedReader(r); + } + + + String version = null; + ArrayList> updates = + new ArrayList>(); + + String str = reader.readLine(); + while (str != null) { + if (str.matches("^Version: *[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9.-]* *$")) { + version = str.substring(8).trim(); + } else if (str.matches("^[0-9]+:\\p{Print}+$")) { + int index = str.indexOf(':'); + int value = Integer.parseInt(str.substring(0, index)); + String desc = str.substring(index+1).trim(); + if (!desc.equals("")) { + updates.add(new ComparablePair(value, desc)); + } + } + // Ignore anything else + str = reader.readLine(); + } + + if (version != null) { + return new UpdateInfo(version, updates); + } else { + return null; + } + } + + + + + private static class UpdateInfoFetcher extends Thread { + + private volatile UpdateInfo info = null; + + @Override + public void run() { + try { + doConnection(); + } catch (IOException e) { + return; + } + } + + + private void doConnection() throws IOException { + URL url; + url = new URL(UPDATE_INFO_URL + "?" + VERSION_PARAM + "=" + + encode(Prefs.getVersion())); + + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + connection.setConnectTimeout(CONNECTION_TIMEOUT); + connection.setInstanceFollowRedirects(true); + connection.setRequestMethod("GET"); + connection.setUseCaches(false); + connection.setRequestProperty("X-OpenRocket-Version", encode(Prefs.getVersion())); + connection.setRequestProperty("X-OpenRocket-ID", encode(Prefs.getUniqueID())); + connection.setRequestProperty("X-OpenRocket-OS", encode( + System.getProperty("os.name") + " " + System.getProperty("os.arch"))); + connection.setRequestProperty("X-OpenRocket-Java", encode( + System.getProperty("java.vendor") + " " + System.getProperty("java.version"))); + connection.setRequestProperty("X-OpenRocket-Country", encode( + System.getProperty("user.country"))); + + InputStream is = null; + try { + connection.connect(); + + if (connection.getResponseCode() == UPDATE_INFO_NO_UPDATE_CODE) { + // No updates are available + info = new UpdateInfo(); + return; + } + + if (connection.getResponseCode() != UPDATE_INFO_UPDATE_AVAILABLE) { + // Error communicating with server + return; + } + + if (!UPDATE_INFO_CONTENT_TYPE.equalsIgnoreCase(connection.getContentType())) { + // Unknown response type + return; + } + + // Update is available, parse input + is = connection.getInputStream(); + String encoding = connection.getContentEncoding(); + if (encoding == null) + encoding = "UTF-8"; + BufferedReader reader = new BufferedReader(new InputStreamReader(is, encoding)); + + + + } finally { + if (is != null) + is.close(); + connection.disconnect(); + } + + + } + + } + + + private static String encode(String str) { + if (str == null) + return "null"; + try { + return URLEncoder.encode(str, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("Unsupported encoding UTF-8", e); + } + } + +}