JAL-4001 most of google analytics client
authorBen Soares <b.soares@dundee.ac.uk>
Mon, 5 Jun 2023 14:17:45 +0000 (15:17 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Mon, 5 Jun 2023 14:17:45 +0000 (15:17 +0100)
src/jalview/analytics/GoogleAnalytics4.java

index 6b9f03a..bd0949d 100644 (file)
 package jalview.analytics;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import java.util.UUID;
 
-public class GoogleAnalytics4 {
-       private static final String JALVIEW_ID = "Jalview Desktop";
-       private static final String SESSION_ID = new Random().toString();
-       private static final String MEASUREMENT_ID = "G-6TMPHMXEQ0";
-       private static final String BASE_URL = "https://www.google-analytics.com/mp/collect";
-
-       private List<Map.Entry<String, String>> queryStringValues;
-       private List<Map.Entry<String, Object>> jsonValues;
-       private List<Map.Entry<String, String>> cookies;
-
-       private void addToJson(String key, List<String> values) {
-       }
-
-       private void addToJson(String key, String value) {
-       }
-
-       private void addToJson(String key, int value) {
-       }
-
-       private void addToJson(String key, boolean value) {
-       }
-
-       private void addToJson(String key, Object[] array) {
-       }
-
-       private void addQueryStringValue(String key, String value) {
-       }
-
-       private void reset() {
-               jsonValues = new ArrayList<>();
-               queryStringValues = new ArrayList<>();
-               cookies = new ArrayList<>();
-       }
-
-       private String buildJson() {
-               StringBuilder sb = new StringBuilder();
-               int indent = 0;
-               sb.append("{");
-               indent++;
-
-               sb.append("}");
-               return sb.toString();
-       }
-
-       private void addJsonObject(StringBuilder sb, int indent, String key, Object value) {
-               indent(sb, indent);
-               sb.append('"').append(key).append('"');
-               sb.append(": ");
-               if (List.class.equals(value.getClass())) {
-                       sb.append('\n');
-               }
-               addJsonValue(sb, indent, value);
-               sb.append(",\n");
-       }
-
-       private void addJsonValue(StringBuilder sb, int indent, Object value) {
-               if (value == null) {
-                       return;
-               }
-               Class c = value.getClass();
-               if (String.class.equals(c)) {
-               } else if (Integer.class.equals(c)) {
-               } else if (Boolean.class.equals(c)) {
-               }
-               sb.append(value);
-       }
-
-       private void indent(StringBuilder sb, int indent) {
-               sb.append("  ".repeat(indent));
-       }
+import jalview.bin.Console;
+
+public class GoogleAnalytics4
+{
+  private static final String JALVIEW_ID = "Jalview Desktop";
+
+  private static final String SESSION_ID = new Random().toString();
+
+  private static final String MEASUREMENT_ID = "G-6TMPHMXEQ0";
+
+  private static final String API_SECRET = "Qb9NSbqkRDqizG6j2BBJ2g";
+
+  // This will generate a different CLIENT_ID each time the application is
+  // launched. Do we want to store it in .jalview_properties?
+  private static final String CLIENT_ID = UUID.randomUUID().toString();
+
+  private static final String BASE_URL = "https://www.google-analytics.com/mp/collect";
+
+  private List<Map.Entry<String, String>> queryStringValues;
+
+  private List<Map.Entry<String, Object>> jsonValues;
+
+  private List<Map.Entry<String, String>> cookieValues;
+
+  public GoogleAnalytics4()
+  {
+    this.reset();
+  }
+
+  public void sendAnalytics()
+  {
+    StringBuilder sb = new StringBuilder();
+    sb.append(BASE_URL);
+    sb.append('?');
+    sb.append(buildQueryString());
+    try
+    {
+      URL url = new URL(sb.toString());
+      URLConnection urlConnection = url.openConnection();
+      HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
+      httpURLConnection.setRequestMethod("POST");
+      httpURLConnection.setDoOutput(true);
+
+      byte[] jsonBytes = buildJson().getBytes(StandardCharsets.UTF_8);
+      int jsonLength = jsonBytes.length;
+
+      httpURLConnection.setFixedLengthStreamingMode(jsonLength);
+      httpURLConnection.setRequestProperty("Content-Type",
+              "application/json; charset=UTF-8");
+      httpURLConnection.connect();
+      try (OutputStream os = httpURLConnection.getOutputStream())
+      {
+        os.write(jsonBytes);
+      }
+
+    } catch (MalformedURLException e)
+    {
+      Console.debug(
+              "Somehow the GoogleAnalytics4 BASE_URL and queryString is malformed.",
+              e);
+      return;
+    } catch (IOException e)
+    {
+      Console.debug("Connection to GoogleAnalytics4 BASE_URL '" + BASE_URL
+              + "' failed.", e);
+    } catch (ClassCastException e)
+    {
+      Console.debug(
+              "Couldn't cast URLConnection to HttpURLConnection in GoogleAnalytics4.",
+              e);
+    }
+
+  }
+
+  private void addToJson(String key, List<Object> values)
+  {
+    jsonValues.add(jsonEntry(key, values));
+  }
+
+  private void addToJson(String key, String value)
+  {
+    jsonValues.add(jsonEntry(key, value));
+  }
+
+  private void addToJson(String key, int value)
+  {
+    jsonValues.add(jsonEntry(key, Integer.valueOf(value)));
+  }
+
+  private void addToJson(String key, boolean value)
+  {
+    jsonValues.add(jsonEntry(key, Boolean.valueOf(value)));
+  }
+
+  private void addQueryStringValue(String key, String value)
+  {
+    queryStringValues.add(qsEntry(key, value));
+  }
+
+  private void addCookieValue(String key, String value)
+  {
+    cookieValues.add(qsEntry(key, value));
+  }
+
+  public void reset()
+  {
+    jsonValues = new ArrayList<>();
+    queryStringValues = new ArrayList<>();
+    cookieValues = new ArrayList<>();
+  }
+
+  private String buildQueryString()
+  {
+    StringBuilder sb = new StringBuilder();
+    for (Map.Entry<String, String> entry : queryStringValues)
+    {
+      if (sb.length() > 0)
+      {
+        sb.append('&');
+      }
+      sb.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8));
+      sb.append('=');
+      sb.append(
+              URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
+    }
+    return sb.toString();
+  }
+
+  private void buildCookieHeaders()
+  {
+    // TODO not needed yet
+  }
+
+  private String buildJson()
+  {
+    StringBuilder sb = new StringBuilder();
+    int indent = 0;
+    sb.append("{");
+    for (Map.Entry<String, Object> entry : jsonValues)
+    {
+
+    }
+    sb.append("}");
+    return sb.toString();
+  }
+
+  private void addJsonObject(StringBuilder sb, int indent,
+          Map.Entry<String, Object> entry)
+  {
+    String key = entry.getKey();
+    Object value = entry.getValue();
+    indent(sb, indent);
+    sb.append('"').append(key).append('"');
+    sb.append(": ");
+    if (List.class.equals(value.getClass()))
+    {
+      sb.append('\n');
+    }
+    addJsonValue(sb, indent, value);
+    sb.append(",\n");
+  }
+
+  private void addJsonValue(StringBuilder sb, int indent, Object value)
+  {
+    if (value == null)
+    {
+      return;
+    }
+    try
+    {
+      Class<? extends Object> c = value.getClass();
+      if (Map.Entry.class.equals(c))
+      {
+        Map.Entry<String, Object> object = (Map.Entry<String, Object>) value;
+        addJsonObject(sb, indent + 1, object);
+      }
+      else if (List.class.equals(c))
+      {
+        indent(sb, indent);
+        sb.append("[\n");
+        for (Object v : (List<Object>) value)
+        {
+          indent(sb, indent + 1);
+          addJsonValue(sb, indent, v);
+          sb.append(",\n");
+        }
+        indent(sb, indent);
+        sb.append("]");
+      }
+      else if (String.class.equals(c))
+      {
+        sb.append('"');
+        sb.append((String) value);
+        sb.append('"');
+      }
+      else if (Integer.class.equals(c))
+      {
+        sb.append(((Integer) value).toString());
+      }
+      else if (Boolean.class.equals(c))
+      {
+        sb.append(((Boolean) value).toString());
+      }
+    } catch (ClassCastException e)
+    {
+      Console.debug(
+              "Could not deal with type of jsonObject " + value.toString(),
+              e);
+    }
+  }
+
+  private void indent(StringBuilder sb, int indent)
+  {
+    sb.append("  ".repeat(indent));
+  }
+
+  private static Map.Entry<String, Object> jsonEntry(String s, Object o)
+  {
+    return new AbstractMap.SimpleEntry<String, Object>(s, o);
+  }
+
+  private static Map.Entry<String, String> qsEntry(String s, String v)
+  {
+    return new AbstractMap.SimpleEntry<String, String>(s, v);
+  }
 }