From 087f95d94f5bd2aff31861f3f9d775317ccaf051 Mon Sep 17 00:00:00 2001 From: Jonathan Almeida Date: Thu, 11 Sep 2014 00:12:22 -0400 Subject: [PATCH 01/37] Incorrect casting of long to double - Fixes #84 --- .../snowplowanalytics/snowplow/tracker/core/Tracker.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java index d7bf38a9..d9636927 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java @@ -93,14 +93,14 @@ public Tracker(Emitter emitter, Subject subject, String namespace, String appId, * @return A completed Payload */ protected Payload completePayload(Payload payload, List context, - double timestamp) { + long timestamp) { payload.add(Parameter.APPID, this.appId); payload.add(Parameter.NAMESPACE, this.namespace); payload.add(Parameter.TRACKER_VERSION, this.trackerVersion); // If timestamp is set to 0, generate one payload.add(Parameter.TIMESTAMP, - (timestamp == 0 ? Util.getTimestamp() : Double.toString(timestamp))); + (timestamp == 0 ? Util.getTimestamp() : Long.toString(timestamp))); // Encodes context data if (context != null) { @@ -176,7 +176,7 @@ public void trackPageView(String pageUrl, String pageTitle, String referrer, * @param timestamp Optional user-provided timestamp for the event */ public void trackPageView(String pageUrl, String pageTitle, String referrer, - double timestamp) { + long timestamp) { trackPageView(pageUrl, pageTitle, referrer, null, timestamp); } @@ -188,7 +188,7 @@ public void trackPageView(String pageUrl, String pageTitle, String referrer, * @param timestamp Optional user-provided timestamp for the event */ public void trackPageView(String pageUrl, String pageTitle, String referrer, - List context, double timestamp) { + List context, long timestamp) { // Precondition checks Preconditions.checkNotNull(pageUrl); Preconditions.checkArgument(!pageUrl.isEmpty(), "pageUrl cannot be empty"); From 43c0374fa4e744c3d0057f98b3113c0666079e91 Mon Sep 17 00:00:00 2001 From: Jonathan Almeida Date: Tue, 11 Nov 2014 15:54:16 -0500 Subject: [PATCH 02/37] Updated CHANGELOG - Version number in build.gradle --- CHANGELOG | 4 ++++ snowplow-java-tracker-core/build.gradle | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 4f8c2d37..72381655 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +Core 0.1.4 (2014-11-xx) +----------------------- +Fixed incorrectly casts timestamp from long to double (#84) + Core 0.1.3 (2014-09-10) ----------------------- Fixed flushBuffer doesn't clear the buffer (#79) diff --git a/snowplow-java-tracker-core/build.gradle b/snowplow-java-tracker-core/build.gradle index 34b534c4..f33a574c 100644 --- a/snowplow-java-tracker-core/build.gradle +++ b/snowplow-java-tracker-core/build.gradle @@ -17,7 +17,7 @@ apply plugin: 'java' apply plugin: 'maven-publish' group = 'com.snowplowanalytics' -version = '0.1.3' +version = '0.1.4' // Where to find the dependencies of our project repositories { From 5de26bca6e5dae8b820a7f156fe407907177e1e6 Mon Sep 17 00:00:00 2001 From: Jonathan Almeida Date: Fri, 14 Nov 2014 22:08:27 -0500 Subject: [PATCH 03/37] Add 'eid' to be generated for each event - Initially, we added the eid to Subject class. When we created a tracking event it would only add an eid if you created a Subject. Along with that, the eid is only generated once and then reused in several events sent - we do not want this. Generating the eid in `completePayload` solves both of these issues for us. - Fixes #95 --- .../snowplowanalytics/snowplow/tracker/core/Subject.java | 6 ------ .../snowplowanalytics/snowplow/tracker/core/Tracker.java | 1 + .../com/snowplowanalytics/snowplow/tracker/SubjectTest.java | 4 ++-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java index 8267fddd..a0e6c104 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java @@ -25,8 +25,6 @@ public class Subject { public Subject() { standardPairs = new HashMap(); - this.setEventId(Util.getEventId()); - // Default Platform this.setPlatform(DevicePlatform.Desktop); @@ -65,10 +63,6 @@ public void setLanguage(String language) { this.standardPairs.put(Parameter.LANGUAGE, language); } - public void setEventId(String eventId) { - this.standardPairs.put(Parameter.EID, eventId); - } - public Map getSubject() { return this.standardPairs; } diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java index d9636927..0aa55155 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java @@ -97,6 +97,7 @@ protected Payload completePayload(Payload payload, List context, payload.add(Parameter.APPID, this.appId); payload.add(Parameter.NAMESPACE, this.namespace); payload.add(Parameter.TRACKER_VERSION, this.trackerVersion); + payload.add(Parameter.EID, Util.getEventId()); // If timestamp is set to 0, generate one payload.add(Parameter.TIMESTAMP, diff --git a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java b/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java index 479ed8e1..1c0c2597 100644 --- a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java +++ b/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java @@ -82,11 +82,11 @@ public void testGetSubject() throws Exception { Subject subject = new Subject(); Map expected = new HashMap(); subject.setTimezone("America/Toronto"); - subject.setEventId("6964d7b6-f25b-45c8-8868-a1574e71ed06"); + subject.setUserId("user1"); expected.put("tz", "America/Toronto"); expected.put("p", "pc"); - expected.put("eid", "6964d7b6-f25b-45c8-8868-a1574e71ed06"); + expected.put("uid", "user1"); assertEquals(expected, subject.getSubject()); } From a5651cca6dab6d4e060174c7516b0aa291cfa16a Mon Sep 17 00:00:00 2001 From: Jonathan Almeida Date: Mon, 17 Nov 2014 01:49:37 -0500 Subject: [PATCH 04/37] Update CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 72381655..214d9b20 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Core 0.1.4 (2014-11-xx) ----------------------- Fixed incorrectly casts timestamp from long to double (#84) +Moved 'eid' from Subject to Tracker class to prevent duplicated event IDs (#95) Core 0.1.3 (2014-09-10) ----------------------- From 7e3b27978105b48f76d3b49387315d81e8a9b03c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ChangZhuo=20Chen=20=28=E9=99=B3=E6=98=8C=E5=80=AC=29?= Date: Sat, 22 Nov 2014 17:08:34 +0800 Subject: [PATCH 05/37] Fix typo --- .../com/snowplowanalytics/snowplow/tracker/core/Tracker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java index d7bf38a9..e8c85261 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java @@ -260,8 +260,8 @@ public void trackStructuredEvent(String category, String action, String label, S Preconditions.checkNotNull(property); Preconditions.checkArgument(!label.isEmpty(), "label cannot be empty"); Preconditions.checkArgument(!property.isEmpty(), "property cannot be empty"); - Preconditions.checkArgument(!category.isEmpty(), "property cannot be empty"); - Preconditions.checkArgument(!action.isEmpty(), "property cannot be empty"); + Preconditions.checkArgument(!category.isEmpty(), "category cannot be empty"); + Preconditions.checkArgument(!action.isEmpty(), "action cannot be empty"); Payload payload = new TrackerPayload(); payload.add(Parameter.EVENT, Constants.EVENT_STRUCTURED); From 2cd45e5d9c7ec1b3fa036357f266cf6b1540105a Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Tue, 25 Nov 2014 15:39:09 +0000 Subject: [PATCH 06/37] Finalized CHANGELOG for Core 0.1.4 --- CHANGELOG | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 214d9b20..8333bd64 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,9 @@ -Core 0.1.4 (2014-11-xx) +Core 0.1.4 (2014-11-25) ----------------------- Fixed incorrectly casts timestamp from long to double (#84) Moved 'eid' from Subject to Tracker class to prevent duplicated event IDs (#95) +Now setting source/targetCompatibility to 1.6, thanks @dstendardi! (#94) +Fixed typos in Tracker preconditions, thanks @czchen! (#99) Core 0.1.3 (2014-09-10) ----------------------- From 458fae9dffd4b343f2896428f4894254778c15ff Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Tue, 25 Nov 2014 16:46:56 +0000 Subject: [PATCH 07/37] Updated auto-generated Version --- .../com/snowplowanalytics/snowplow/tracker/core/Version.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java index 6040b656..3f1b0772 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java @@ -14,6 +14,6 @@ package com.snowplowanalytics.snowplow.tracker.core; public class Version { - static final String TRACKER = "java-core-0.1.3"; - static final String VERSION = "0.1.3"; + static final String TRACKER = "java-core-0.1.4"; + static final String VERSION = "0.1.4"; } From 2e590249ccfb8bd57090338c8a27cf7580cd32a0 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Tue, 25 Nov 2014 17:15:50 +0000 Subject: [PATCH 08/37] Bumped Core version to 0.1.4 (#101) --- CHANGELOG | 4 ++++ build.gradle | 2 +- .../java/com/snowplowanalytics/snowplow/tracker/Version.java | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8333bd64..b9c57898 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +Java 0.5.2 (2014-11-25) +----------------------- +Bumped Core version to 0.1.4 (#101) + Core 0.1.4 (2014-11-25) ----------------------- Fixed incorrectly casts timestamp from long to double (#84) diff --git a/build.gradle b/build.gradle index a7b205af..3b50d72c 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ dependencies { allprojects { apply plugin: 'java' group = 'com.snowplowanalytics' - version = '0.5.1' + version = '0.5.2' sourceCompatibility = '1.6' targetCompatibility = '1.6' repositories { diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java index 4078abd1..2d7c8e54 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java @@ -14,6 +14,6 @@ package com.snowplowanalytics.snowplow.tracker; public class Version { - static final String TRACKER = "java-0.5.1"; - static final String VERSION = "0.5.1"; + static final String TRACKER = "java-0.5.2"; + static final String VERSION = "0.5.2"; } From 7996e414b9004f0b391dfc3832ed60a563fccec3 Mon Sep 17 00:00:00 2001 From: XiaoyiLI Date: Fri, 19 Dec 2014 12:08:11 +0100 Subject: [PATCH 09/37] trackScreenView schema incorrect trackScreenView schema should put "/screen_view/" in stead of "/context/" --- .../com/snowplowanalytics/snowplow/tracker/core/Tracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java index f364bce7..b41cd95b 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java @@ -542,7 +542,7 @@ public void trackScreenView(String name, String id, List context, SchemaPayload payload = new SchemaPayload(); - payload.setSchema( this.baseSchemaPath + "/contexts/" + + payload.setSchema( this.baseSchemaPath + "/screen_view/" + this.schemaTag + "/" + this.schemaVersion); payload.setData(trackerPayload); From 9f0be1047e13c2b2bd302dba278ae0c042249279 Mon Sep 17 00:00:00 2001 From: Hamid Palo Date: Mon, 22 Dec 2014 08:00:08 -0500 Subject: [PATCH 10/37] Remove guava as a dependency. The only thing used from guava was Preconditions.java. With this, that file is copy/pasted and Android consumers are happy to be under the dex limit again. Fixes: https://github.com/snowplow/snowplow-java-tracker/issues/86 --- snowplow-java-tracker-core/build.gradle | 3 - .../snowplow/tracker/core/Tracker.java | 2 +- .../tracker/core/payload/SchemaPayload.java | 3 +- .../tracker/core/util/Preconditions.java | 437 ++++++++++++++++++ 4 files changed, 439 insertions(+), 6 deletions(-) create mode 100644 snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java diff --git a/snowplow-java-tracker-core/build.gradle b/snowplow-java-tracker-core/build.gradle index f33a574c..2e186f93 100644 --- a/snowplow-java-tracker-core/build.gradle +++ b/snowplow-java-tracker-core/build.gradle @@ -42,9 +42,6 @@ dependencies { // Jackson JSON processor compile 'com.fasterxml.jackson.core:jackson-databind:2.4.1.1' - // Contracts - compile 'com.google.guava:guava:17.0' - testCompile 'junit:junit:4.11' } diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java index f364bce7..844f131c 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java @@ -13,11 +13,11 @@ package com.snowplowanalytics.snowplow.tracker.core; -import com.google.common.base.Preconditions; import com.snowplowanalytics.snowplow.tracker.core.emitter.Emitter; import com.snowplowanalytics.snowplow.tracker.core.payload.Payload; import com.snowplowanalytics.snowplow.tracker.core.payload.SchemaPayload; import com.snowplowanalytics.snowplow.tracker.core.payload.TrackerPayload; +import com.snowplowanalytics.snowplow.tracker.core.util.Preconditions; import java.util.HashMap; import java.util.LinkedList; diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java index 2dd085fb..c97edaf2 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java @@ -20,10 +20,9 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.base.Preconditions; import com.snowplowanalytics.snowplow.tracker.core.Parameter; import com.snowplowanalytics.snowplow.tracker.core.Util; - +import com.snowplowanalytics.snowplow.tracker.core.util.Preconditions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java new file mode 100644 index 00000000..bad5245e --- /dev/null +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java @@ -0,0 +1,437 @@ +package com.snowplowanalytics.snowplow.tracker.core.util; + +/** + * Note: + * + * This has been copy/pasted from Guava with modifications to avoid including the whole library. + * Original source: https://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/base/Preconditions.java + */ + +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * Static convenience methods that help a method or constructor check whether it was invoked + * correctly (whether its preconditions have been met). These methods generally accept a + * {@code boolean} expression which is expected to be {@code true} (or in the case of {@code + * checkNotNull}, an object reference which is expected to be non-null). When {@code false} (or + * {@code null}) is passed instead, the {@code Preconditions} method throws an unchecked exception, + * which helps the calling method communicate to its caller that that caller has made + * a mistake. Example:
   {@code
+ *
+ *   /**
+ *    * Returns the positive square root of the given value.
+ *    *
+ *    * @throws IllegalArgumentException if the value is negative
+ *    *}{@code /
+ *   public static double sqrt(double value) {
+ *     Preconditions.checkArgument(value >= 0.0, "negative value: %s", value);
+ *     // calculate the square root
+ *   }
+ *
+ *   void exampleBadCaller() {
+ *     double d = sqrt(-1.0);
+ *   }}
+ * + * In this example, {@code checkArgument} throws an {@code IllegalArgumentException} to indicate + * that {@code exampleBadCaller} made an error in its call to {@code sqrt}. + * + *

Warning about performance

+ * + *

The goal of this class is to improve readability of code, but in some circumstances this may + * come at a significant performance cost. Remember that parameter values for message construction + * must all be computed eagerly, and autoboxing and varargs array creation may happen as well, even + * when the precondition check then succeeds (as it should almost always do in production). In some + * circumstances these wasted CPU cycles and allocations can add up to a real problem. + * Performance-sensitive precondition checks can always be converted to the customary form: + *

   {@code
+ *
+ *   if (value < 0.0) {
+ *     throw new IllegalArgumentException("negative value: " + value);
+ *   }}
+ * + *

Other types of preconditions

+ * + *

Not every type of precondition failure is supported by these methods. Continue to throw + * standard JDK exceptions such as {@link java.util.NoSuchElementException} or {@link + * UnsupportedOperationException} in the situations they are intended for. + * + *

Non-preconditions

+ * + *

It is of course possible to use the methods of this class to check for invalid conditions + * which are not the caller's fault. Doing so is not recommended because it is + * misleading to future readers of the code and of stack traces. See + * Conditional + * failures explained in the Guava User Guide for more advice. + * + *

{@code java.util.Objects.requireNonNull()}

+ * + *

Only {@code %s} is supported

+ * + *

In {@code Preconditions} error message template strings, only the {@code "%s"} specifier is + * supported, not the full range of {@link java.util.Formatter} specifiers. + * + *

More information

+ * + *

See the Guava User Guide on + * using {@code + * Preconditions}. + * + * @author Kevin Bourrillion + * @since 2.0 (imported from Google Collections Library) + */ +public final class Preconditions { + private Preconditions() {} + + /** + * Ensures the truth of an expression involving one or more parameters to the calling method. + * + * @param expression a boolean expression + * @throws IllegalArgumentException if {@code expression} is false + */ + public static void checkArgument(boolean expression) { + if (!expression) { + throw new IllegalArgumentException(); + } + } + + /** + * Ensures the truth of an expression involving one or more parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)} + * @throws IllegalArgumentException if {@code expression} is false + */ + public static void checkArgument(boolean expression, Object errorMessage) { + if (!expression) { + throw new IllegalArgumentException(String.valueOf(errorMessage)); + } + } + + /** + * Ensures the truth of an expression involving one or more parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessageTemplate a template for the exception message should the check fail. The + * message is formed by replacing each {@code %s} placeholder in the template with an + * argument. These are matched by position - the first {@code %s} gets {@code + * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message + * in square braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message template. Arguments + * are converted to strings using {@link String#valueOf(Object)}. + * @throws IllegalArgumentException if {@code expression} is false + * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or + * {@code errorMessageArgs} is null (don't let this happen) + */ + public static void checkArgument(boolean expression, + String errorMessageTemplate, + Object... errorMessageArgs) { + if (!expression) { + throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs)); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @throws IllegalStateException if {@code expression} is false + */ + public static void checkState(boolean expression) { + if (!expression) { + throw new IllegalStateException(); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)} + * @throws IllegalStateException if {@code expression} is false + */ + public static void checkState(boolean expression, Object errorMessage) { + if (!expression) { + throw new IllegalStateException(String.valueOf(errorMessage)); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessageTemplate a template for the exception message should the check fail. The + * message is formed by replacing each {@code %s} placeholder in the template with an + * argument. These are matched by position - the first {@code %s} gets {@code + * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message + * in square braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message template. Arguments + * are converted to strings using {@link String#valueOf(Object)}. + * @throws IllegalStateException if {@code expression} is false + * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or + * {@code errorMessageArgs} is null (don't let this happen) + */ + public static void checkState(boolean expression, + String errorMessageTemplate, + Object... errorMessageArgs) { + if (!expression) { + throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs)); + } + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)} + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference, Object errorMessage) { + if (reference == null) { + throw new NullPointerException(String.valueOf(errorMessage)); + } + return reference; + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @param errorMessageTemplate a template for the exception message should the check fail. The + * message is formed by replacing each {@code %s} placeholder in the template with an + * argument. These are matched by position - the first {@code %s} gets {@code + * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message + * in square braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message template. Arguments + * are converted to strings using {@link String#valueOf(Object)}. + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference, + String errorMessageTemplate, + Object... errorMessageArgs) { + if (reference == null) { + // If either of these parameters is null, the right thing happens anyway + throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs)); + } + return reference; + } + + /* + * All recent hotspots (as of 2009) *really* like to have the natural code + * + * if (guardExpression) { + * throw new BadException(messageExpression); + * } + * + * refactored so that messageExpression is moved to a separate String-returning method. + * + * if (guardExpression) { + * throw new BadException(badMsg(...)); + * } + * + * The alternative natural refactorings into void or Exception-returning methods are much slower. + * This is a big deal - we're talking factors of 2-8 in microbenchmarks, not just 10-20%. (This + * is a hotspot optimizer bug, which should be fixed, but that's a separate, big project). + * + * The coding pattern above is heavily used in java.util, e.g. in ArrayList. There is a + * RangeCheckMicroBenchmark in the JDK that was used to test this. + * + * But the methods in this class want to throw different exceptions, depending on the args, so it + * appears that this pattern is not directly applicable. But we can use the ridiculous, devious + * trick of throwing an exception in the middle of the construction of another exception. Hotspot + * is fine with that. + */ + + /** + * Ensures that {@code index} specifies a valid element in an array, list or string of size + * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. + * + * @param index a user-supplied index identifying an element of an array, list or string + * @param size the size of that array, list or string + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkElementIndex(int index, int size) { + return checkElementIndex(index, size, "index"); + } + + /** + * Ensures that {@code index} specifies a valid element in an array, list or string of size + * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. + * + * @param index a user-supplied index identifying an element of an array, list or string + * @param size the size of that array, list or string + * @param desc the text to use to describe this index in an error message + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkElementIndex( + int index, int size, String desc) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(badElementIndex(index, size, desc)); + } + return index; + } + + private static String badElementIndex(int index, int size, String desc) { + if (index < 0) { + return format("%s (%s) must not be negative", desc, index); + } else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } else { // index >= size + return format("%s (%s) must be less than size (%s)", desc, index, size); + } + } + + /** + * Ensures that {@code index} specifies a valid position in an array, list or string of + * size {@code size}. A position index may range from zero to {@code size}, inclusive. + * + * @param index a user-supplied index identifying a position in an array, list or string + * @param size the size of that array, list or string + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkPositionIndex(int index, int size) { + return checkPositionIndex(index, size, "index"); + } + + /** + * Ensures that {@code index} specifies a valid position in an array, list or string of + * size {@code size}. A position index may range from zero to {@code size}, inclusive. + * + * @param index a user-supplied index identifying a position in an array, list or string + * @param size the size of that array, list or string + * @param desc the text to use to describe this index in an error message + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkPositionIndex(int index, int size, String desc) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc)); + } + return index; + } + + private static String badPositionIndex(int index, int size, String desc) { + if (index < 0) { + return format("%s (%s) must not be negative", desc, index); + } else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } else { // index > size + return format("%s (%s) must not be greater than size (%s)", desc, index, size); + } + } + + /** + * Ensures that {@code start} and {@code end} specify a valid positions in an array, list + * or string of size {@code size}, and are in order. A position index may range from zero to + * {@code size}, inclusive. + * + * @param start a user-supplied index identifying a starting position in an array, list or string + * @param end a user-supplied index identifying a ending position in an array, list or string + * @param size the size of that array, list or string + * @throws IndexOutOfBoundsException if either index is negative or is greater than {@code size}, + * or if {@code end} is less than {@code start} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static void checkPositionIndexes(int start, int end, int size) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (start < 0 || end < start || end > size) { + throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); + } + } + + private static String badPositionIndexes(int start, int end, int size) { + if (start < 0 || start > size) { + return badPositionIndex(start, size, "start index"); + } + if (end < 0 || end > size) { + return badPositionIndex(end, size, "end index"); + } + // end < start + return format("end index (%s) must not be less than start index (%s)", end, start); + } + + /** + * Substitutes each {@code %s} in {@code template} with an argument. These are matched by + * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than + * placeholders, the unmatched arguments will be appended to the end of the formatted message in + * square braces. + * + * @param template a non-null string containing 0 or more {@code %s} placeholders. + * @param args the arguments to be substituted into the message template. Arguments are converted + * to strings using {@link String#valueOf(Object)}. Arguments can be null. + */ + // Note that this is somewhat-improperly used from Verify.java as well. + static String format(String template, Object... args) { + template = String.valueOf(template); // null -> "null" + + // start substituting the arguments into the '%s' placeholders + StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); + int templateStart = 0; + int i = 0; + while (i < args.length) { + int placeholderStart = template.indexOf("%s", templateStart); + if (placeholderStart == -1) { + break; + } + builder.append(template.substring(templateStart, placeholderStart)); + builder.append(args[i++]); + templateStart = placeholderStart + 2; + } + builder.append(template.substring(templateStart)); + + // if we run out of placeholders, append the extra args in square braces + if (i < args.length) { + builder.append(" ["); + builder.append(args[i++]); + while (i < args.length) { + builder.append(", "); + builder.append(args[i++]); + } + builder.append(']'); + } + + return builder.toString(); + } +} \ No newline at end of file From b8c9baab0751a8f732863621b793c6b45e22bbc7 Mon Sep 17 00:00:00 2001 From: Jonathan Almeida Date: Wed, 8 Oct 2014 21:17:14 -0400 Subject: [PATCH 11/37] Replace Map in trackUnstructed to SchemaPayload --- .../snowplow/tracker/core/Tracker.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java index f364bce7..be97f45a 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java @@ -283,7 +283,7 @@ public void trackStructuredEvent(String category, String action, String label, S A "data" field containing the event properties and A "schema" field identifying the schema against which the data is validated */ - public void trackUnstructuredEvent(Map eventData) { + public void trackUnstructuredEvent(SchemaPayload eventData) { trackUnstructuredEvent(eventData, null, 0); } @@ -294,7 +294,7 @@ public void trackUnstructuredEvent(Map eventData) { * A "schema" field identifying the schema against which the data is validated * @param context Custom context for the event */ - public void trackUnstructuredEvent(Map eventData, List context) { + public void trackUnstructuredEvent(SchemaPayload eventData, List context) { trackUnstructuredEvent(eventData, context, 0); } @@ -305,7 +305,7 @@ public void trackUnstructuredEvent(Map eventData, List eventData, long timestamp) { + public void trackUnstructuredEvent(SchemaPayload eventData, long timestamp) { trackUnstructuredEvent(eventData, null, timestamp); } @@ -317,13 +317,13 @@ public void trackUnstructuredEvent(Map eventData, long timestamp * @param context Custom context for the event * @param timestamp Optional user-provided timestamp for the event */ - public void trackUnstructuredEvent(Map eventData, List context, + public void trackUnstructuredEvent(SchemaPayload eventData, List context, long timestamp) { Payload payload = new TrackerPayload(); SchemaPayload envelope = new SchemaPayload(); envelope.setSchema(unstructSchema); - envelope.setData(eventData); + envelope.setData(eventData.getMap()); payload.add(Parameter.EVENT, Constants.EVENT_UNSTRUCTURED); payload.addMap(envelope.getMap(), base64Encoded, @@ -546,6 +546,6 @@ public void trackScreenView(String name, String id, List context, this.schemaTag + "/" + this.schemaVersion); payload.setData(trackerPayload); - trackUnstructuredEvent(payload.getMap(), context, timestamp); + trackUnstructuredEvent(payload, context, timestamp); } } From 9034a8891f235a7c73a31611b6e7e8550f74adb7 Mon Sep 17 00:00:00 2001 From: Jonathan Almeida Date: Wed, 8 Oct 2014 21:18:02 -0400 Subject: [PATCH 12/37] Added deprecated on SchemaPayload 'add' methods --- .../snowplow/tracker/core/payload/SchemaPayload.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java index 2dd085fb..3603c3e5 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java @@ -80,6 +80,7 @@ public SchemaPayload setData(Object data) { return this; } + @Deprecated @Override public void add(String key, String value) { /* @@ -89,6 +90,7 @@ public void add(String key, String value) { logger.debug("add(String, String) method called: Doing nothing."); } + @Deprecated @Override public void add(String key, Object value) { /* @@ -98,6 +100,7 @@ public void add(String key, Object value) { logger.debug("add(String, Object) method called: Doing nothing."); } + @Deprecated @Override public void addMap(Map map) { /* @@ -107,6 +110,7 @@ public void addMap(Map map) { logger.debug("addMap(Map) method called: Doing nothing."); } + @Deprecated @Override public void addMap(Map map, Boolean base64_encoded, String type_encoded, String type_no_encoded) { From 4ba92bb7bd8d7a2cac3ea7a8d6caafc735208d3e Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Thu, 25 Dec 2014 19:15:44 +0200 Subject: [PATCH 13/37] Prepped for Core 0.2.0 release --- CHANGELOG | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index b9c57898..7a5e55fd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,11 @@ +Core 0.2.0 (2014-12-XX) +----------------------- +Fixed incorrect schema for trackScreenView, thanks @lixiaoyi! (#104) +Removed Guava as a dependency, thanks @hamidp! (#105) +Made eventData a SchemaPayload in trackUnstructuredEvent, thanks @jonalmeida! (#76) +Added @Deprecated on the SchemaPayload methods not used, thanks @jonalmeida! (#85) +Moved platform setting out of Subject into Tracker (#103) + Java 0.5.2 (2014-11-25) ----------------------- Bumped Core version to 0.1.4 (#101) From d74f9cdd0945d918ff74f37a89c4a9ca4d2d90e4 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Thu, 25 Dec 2014 21:15:02 +0200 Subject: [PATCH 14/37] Updated CHANGELOG to include Vagrant work --- CHANGELOG | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 7a5e55fd..f75478e5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,14 @@ +Java 0.6.0 (2014-12-XX) +----------------------- +Bumped Core version to 0.2.0 (#108) +Added dedicated Vagrant setup (#106) + Core 0.2.0 (2014-12-XX) ----------------------- Fixed incorrect schema for trackScreenView, thanks @lixiaoyi! (#104) Removed Guava as a dependency, thanks @hamidp! (#105) Made eventData a SchemaPayload in trackUnstructuredEvent, thanks @jonalmeida! (#76) -Added @Deprecated on the SchemaPayload methods not used, thanks @jonalmeida! (#85) +Added @Deprecated on the unused SchemaPayload methods, thanks @jonalmeida! (#85) Moved platform setting out of Subject into Tracker (#103) Java 0.5.2 (2014-11-25) From 7b3863ad8c783086dd1747a8d1991bf936601ad7 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Thu, 25 Dec 2014 11:55:05 +0200 Subject: [PATCH 15/37] Added dedicated Vagrant setup (closes #106) --- .gitignore | 4 ++++ Vagrantfile | 24 +++++++++++++++++++++ vagrant/.gitignore | 8 +++++++ vagrant/ansible.hosts | 2 ++ vagrant/peru.yaml | 14 ++++++++++++ vagrant/push.bash | 4 ++++ vagrant/up.bash | 50 +++++++++++++++++++++++++++++++++++++++++++ vagrant/up.guidance | 3 +++ vagrant/up.playbooks | 2 ++ 9 files changed, 111 insertions(+) create mode 100644 Vagrantfile create mode 100644 vagrant/.gitignore create mode 100644 vagrant/ansible.hosts create mode 100644 vagrant/peru.yaml create mode 100755 vagrant/push.bash create mode 100755 vagrant/up.bash create mode 100644 vagrant/up.guidance create mode 100644 vagrant/up.playbooks diff --git a/.gitignore b/.gitignore index c3017731..55b41818 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,7 @@ local.properties # Ignoring Version.java since its auto-generated #Version.java + +# Vagrant +.vagrant + diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 00000000..7cf18f20 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,24 @@ +Vagrant.configure("2") do |config| + + config.vm.box = "ubuntu/trusty64" + config.vm.hostname = "snowplow-java-tracker" + config.ssh.forward_agent = true + + config.vm.provider :virtualbox do |vb| + vb.name = Dir.pwd().split("/")[-1] + "-" + Time.now.to_f.to_i.to_s + vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] + vb.customize [ "guestproperty", "set", :id, "--timesync-threshold", 10000 ] + # Need a bit of memory for Java + vb.memory = 2560 + end + + config.vm.provision :shell do |sh| + sh.path = "vagrant/up.bash" + end + + # Requires Vagrant 1.7.0+ + config.push.define "binary", strategy: "local-exec" do |push| + push.script = "vagrant/push.bash" + end + +end diff --git a/vagrant/.gitignore b/vagrant/.gitignore new file mode 100644 index 00000000..d0e94a5b --- /dev/null +++ b/vagrant/.gitignore @@ -0,0 +1,8 @@ +* +!.gitignore +!peru.yaml +!ansible.hosts +!up.bash +!up.playbooks +!up.guidance +!push.bash diff --git a/vagrant/ansible.hosts b/vagrant/ansible.hosts new file mode 100644 index 00000000..588fa08c --- /dev/null +++ b/vagrant/ansible.hosts @@ -0,0 +1,2 @@ +[vagrant] +127.0.0.1:2222 diff --git a/vagrant/peru.yaml b/vagrant/peru.yaml new file mode 100644 index 00000000..053f6b0b --- /dev/null +++ b/vagrant/peru.yaml @@ -0,0 +1,14 @@ +imports: + ansible: ansible + ansible_playbooks: oss-playbooks + +curl module ansible: + # Equivalent of git cloning tags/v1.6.6 but much, much faster + url: https://codeload.github.com/ansible/ansible/zip/69d85c22c7475ccf8169b6ec9dee3ee28c92a314 + build: unzip ansible-69d85c22c7475ccf8169b6ec9dee3ee28c92a314.zip + export: ansible-69d85c22c7475ccf8169b6ec9dee3ee28c92a314 + +git module ansible_playbooks: + url: https://github.com/snowplow/ansible-playbooks.git + # Comment out to fetch a specific rev instead of master: + # rev: xxx diff --git a/vagrant/push.bash b/vagrant/push.bash new file mode 100755 index 00000000..df2ec16a --- /dev/null +++ b/vagrant/push.bash @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +echo "Not yet implemented, see https://github.com/snowplow/snowplow-java-tracker/issues/107" diff --git a/vagrant/up.bash b/vagrant/up.bash new file mode 100755 index 00000000..7450ae89 --- /dev/null +++ b/vagrant/up.bash @@ -0,0 +1,50 @@ +#!/bin/bash +set -e + +vagrant_dir=/vagrant/vagrant +bashrc=/home/vagrant/.bashrc + +echo "========================================" +echo "INSTALLING PERU AND ANSIBLE DEPENDENCIES" +echo "----------------------------------------" +apt-get update +apt-get install -y language-pack-en git unzip libyaml-dev python3-pip python-yaml python-paramiko python-jinja2 + +echo "===============" +echo "INSTALLING PERU" +echo "---------------" +sudo pip3 install peru + +echo "=======================================" +echo "CLONING ANSIBLE AND PLAYBOOKS WITH PERU" +echo "---------------------------------------" +cd ${vagrant_dir} && peru sync -v +echo "... done" + +env_setup=${vagrant_dir}/ansible/hacking/env-setup +hosts=${vagrant_dir}/ansible.hosts + +echo "===================" +echo "CONFIGURING ANSIBLE" +echo "-------------------" +touch ${bashrc} +echo "source ${env_setup}" >> ${bashrc} +echo "export ANSIBLE_HOSTS=${hosts}" >> ${bashrc} +echo "... done" + +echo "==========================================" +echo "RUNNING PLAYBOOKS WITH ANSIBLE*" +echo "* no output while each playbook is running" +echo "------------------------------------------" +while read pb; do + su - -c "source ${env_setup} && ${vagrant_dir}/ansible/bin/ansible-playbook ${vagrant_dir}/${pb} --connection=local --inventory-file=${hosts}" vagrant +done <${vagrant_dir}/up.playbooks + +guidance=${vagrant_dir}/up.guidance + +if [ -f ${guidance} ]; then + echo "===========" + echo "PLEASE READ" + echo "-----------" + cat $guidance +fi diff --git a/vagrant/up.guidance b/vagrant/up.guidance new file mode 100644 index 00000000..0575dbc6 --- /dev/null +++ b/vagrant/up.guidance @@ -0,0 +1,3 @@ +To get started: +vagrant ssh +cd /vagrant diff --git a/vagrant/up.playbooks b/vagrant/up.playbooks new file mode 100644 index 00000000..82d63689 --- /dev/null +++ b/vagrant/up.playbooks @@ -0,0 +1,2 @@ +oss-playbooks/java6.yml +oss-playbooks/gradle.yml From c78c078225891fa4ac155b6167caf45571767333 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Thu, 25 Dec 2014 23:50:54 +0200 Subject: [PATCH 16/37] Updated guidance message --- vagrant/up.guidance | 1 + 1 file changed, 1 insertion(+) diff --git a/vagrant/up.guidance b/vagrant/up.guidance index 0575dbc6..c359beac 100644 --- a/vagrant/up.guidance +++ b/vagrant/up.guidance @@ -1,3 +1,4 @@ To get started: vagrant ssh cd /vagrant +gradle test From 410314e3ba3d1d7897d8c9d2d89583f6a8be9f04 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Thu, 25 Dec 2014 23:51:06 +0200 Subject: [PATCH 17/37] Moved platform setting out of Subject into Tracker (#103) --- .../snowplow/tracker/core/Subject.java | 7 ------- .../snowplow/tracker/core/Tracker.java | 16 ++++++++++++++-- .../snowplow/tracker/SubjectTest.java | 17 ----------------- .../snowplow/tracker/TrackerTest.java | 18 ++++++++++++++++++ 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java index a0e6c104..e1e6c243 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java @@ -25,18 +25,11 @@ public class Subject { public Subject() { standardPairs = new HashMap(); - // Default Platform - this.setPlatform(DevicePlatform.Desktop); - // Default Timezone TimeZone tz = Calendar.getInstance().getTimeZone(); this.setTimezone(tz.getID()); } - public void setPlatform(DevicePlatform platform) { - this.standardPairs.put(Parameter.PLATFORM, platform.toString()); - } - public void setUserId(String userId) { this.standardPairs.put(Parameter.UID, userId); } diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java index 8ad922d4..ea46c78e 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java @@ -28,6 +28,7 @@ public class Tracker { private boolean base64Encoded = true; private Emitter emitter; + private DevicePlatform platform; private String appId; private String namespace; private String contextSchema; @@ -82,6 +83,8 @@ public Tracker(Emitter emitter, Subject subject, String namespace, String appId, this.namespace = namespace; this.subject = subject; this.trackerVersion = Version.TRACKER; + this.platform = DevicePlatform.Desktop; + this.setSchema(Constants.DEFAULT_IGLU_VENDOR, Constants.DEFAULT_SCHEMA_TAG, Constants.DEFAULT_SCHEMA_VERSION); } @@ -94,6 +97,7 @@ public Tracker(Emitter emitter, Subject subject, String namespace, String appId, */ protected Payload completePayload(Payload payload, List context, long timestamp) { + payload.add(Parameter.PLATFORM, this.platform.toString()); payload.add(Parameter.APPID, this.appId); payload.add(Parameter.NAMESPACE, this.namespace); payload.add(Parameter.TRACKER_VERSION, this.trackerVersion); @@ -124,6 +128,14 @@ protected Payload completePayload(Payload payload, List context, return payload; } + public void setPlatform(DevicePlatform platform) { + this.platform = platform; + } + + public DevicePlatform getPlatform() { + return this.platform; + } + protected void setTrackerVersion(String version) { this.trackerVersion = version; } @@ -280,8 +292,8 @@ public void trackStructuredEvent(String category, String action, String label, S /** * * @param eventData The properties of the event. Has two field: - A "data" field containing the event properties and - A "schema" field identifying the schema against which the data is validated + * A "data" field containing the event properties and + * A "schema" field identifying the schema against which the data is validated */ public void trackUnstructuredEvent(SchemaPayload eventData) { trackUnstructuredEvent(eventData, null, 0); diff --git a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java b/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java index 1c0c2597..1679fa71 100644 --- a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java +++ b/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java @@ -12,21 +12,6 @@ public class SubjectTest extends TestCase { - @Test - public void testSetPlatform() throws Exception { - Subject subject = new Subject(); - subject.getSubject().get("p"); - assertEquals("pc", subject.getSubject().get("p")); - } - - @Test - public void testSetPlatform2() throws Exception { - Subject subject = new Subject(); - subject.setPlatform(DevicePlatform.ConnectedTV); - subject.getSubject().get("p"); - assertEquals("tv", subject.getSubject().get("p")); - } - @Test public void testSetUserId() throws Exception { Subject subject = new Subject(); @@ -46,7 +31,6 @@ public void testSetViewPort() throws Exception { Subject subject = new Subject(); subject.setViewPort(150, 100); assertEquals("150x100", subject.getSubject().get("vp")); - } @Test @@ -85,7 +69,6 @@ public void testGetSubject() throws Exception { subject.setUserId("user1"); expected.put("tz", "America/Toronto"); - expected.put("p", "pc"); expected.put("uid", "user1"); assertEquals(expected, subject.getSubject()); diff --git a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java b/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java index d58f6c26..db09953e 100644 --- a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java +++ b/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java @@ -2,6 +2,7 @@ import com.snowplowanalytics.snowplow.tracker.core.Subject; import com.snowplowanalytics.snowplow.tracker.core.Tracker; +import com.snowplowanalytics.snowplow.tracker.core.DevicePlatform; import com.snowplowanalytics.snowplow.tracker.core.TransactionItem; import com.snowplowanalytics.snowplow.tracker.core.emitter.BufferOption; import com.snowplowanalytics.snowplow.tracker.core.emitter.Emitter; @@ -23,6 +24,23 @@ public class TrackerTest extends TestCase { // private static String testURL = "segfault.ngrok.com"; private static String testURL = "d3rkrsqld9gmqf.cloudfront.net"; + @Test + public void testDefaultPlatform() throws Exception { + Emitter emitter = new Emitter(testURL, HttpMethod.POST); + Subject subject = new Subject(); + Tracker tracker = new Tracker(emitter, subject, "AF003", "cloudfront", false); + assertEquals(DevicePlatform.Desktop, tracker.getPlatform()); + } + + @Test + public void testSetPlatform() throws Exception { + Emitter emitter = new Emitter(testURL, HttpMethod.POST); + Subject subject = new Subject(); + Tracker tracker = new Tracker(emitter, subject, "AF003", "cloudfront", false); + tracker.setPlatform(DevicePlatform.ConnectedTV); + assertEquals(DevicePlatform.ConnectedTV, tracker.getPlatform()); + } + @Test public void testSetSchema() throws Exception { From afe03ca30567d39f874052fe4fbbd532ff9c1501 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Fri, 26 Dec 2014 00:16:37 +0200 Subject: [PATCH 18/37] Made setSubject method on Tracker public (closes #109) --- CHANGELOG | 1 + .../snowplow/tracker/core/Tracker.java | 6 +++++- .../snowplow/tracker/TrackerTest.java | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index f75478e5..0e82afc2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ Removed Guava as a dependency, thanks @hamidp! (#105) Made eventData a SchemaPayload in trackUnstructuredEvent, thanks @jonalmeida! (#76) Added @Deprecated on the unused SchemaPayload methods, thanks @jonalmeida! (#85) Moved platform setting out of Subject into Tracker (#103) +Made setSubject method on Tracker public (#109) Java 0.5.2 (2014-11-25) ----------------------- diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java index ea46c78e..b7ab44af 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java @@ -144,10 +144,14 @@ private void addTrackerPayload(Payload payload) { this.emitter.addToBuffer(payload); } - private void setSubject(Subject subject) { + public void setSubject(Subject subject) { this.subject = subject; } + public Subject getSubject() { + return this.subject; + } + /** * Sets the JSON schema to be used mainly for self-describing JSON. * @param vendor Schema vendor diff --git a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java b/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java index db09953e..1c4336e4 100644 --- a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java +++ b/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java @@ -41,6 +41,20 @@ public void testSetPlatform() throws Exception { assertEquals(DevicePlatform.ConnectedTV, tracker.getPlatform()); } + @Test + public void testSetSubject() throws Exception { + Emitter emitter = new Emitter(testURL, HttpMethod.POST); + Subject s1 = new Subject(); + Tracker tracker = new Tracker(emitter, s1, "AF003", "cloudfront", false); + Subject s2 = new Subject(); + s2.setColorDepth(24); + tracker.setSubject(s2); + Map subjectPairs = new HashMap(); + subjectPairs.put("tz", "Etc/UTC"); + subjectPairs.put("cd", "24"); + assertEquals(subjectPairs, tracker.getSubject().getSubject()); + } + @Test public void testSetSchema() throws Exception { From cab4c2defe8d53c5630fb42384d74631d076d4ac Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Fri, 26 Dec 2014 00:37:16 +0200 Subject: [PATCH 19/37] Tidied up approach to schema constants in Tracker (closes #110) --- CHANGELOG | 1 + .../snowplow/tracker/core/Constants.java | 10 ++++--- .../snowplow/tracker/core/Tracker.java | 30 ++----------------- .../snowplow/tracker/core/Version.java | 5 ++-- .../tracker/core/emitter/Emitter.java | 2 +- .../snowplow/tracker/Version.java | 5 ++-- 6 files changed, 17 insertions(+), 36 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0e82afc2..5510af69 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,7 @@ Made eventData a SchemaPayload in trackUnstructuredEvent, thanks @jonalmeida! (# Added @Deprecated on the unused SchemaPayload methods, thanks @jonalmeida! (#85) Moved platform setting out of Subject into Tracker (#103) Made setSubject method on Tracker public (#109) +Tidied up approach to schema constants in Tracker (#110) Java 0.5.2 (2014-11-25) ----------------------- diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java index 2458f5a7..42378d50 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java @@ -14,11 +14,13 @@ package com.snowplowanalytics.snowplow.tracker.core; public class Constants { - public static final String DEFAULT_VENDOR = "com.snowplowanalytics.snowplow"; - public static final String DEFAULT_IGLU_VENDOR = "iglu:com.snowplowanalytics.snowplow"; - public static final String DEFAULT_SCHEMA_TAG = "jsonschema"; - public static final String DEFAULT_SCHEMA_VERSION = "1-0-0"; + public static final String PROTOCOL_VENDOR = "com.snowplowanalytics.snowplow"; + public static final String PROTOCOL_VERSION = "tp2"; // Tracker Protocol v2 + public static final String SCHEMA_PAYLOAD_DATA = "iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-0"; + public static final String SCHEMA_CONTEXTS = "iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0"; + public static final String SCHEMA_UNSTRUCT_EVENT = "iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0"; + public static final String SCHEMA_SCREEN_VIEW = "iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0"; public static final String EVENT_PAGE_VIEW = "pv"; public static final String EVENT_STRUCTURED = "se"; diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java index b7ab44af..8c522448 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java @@ -31,12 +31,7 @@ public class Tracker { private DevicePlatform platform; private String appId; private String namespace; - private String contextSchema; - private String baseSchemaPath; - private String schemaTag; - private String schemaVersion; private String trackerVersion; - private String unstructSchema; private Subject subject; /** @@ -84,9 +79,6 @@ public Tracker(Emitter emitter, Subject subject, String namespace, String appId, this.subject = subject; this.trackerVersion = Version.TRACKER; this.platform = DevicePlatform.Desktop; - - this.setSchema(Constants.DEFAULT_IGLU_VENDOR, Constants.DEFAULT_SCHEMA_TAG, - Constants.DEFAULT_SCHEMA_VERSION); } /** @@ -110,7 +102,7 @@ protected Payload completePayload(Payload payload, List context, // Encodes context data if (context != null) { SchemaPayload envelope = new SchemaPayload(); - envelope.setSchema(contextSchema); + envelope.setSchema(Constants.SCHEMA_CONTEXTS); // We can do better here, rather than re-iterate through the list List contextDataList = new LinkedList(); @@ -152,20 +144,6 @@ public Subject getSubject() { return this.subject; } - /** - * Sets the JSON schema to be used mainly for self-describing JSON. - * @param vendor Schema vendor - * @param schemaTag Schema tag type - * @param version Schema version tag - */ - public void setSchema(String vendor, String schemaTag, String version) { - this.contextSchema = vendor + "/contexts/" + schemaTag + "/" + version; - this.unstructSchema = vendor + "/unstruct_event/" + schemaTag + "/" + version; - this.baseSchemaPath = vendor; - this.schemaTag = schemaTag; - this.schemaVersion = version; - } - /** * @param pageUrl URL of the viewed page * @param pageTitle Title of the viewed page @@ -338,7 +316,7 @@ public void trackUnstructuredEvent(SchemaPayload eventData, List Payload payload = new TrackerPayload(); SchemaPayload envelope = new SchemaPayload(); - envelope.setSchema(unstructSchema); + envelope.setSchema(Constants.SCHEMA_UNSTRUCT_EVENT); envelope.setData(eventData.getMap()); payload.add(Parameter.EVENT, Constants.EVENT_UNSTRUCTURED); @@ -557,9 +535,7 @@ public void trackScreenView(String name, String id, List context, trackerPayload.add(Parameter.SV_ID, id); SchemaPayload payload = new SchemaPayload(); - - payload.setSchema( this.baseSchemaPath + "/screen_view/" + - this.schemaTag + "/" + this.schemaVersion); + payload.setSchema(Constants.SCHEMA_SCREEN_VIEW); payload.setData(trackerPayload); trackUnstructuredEvent(payload, context, timestamp); diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java index 3f1b0772..6ebed462 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java @@ -13,7 +13,8 @@ package com.snowplowanalytics.snowplow.tracker.core; +// DO NOT EDIT. AUTO-GENERATED. public class Version { - static final String TRACKER = "java-core-0.1.4"; - static final String VERSION = "0.1.4"; + static final String TRACKER = "java-core-0.2.0"; + static final String VERSION = "0.2.0"; } diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java index 2d43cbd7..99da104c 100644 --- a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java +++ b/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java @@ -103,7 +103,7 @@ public Emitter(String URI, HttpMethod httpMethod, RequestCallback callback) { uri = new URIBuilder() .setScheme("http") .setHost(URI) - .setPath("/" + Constants.DEFAULT_VENDOR + "/tp2"); + .setPath("/" + Constants.PROTOCOL_VENDOR + "/" + Constants.PROTOCOL_VERSION); } this.requestCallback = callback; this.httpMethod = httpMethod; diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java index 2d7c8e54..caa7be1b 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java @@ -13,7 +13,8 @@ package com.snowplowanalytics.snowplow.tracker; +// DO NOT EDIT. AUTO-GENERATED. public class Version { - static final String TRACKER = "java-0.5.2"; - static final String VERSION = "0.5.2"; + static final String TRACKER = "java-0.6.0"; + static final String VERSION = "0.6.0"; } From 5a98d05fe7fb5997b7659b7a20cc80872665c658 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Fri, 26 Dec 2014 00:48:34 +0200 Subject: [PATCH 20/37] Added Quickstart section to README (closes #111) --- CHANGELOG | 1 + README.md | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5510af69..fe96b908 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Java 0.6.0 (2014-12-XX) ----------------------- Bumped Core version to 0.2.0 (#108) +Added Quickstart section to README (#111) Added dedicated Vagrant setup (#106) Core 0.2.0 (2014-12-XX) diff --git a/README.md b/README.md index 05f6d37b..4d8808d2 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,22 @@ ## Overview -Add analytics to your Java software with the **[Snowplow] [snowplow]** event tracker for **[Java] [java]** (Android support is coming soon). +Add analytics to your Java software with the **[Snowplow] [snowplow]** event tracker for **[Java] [java]**. See also: **[Snowplow Android Tracker] [snowplow-android-tracker]**. With this tracker you can collect event data from your Java-based desktop and server apps, servlets and games. Supports JDK6+. +## Quickstart + +Assuming git, **[Vagrant] [vagrant-install]** and **[VirtualBox] [virtualbox-install]** installed: + +```bash + host$ git clone https://github.com/snowplow/snowplow-java-tracker.git + host$ cd snowplow-java-tracker + host$ vagrant up && vagrant ssh +guest$ cd /vagrant +guest$ gradle test +``` + ## Find out more | Technical Docs | Setup Guide | Roadmap | Contributing | @@ -17,7 +29,7 @@ With this tracker you can collect event data from your Java-based desktop and se ## Copyright and license -The Snowplow Java Tracker is copyright 2014 Snowplow Analytics Ltd. +The Snowplow Java Tracker is copyright 2014-2015 Snowplow Analytics Ltd. Licensed under the **[Apache License, Version 2.0] [license]** (the "License"); you may not use this software except in compliance with the License. @@ -31,9 +43,10 @@ limitations under the License. [java]: http://www.java.com/en/ [snowplow]: http://snowplowanalytics.com +[snowplow-android-tracker]: https://github.com/snowplow/snowplow-android-tracker/ -[dependencies]: https://drive.google.com/folderview?id=0B9v7AAtH8DSpWWZ1c3RUZjU3WlU&usp=sharing -[documentation]: https://gleasonk.github.io/Saggezza/JavaDoc/index.html +[vagrant-install]: http://docs.vagrantup.com/v2/installation/index.html +[virtualbox-install]: https://www.virtualbox.org/wiki/Downloads [techdocs-image]: https://d3i6fms1cm1j0i.cloudfront.net/github/images/techdocs.png [setup-image]: https://d3i6fms1cm1j0i.cloudfront.net/github/images/setup.png From 4ec0bd9b85074ac1e6149cd48fc8ec870c9d92bb Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Fri, 26 Dec 2014 17:44:34 +0200 Subject: [PATCH 21/37] Added warning that Version.java is auto-generated (closes #112) --- CHANGELOG | 1 + build.gradle | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index fe96b908..7ef2d7e7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ Java 0.6.0 (2014-12-XX) Bumped Core version to 0.2.0 (#108) Added Quickstart section to README (#111) Added dedicated Vagrant setup (#106) +Added warning that Version.java is auto-generated (#112) Core 0.2.0 (2014-12-XX) ----------------------- diff --git a/build.gradle b/build.gradle index 3b50d72c..3a545e45 100644 --- a/build.gradle +++ b/build.gradle @@ -91,6 +91,7 @@ task generateSources { package com.snowplowanalytics.snowplow.tracker; +// DO NOT EDIT. AUTO-GENERATED. public class Version { static final String TRACKER = "java-$project.version"; static final String VERSION = "$project.version"; From 92ea033147948592965d2b209a83a18202b8b4f5 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Fri, 26 Dec 2014 17:47:57 +0200 Subject: [PATCH 22/37] Added warning that Version.java is auto-generated (closes #113) --- CHANGELOG | 1 + snowplow-java-tracker-core/build.gradle | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7ef2d7e7..4405ad10 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,7 @@ Added @Deprecated on the unused SchemaPayload methods, thanks @jonalmeida! (#85) Moved platform setting out of Subject into Tracker (#103) Made setSubject method on Tracker public (#109) Tidied up approach to schema constants in Tracker (#110) +Added warning that Version.java is auto-generated (#113) Java 0.5.2 (2014-11-25) ----------------------- diff --git a/snowplow-java-tracker-core/build.gradle b/snowplow-java-tracker-core/build.gradle index 2e186f93..1b1c5a7d 100644 --- a/snowplow-java-tracker-core/build.gradle +++ b/snowplow-java-tracker-core/build.gradle @@ -89,6 +89,7 @@ task generateSources { package com.snowplowanalytics.snowplow.tracker.core; +// DO NOT EDIT. AUTO-GENERATED. public class Version { static final String TRACKER = "java-core-$project.version"; static final String VERSION = "$project.version"; From c8ce749043d2ab4a6d34c224627ba9abf0d87cd2 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Fri, 26 Dec 2014 17:50:34 +0200 Subject: [PATCH 23/37] Incremented versions --- build.gradle | 2 +- snowplow-java-tracker-core/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 3a545e45..82012c0a 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ dependencies { allprojects { apply plugin: 'java' group = 'com.snowplowanalytics' - version = '0.5.2' + version = '0.6.0' sourceCompatibility = '1.6' targetCompatibility = '1.6' repositories { diff --git a/snowplow-java-tracker-core/build.gradle b/snowplow-java-tracker-core/build.gradle index 1b1c5a7d..6b0b567e 100644 --- a/snowplow-java-tracker-core/build.gradle +++ b/snowplow-java-tracker-core/build.gradle @@ -17,7 +17,7 @@ apply plugin: 'java' apply plugin: 'maven-publish' group = 'com.snowplowanalytics' -version = '0.1.4' +version = '0.2.0' // Where to find the dependencies of our project repositories { From f7a5610fa9433babb2acebd6a6776a16e788d730 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 27 Dec 2014 14:30:45 +0200 Subject: [PATCH 24/37] Finalized release dates --- CHANGELOG | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 4405ad10..f9fc7383 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,11 +1,11 @@ -Java 0.6.0 (2014-12-XX) +Java 0.6.0 (2014-12-27) ----------------------- Bumped Core version to 0.2.0 (#108) Added Quickstart section to README (#111) Added dedicated Vagrant setup (#106) Added warning that Version.java is auto-generated (#112) -Core 0.2.0 (2014-12-XX) +Core 0.2.0 (2014-12-27) ----------------------- Fixed incorrect schema for trackScreenView, thanks @lixiaoyi! (#104) Removed Guava as a dependency, thanks @hamidp! (#105) From 07935c366348fd6695eaef4d43cdfa05cd4f9932 Mon Sep 17 00:00:00 2001 From: David Stendardi Date: Tue, 6 Jan 2015 13:21:15 +0100 Subject: [PATCH 25/37] [layout] merge modules --- build.gradle | 52 +++--- settings.gradle | 15 -- snowplow-java-tracker-core/build.gradle | 102 ----------- .../gradle/wrapper/gradle-wrapper.properties | 6 - snowplow-java-tracker-core/gradlew | 164 ------------------ snowplow-java-tracker-core/gradlew.bat | 90 ---------- .../snowplow/tracker/core/Base64.java | 0 .../snowplow/tracker/core/Constants.java | 0 .../snowplow/tracker/core/DevicePlatform.java | 0 .../snowplow/tracker/core/Parameter.java | 0 .../snowplow/tracker/core/Subject.java | 0 .../snowplow/tracker/core/Tracker.java | 0 .../tracker/core/TransactionItem.java | 0 .../snowplow/tracker/core/Util.java | 0 .../snowplow/tracker/core/Version.java | 0 .../tracker/core/emitter/BufferOption.java | 0 .../tracker/core/emitter/Emitter.java | 0 .../tracker/core/emitter/HttpMethod.java | 0 .../tracker/core/emitter/RequestCallback.java | 0 .../tracker/core/emitter/RequestMethod.java | 0 .../tracker/core/payload/Payload.java | 0 .../tracker/core/payload/SchemaPayload.java | 0 .../tracker/core/payload/TrackerPayload.java | 0 .../tracker/core/util/Preconditions.java | 0 .../snowplow/tracker/EmitterTest.java | 12 +- .../snowplow/tracker/SubjectTest.java | 8 +- .../snowplow/tracker/TrackerPayloadTest.java | 5 +- .../snowplow/tracker/TrackerTest.java | 30 ++-- .../snowplow/tracker/UtilTest.java | 7 +- 29 files changed, 51 insertions(+), 440 deletions(-) delete mode 100644 settings.gradle delete mode 100644 snowplow-java-tracker-core/build.gradle delete mode 100644 snowplow-java-tracker-core/gradle/wrapper/gradle-wrapper.properties delete mode 100755 snowplow-java-tracker-core/gradlew delete mode 100644 snowplow-java-tracker-core/gradlew.bat rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/Base64.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/DevicePlatform.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/Parameter.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/TransactionItem.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/Util.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/BufferOption.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/HttpMethod.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestCallback.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestMethod.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/Payload.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/TrackerPayload.java (100%) rename {snowplow-java-tracker-core/src => src}/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java (100%) rename {snowplow-java-tracker-core/src => src}/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java (87%) rename {snowplow-java-tracker-core/src => src}/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java (93%) rename {snowplow-java-tracker-core/src => src}/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java (98%) rename {snowplow-java-tracker-core/src => src}/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java (89%) rename {snowplow-java-tracker-core/src => src}/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java (90%) diff --git a/build.gradle b/build.gradle index 82012c0a..b8abacf3 100644 --- a/build.gradle +++ b/build.gradle @@ -11,28 +11,38 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -// Applying the java plugin to add support for Java apply plugin: 'java' -// As per http://www.gradle.org/docs/current/userguide/publishing_maven.html apply plugin: 'maven-publish' - +apply plugin: 'idea' apply plugin: 'war' -dependencies { - compile project(':snowplow-java-tracker-core') - runtime project(':snowplow-java-tracker-core') + +group = 'com.snowplowanalytics' +version = '0.6.0' +sourceCompatibility = '1.6' +targetCompatibility = '1.6' +repositories { + // Use 'maven central' for resolving our dependencies + mavenCentral() } -allprojects { - apply plugin: 'java' - group = 'com.snowplowanalytics' - version = '0.6.0' - sourceCompatibility = '1.6' - targetCompatibility = '1.6' - repositories { - // Use 'maven central' for resolving our dependencies - mavenCentral() - } +dependencies { + + // Apache Commons + compile 'commons-codec:commons-codec:1.2' + compile 'commons-net:commons-net:3.3' + + // Apache HTTP + compile 'org.apache.httpcomponents:httpclient:4.3.3' + compile 'org.apache.httpcomponents:httpasyncclient:4.0.1' + + // SLF4J logging API + compile 'org.slf4j:slf4j-simple:1.7.7' + + // Jackson JSON processor + compile 'com.fasterxml.jackson.core:jackson-databind:2.4.1.1' + + testCompile 'junit:junit:4.11' } @@ -58,16 +68,6 @@ publishing { } } -task testAll(dependsOn: assemble) { - subprojects.each {project -> - project.tasks.withType(Jar).each { - - // Dependencies for our production and test code - dependencies { - } - } - } -} task generateSources { project.ext.set("outputDir", "$projectDir/src/main/java/com/snowplowanalytics/snowplow/tracker") diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index ef042527..00000000 --- a/settings.gradle +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -rootProject.name = 'snowplow-java-tracker' -include 'snowplow-java-tracker-core' diff --git a/snowplow-java-tracker-core/build.gradle b/snowplow-java-tracker-core/build.gradle deleted file mode 100644 index 6b0b567e..00000000 --- a/snowplow-java-tracker-core/build.gradle +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -// Applying the java plugin to add support for Java -apply plugin: 'java' -// As per http://www.gradle.org/docs/current/userguide/publishing_maven.html -apply plugin: 'maven-publish' - -group = 'com.snowplowanalytics' -version = '0.2.0' - -// Where to find the dependencies of our project -repositories { - // Use 'maven central' for resolving our dependencies - mavenCentral() -} - -// Dependencies for our production and test code -dependencies { - - // Apache Commons - compile 'commons-codec:commons-codec:1.2' - compile 'commons-net:commons-net:3.3' - - // Apache HTTP - compile 'org.apache.httpcomponents:httpclient:4.3.3' - compile 'org.apache.httpcomponents:httpasyncclient:4.0.1' - - // SLF4J logging API - compile 'org.slf4j:slf4j-simple:1.7.7' - - // Jackson JSON processor - compile 'com.fasterxml.jackson.core:jackson-databind:2.4.1.1' - - testCompile 'junit:junit:4.11' -} - -task sourceJar(type: Jar, dependsOn: 'generateSources') { - from sourceSets.main.allJava -} - -// Publishing -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - - artifact sourceJar { - classifier "sources" - } - } - } - repositories { - maven { - url "$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo - } - } -} - -task generateSources { - project.ext.set("outputDir", "$projectDir/src/main/java/com/snowplowanalytics/snowplow/tracker/core") - doFirst { - println outputDir - def srcFile = new File((String)outputDir, "Version.java") - srcFile.parentFile.mkdirs() - srcFile.write( -"""/* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -package com.snowplowanalytics.snowplow.tracker.core; - -// DO NOT EDIT. AUTO-GENERATED. -public class Version { - static final String TRACKER = "java-core-$project.version"; - static final String VERSION = "$project.version"; -} -""") - } -} - -compileJava.dependsOn generateSources -compileJava.source generateSources.outputs.files, sourceSets.main.java diff --git a/snowplow-java-tracker-core/gradle/wrapper/gradle-wrapper.properties b/snowplow-java-tracker-core/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 44d0fd0e..00000000 --- a/snowplow-java-tracker-core/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Tue Jun 24 14:10:30 EDT 2014 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-all.zip diff --git a/snowplow-java-tracker-core/gradlew b/snowplow-java-tracker-core/gradlew deleted file mode 100755 index 91a7e269..00000000 --- a/snowplow-java-tracker-core/gradlew +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/snowplow-java-tracker-core/gradlew.bat b/snowplow-java-tracker-core/gradlew.bat deleted file mode 100644 index aec99730..00000000 --- a/snowplow-java-tracker-core/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Base64.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Base64.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Base64.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/Base64.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/DevicePlatform.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/DevicePlatform.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/DevicePlatform.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/DevicePlatform.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Parameter.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Parameter.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Parameter.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/Parameter.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/TransactionItem.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/TransactionItem.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/TransactionItem.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/TransactionItem.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Util.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Util.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Util.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/Util.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/BufferOption.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/BufferOption.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/BufferOption.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/BufferOption.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/HttpMethod.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/HttpMethod.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/HttpMethod.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/HttpMethod.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestCallback.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestCallback.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestCallback.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestCallback.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestMethod.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestMethod.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestMethod.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestMethod.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/Payload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/Payload.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/Payload.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/Payload.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/TrackerPayload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/TrackerPayload.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/TrackerPayload.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/TrackerPayload.java diff --git a/snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java similarity index 100% rename from snowplow-java-tracker-core/src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java diff --git a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java similarity index 87% rename from snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java rename to src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java index de9d2f78..9fa74505 100644 --- a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java @@ -1,24 +1,16 @@ package com.snowplowanalytics.snowplow.tracker; -import com.snowplowanalytics.snowplow.tracker.core.emitter.BufferOption; -import com.snowplowanalytics.snowplow.tracker.core.emitter.Emitter; -import com.snowplowanalytics.snowplow.tracker.core.emitter.HttpMethod; -import com.snowplowanalytics.snowplow.tracker.core.emitter.RequestCallback; -import com.snowplowanalytics.snowplow.tracker.core.emitter.RequestMethod; +import com.snowplowanalytics.snowplow.tracker.core.emitter.*; import com.snowplowanalytics.snowplow.tracker.core.payload.Payload; import com.snowplowanalytics.snowplow.tracker.core.payload.TrackerPayload; - -import junit.framework.TestCase; - import org.junit.Test; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; -public class EmitterTest extends TestCase { +public class EmitterTest { -// private static String testURL = "segfault.ngrok.com"; private static String testURL = "d3rkrsqld9gmqf.cloudfront.net"; @Test diff --git a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java similarity index 93% rename from snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java rename to src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java index 1679fa71..ed799dcb 100644 --- a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java @@ -1,16 +1,14 @@ package com.snowplowanalytics.snowplow.tracker; -import com.snowplowanalytics.snowplow.tracker.core.DevicePlatform; import com.snowplowanalytics.snowplow.tracker.core.Subject; - -import junit.framework.TestCase; - import org.junit.Test; import java.util.HashMap; import java.util.Map; -public class SubjectTest extends TestCase { +import static org.junit.Assert.assertEquals; + +public class SubjectTest { @Test public void testSetUserId() throws Exception { diff --git a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java similarity index 98% rename from snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java rename to src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java index 98d6ccd9..6569a365 100644 --- a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java @@ -4,7 +4,6 @@ import com.snowplowanalytics.snowplow.tracker.core.payload.SchemaPayload; import com.snowplowanalytics.snowplow.tracker.core.payload.TrackerPayload; -import junit.framework.TestCase; import org.junit.Test; @@ -13,7 +12,9 @@ import java.util.LinkedHashMap; import java.util.Map; -public class TrackerPayloadTest extends TestCase { +import static org.junit.Assert.assertEquals; + +public class TrackerPayloadTest { @Test public void testAddString() throws Exception { diff --git a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java similarity index 89% rename from snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java rename to src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java index 1c4336e4..fc47dbb7 100644 --- a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java @@ -1,32 +1,27 @@ package com.snowplowanalytics.snowplow.tracker; +import com.snowplowanalytics.snowplow.tracker.core.DevicePlatform; import com.snowplowanalytics.snowplow.tracker.core.Subject; import com.snowplowanalytics.snowplow.tracker.core.Tracker; -import com.snowplowanalytics.snowplow.tracker.core.DevicePlatform; import com.snowplowanalytics.snowplow.tracker.core.TransactionItem; import com.snowplowanalytics.snowplow.tracker.core.emitter.BufferOption; import com.snowplowanalytics.snowplow.tracker.core.emitter.Emitter; import com.snowplowanalytics.snowplow.tracker.core.emitter.HttpMethod; import com.snowplowanalytics.snowplow.tracker.core.emitter.RequestMethod; import com.snowplowanalytics.snowplow.tracker.core.payload.SchemaPayload; - -import junit.framework.TestCase; - import org.junit.Test; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; +import java.util.*; + +import static org.junit.Assert.assertEquals; -public class TrackerTest extends TestCase { +public class TrackerTest { -// private static String testURL = "segfault.ngrok.com"; - private static String testURL = "d3rkrsqld9gmqf.cloudfront.net"; + private static String TESTURL = "d3rkrsqld9gmqf.cloudfront.net"; @Test public void testDefaultPlatform() throws Exception { - Emitter emitter = new Emitter(testURL, HttpMethod.POST); + Emitter emitter = new Emitter(TESTURL, HttpMethod.POST); Subject subject = new Subject(); Tracker tracker = new Tracker(emitter, subject, "AF003", "cloudfront", false); assertEquals(DevicePlatform.Desktop, tracker.getPlatform()); @@ -34,7 +29,7 @@ public void testDefaultPlatform() throws Exception { @Test public void testSetPlatform() throws Exception { - Emitter emitter = new Emitter(testURL, HttpMethod.POST); + Emitter emitter = new Emitter(TESTURL, HttpMethod.POST); Subject subject = new Subject(); Tracker tracker = new Tracker(emitter, subject, "AF003", "cloudfront", false); tracker.setPlatform(DevicePlatform.ConnectedTV); @@ -43,7 +38,8 @@ public void testSetPlatform() throws Exception { @Test public void testSetSubject() throws Exception { - Emitter emitter = new Emitter(testURL, HttpMethod.POST); + TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC")); + Emitter emitter = new Emitter(TESTURL, HttpMethod.POST); Subject s1 = new Subject(); Tracker tracker = new Tracker(emitter, s1, "AF003", "cloudfront", false); Subject s2 = new Subject(); @@ -77,7 +73,7 @@ public void testTrackPageView2() throws Exception { @Test public void testTrackPageView3() throws Exception { - Emitter emitter = new Emitter(testURL, HttpMethod.POST); + Emitter emitter = new Emitter(TESTURL, HttpMethod.POST); Subject subject = new Subject(); subject.setViewPort(320, 480); Tracker tracker = new Tracker(emitter, subject, "AF003", "cloudfront", false); @@ -143,7 +139,7 @@ public void testTrackEcommerceTransactionItem() throws Exception { @Test public void testTrackEcommerceTransaction() throws Exception { - Emitter emitter = new Emitter(testURL, HttpMethod.POST); + Emitter emitter = new Emitter(TESTURL, HttpMethod.POST); Tracker tracker = new Tracker(emitter, "AF003", "cloudfront", false); emitter.setRequestMethod(RequestMethod.Asynchronous); @@ -182,7 +178,7 @@ public void testTrackEcommerceTransaction3() throws Exception { @Test public void testTrackScreenView() throws Exception { - Emitter emitter = new Emitter(testURL, HttpMethod.POST); + Emitter emitter = new Emitter(TESTURL, HttpMethod.POST); Subject subject = new Subject(); subject.setViewPort(320, 480); Tracker tracker = new Tracker(emitter, subject, "AF003", "cloudfront", false); diff --git a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java similarity index 90% rename from snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java rename to src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java index cee8bcb6..c4ca10f6 100644 --- a/snowplow-java-tracker-core/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java @@ -2,15 +2,16 @@ import com.fasterxml.jackson.databind.JsonNode; import com.snowplowanalytics.snowplow.tracker.core.Util; - -import junit.framework.TestCase; import org.junit.Test; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; -public class UtilTest extends TestCase { +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class UtilTest { @Test public void testGetTimestamp() { assertNotNull(Util.getTimestamp()); From 9e366243211ab51a8fa42d2130e4db95d309ed30 Mon Sep 17 00:00:00 2001 From: David Stendardi Date: Tue, 6 Jan 2015 13:52:56 +0100 Subject: [PATCH 26/37] [layout] remove war packaging, remove core package --- CHANGELOG | 4 + build.gradle | 1 - .../snowplow/tracker/{core => }/Base64.java | 2 +- .../tracker/{core => }/Constants.java | 2 +- .../tracker/{core => }/DevicePlatform.java | 2 +- .../tracker/{core => }/Parameter.java | 2 +- .../snowplow/tracker/Subject.java | 44 +- .../snowplow/tracker/Tracker.java | 507 +++++++++++++++- .../snowplow/tracker/TransactionItem.java | 36 +- .../snowplow/tracker/{core => }/Util.java | 6 +- .../snowplow/tracker/core/Subject.java | 62 -- .../snowplow/tracker/core/Tracker.java | 543 ------------------ .../tracker/core/TransactionItem.java | 51 -- .../snowplow/tracker/core/Version.java | 20 - .../tracker/core/emitter/Emitter.java | 267 --------- .../tracker/core/payload/SchemaPayload.java | 141 ----- .../tracker/core/payload/TrackerPayload.java | 126 ---- .../{core => }/emitter/BufferOption.java | 2 +- .../snowplow/tracker/emitter/Emitter.java | 220 ++++++- .../{core => }/emitter/HttpMethod.java | 2 +- .../{core => }/emitter/RequestCallback.java | 4 +- .../{core => }/emitter/RequestMethod.java | 2 +- .../tracker/{core => }/payload/Payload.java | 6 +- .../tracker/payload/SchemaPayload.java | 127 +++- .../tracker/payload/TrackerPayload.java | 111 +++- .../{core => }/util/Preconditions.java | 2 +- .../snowplow/tracker/EmitterTest.java | 6 +- .../snowplow/tracker/SubjectTest.java | 1 - .../snowplow/tracker/TrackerPayloadTest.java | 8 +- .../snowplow/tracker/TrackerTest.java | 14 +- .../snowplow/tracker/UtilTest.java | 1 - 31 files changed, 1040 insertions(+), 1282 deletions(-) rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/Base64.java (99%) rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/Constants.java (96%) rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/DevicePlatform.java (96%) rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/Parameter.java (98%) rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/Util.java (92%) delete mode 100644 src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java delete mode 100644 src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java delete mode 100644 src/main/java/com/snowplowanalytics/snowplow/tracker/core/TransactionItem.java delete mode 100644 src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java delete mode 100644 src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java delete mode 100644 src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java delete mode 100644 src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/TrackerPayload.java rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/emitter/BufferOption.java (95%) rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/emitter/HttpMethod.java (94%) rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/emitter/RequestCallback.java (87%) rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/emitter/RequestMethod.java (94%) rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/payload/Payload.java (97%) rename src/main/java/com/snowplowanalytics/snowplow/tracker/{core => }/util/Preconditions.java (99%) diff --git a/CHANGELOG b/CHANGELOG index f9fc7383..1fa1ae08 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +Java 0.?.? (?) +-------------- +Merged root and core module + Java 0.6.0 (2014-12-27) ----------------------- Bumped Core version to 0.2.0 (#108) diff --git a/build.gradle b/build.gradle index b8abacf3..9bde5cbd 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,6 @@ apply plugin: 'java' apply plugin: 'maven-publish' apply plugin: 'idea' -apply plugin: 'war' group = 'com.snowplowanalytics' diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Base64.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Base64.java similarity index 99% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/Base64.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/Base64.java index 2a4220fc..1975fb79 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Base64.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Base64.java @@ -28,7 +28,7 @@ * SUCH DAMAGE. */ -package com.snowplowanalytics.snowplow.tracker.core; +package com.snowplowanalytics.snowplow.tracker; import java.io.UnsupportedEncodingException; diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Constants.java similarity index 96% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/Constants.java index 42378d50..f34a4685 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Constants.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Constants.java @@ -11,7 +11,7 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -package com.snowplowanalytics.snowplow.tracker.core; +package com.snowplowanalytics.snowplow.tracker; public class Constants { public static final String PROTOCOL_VENDOR = "com.snowplowanalytics.snowplow"; diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/DevicePlatform.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/DevicePlatform.java similarity index 96% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/DevicePlatform.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/DevicePlatform.java index 4a85379c..ca62565d 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/DevicePlatform.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/DevicePlatform.java @@ -11,7 +11,7 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -package com.snowplowanalytics.snowplow.tracker.core; +package com.snowplowanalytics.snowplow.tracker; public enum DevicePlatform { Web { diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Parameter.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Parameter.java similarity index 98% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/Parameter.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/Parameter.java index 2fd31e92..469eaf56 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Parameter.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Parameter.java @@ -11,7 +11,7 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -package com.snowplowanalytics.snowplow.tracker.core; +package com.snowplowanalytics.snowplow.tracker; public class Parameter { // General diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/Subject.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Subject.java index d95fe1d0..848fe174 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/Subject.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Subject.java @@ -13,10 +13,50 @@ package com.snowplowanalytics.snowplow.tracker; -public class Subject extends com.snowplowanalytics.snowplow.tracker.core.Subject { +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; +import java.util.TimeZone; + +public class Subject { + + private HashMap standardPairs; public Subject() { - super(); + standardPairs = new HashMap(); + + // Default Timezone + TimeZone tz = Calendar.getInstance().getTimeZone(); + this.setTimezone(tz.getID()); + } + + public void setUserId(String userId) { + this.standardPairs.put(Parameter.UID, userId); + } + + public void setScreenResolution(int width, int height) { + String res = Integer.toString(width) + "x" + Integer.toString(height); + this.standardPairs.put(Parameter.RESOLUTION, res); + } + + public void setViewPort(int width, int height) { + String res = Integer.toString(width) + "x" + Integer.toString(height); + this.standardPairs.put(Parameter.VIEWPORT, res); + } + + public void setColorDepth(int depth) { + this.standardPairs.put(Parameter.COLOR_DEPTH, Integer.toString(depth)); + } + + public void setTimezone(String timezone) { + this.standardPairs.put(Parameter.TIMEZONE, timezone); + } + + public void setLanguage(String language) { + this.standardPairs.put(Parameter.LANGUAGE, language); } + public Map getSubject() { + return this.standardPairs; + } } diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java index aaca4361..27d57299 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java @@ -13,19 +13,34 @@ package com.snowplowanalytics.snowplow.tracker; -import com.snowplowanalytics.snowplow.tracker.core.Subject; -import com.snowplowanalytics.snowplow.tracker.core.emitter.Emitter; +import com.snowplowanalytics.snowplow.tracker.emitter.Emitter; +import com.snowplowanalytics.snowplow.tracker.payload.Payload; +import com.snowplowanalytics.snowplow.tracker.payload.SchemaPayload; +import com.snowplowanalytics.snowplow.tracker.payload.TrackerPayload; +import com.snowplowanalytics.snowplow.tracker.util.Preconditions; -public class Tracker extends com.snowplowanalytics.snowplow.tracker.core.Tracker { +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class Tracker { + + private boolean base64Encoded = true; + private Emitter emitter; + private DevicePlatform platform; + private String appId; + private String namespace; + private String trackerVersion; + private Subject subject; /** * @param emitter Emitter to which events will be sent * @param namespace Identifier for the Tracker instance * @param appId Application ID */ - public Tracker(com.snowplowanalytics.snowplow.tracker.core.emitter.Emitter emitter, String namespace, String appId) { - super(emitter, namespace, appId); - super.setTrackerVersion(Version.TRACKER); + public Tracker(Emitter emitter, String namespace, String appId) { + this(emitter, null, namespace, appId, true); } /** @@ -34,9 +49,8 @@ public Tracker(com.snowplowanalytics.snowplow.tracker.core.emitter.Emitter emitt * @param namespace Identifier for the Tracker instance * @param appId Application ID */ - public Tracker(Emitter emitter, com.snowplowanalytics.snowplow.tracker.core.Subject subject, String namespace, String appId) { - super(emitter, subject, namespace, appId); - super.setTrackerVersion(Version.TRACKER); + public Tracker(Emitter emitter, Subject subject, String namespace, String appId) { + this(emitter, subject, namespace, appId, true); } /** @@ -46,8 +60,7 @@ public Tracker(Emitter emitter, com.snowplowanalytics.snowplow.tracker.core.Subj * @param base64Encoded Whether JSONs in the payload should be base-64 encoded */ public Tracker(Emitter emitter, String namespace, String appId, boolean base64Encoded) { - super(emitter, namespace, appId, base64Encoded); - super.setTrackerVersion(Version.TRACKER); + this(emitter, null, namespace, appId, base64Encoded); } /** @@ -57,8 +70,474 @@ public Tracker(Emitter emitter, String namespace, String appId, boolean base64En * @param appId Application ID * @param base64Encoded Whether JSONs in the payload should be base-64 encoded */ - public Tracker(Emitter emitter, Subject subject, String namespace, String appId, boolean base64Encoded) { - super(emitter, subject, namespace, appId, base64Encoded); - super.setTrackerVersion(Version.TRACKER); + public Tracker(Emitter emitter, Subject subject, String namespace, String appId, + boolean base64Encoded) { + this.emitter = emitter; + this.appId = appId; + this.base64Encoded = base64Encoded; + this.namespace = namespace; + this.subject = subject; + this.trackerVersion = Version.TRACKER; + this.platform = DevicePlatform.Desktop; + } + + /** + * @param payload Payload builder + * @param context Custom context for the event + * @param timestamp Optional user-provided timestamp for the event + * @return A completed Payload + */ + protected Payload completePayload(Payload payload, List context, + long timestamp) { + payload.add(Parameter.PLATFORM, this.platform.toString()); + payload.add(Parameter.APPID, this.appId); + payload.add(Parameter.NAMESPACE, this.namespace); + payload.add(Parameter.TRACKER_VERSION, this.trackerVersion); + payload.add(Parameter.EID, Util.getEventId()); + + // If timestamp is set to 0, generate one + payload.add(Parameter.TIMESTAMP, + (timestamp == 0 ? Util.getTimestamp() : Long.toString(timestamp))); + + // Encodes context data + if (context != null) { + SchemaPayload envelope = new SchemaPayload(); + envelope.setSchema(Constants.SCHEMA_CONTEXTS); + + // We can do better here, rather than re-iterate through the list + List contextDataList = new LinkedList(); + for (SchemaPayload schemaPayload : context) { + contextDataList.add(schemaPayload.getMap()); + } + + envelope.setData(contextDataList); + payload.addMap(envelope.getMap(), this.base64Encoded, Parameter.CONTEXT_ENCODED, + Parameter.CONTEXT); + } + + if (this.subject != null) payload.addMap(new HashMap(subject.getSubject())); + + return payload; + } + + public void setPlatform(DevicePlatform platform) { + this.platform = platform; + } + + public DevicePlatform getPlatform() { + return this.platform; + } + + protected void setTrackerVersion(String version) { + this.trackerVersion = version; + } + + private void addTrackerPayload(Payload payload) { + this.emitter.addToBuffer(payload); + } + + public void setSubject(Subject subject) { + this.subject = subject; + } + + public Subject getSubject() { + return this.subject; + } + + /** + * @param pageUrl URL of the viewed page + * @param pageTitle Title of the viewed page + * @param referrer Referrer of the page + */ + public void trackPageView(String pageUrl, String pageTitle, String referrer) { + trackPageView(pageUrl, pageTitle, referrer, null, 0); + } + + /** + * @param pageUrl URL of the viewed page + * @param pageTitle Title of the viewed page + * @param referrer Referrer of the page + * @param context Custom context for the event + */ + public void trackPageView(String pageUrl, String pageTitle, String referrer, + List context) { + trackPageView(pageUrl,pageTitle, referrer, context, 0); + } + + /** + * @param pageUrl URL of the viewed page + * @param pageTitle Title of the viewed page + * @param referrer Referrer of the page + * @param timestamp Optional user-provided timestamp for the event + */ + public void trackPageView(String pageUrl, String pageTitle, String referrer, + long timestamp) { + trackPageView(pageUrl, pageTitle, referrer, null, timestamp); + } + + /** + * @param pageUrl URL of the viewed page + * @param pageTitle Title of the viewed page + * @param referrer Referrer of the page + * @param context Custom context for the event + * @param timestamp Optional user-provided timestamp for the event + */ + public void trackPageView(String pageUrl, String pageTitle, String referrer, + List context, long timestamp) { + // Precondition checks + Preconditions.checkNotNull(pageUrl); + Preconditions.checkArgument(!pageUrl.isEmpty(), "pageUrl cannot be empty"); + Preconditions.checkArgument(!pageTitle.isEmpty(), "pageTitle cannot be empty"); + Preconditions.checkArgument(!referrer.isEmpty(), "referrer cannot be empty"); + + Payload payload = new TrackerPayload(); + payload.add(Parameter.EVENT, Constants.EVENT_PAGE_VIEW); + payload.add(Parameter.PAGE_URL, pageUrl); + payload.add(Parameter.PAGE_TITLE, pageTitle); + payload.add(Parameter.PAGE_REFR, referrer); + + completePayload(payload, context, timestamp); + + addTrackerPayload(payload); + } + + /** + * @param category Category of the event + * @param action The event itself + * @param label Refer to the object the action is performed on + * @param property Property associated with either the action or the object + * @param value A value associated with the user action + */ + public void trackStructuredEvent(String category, String action, String label, String property, + int value) { + trackStructuredEvent(category, action, label, property, value, null, 0); + } + + /** + * @param category Category of the event + * @param action The event itself + * @param label Refer to the object the action is performed on + * @param property Property associated with either the action or the object + * @param value A value associated with the user action + * @param context Custom context for the event + */ + public void trackStructuredEvent(String category, String action, String label, String property, + int value, List context) { + trackStructuredEvent(category, action, label, property, value, context, 0); + } + + /** + * @param category Category of the event + * @param action The event itself + * @param label Refer to the object the action is performed on + * @param property Property associated with either the action or the object + * @param value A value associated with the user action + * @param timestamp Optional user-provided timestamp for the event + */ + public void trackStructuredEvent(String category, String action, String label, String property, + int value, long timestamp) { + trackStructuredEvent(category, action, label, property, value, null, timestamp); + } + + /** + * @param category Category of the event + * @param action The event itself + * @param label Refer to the object the action is performed on + * @param property Property associated with either the action or the object + * @param value A value associated with the user action + * @param context Custom context for the event + * @param timestamp Optional user-provided timestamp for the event + */ + public void trackStructuredEvent(String category, String action, String label, String property, + int value, List context, long timestamp) { + // Precondition checks + Preconditions.checkNotNull(label); + Preconditions.checkNotNull(property); + Preconditions.checkArgument(!label.isEmpty(), "label cannot be empty"); + Preconditions.checkArgument(!property.isEmpty(), "property cannot be empty"); + Preconditions.checkArgument(!category.isEmpty(), "category cannot be empty"); + Preconditions.checkArgument(!action.isEmpty(), "action cannot be empty"); + + Payload payload = new TrackerPayload(); + payload.add(Parameter.EVENT, Constants.EVENT_STRUCTURED); + payload.add(Parameter.SE_CATEGORY, category); + payload.add(Parameter.SE_ACTION, action); + payload.add(Parameter.SE_LABEL, label); + payload.add(Parameter.SE_PROPERTY, property); + payload.add(Parameter.SE_VALUE, Double.toString(value)); + + completePayload(payload, context, timestamp); + + addTrackerPayload(payload); + } + + /** + * + * @param eventData The properties of the event. Has two field: + * A "data" field containing the event properties and + * A "schema" field identifying the schema against which the data is validated + */ + public void trackUnstructuredEvent(SchemaPayload eventData) { + trackUnstructuredEvent(eventData, null, 0); + } + + /** + * + * @param eventData The properties of the event. Has two field: + * A "data" field containing the event properties and + * A "schema" field identifying the schema against which the data is validated + * @param context Custom context for the event + */ + public void trackUnstructuredEvent(SchemaPayload eventData, List context) { + trackUnstructuredEvent(eventData, context, 0); + } + + /** + * + * @param eventData The properties of the event. Has two field: + * A "data" field containing the event properties and + * A "schema" field identifying the schema against which the data is validated + * @param timestamp Optional user-provided timestamp for the event + */ + public void trackUnstructuredEvent(SchemaPayload eventData, long timestamp) { + trackUnstructuredEvent(eventData, null, timestamp); + } + + /** + * + * @param eventData The properties of the event. Has two field: + * A "data" field containing the event properties and + * A "schema" field identifying the schema against which the data is validated + * @param context Custom context for the event + * @param timestamp Optional user-provided timestamp for the event + */ + public void trackUnstructuredEvent(SchemaPayload eventData, List context, + long timestamp) { + Payload payload = new TrackerPayload(); + SchemaPayload envelope = new SchemaPayload(); + + envelope.setSchema(Constants.SCHEMA_UNSTRUCT_EVENT); + envelope.setData(eventData.getMap()); + + payload.add(Parameter.EVENT, Constants.EVENT_UNSTRUCTURED); + payload.addMap(envelope.getMap(), base64Encoded, + Parameter.UNSTRUCTURED_ENCODED, Parameter.UNSTRUCTURED); + + completePayload(payload, context, timestamp); + + addTrackerPayload(payload); + } + + /** + * This is an internal method called by track_ecommerce_transaction. It is not for public use. + * @param order_id Order ID + * @param sku Item SKU + * @param price Item price + * @param quantity Item quantity + * @param name Item name + * @param category Item category + * @param currency The currency the price is expressed in + * @param context Custom context for the event + * @param timestamp Optional user-provided timestamp for the event + */ + protected void trackEcommerceTransactionItem(String order_id, String sku, Double price, + Integer quantity, String name, String category, + String currency, List context, + long timestamp) { + // Precondition checks + Preconditions.checkNotNull(name); + Preconditions.checkNotNull(category); + Preconditions.checkNotNull(currency); + Preconditions.checkArgument(!order_id.isEmpty(), "order_id cannot be empty"); + Preconditions.checkArgument(!sku.isEmpty(), "sku cannot be empty"); + Preconditions.checkArgument(!name.isEmpty(), "name cannot be empty"); + Preconditions.checkArgument(!category.isEmpty(), "category cannot be empty"); + Preconditions.checkArgument(!currency.isEmpty(), "currency cannot be empty"); + + Payload payload = new TrackerPayload(); + payload.add(Parameter.EVENT, Constants.EVENT_ECOMM_ITEM); + payload.add(Parameter.TI_ITEM_ID, order_id); + payload.add(Parameter.TI_ITEM_SKU, sku); + payload.add(Parameter.TI_ITEM_NAME, name); + payload.add(Parameter.TI_ITEM_CATEGORY, category); + payload.add(Parameter.TI_ITEM_PRICE, Double.toString(price)); + payload.add(Parameter.TI_ITEM_QUANTITY, Double.toString(quantity)); + payload.add(Parameter.TI_ITEM_CURRENCY, currency); + + completePayload(payload, context, timestamp); + + addTrackerPayload(payload); + } + + /** + * @param order_id ID of the eCommerce transaction + * @param total_value Total transaction value + * @param affiliation Transaction affiliation + * @param tax_value Transaction tax value + * @param shipping Delivery cost charged + * @param city Delivery address city + * @param state Delivery address state + * @param country Delivery address country + * @param currency The currency the price is expressed in + * @param items The items in the transaction + */ + public void trackEcommerceTransaction(String order_id, Double total_value, String affiliation, + Double tax_value, Double shipping, String city, + String state, String country, String currency, + List items) { + trackEcommerceTransaction(order_id, total_value, affiliation, tax_value, shipping, city, + state, country, currency, items, null, 0); + } + + /** + * @param order_id ID of the eCommerce transaction + * @param total_value Total transaction value + * @param affiliation Transaction affiliation + * @param tax_value Transaction tax value + * @param shipping Delivery cost charged + * @param city Delivery address city + * @param state Delivery address state + * @param country Delivery address country + * @param currency The currency the price is expressed in + * @param items The items in the transaction + * @param context Custom context for the event + */ + public void trackEcommerceTransaction(String order_id, Double total_value, String affiliation, + Double tax_value, Double shipping, String city, + String state, String country, String currency, + List items, List context) { + trackEcommerceTransaction(order_id, total_value, affiliation, tax_value, shipping, city, + state, country, currency, items, context, 0); + } + + /** + * @param order_id ID of the eCommerce transaction + * @param total_value Total transaction value + * @param affiliation Transaction affiliation + * @param tax_value Transaction tax value + * @param shipping Delivery cost charged + * @param city Delivery address city + * @param state Delivery address state + * @param country Delivery address country + * @param currency The currency the price is expressed in + * @param items The items in the transaction + * @param timestamp Optional user-provided timestamp for the event + */ + public void trackEcommerceTransaction(String order_id, Double total_value, String affiliation, + Double tax_value, Double shipping, String city, + String state, String country, String currency, + List items, long timestamp) { + trackEcommerceTransaction(order_id, total_value, affiliation, tax_value, shipping, city, + state, country, currency, items, null, timestamp); + } + + /** + * @param order_id ID of the eCommerce transaction + * @param total_value Total transaction value + * @param affiliation Transaction affiliation + * @param tax_value Transaction tax value + * @param shipping Delivery cost charged + * @param city Delivery address city + * @param state Delivery address state + * @param country Delivery address country + * @param currency The currency the price is expressed in + * @param items The items in the transaction + * @param context Custom context for the event + * @param timestamp Optional user-provided timestamp for the event + */ + @SuppressWarnings("unchecked") + public void trackEcommerceTransaction(String order_id, Double total_value, String affiliation, + Double tax_value, Double shipping, String city, + String state, String country, String currency, + List items, List context, + long timestamp) { + // Precondition checks + Preconditions.checkNotNull(affiliation); + Preconditions.checkNotNull(city); + Preconditions.checkNotNull(state); + Preconditions.checkNotNull(country); + Preconditions.checkNotNull(currency); + Preconditions.checkArgument(!order_id.isEmpty(), "order_id cannot be empty"); + Preconditions.checkArgument(!affiliation.isEmpty(), "affiliation cannot be empty"); + Preconditions.checkArgument(!city.isEmpty(), "city cannot be empty"); + Preconditions.checkArgument(!state.isEmpty(), "state cannot be empty"); + Preconditions.checkArgument(!country.isEmpty(), "country cannot be empty"); + Preconditions.checkArgument(!currency.isEmpty(), "currency cannot be empty"); + + Payload payload = new TrackerPayload(); + payload.add(Parameter.EVENT, Constants.EVENT_ECOMM); + payload.add(Parameter.TR_ID, order_id); + payload.add(Parameter.TR_TOTAL, Double.toString(total_value)); + payload.add(Parameter.TR_AFFILIATION, affiliation); + payload.add(Parameter.TR_TAX, Double.toString(tax_value)); + payload.add(Parameter.TR_SHIPPING, Double.toString(shipping)); + payload.add(Parameter.TR_CITY, city); + payload.add(Parameter.TR_STATE, state); + payload.add(Parameter.TR_COUNTRY, country); + payload.add(Parameter.TR_CURRENCY, currency); + + completePayload(payload, context, timestamp); + + for (TransactionItem item : items) { + trackEcommerceTransactionItem( + (String) item.get(Parameter.TI_ITEM_ID), + (String) item.get(Parameter.TI_ITEM_SKU), + (Double) item.get(Parameter.TI_ITEM_PRICE), + (Integer) item.get(Parameter.TI_ITEM_QUANTITY), + (String) item.get(Parameter.TI_ITEM_NAME), + (String) item.get(Parameter.TI_ITEM_CATEGORY), + (String) item.get(Parameter.TI_ITEM_CURRENCY), + (List) item.get(Parameter.CONTEXT), + timestamp); + } + + addTrackerPayload(payload); + } + + /** + * @param name The name of the screen view event + * @param id Screen view ID + */ + public void trackScreenView(String name, String id) { + trackScreenView(name, id, null, 0); + } + + /** + * @param name The name of the screen view event + * @param id Screen view ID + * @param context Custom context for the event + */ + public void trackScreenView(String name, String id, List context) { + trackScreenView(name, id, context, 0); + } + + /** + * @param name The name of the screen view event + * @param id Screen view ID + * @param timestamp Optional user-provided timestamp for the event + */ + public void trackScreenView(String name, String id, long timestamp) { + trackScreenView(name, id, null, timestamp); + } + + /** + * @param name The name of the screen view event + * @param id Screen view ID + * @param context Custom context for the event + * @param timestamp Optional user-provided timestamp for the event + */ + public void trackScreenView(String name, String id, List context, + long timestamp) { + Preconditions.checkArgument(name != null || id != null); + TrackerPayload trackerPayload = new TrackerPayload(); + + trackerPayload.add(Parameter.SV_NAME, name); + trackerPayload.add(Parameter.SV_ID, id); + + SchemaPayload payload = new SchemaPayload(); + payload.setSchema(Constants.SCHEMA_SCREEN_VIEW); + payload.setData(trackerPayload); + + trackUnstructuredEvent(payload, context, timestamp); } } diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/TransactionItem.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/TransactionItem.java index 0b6da54d..7a56b84e 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/TransactionItem.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/TransactionItem.java @@ -13,19 +13,39 @@ package com.snowplowanalytics.snowplow.tracker; -import com.snowplowanalytics.snowplow.tracker.core.payload.SchemaPayload; +import com.snowplowanalytics.snowplow.tracker.payload.SchemaPayload; +import java.util.HashMap; import java.util.List; -public class TransactionItem extends com.snowplowanalytics.snowplow.tracker.core.TransactionItem { +public class TransactionItem extends HashMap { - public TransactionItem(String order_id, String sku, double price, int quantity, String name, - String category, String currency) { - super(order_id, sku, price, quantity, name, category, currency); + public TransactionItem (String order_id, String sku, double price, int quantity, String name, + String category, String currency) { + this(order_id,sku, price, quantity, name, category, currency, null); } - public TransactionItem(String order_id, String sku, double price, int quantity, String name, - String category, String currency, List context) { - super(order_id, sku, price, quantity, name, category, currency, context); + public TransactionItem (String order_id, String sku, double price, int quantity, String name, + String category, String currency, List context) { + put(Parameter.EVENT, "ti"); + put(Parameter.TI_ITEM_ID, order_id); + put(Parameter.TI_ITEM_SKU, sku); + put(Parameter.TI_ITEM_NAME, name); + put(Parameter.TI_ITEM_CATEGORY, category); + put(Parameter.TI_ITEM_PRICE, price); + put(Parameter.TI_ITEM_QUANTITY, quantity); + put(Parameter.TI_ITEM_CURRENCY, currency); + + put(Parameter.CONTEXT, context); + + put(Parameter.TIMESTAMP, Util.getTimestamp()); + } + + @SuppressWarnings({"unchecked", "ConstantConditions"}) + @Override + public Object put(Object key, Object value) { + if (value != null || value != "") return super.put(key, value); + else + return null; } } diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Util.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Util.java similarity index 92% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/Util.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/Util.java index 26f88d06..f19a57af 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Util.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Util.java @@ -11,14 +11,11 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -package com.snowplowanalytics.snowplow.tracker.core; +package com.snowplowanalytics.snowplow.tracker; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Map; @@ -26,7 +23,6 @@ import java.util.UUID; public class Util { - private static final Logger logger = LoggerFactory.getLogger(Util.class); private static ObjectMapper sObjectMapper = new ObjectMapper(); public static ObjectMapper defaultMapper() { return sObjectMapper; diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java deleted file mode 100644 index e1e6c243..00000000 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Subject.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -package com.snowplowanalytics.snowplow.tracker.core; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; -import java.util.TimeZone; - -public class Subject { - - private HashMap standardPairs; - - public Subject() { - standardPairs = new HashMap(); - - // Default Timezone - TimeZone tz = Calendar.getInstance().getTimeZone(); - this.setTimezone(tz.getID()); - } - - public void setUserId(String userId) { - this.standardPairs.put(Parameter.UID, userId); - } - - public void setScreenResolution(int width, int height) { - String res = Integer.toString(width) + "x" + Integer.toString(height); - this.standardPairs.put(Parameter.RESOLUTION, res); - } - - public void setViewPort(int width, int height) { - String res = Integer.toString(width) + "x" + Integer.toString(height); - this.standardPairs.put(Parameter.VIEWPORT, res); - } - - public void setColorDepth(int depth) { - this.standardPairs.put(Parameter.COLOR_DEPTH, Integer.toString(depth)); - } - - public void setTimezone(String timezone) { - this.standardPairs.put(Parameter.TIMEZONE, timezone); - } - - public void setLanguage(String language) { - this.standardPairs.put(Parameter.LANGUAGE, language); - } - - public Map getSubject() { - return this.standardPairs; - } -} diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java deleted file mode 100644 index 8c522448..00000000 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Tracker.java +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -package com.snowplowanalytics.snowplow.tracker.core; - -import com.snowplowanalytics.snowplow.tracker.core.emitter.Emitter; -import com.snowplowanalytics.snowplow.tracker.core.payload.Payload; -import com.snowplowanalytics.snowplow.tracker.core.payload.SchemaPayload; -import com.snowplowanalytics.snowplow.tracker.core.payload.TrackerPayload; -import com.snowplowanalytics.snowplow.tracker.core.util.Preconditions; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -public class Tracker { - - private boolean base64Encoded = true; - private Emitter emitter; - private DevicePlatform platform; - private String appId; - private String namespace; - private String trackerVersion; - private Subject subject; - - /** - * @param emitter Emitter to which events will be sent - * @param namespace Identifier for the Tracker instance - * @param appId Application ID - */ - public Tracker(Emitter emitter, String namespace, String appId) { - this(emitter, null, namespace, appId, true); - } - - /** - * @param emitter Emitter to which events will be sent - * @param subject Subject to be tracked - * @param namespace Identifier for the Tracker instance - * @param appId Application ID - */ - public Tracker(Emitter emitter, Subject subject, String namespace, String appId) { - this(emitter, subject, namespace, appId, true); - } - - /** - * @param emitter Emitter to which events will be sent - * @param namespace Identifier for the Tracker instance - * @param appId Application ID - * @param base64Encoded Whether JSONs in the payload should be base-64 encoded - */ - public Tracker(Emitter emitter, String namespace, String appId, boolean base64Encoded) { - this(emitter, null, namespace, appId, base64Encoded); - } - - /** - * @param emitter Emitter to which events will be sent - * @param subject Subject to be tracked - * @param namespace Identifier for the Tracker instance - * @param appId Application ID - * @param base64Encoded Whether JSONs in the payload should be base-64 encoded - */ - public Tracker(Emitter emitter, Subject subject, String namespace, String appId, - boolean base64Encoded) { - this.emitter = emitter; - this.appId = appId; - this.base64Encoded = base64Encoded; - this.namespace = namespace; - this.subject = subject; - this.trackerVersion = Version.TRACKER; - this.platform = DevicePlatform.Desktop; - } - - /** - * @param payload Payload builder - * @param context Custom context for the event - * @param timestamp Optional user-provided timestamp for the event - * @return A completed Payload - */ - protected Payload completePayload(Payload payload, List context, - long timestamp) { - payload.add(Parameter.PLATFORM, this.platform.toString()); - payload.add(Parameter.APPID, this.appId); - payload.add(Parameter.NAMESPACE, this.namespace); - payload.add(Parameter.TRACKER_VERSION, this.trackerVersion); - payload.add(Parameter.EID, Util.getEventId()); - - // If timestamp is set to 0, generate one - payload.add(Parameter.TIMESTAMP, - (timestamp == 0 ? Util.getTimestamp() : Long.toString(timestamp))); - - // Encodes context data - if (context != null) { - SchemaPayload envelope = new SchemaPayload(); - envelope.setSchema(Constants.SCHEMA_CONTEXTS); - - // We can do better here, rather than re-iterate through the list - List contextDataList = new LinkedList(); - for (SchemaPayload schemaPayload : context) { - contextDataList.add(schemaPayload.getMap()); - } - - envelope.setData(contextDataList); - payload.addMap(envelope.getMap(), this.base64Encoded, Parameter.CONTEXT_ENCODED, - Parameter.CONTEXT); - } - - if (this.subject != null) payload.addMap(new HashMap(subject.getSubject())); - - return payload; - } - - public void setPlatform(DevicePlatform platform) { - this.platform = platform; - } - - public DevicePlatform getPlatform() { - return this.platform; - } - - protected void setTrackerVersion(String version) { - this.trackerVersion = version; - } - - private void addTrackerPayload(Payload payload) { - this.emitter.addToBuffer(payload); - } - - public void setSubject(Subject subject) { - this.subject = subject; - } - - public Subject getSubject() { - return this.subject; - } - - /** - * @param pageUrl URL of the viewed page - * @param pageTitle Title of the viewed page - * @param referrer Referrer of the page - */ - public void trackPageView(String pageUrl, String pageTitle, String referrer) { - trackPageView(pageUrl, pageTitle, referrer, null, 0); - } - - /** - * @param pageUrl URL of the viewed page - * @param pageTitle Title of the viewed page - * @param referrer Referrer of the page - * @param context Custom context for the event - */ - public void trackPageView(String pageUrl, String pageTitle, String referrer, - List context) { - trackPageView(pageUrl,pageTitle, referrer, context, 0); - } - - /** - * @param pageUrl URL of the viewed page - * @param pageTitle Title of the viewed page - * @param referrer Referrer of the page - * @param timestamp Optional user-provided timestamp for the event - */ - public void trackPageView(String pageUrl, String pageTitle, String referrer, - long timestamp) { - trackPageView(pageUrl, pageTitle, referrer, null, timestamp); - } - - /** - * @param pageUrl URL of the viewed page - * @param pageTitle Title of the viewed page - * @param referrer Referrer of the page - * @param context Custom context for the event - * @param timestamp Optional user-provided timestamp for the event - */ - public void trackPageView(String pageUrl, String pageTitle, String referrer, - List context, long timestamp) { - // Precondition checks - Preconditions.checkNotNull(pageUrl); - Preconditions.checkArgument(!pageUrl.isEmpty(), "pageUrl cannot be empty"); - Preconditions.checkArgument(!pageTitle.isEmpty(), "pageTitle cannot be empty"); - Preconditions.checkArgument(!referrer.isEmpty(), "referrer cannot be empty"); - - Payload payload = new TrackerPayload(); - payload.add(Parameter.EVENT, Constants.EVENT_PAGE_VIEW); - payload.add(Parameter.PAGE_URL, pageUrl); - payload.add(Parameter.PAGE_TITLE, pageTitle); - payload.add(Parameter.PAGE_REFR, referrer); - - completePayload(payload, context, timestamp); - - addTrackerPayload(payload); - } - - /** - * @param category Category of the event - * @param action The event itself - * @param label Refer to the object the action is performed on - * @param property Property associated with either the action or the object - * @param value A value associated with the user action - */ - public void trackStructuredEvent(String category, String action, String label, String property, - int value) { - trackStructuredEvent(category, action, label, property, value, null, 0); - } - - /** - * @param category Category of the event - * @param action The event itself - * @param label Refer to the object the action is performed on - * @param property Property associated with either the action or the object - * @param value A value associated with the user action - * @param context Custom context for the event - */ - public void trackStructuredEvent(String category, String action, String label, String property, - int value, List context) { - trackStructuredEvent(category, action, label, property, value, context, 0); - } - - /** - * @param category Category of the event - * @param action The event itself - * @param label Refer to the object the action is performed on - * @param property Property associated with either the action or the object - * @param value A value associated with the user action - * @param timestamp Optional user-provided timestamp for the event - */ - public void trackStructuredEvent(String category, String action, String label, String property, - int value, long timestamp) { - trackStructuredEvent(category, action, label, property, value, null, timestamp); - } - - /** - * @param category Category of the event - * @param action The event itself - * @param label Refer to the object the action is performed on - * @param property Property associated with either the action or the object - * @param value A value associated with the user action - * @param context Custom context for the event - * @param timestamp Optional user-provided timestamp for the event - */ - public void trackStructuredEvent(String category, String action, String label, String property, - int value, List context, long timestamp) { - // Precondition checks - Preconditions.checkNotNull(label); - Preconditions.checkNotNull(property); - Preconditions.checkArgument(!label.isEmpty(), "label cannot be empty"); - Preconditions.checkArgument(!property.isEmpty(), "property cannot be empty"); - Preconditions.checkArgument(!category.isEmpty(), "category cannot be empty"); - Preconditions.checkArgument(!action.isEmpty(), "action cannot be empty"); - - Payload payload = new TrackerPayload(); - payload.add(Parameter.EVENT, Constants.EVENT_STRUCTURED); - payload.add(Parameter.SE_CATEGORY, category); - payload.add(Parameter.SE_ACTION, action); - payload.add(Parameter.SE_LABEL, label); - payload.add(Parameter.SE_PROPERTY, property); - payload.add(Parameter.SE_VALUE, Double.toString(value)); - - completePayload(payload, context, timestamp); - - addTrackerPayload(payload); - } - - /** - * - * @param eventData The properties of the event. Has two field: - * A "data" field containing the event properties and - * A "schema" field identifying the schema against which the data is validated - */ - public void trackUnstructuredEvent(SchemaPayload eventData) { - trackUnstructuredEvent(eventData, null, 0); - } - - /** - * - * @param eventData The properties of the event. Has two field: - * A "data" field containing the event properties and - * A "schema" field identifying the schema against which the data is validated - * @param context Custom context for the event - */ - public void trackUnstructuredEvent(SchemaPayload eventData, List context) { - trackUnstructuredEvent(eventData, context, 0); - } - - /** - * - * @param eventData The properties of the event. Has two field: - * A "data" field containing the event properties and - * A "schema" field identifying the schema against which the data is validated - * @param timestamp Optional user-provided timestamp for the event - */ - public void trackUnstructuredEvent(SchemaPayload eventData, long timestamp) { - trackUnstructuredEvent(eventData, null, timestamp); - } - - /** - * - * @param eventData The properties of the event. Has two field: - * A "data" field containing the event properties and - * A "schema" field identifying the schema against which the data is validated - * @param context Custom context for the event - * @param timestamp Optional user-provided timestamp for the event - */ - public void trackUnstructuredEvent(SchemaPayload eventData, List context, - long timestamp) { - Payload payload = new TrackerPayload(); - SchemaPayload envelope = new SchemaPayload(); - - envelope.setSchema(Constants.SCHEMA_UNSTRUCT_EVENT); - envelope.setData(eventData.getMap()); - - payload.add(Parameter.EVENT, Constants.EVENT_UNSTRUCTURED); - payload.addMap(envelope.getMap(), base64Encoded, - Parameter.UNSTRUCTURED_ENCODED, Parameter.UNSTRUCTURED); - - completePayload(payload, context, timestamp); - - addTrackerPayload(payload); - } - - /** - * This is an internal method called by track_ecommerce_transaction. It is not for public use. - * @param order_id Order ID - * @param sku Item SKU - * @param price Item price - * @param quantity Item quantity - * @param name Item name - * @param category Item category - * @param currency The currency the price is expressed in - * @param context Custom context for the event - * @param timestamp Optional user-provided timestamp for the event - */ - protected void trackEcommerceTransactionItem(String order_id, String sku, Double price, - Integer quantity, String name, String category, - String currency, List context, - long timestamp) { - // Precondition checks - Preconditions.checkNotNull(name); - Preconditions.checkNotNull(category); - Preconditions.checkNotNull(currency); - Preconditions.checkArgument(!order_id.isEmpty(), "order_id cannot be empty"); - Preconditions.checkArgument(!sku.isEmpty(), "sku cannot be empty"); - Preconditions.checkArgument(!name.isEmpty(), "name cannot be empty"); - Preconditions.checkArgument(!category.isEmpty(), "category cannot be empty"); - Preconditions.checkArgument(!currency.isEmpty(), "currency cannot be empty"); - - Payload payload = new TrackerPayload(); - payload.add(Parameter.EVENT, Constants.EVENT_ECOMM_ITEM); - payload.add(Parameter.TI_ITEM_ID, order_id); - payload.add(Parameter.TI_ITEM_SKU, sku); - payload.add(Parameter.TI_ITEM_NAME, name); - payload.add(Parameter.TI_ITEM_CATEGORY, category); - payload.add(Parameter.TI_ITEM_PRICE, Double.toString(price)); - payload.add(Parameter.TI_ITEM_QUANTITY, Double.toString(quantity)); - payload.add(Parameter.TI_ITEM_CURRENCY, currency); - - completePayload(payload, context, timestamp); - - addTrackerPayload(payload); - } - - /** - * @param order_id ID of the eCommerce transaction - * @param total_value Total transaction value - * @param affiliation Transaction affiliation - * @param tax_value Transaction tax value - * @param shipping Delivery cost charged - * @param city Delivery address city - * @param state Delivery address state - * @param country Delivery address country - * @param currency The currency the price is expressed in - * @param items The items in the transaction - */ - public void trackEcommerceTransaction(String order_id, Double total_value, String affiliation, - Double tax_value, Double shipping, String city, - String state, String country, String currency, - List items) { - trackEcommerceTransaction(order_id, total_value, affiliation, tax_value, shipping, city, - state, country, currency, items, null, 0); - } - - /** - * @param order_id ID of the eCommerce transaction - * @param total_value Total transaction value - * @param affiliation Transaction affiliation - * @param tax_value Transaction tax value - * @param shipping Delivery cost charged - * @param city Delivery address city - * @param state Delivery address state - * @param country Delivery address country - * @param currency The currency the price is expressed in - * @param items The items in the transaction - * @param context Custom context for the event - */ - public void trackEcommerceTransaction(String order_id, Double total_value, String affiliation, - Double tax_value, Double shipping, String city, - String state, String country, String currency, - List items, List context) { - trackEcommerceTransaction(order_id, total_value, affiliation, tax_value, shipping, city, - state, country, currency, items, context, 0); - } - - /** - * @param order_id ID of the eCommerce transaction - * @param total_value Total transaction value - * @param affiliation Transaction affiliation - * @param tax_value Transaction tax value - * @param shipping Delivery cost charged - * @param city Delivery address city - * @param state Delivery address state - * @param country Delivery address country - * @param currency The currency the price is expressed in - * @param items The items in the transaction - * @param timestamp Optional user-provided timestamp for the event - */ - public void trackEcommerceTransaction(String order_id, Double total_value, String affiliation, - Double tax_value, Double shipping, String city, - String state, String country, String currency, - List items, long timestamp) { - trackEcommerceTransaction(order_id, total_value, affiliation, tax_value, shipping, city, - state, country, currency, items, null, timestamp); - } - - /** - * @param order_id ID of the eCommerce transaction - * @param total_value Total transaction value - * @param affiliation Transaction affiliation - * @param tax_value Transaction tax value - * @param shipping Delivery cost charged - * @param city Delivery address city - * @param state Delivery address state - * @param country Delivery address country - * @param currency The currency the price is expressed in - * @param items The items in the transaction - * @param context Custom context for the event - * @param timestamp Optional user-provided timestamp for the event - */ - @SuppressWarnings("unchecked") - public void trackEcommerceTransaction(String order_id, Double total_value, String affiliation, - Double tax_value, Double shipping, String city, - String state, String country, String currency, - List items, List context, - long timestamp) { - // Precondition checks - Preconditions.checkNotNull(affiliation); - Preconditions.checkNotNull(city); - Preconditions.checkNotNull(state); - Preconditions.checkNotNull(country); - Preconditions.checkNotNull(currency); - Preconditions.checkArgument(!order_id.isEmpty(), "order_id cannot be empty"); - Preconditions.checkArgument(!affiliation.isEmpty(), "affiliation cannot be empty"); - Preconditions.checkArgument(!city.isEmpty(), "city cannot be empty"); - Preconditions.checkArgument(!state.isEmpty(), "state cannot be empty"); - Preconditions.checkArgument(!country.isEmpty(), "country cannot be empty"); - Preconditions.checkArgument(!currency.isEmpty(), "currency cannot be empty"); - - Payload payload = new TrackerPayload(); - payload.add(Parameter.EVENT, Constants.EVENT_ECOMM); - payload.add(Parameter.TR_ID, order_id); - payload.add(Parameter.TR_TOTAL, Double.toString(total_value)); - payload.add(Parameter.TR_AFFILIATION, affiliation); - payload.add(Parameter.TR_TAX, Double.toString(tax_value)); - payload.add(Parameter.TR_SHIPPING, Double.toString(shipping)); - payload.add(Parameter.TR_CITY, city); - payload.add(Parameter.TR_STATE, state); - payload.add(Parameter.TR_COUNTRY, country); - payload.add(Parameter.TR_CURRENCY, currency); - - completePayload(payload, context, timestamp); - - for (TransactionItem item : items) { - trackEcommerceTransactionItem( - (String) item.get(Parameter.TI_ITEM_ID), - (String) item.get(Parameter.TI_ITEM_SKU), - (Double) item.get(Parameter.TI_ITEM_PRICE), - (Integer) item.get(Parameter.TI_ITEM_QUANTITY), - (String) item.get(Parameter.TI_ITEM_NAME), - (String) item.get(Parameter.TI_ITEM_CATEGORY), - (String) item.get(Parameter.TI_ITEM_CURRENCY), - (List) item.get(Parameter.CONTEXT), - timestamp); - } - - addTrackerPayload(payload); - } - - /** - * @param name The name of the screen view event - * @param id Screen view ID - */ - public void trackScreenView(String name, String id) { - trackScreenView(name, id, null, 0); - } - - /** - * @param name The name of the screen view event - * @param id Screen view ID - * @param context Custom context for the event - */ - public void trackScreenView(String name, String id, List context) { - trackScreenView(name, id, context, 0); - } - - /** - * @param name The name of the screen view event - * @param id Screen view ID - * @param timestamp Optional user-provided timestamp for the event - */ - public void trackScreenView(String name, String id, long timestamp) { - trackScreenView(name, id, null, timestamp); - } - - /** - * @param name The name of the screen view event - * @param id Screen view ID - * @param context Custom context for the event - * @param timestamp Optional user-provided timestamp for the event - */ - public void trackScreenView(String name, String id, List context, - long timestamp) { - Preconditions.checkArgument(name != null || id != null); - TrackerPayload trackerPayload = new TrackerPayload(); - - trackerPayload.add(Parameter.SV_NAME, name); - trackerPayload.add(Parameter.SV_ID, id); - - SchemaPayload payload = new SchemaPayload(); - payload.setSchema(Constants.SCHEMA_SCREEN_VIEW); - payload.setData(trackerPayload); - - trackUnstructuredEvent(payload, context, timestamp); - } -} diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/TransactionItem.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/TransactionItem.java deleted file mode 100644 index e4d756ad..00000000 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/TransactionItem.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -package com.snowplowanalytics.snowplow.tracker.core; - -import com.snowplowanalytics.snowplow.tracker.core.payload.SchemaPayload; - -import java.util.HashMap; -import java.util.List; - -public class TransactionItem extends HashMap { - - public TransactionItem (String order_id, String sku, double price, int quantity, String name, - String category, String currency) { - this(order_id,sku, price, quantity, name, category, currency, null); - } - - public TransactionItem (String order_id, String sku, double price, int quantity, String name, - String category, String currency, List context) { - put(Parameter.EVENT, "ti"); - put(Parameter.TI_ITEM_ID, order_id); - put(Parameter.TI_ITEM_SKU, sku); - put(Parameter.TI_ITEM_NAME, name); - put(Parameter.TI_ITEM_CATEGORY, category); - put(Parameter.TI_ITEM_PRICE, price); - put(Parameter.TI_ITEM_QUANTITY, quantity); - put(Parameter.TI_ITEM_CURRENCY, currency); - - put(Parameter.CONTEXT, context); - - put(Parameter.TIMESTAMP, Util.getTimestamp()); - } - - @SuppressWarnings({"unchecked", "ConstantConditions"}) - @Override - public Object put(Object key, Object value) { - if (value != null || value != "") return super.put(key, value); - else - return null; - } -} diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java deleted file mode 100644 index 6ebed462..00000000 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/Version.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -package com.snowplowanalytics.snowplow.tracker.core; - -// DO NOT EDIT. AUTO-GENERATED. -public class Version { - static final String TRACKER = "java-core-0.2.0"; - static final String VERSION = "0.2.0"; -} diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java deleted file mode 100644 index 99da104c..00000000 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/Emitter.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -package com.snowplowanalytics.snowplow.tracker.core.emitter; - -import com.snowplowanalytics.snowplow.tracker.core.Constants; -import com.snowplowanalytics.snowplow.tracker.core.payload.Payload; -import com.snowplowanalytics.snowplow.tracker.core.payload.SchemaPayload; - -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; -import org.apache.http.impl.nio.client.HttpAsyncClients; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -public class Emitter { - - private URIBuilder uri; - private RequestMethod requestMethod = RequestMethod.Synchronous; - private CloseableHttpClient httpClient; - private CloseableHttpAsyncClient httpAsyncClient; - private final ArrayList buffer = new ArrayList(); - - private final Logger logger = LoggerFactory.getLogger(Emitter.class); - - protected BufferOption option = BufferOption.Default; - protected RequestCallback requestCallback; - protected HttpMethod httpMethod = HttpMethod.GET; - - /** - * Default constructor does nothing. - */ - public Emitter() { - - } - - /** - * Create an Emitter instance with a collector URL. - * @param URI The collector URL. Don't include "http://" - this is done automatically. - */ - public Emitter(String URI) { - this(URI, HttpMethod.GET, null); - } - - /** - * Create an Emitter instance with a collector URL, and callback function. - * @param URI The collector URL. Don't include "http://" - this is done automatically. - * @param callback The callback function to handle success/failure cases when sending events. - */ - public Emitter(String URI, RequestCallback callback) { - this(URI, HttpMethod.GET, callback); - } - - /** - * Create an Emitter instance with a collector URL, - * @param URI The collector URL. Don't include "http://" - this is done automatically. - * @param httpMethod The HTTP request method. If GET, BufferOption is set to Instant. - */ - public Emitter(String URI, HttpMethod httpMethod) { - this(URI, httpMethod, null); - } - - /** - * Create an Emitter instance with a collector URL and HttpMethod to send requests. - * @param URI The collector URL. Don't include "http://" - this is done automatically. - * @param httpMethod The HTTP request method. If GET, BufferOption is set to Instant. - * @param callback The callback function to handle success/failure cases when sending events. - */ - public Emitter(String URI, HttpMethod httpMethod, RequestCallback callback) { - if (httpMethod == HttpMethod.GET) { - uri = new URIBuilder() - .setScheme("http") - .setHost(URI) - .setPath("/i"); - } else { // POST - uri = new URIBuilder() - .setScheme("http") - .setHost(URI) - .setPath("/" + Constants.PROTOCOL_VENDOR + "/" + Constants.PROTOCOL_VERSION); - } - this.requestCallback = callback; - this.httpMethod = httpMethod; - this.httpClient = HttpClients.createDefault(); - - if (httpMethod == HttpMethod.GET) { - this.setBufferOption(BufferOption.Instant); - } - - } - - /** - * Sets whether the buffer should send events instantly or after the buffer has reached - * it's limit. By default, this is set to BufferOption Default. - * @param option Set the BufferOption enum to Instant send events upon creation. - */ - public void setBufferOption(BufferOption option) { - this.option = option; - } - - /** - * Sets whether requests should be sent synchronously or asynchronously. - * @param option The HTTP request method - */ - public void setRequestMethod(RequestMethod option) { - this.requestMethod = option; - this.httpAsyncClient = HttpAsyncClients.createDefault(); - this.httpAsyncClient.start(); - } - - /** - * Add event payloads to the emitter's buffer - * @param payload Payload to be added - * @return Returns the boolean value if the event was successfully added to the buffer - */ - public boolean addToBuffer(Payload payload) { - boolean ret = buffer.add(payload); - if (buffer.size() == option.getCode()) - flushBuffer(); - return ret; - } - - /** - * Sends all events in the buffer to the collector. - */ - public void flushBuffer() { - if (buffer.isEmpty()) { - logger.debug("Buffer is empty, exiting flush operation.."); - return; - } - - if (httpMethod == HttpMethod.GET) { - int success_count = 0; - LinkedList unsentPayloads = new LinkedList(); - - for (Payload payload : buffer) { - int status_code = sendGetData(payload).getStatusLine().getStatusCode(); - if (status_code == 200) - success_count++; - else - unsentPayloads.add(payload); - } - - if (unsentPayloads.size() == 0) { - if (requestCallback != null) - requestCallback.onSuccess(success_count); - } - else if (requestCallback != null) - requestCallback.onFailure(success_count, unsentPayloads); - - } else if (httpMethod == HttpMethod.POST) { - LinkedList unsentPayload = new LinkedList(); - - SchemaPayload postPayload = new SchemaPayload(); - postPayload.setSchema(Constants.SCHEMA_PAYLOAD_DATA); - - ArrayList eventMaps = new ArrayList(); - for (Payload payload : buffer) { - eventMaps.add(payload.getMap()); - } - postPayload.setData(eventMaps); - - int status_code = sendPostData(postPayload).getStatusLine().getStatusCode(); - if (status_code == 200 && requestCallback != null) - requestCallback.onSuccess(buffer.size()); - else if (requestCallback != null){ - unsentPayload.add(postPayload); - requestCallback.onFailure(0, unsentPayload); - } - } - - // Empties current buffer - buffer.clear(); - } - - protected HttpResponse sendPostData(Payload payload) { - HttpPost httpPost = new HttpPost(uri.toString()); - httpPost.addHeader("Content-Type", "application/json; charset=utf-8"); - HttpResponse httpResponse = null; - - try { - StringEntity params = new StringEntity(payload.toString()); - httpPost.setEntity(params); - if (requestMethod == RequestMethod.Asynchronous) { - Future future = httpAsyncClient.execute(httpPost, null); - httpResponse = future.get(); - } else { - httpResponse = httpClient.execute(httpPost); - } - logger.debug(httpResponse.getStatusLine().toString()); - } catch (UnsupportedEncodingException e) { - logger.error("Encoding exception with the payload."); - e.printStackTrace(); - } catch (IOException e) { - logger.error("Error when sending HTTP POST."); - e.printStackTrace(); - } catch (InterruptedException e) { - logger.error("Interruption error when sending HTTP POST request."); - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - return httpResponse; - } - - @SuppressWarnings("unchecked") - protected HttpResponse sendGetData(Payload payload) { - HashMap hashMap = (HashMap) payload.getMap(); - Iterator iterator = hashMap.keySet().iterator(); - HttpResponse httpResponse = null; - - while (iterator.hasNext()) { - String key = iterator.next(); - String value = (String) hashMap.get(key); - uri.setParameter(key, value); - } - - try { - HttpGet httpGet = new HttpGet(uri.build()); - if (requestMethod == RequestMethod.Asynchronous) { - Future future = httpAsyncClient.execute(httpGet, null); - httpResponse = future.get(); - } else { - httpResponse = httpClient.execute(httpGet); - } - logger.debug(httpResponse.getStatusLine().toString()); - } catch (IOException e) { - logger.error("Error when sending HTTP GET error."); - e.printStackTrace(); - } catch (URISyntaxException e) { - logger.error("Error when creating HTTP GET request. Probably parsing error.."); - e.printStackTrace(); - } catch (InterruptedException e) { - logger.error("Interruption error when sending HTTP GET request."); - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - return httpResponse; - } -} diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java deleted file mode 100644 index 4ac6d763..00000000 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/SchemaPayload.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -package com.snowplowanalytics.snowplow.tracker.core.payload; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.snowplowanalytics.snowplow.tracker.core.Parameter; -import com.snowplowanalytics.snowplow.tracker.core.Util; -import com.snowplowanalytics.snowplow.tracker.core.util.Preconditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class SchemaPayload implements Payload { - - private final ObjectMapper objectMapper = Util.defaultMapper(); - private final Logger logger = LoggerFactory.getLogger(SchemaPayload.class); - private ObjectNode objectNode = objectMapper.createObjectNode(); - - public SchemaPayload() { } - - public SchemaPayload(Payload payload) { - ObjectNode data; - - if (payload.getClass() == TrackerPayload.class) { - logger.debug("Payload class is a TrackerPayload instance."); - logger.debug("Trying getNode()"); - data = (ObjectNode) payload.getNode(); - } else { - logger.debug("Converting Payload map to ObjectNode."); - data = objectMapper.valueToTree(payload.getMap()); - } - objectNode.set(Parameter.DATA, data); - } - - public SchemaPayload setSchema(String schema) { - Preconditions.checkNotNull(schema, "schema cannot be null"); - Preconditions.checkArgument(!schema.isEmpty(), "schema cannot be empty."); - - logger.debug("Setting schema: {}", schema); - objectNode.put(Parameter.SCHEMA, schema); - return this; - } - - public SchemaPayload setData(Payload data) { - try { - objectNode.putPOJO(Parameter.DATA, objectMapper.writeValueAsString(data.getMap())); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - return this; - } - - public SchemaPayload setData(Object data) { - try { - objectNode.putPOJO(Parameter.DATA, objectMapper.writeValueAsString(data)); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - return this; - } - - @Deprecated - @Override - public void add(String key, String value) { - /* - * We intentionally do nothing because we do not want our SchemaPayload - * to do anything except accept a 'data' and 'schema' - */ - logger.debug("add(String, String) method called: Doing nothing."); - } - - @Deprecated - @Override - public void add(String key, Object value) { - /* - * We intentionally do nothing because we do not want our SchemaPayload - * to do anything except accept a 'data' and 'schema' - */ - logger.debug("add(String, Object) method called: Doing nothing."); - } - - @Deprecated - @Override - public void addMap(Map map) { - /* - * We intentionally do nothing because we do not want our SchemaPayload - * to do anything except accept a 'data' and 'schema' - */ - logger.debug("addMap(Map) method called: Doing nothing."); - } - - @Deprecated - @Override - public void addMap(Map map, Boolean base64_encoded, String type_encoded, - String type_no_encoded) { - /* - * We intentionally do nothing because we do not want our SchemaPayload - * to do anything except accept a 'data' and 'schema' - */ - logger.debug("addMap(Map, Boolean, String, String) method called: Doing nothing."); - } - - public Map getMap() { - HashMap map = new HashMap(); - try { - map = objectMapper.readValue(objectNode.toString(), - new TypeReference(){}); - } catch (JsonMappingException e) { - e.printStackTrace(); - } catch (JsonParseException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return map; - } - - public JsonNode getNode() { return objectNode; } - - public String toString() { return objectNode.toString(); } -} diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/TrackerPayload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/TrackerPayload.java deleted file mode 100644 index 4a3cb354..00000000 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/TrackerPayload.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2014 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -package com.snowplowanalytics.snowplow.tracker.core.payload; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.snowplowanalytics.snowplow.tracker.core.Util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class TrackerPayload implements Payload { - - private final ObjectMapper objectMapper = Util.defaultMapper(); - private final Logger logger = LoggerFactory.getLogger(TrackerPayload.class); - private ObjectNode objectNode = objectMapper.createObjectNode(); - - @Override - public void add(String key, String value) { - if (value == null || value.isEmpty()) { - logger.debug("kv-value is empty. Returning out without adding key.."); - return; - } - - logger.debug("Adding new key: {} with value: {}", key, value); - objectNode.put(key, value); - } - - @Override - public void add(String key, Object value) { - if (value == null) { - logger.debug("kv-value is empty. Returning out without adding key.."); - return; - } - - logger.debug("Adding new key: {} with object value: {}", key, value); - try { - objectNode.putPOJO(key, objectMapper.writeValueAsString(value)); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - } - - @Override - public void addMap(Map map) { - // Return if we don't have a map - if (map == null) { - logger.debug("Map passed in is null. Returning without adding map.."); - return; - } - - Set keys = map.keySet(); - for(String key : keys) { - add(key, map.get(key)); - } - } - - @Override - public void addMap(Map map, Boolean base64_encoded, String type_encoded, String type_no_encoded) { - // Return if we don't have a map - if (map == null) { - logger.debug("Map passed in is null. Returning nothing.."); - return; - } - - String mapString; - try { - mapString = objectMapper.writeValueAsString(map); - } catch (JsonProcessingException e) { - e.printStackTrace(); - return; // Return because we can't continue - } - - if (base64_encoded) { // base64 encoded data - objectNode.put(type_encoded, Util.base64Encode(mapString)); - } else { // add it as a child node - add(type_no_encoded, mapString); - } - } - - public JsonNode getNode() { - return objectNode; - } - - @Override - public Map getMap() { - HashMap map = new HashMap(); - try { - logger.debug("Attempting to create a Map structure from ObjectNode."); - map = objectMapper.readValue(objectNode.toString(), new TypeReference(){}); - } catch (JsonMappingException e) { - e.printStackTrace(); - } catch (JsonParseException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return map; - } - - @Override - public String toString() { - return objectNode.toString(); - } -} diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/BufferOption.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/BufferOption.java similarity index 95% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/BufferOption.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/BufferOption.java index bcbcdcea..d9e67f04 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/BufferOption.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/BufferOption.java @@ -11,7 +11,7 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -package com.snowplowanalytics.snowplow.tracker.core.emitter; +package com.snowplowanalytics.snowplow.tracker.emitter; /** * BufferOption is used to set the buffer size of your Emitter. diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/Emitter.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/Emitter.java index ff8f911c..40c3baa0 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/Emitter.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/Emitter.java @@ -13,17 +13,55 @@ package com.snowplowanalytics.snowplow.tracker.emitter; -import com.snowplowanalytics.snowplow.tracker.core.emitter.HttpMethod; -import com.snowplowanalytics.snowplow.tracker.core.emitter.RequestCallback; +import com.snowplowanalytics.snowplow.tracker.Constants; +import com.snowplowanalytics.snowplow.tracker.payload.Payload; +import com.snowplowanalytics.snowplow.tracker.payload.SchemaPayload; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; +import org.apache.http.impl.nio.client.HttpAsyncClients; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public class Emitter extends com.snowplowanalytics.snowplow.tracker.core.emitter.Emitter { +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public class Emitter { + + private URIBuilder uri; + private RequestMethod requestMethod = RequestMethod.Synchronous; + private CloseableHttpClient httpClient; + private CloseableHttpAsyncClient httpAsyncClient; + private final ArrayList buffer = new ArrayList(); + + private final Logger logger = LoggerFactory.getLogger(Emitter.class); + + protected BufferOption option = BufferOption.Default; + protected RequestCallback requestCallback; + protected HttpMethod httpMethod = HttpMethod.GET; + + /** + * Default constructor does nothing. + */ + public Emitter() { + + } /** * Create an Emitter instance with a collector URL. * @param URI The collector URL. Don't include "http://" - this is done automatically. */ public Emitter(String URI) { - super(URI); + this(URI, HttpMethod.GET, null); } /** @@ -32,7 +70,7 @@ public Emitter(String URI) { * @param callback The callback function to handle success/failure cases when sending events. */ public Emitter(String URI, RequestCallback callback) { - super(URI, callback); + this(URI, HttpMethod.GET, callback); } /** @@ -41,7 +79,7 @@ public Emitter(String URI, RequestCallback callback) { * @param httpMethod The HTTP request method. If GET, BufferOption is set to Instant. */ public Emitter(String URI, HttpMethod httpMethod) { - super(URI, httpMethod); + this(URI, httpMethod, null); } /** @@ -51,6 +89,174 @@ public Emitter(String URI, HttpMethod httpMethod) { * @param callback The callback function to handle success/failure cases when sending events. */ public Emitter(String URI, HttpMethod httpMethod, RequestCallback callback) { - super(URI, httpMethod, callback); + if (httpMethod == HttpMethod.GET) { + uri = new URIBuilder() + .setScheme("http") + .setHost(URI) + .setPath("/i"); + } else { // POST + uri = new URIBuilder() + .setScheme("http") + .setHost(URI) + .setPath("/" + Constants.PROTOCOL_VENDOR + "/" + Constants.PROTOCOL_VERSION); + } + this.requestCallback = callback; + this.httpMethod = httpMethod; + this.httpClient = HttpClients.createDefault(); + + if (httpMethod == HttpMethod.GET) { + this.setBufferOption(BufferOption.Instant); + } + + } + + /** + * Sets whether the buffer should send events instantly or after the buffer has reached + * it's limit. By default, this is set to BufferOption Default. + * @param option Set the BufferOption enum to Instant send events upon creation. + */ + public void setBufferOption(BufferOption option) { + this.option = option; + } + + /** + * Sets whether requests should be sent synchronously or asynchronously. + * @param option The HTTP request method + */ + public void setRequestMethod(RequestMethod option) { + this.requestMethod = option; + this.httpAsyncClient = HttpAsyncClients.createDefault(); + this.httpAsyncClient.start(); + } + + /** + * Add event payloads to the emitter's buffer + * @param payload Payload to be added + * @return Returns the boolean value if the event was successfully added to the buffer + */ + public boolean addToBuffer(Payload payload) { + boolean ret = buffer.add(payload); + if (buffer.size() == option.getCode()) + flushBuffer(); + return ret; + } + + /** + * Sends all events in the buffer to the collector. + */ + public void flushBuffer() { + if (buffer.isEmpty()) { + logger.debug("Buffer is empty, exiting flush operation.."); + return; + } + + if (httpMethod == HttpMethod.GET) { + int success_count = 0; + LinkedList unsentPayloads = new LinkedList(); + + for (Payload payload : buffer) { + int status_code = sendGetData(payload).getStatusLine().getStatusCode(); + if (status_code == 200) + success_count++; + else + unsentPayloads.add(payload); + } + + if (unsentPayloads.size() == 0) { + if (requestCallback != null) + requestCallback.onSuccess(success_count); + } + else if (requestCallback != null) + requestCallback.onFailure(success_count, unsentPayloads); + + } else if (httpMethod == HttpMethod.POST) { + LinkedList unsentPayload = new LinkedList(); + + SchemaPayload postPayload = new SchemaPayload(); + postPayload.setSchema(Constants.SCHEMA_PAYLOAD_DATA); + + ArrayList eventMaps = new ArrayList(); + for (Payload payload : buffer) { + eventMaps.add(payload.getMap()); + } + postPayload.setData(eventMaps); + + int status_code = sendPostData(postPayload).getStatusLine().getStatusCode(); + if (status_code == 200 && requestCallback != null) + requestCallback.onSuccess(buffer.size()); + else if (requestCallback != null){ + unsentPayload.add(postPayload); + requestCallback.onFailure(0, unsentPayload); + } + } + + // Empties current buffer + buffer.clear(); + } + + protected HttpResponse sendPostData(Payload payload) { + HttpPost httpPost = new HttpPost(uri.toString()); + httpPost.addHeader("Content-Type", "application/json; charset=utf-8"); + HttpResponse httpResponse = null; + + try { + StringEntity params = new StringEntity(payload.toString()); + httpPost.setEntity(params); + if (requestMethod == RequestMethod.Asynchronous) { + Future future = httpAsyncClient.execute(httpPost, null); + httpResponse = future.get(); + } else { + httpResponse = httpClient.execute(httpPost); + } + logger.debug(httpResponse.getStatusLine().toString()); + } catch (UnsupportedEncodingException e) { + logger.error("Encoding exception with the payload."); + e.printStackTrace(); + } catch (IOException e) { + logger.error("Error when sending HTTP POST."); + e.printStackTrace(); + } catch (InterruptedException e) { + logger.error("Interruption error when sending HTTP POST request."); + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + return httpResponse; + } + + @SuppressWarnings("unchecked") + protected HttpResponse sendGetData(Payload payload) { + HashMap hashMap = (HashMap) payload.getMap(); + Iterator iterator = hashMap.keySet().iterator(); + HttpResponse httpResponse = null; + + while (iterator.hasNext()) { + String key = iterator.next(); + String value = (String) hashMap.get(key); + uri.setParameter(key, value); + } + + try { + HttpGet httpGet = new HttpGet(uri.build()); + if (requestMethod == RequestMethod.Asynchronous) { + Future future = httpAsyncClient.execute(httpGet, null); + httpResponse = future.get(); + } else { + httpResponse = httpClient.execute(httpGet); + } + logger.debug(httpResponse.getStatusLine().toString()); + } catch (IOException e) { + logger.error("Error when sending HTTP GET error."); + e.printStackTrace(); + } catch (URISyntaxException e) { + logger.error("Error when creating HTTP GET request. Probably parsing error.."); + e.printStackTrace(); + } catch (InterruptedException e) { + logger.error("Interruption error when sending HTTP GET request."); + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + return httpResponse; } } diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/HttpMethod.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/HttpMethod.java similarity index 94% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/HttpMethod.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/HttpMethod.java index 70350b6f..1204c163 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/HttpMethod.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/HttpMethod.java @@ -11,7 +11,7 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -package com.snowplowanalytics.snowplow.tracker.core.emitter; +package com.snowplowanalytics.snowplow.tracker.emitter; /** * HttpMethod is used to set the request method for your Emitter (i.e. GET or POST requests). diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestCallback.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/RequestCallback.java similarity index 87% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestCallback.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/RequestCallback.java index 035668a6..e73c6689 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestCallback.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/RequestCallback.java @@ -11,9 +11,9 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -package com.snowplowanalytics.snowplow.tracker.core.emitter; +package com.snowplowanalytics.snowplow.tracker.emitter; -import com.snowplowanalytics.snowplow.tracker.core.payload.Payload; +import com.snowplowanalytics.snowplow.tracker.payload.Payload; import java.util.List; diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestMethod.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/RequestMethod.java similarity index 94% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestMethod.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/RequestMethod.java index 68e14096..e7a0cfd6 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/emitter/RequestMethod.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/emitter/RequestMethod.java @@ -11,7 +11,7 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -package com.snowplowanalytics.snowplow.tracker.core.emitter; +package com.snowplowanalytics.snowplow.tracker.emitter; /** * RequestMethod is used to choose how network requests should be sent. diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/Payload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/Payload.java similarity index 97% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/Payload.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/payload/Payload.java index eeba53a5..b656a862 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/payload/Payload.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/Payload.java @@ -11,13 +11,15 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -package com.snowplowanalytics.snowplow.tracker.core.payload; +package com.snowplowanalytics.snowplow.tracker.payload; // Java + +import com.fasterxml.jackson.databind.JsonNode; + import java.util.Map; // JSON -import com.fasterxml.jackson.databind.JsonNode; /** * Payload interface diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java index e825f202..34f9663c 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java @@ -13,6 +13,129 @@ package com.snowplowanalytics.snowplow.tracker.payload; -public class SchemaPayload - extends com.snowplowanalytics.snowplow.tracker.core.payload.SchemaPayload { +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.snowplowanalytics.snowplow.tracker.Parameter; +import com.snowplowanalytics.snowplow.tracker.Util; +import com.snowplowanalytics.snowplow.tracker.util.Preconditions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class SchemaPayload implements Payload { + + private final ObjectMapper objectMapper = Util.defaultMapper(); + private final Logger LOGGER = LoggerFactory.getLogger(SchemaPayload.class); + private ObjectNode objectNode = objectMapper.createObjectNode(); + + public SchemaPayload() { } + + public SchemaPayload(Payload payload) { + ObjectNode data; + + if (payload.getClass() == TrackerPayload.class) { + LOGGER.debug("Payload class is a TrackerPayload instance."); + LOGGER.debug("Trying getNode()"); + data = (ObjectNode) payload.getNode(); + } else { + LOGGER.debug("Converting Payload map to ObjectNode."); + data = objectMapper.valueToTree(payload.getMap()); + } + objectNode.set(Parameter.DATA, data); + } + + public SchemaPayload setSchema(String schema) { + Preconditions.checkNotNull(schema, "schema cannot be null"); + Preconditions.checkArgument(!schema.isEmpty(), "schema cannot be empty."); + + LOGGER.debug("Setting schema: {}", schema); + objectNode.put(Parameter.SCHEMA, schema); + return this; + } + + public SchemaPayload setData(Payload data) { + try { + objectNode.putPOJO(Parameter.DATA, objectMapper.writeValueAsString(data.getMap())); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + return this; + } + + public SchemaPayload setData(Object data) { + try { + objectNode.putPOJO(Parameter.DATA, objectMapper.writeValueAsString(data)); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + return this; + } + + @Deprecated + @Override + public void add(String key, String value) { + /* + * We intentionally do nothing because we do not want our SchemaPayload + * to do anything except accept a 'data' and 'schema' + */ + LOGGER.debug("add(String, String) method called: Doing nothing."); + } + + @Deprecated + @Override + public void add(String key, Object value) { + /* + * We intentionally do nothing because we do not want our SchemaPayload + * to do anything except accept a 'data' and 'schema' + */ + LOGGER.debug("add(String, Object) method called: Doing nothing."); + } + + @Deprecated + @Override + public void addMap(Map map) { + /* + * We intentionally do nothing because we do not want our SchemaPayload + * to do anything except accept a 'data' and 'schema' + */ + LOGGER.debug("addMap(Map) method called: Doing nothing."); + } + + @Deprecated + @Override + public void addMap(Map map, Boolean base64_encoded, String type_encoded, + String type_no_encoded) { + /* + * We intentionally do nothing because we do not want our SchemaPayload + * to do anything except accept a 'data' and 'schema' + */ + LOGGER.debug("addMap(Map, Boolean, String, String) method called: Doing nothing."); + } + + public Map getMap() { + HashMap map = new HashMap(); + try { + map = objectMapper.readValue(objectNode.toString(), + new TypeReference(){}); + } catch (JsonMappingException e) { + e.printStackTrace(); + } catch (JsonParseException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return map; + } + + public JsonNode getNode() { return objectNode; } + + public String toString() { return objectNode.toString(); } } diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/TrackerPayload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/TrackerPayload.java index 0ca4ccbf..cce1927f 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/TrackerPayload.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/TrackerPayload.java @@ -13,6 +13,113 @@ package com.snowplowanalytics.snowplow.tracker.payload; -public class TrackerPayload - extends com.snowplowanalytics.snowplow.tracker.core.payload.TrackerPayload { +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.snowplowanalytics.snowplow.tracker.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class TrackerPayload implements Payload { + + private final ObjectMapper objectMapper = Util.defaultMapper(); + private final Logger LOGGER = LoggerFactory.getLogger(TrackerPayload.class); + private ObjectNode objectNode = objectMapper.createObjectNode(); + + @Override + public void add(String key, String value) { + if (value == null || value.isEmpty()) { + LOGGER.debug("kv-value is empty. Returning out without adding key.."); + return; + } + + LOGGER.debug("Adding new key: {} with value: {}", key, value); + objectNode.put(key, value); + } + + @Override + public void add(String key, Object value) { + if (value == null) { + LOGGER.debug("kv-value is empty. Returning out without adding key.."); + return; + } + + LOGGER.debug("Adding new key: {} with object value: {}", key, value); + try { + objectNode.putPOJO(key, objectMapper.writeValueAsString(value)); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + } + + @Override + public void addMap(Map map) { + // Return if we don't have a map + if (map == null) { + LOGGER.debug("Map passed in is null. Returning without adding map.."); + return; + } + + Set keys = map.keySet(); + for(String key : keys) { + add(key, map.get(key)); + } + } + + @Override + public void addMap(Map map, Boolean base64_encoded, String type_encoded, String type_no_encoded) { + // Return if we don't have a map + if (map == null) { + LOGGER.debug("Map passed in is null. Returning nothing.."); + return; + } + + String mapString; + try { + mapString = objectMapper.writeValueAsString(map); + } catch (JsonProcessingException e) { + e.printStackTrace(); + return; // Return because we can't continue + } + + if (base64_encoded) { // base64 encoded data + objectNode.put(type_encoded, Util.base64Encode(mapString)); + } else { // add it as a child node + add(type_no_encoded, mapString); + } + } + + public JsonNode getNode() { + return objectNode; + } + + @Override + public Map getMap() { + HashMap map = new HashMap(); + try { + LOGGER.debug("Attempting to create a Map structure from ObjectNode."); + map = objectMapper.readValue(objectNode.toString(), new TypeReference(){}); + } catch (JsonMappingException e) { + e.printStackTrace(); + } catch (JsonParseException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return map; + } + + @Override + public String toString() { + return objectNode.toString(); + } } diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/util/Preconditions.java similarity index 99% rename from src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java rename to src/main/java/com/snowplowanalytics/snowplow/tracker/util/Preconditions.java index bad5245e..86443bd5 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/core/util/Preconditions.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/util/Preconditions.java @@ -1,4 +1,4 @@ -package com.snowplowanalytics.snowplow.tracker.core.util; +package com.snowplowanalytics.snowplow.tracker.util; /** * Note: diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java index 9fa74505..ed0e7839 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java @@ -1,8 +1,8 @@ package com.snowplowanalytics.snowplow.tracker; -import com.snowplowanalytics.snowplow.tracker.core.emitter.*; -import com.snowplowanalytics.snowplow.tracker.core.payload.Payload; -import com.snowplowanalytics.snowplow.tracker.core.payload.TrackerPayload; +import com.snowplowanalytics.snowplow.tracker.emitter.*; +import com.snowplowanalytics.snowplow.tracker.payload.Payload; +import com.snowplowanalytics.snowplow.tracker.payload.TrackerPayload; import org.junit.Test; import java.util.ArrayList; diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java index ed799dcb..8c26db7b 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/SubjectTest.java @@ -1,6 +1,5 @@ package com.snowplowanalytics.snowplow.tracker; -import com.snowplowanalytics.snowplow.tracker.core.Subject; import org.junit.Test; import java.util.HashMap; diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java index 6569a365..6423363d 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java @@ -1,10 +1,8 @@ package com.snowplowanalytics.snowplow.tracker; -import com.snowplowanalytics.snowplow.tracker.core.payload.Payload; -import com.snowplowanalytics.snowplow.tracker.core.payload.SchemaPayload; -import com.snowplowanalytics.snowplow.tracker.core.payload.TrackerPayload; - - +import com.snowplowanalytics.snowplow.tracker.payload.Payload; +import com.snowplowanalytics.snowplow.tracker.payload.SchemaPayload; +import com.snowplowanalytics.snowplow.tracker.payload.TrackerPayload; import org.junit.Test; import java.util.ArrayList; diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java index fc47dbb7..f25e292c 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java @@ -1,14 +1,10 @@ package com.snowplowanalytics.snowplow.tracker; -import com.snowplowanalytics.snowplow.tracker.core.DevicePlatform; -import com.snowplowanalytics.snowplow.tracker.core.Subject; -import com.snowplowanalytics.snowplow.tracker.core.Tracker; -import com.snowplowanalytics.snowplow.tracker.core.TransactionItem; -import com.snowplowanalytics.snowplow.tracker.core.emitter.BufferOption; -import com.snowplowanalytics.snowplow.tracker.core.emitter.Emitter; -import com.snowplowanalytics.snowplow.tracker.core.emitter.HttpMethod; -import com.snowplowanalytics.snowplow.tracker.core.emitter.RequestMethod; -import com.snowplowanalytics.snowplow.tracker.core.payload.SchemaPayload; +import com.snowplowanalytics.snowplow.tracker.emitter.BufferOption; +import com.snowplowanalytics.snowplow.tracker.emitter.Emitter; +import com.snowplowanalytics.snowplow.tracker.emitter.HttpMethod; +import com.snowplowanalytics.snowplow.tracker.emitter.RequestMethod; +import com.snowplowanalytics.snowplow.tracker.payload.SchemaPayload; import org.junit.Test; import java.util.*; diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java index c4ca10f6..31d25def 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java @@ -1,7 +1,6 @@ package com.snowplowanalytics.snowplow.tracker; import com.fasterxml.jackson.databind.JsonNode; -import com.snowplowanalytics.snowplow.tracker.core.Util; import org.junit.Test; import java.util.ArrayList; From ac2b9d98e0279c83cf3d8b8a7298765dd24f594e Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 24 Jan 2015 01:20:59 +0000 Subject: [PATCH 27/37] Added Guava back as a dependency (closes #123) --- build.gradle | 3 + .../snowplow/tracker/Tracker.java | 3 +- .../tracker/payload/SchemaPayload.java | 3 +- .../snowplow/tracker/util/Preconditions.java | 437 ------------------ 4 files changed, 7 insertions(+), 439 deletions(-) delete mode 100644 src/main/java/com/snowplowanalytics/snowplow/tracker/util/Preconditions.java diff --git a/build.gradle b/build.gradle index 9bde5cbd..06059104 100644 --- a/build.gradle +++ b/build.gradle @@ -41,6 +41,9 @@ dependencies { // Jackson JSON processor compile 'com.fasterxml.jackson.core:jackson-databind:2.4.1.1' + // Preconditions + compile 'com.google.guava:guava:17.0' + testCompile 'junit:junit:4.11' } diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java index 27d57299..58ee4b09 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java @@ -17,7 +17,8 @@ import com.snowplowanalytics.snowplow.tracker.payload.Payload; import com.snowplowanalytics.snowplow.tracker.payload.SchemaPayload; import com.snowplowanalytics.snowplow.tracker.payload.TrackerPayload; -import com.snowplowanalytics.snowplow.tracker.util.Preconditions; + +import com.google.common.base.Preconditions; import java.util.HashMap; import java.util.LinkedList; diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java index 34f9663c..9a988fc0 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java @@ -22,10 +22,11 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.snowplowanalytics.snowplow.tracker.Parameter; import com.snowplowanalytics.snowplow.tracker.Util; -import com.snowplowanalytics.snowplow.tracker.util.Preconditions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Preconditions; + import java.io.IOException; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/util/Preconditions.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/util/Preconditions.java deleted file mode 100644 index 86443bd5..00000000 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/util/Preconditions.java +++ /dev/null @@ -1,437 +0,0 @@ -package com.snowplowanalytics.snowplow.tracker.util; - -/** - * Note: - * - * This has been copy/pasted from Guava with modifications to avoid including the whole library. - * Original source: https://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/base/Preconditions.java - */ - -/* - * Copyright (C) 2007 The Guava Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -/** - * Static convenience methods that help a method or constructor check whether it was invoked - * correctly (whether its preconditions have been met). These methods generally accept a - * {@code boolean} expression which is expected to be {@code true} (or in the case of {@code - * checkNotNull}, an object reference which is expected to be non-null). When {@code false} (or - * {@code null}) is passed instead, the {@code Preconditions} method throws an unchecked exception, - * which helps the calling method communicate to its caller that that caller has made - * a mistake. Example:

   {@code
- *
- *   /**
- *    * Returns the positive square root of the given value.
- *    *
- *    * @throws IllegalArgumentException if the value is negative
- *    *}{@code /
- *   public static double sqrt(double value) {
- *     Preconditions.checkArgument(value >= 0.0, "negative value: %s", value);
- *     // calculate the square root
- *   }
- *
- *   void exampleBadCaller() {
- *     double d = sqrt(-1.0);
- *   }}
- * - * In this example, {@code checkArgument} throws an {@code IllegalArgumentException} to indicate - * that {@code exampleBadCaller} made an error in its call to {@code sqrt}. - * - *

Warning about performance

- * - *

The goal of this class is to improve readability of code, but in some circumstances this may - * come at a significant performance cost. Remember that parameter values for message construction - * must all be computed eagerly, and autoboxing and varargs array creation may happen as well, even - * when the precondition check then succeeds (as it should almost always do in production). In some - * circumstances these wasted CPU cycles and allocations can add up to a real problem. - * Performance-sensitive precondition checks can always be converted to the customary form: - *

   {@code
- *
- *   if (value < 0.0) {
- *     throw new IllegalArgumentException("negative value: " + value);
- *   }}
- * - *

Other types of preconditions

- * - *

Not every type of precondition failure is supported by these methods. Continue to throw - * standard JDK exceptions such as {@link java.util.NoSuchElementException} or {@link - * UnsupportedOperationException} in the situations they are intended for. - * - *

Non-preconditions

- * - *

It is of course possible to use the methods of this class to check for invalid conditions - * which are not the caller's fault. Doing so is not recommended because it is - * misleading to future readers of the code and of stack traces. See - * Conditional - * failures explained in the Guava User Guide for more advice. - * - *

{@code java.util.Objects.requireNonNull()}

- * - *

Only {@code %s} is supported

- * - *

In {@code Preconditions} error message template strings, only the {@code "%s"} specifier is - * supported, not the full range of {@link java.util.Formatter} specifiers. - * - *

More information

- * - *

See the Guava User Guide on - * using {@code - * Preconditions}. - * - * @author Kevin Bourrillion - * @since 2.0 (imported from Google Collections Library) - */ -public final class Preconditions { - private Preconditions() {} - - /** - * Ensures the truth of an expression involving one or more parameters to the calling method. - * - * @param expression a boolean expression - * @throws IllegalArgumentException if {@code expression} is false - */ - public static void checkArgument(boolean expression) { - if (!expression) { - throw new IllegalArgumentException(); - } - } - - /** - * Ensures the truth of an expression involving one or more parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessage the exception message to use if the check fails; will be converted to a - * string using {@link String#valueOf(Object)} - * @throws IllegalArgumentException if {@code expression} is false - */ - public static void checkArgument(boolean expression, Object errorMessage) { - if (!expression) { - throw new IllegalArgumentException(String.valueOf(errorMessage)); - } - } - - /** - * Ensures the truth of an expression involving one or more parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessageTemplate a template for the exception message should the check fail. The - * message is formed by replacing each {@code %s} placeholder in the template with an - * argument. These are matched by position - the first {@code %s} gets {@code - * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message - * in square braces. Unmatched placeholders will be left as-is. - * @param errorMessageArgs the arguments to be substituted into the message template. Arguments - * are converted to strings using {@link String#valueOf(Object)}. - * @throws IllegalArgumentException if {@code expression} is false - * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or - * {@code errorMessageArgs} is null (don't let this happen) - */ - public static void checkArgument(boolean expression, - String errorMessageTemplate, - Object... errorMessageArgs) { - if (!expression) { - throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs)); - } - } - - /** - * Ensures the truth of an expression involving the state of the calling instance, but not - * involving any parameters to the calling method. - * - * @param expression a boolean expression - * @throws IllegalStateException if {@code expression} is false - */ - public static void checkState(boolean expression) { - if (!expression) { - throw new IllegalStateException(); - } - } - - /** - * Ensures the truth of an expression involving the state of the calling instance, but not - * involving any parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessage the exception message to use if the check fails; will be converted to a - * string using {@link String#valueOf(Object)} - * @throws IllegalStateException if {@code expression} is false - */ - public static void checkState(boolean expression, Object errorMessage) { - if (!expression) { - throw new IllegalStateException(String.valueOf(errorMessage)); - } - } - - /** - * Ensures the truth of an expression involving the state of the calling instance, but not - * involving any parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessageTemplate a template for the exception message should the check fail. The - * message is formed by replacing each {@code %s} placeholder in the template with an - * argument. These are matched by position - the first {@code %s} gets {@code - * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message - * in square braces. Unmatched placeholders will be left as-is. - * @param errorMessageArgs the arguments to be substituted into the message template. Arguments - * are converted to strings using {@link String#valueOf(Object)}. - * @throws IllegalStateException if {@code expression} is false - * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or - * {@code errorMessageArgs} is null (don't let this happen) - */ - public static void checkState(boolean expression, - String errorMessageTemplate, - Object... errorMessageArgs) { - if (!expression) { - throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs)); - } - } - - /** - * Ensures that an object reference passed as a parameter to the calling method is not null. - * - * @param reference an object reference - * @return the non-null reference that was validated - * @throws NullPointerException if {@code reference} is null - */ - public static T checkNotNull(T reference) { - if (reference == null) { - throw new NullPointerException(); - } - return reference; - } - - /** - * Ensures that an object reference passed as a parameter to the calling method is not null. - * - * @param reference an object reference - * @param errorMessage the exception message to use if the check fails; will be converted to a - * string using {@link String#valueOf(Object)} - * @return the non-null reference that was validated - * @throws NullPointerException if {@code reference} is null - */ - public static T checkNotNull(T reference, Object errorMessage) { - if (reference == null) { - throw new NullPointerException(String.valueOf(errorMessage)); - } - return reference; - } - - /** - * Ensures that an object reference passed as a parameter to the calling method is not null. - * - * @param reference an object reference - * @param errorMessageTemplate a template for the exception message should the check fail. The - * message is formed by replacing each {@code %s} placeholder in the template with an - * argument. These are matched by position - the first {@code %s} gets {@code - * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message - * in square braces. Unmatched placeholders will be left as-is. - * @param errorMessageArgs the arguments to be substituted into the message template. Arguments - * are converted to strings using {@link String#valueOf(Object)}. - * @return the non-null reference that was validated - * @throws NullPointerException if {@code reference} is null - */ - public static T checkNotNull(T reference, - String errorMessageTemplate, - Object... errorMessageArgs) { - if (reference == null) { - // If either of these parameters is null, the right thing happens anyway - throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs)); - } - return reference; - } - - /* - * All recent hotspots (as of 2009) *really* like to have the natural code - * - * if (guardExpression) { - * throw new BadException(messageExpression); - * } - * - * refactored so that messageExpression is moved to a separate String-returning method. - * - * if (guardExpression) { - * throw new BadException(badMsg(...)); - * } - * - * The alternative natural refactorings into void or Exception-returning methods are much slower. - * This is a big deal - we're talking factors of 2-8 in microbenchmarks, not just 10-20%. (This - * is a hotspot optimizer bug, which should be fixed, but that's a separate, big project). - * - * The coding pattern above is heavily used in java.util, e.g. in ArrayList. There is a - * RangeCheckMicroBenchmark in the JDK that was used to test this. - * - * But the methods in this class want to throw different exceptions, depending on the args, so it - * appears that this pattern is not directly applicable. But we can use the ridiculous, devious - * trick of throwing an exception in the middle of the construction of another exception. Hotspot - * is fine with that. - */ - - /** - * Ensures that {@code index} specifies a valid element in an array, list or string of size - * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. - * - * @param index a user-supplied index identifying an element of an array, list or string - * @param size the size of that array, list or string - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static int checkElementIndex(int index, int size) { - return checkElementIndex(index, size, "index"); - } - - /** - * Ensures that {@code index} specifies a valid element in an array, list or string of size - * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. - * - * @param index a user-supplied index identifying an element of an array, list or string - * @param size the size of that array, list or string - * @param desc the text to use to describe this index in an error message - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static int checkElementIndex( - int index, int size, String desc) { - // Carefully optimized for execution by hotspot (explanatory comment above) - if (index < 0 || index >= size) { - throw new IndexOutOfBoundsException(badElementIndex(index, size, desc)); - } - return index; - } - - private static String badElementIndex(int index, int size, String desc) { - if (index < 0) { - return format("%s (%s) must not be negative", desc, index); - } else if (size < 0) { - throw new IllegalArgumentException("negative size: " + size); - } else { // index >= size - return format("%s (%s) must be less than size (%s)", desc, index, size); - } - } - - /** - * Ensures that {@code index} specifies a valid position in an array, list or string of - * size {@code size}. A position index may range from zero to {@code size}, inclusive. - * - * @param index a user-supplied index identifying a position in an array, list or string - * @param size the size of that array, list or string - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static int checkPositionIndex(int index, int size) { - return checkPositionIndex(index, size, "index"); - } - - /** - * Ensures that {@code index} specifies a valid position in an array, list or string of - * size {@code size}. A position index may range from zero to {@code size}, inclusive. - * - * @param index a user-supplied index identifying a position in an array, list or string - * @param size the size of that array, list or string - * @param desc the text to use to describe this index in an error message - * @return the value of {@code index} - * @throws IndexOutOfBoundsException if {@code index} is negative or is greater than {@code size} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static int checkPositionIndex(int index, int size, String desc) { - // Carefully optimized for execution by hotspot (explanatory comment above) - if (index < 0 || index > size) { - throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc)); - } - return index; - } - - private static String badPositionIndex(int index, int size, String desc) { - if (index < 0) { - return format("%s (%s) must not be negative", desc, index); - } else if (size < 0) { - throw new IllegalArgumentException("negative size: " + size); - } else { // index > size - return format("%s (%s) must not be greater than size (%s)", desc, index, size); - } - } - - /** - * Ensures that {@code start} and {@code end} specify a valid positions in an array, list - * or string of size {@code size}, and are in order. A position index may range from zero to - * {@code size}, inclusive. - * - * @param start a user-supplied index identifying a starting position in an array, list or string - * @param end a user-supplied index identifying a ending position in an array, list or string - * @param size the size of that array, list or string - * @throws IndexOutOfBoundsException if either index is negative or is greater than {@code size}, - * or if {@code end} is less than {@code start} - * @throws IllegalArgumentException if {@code size} is negative - */ - public static void checkPositionIndexes(int start, int end, int size) { - // Carefully optimized for execution by hotspot (explanatory comment above) - if (start < 0 || end < start || end > size) { - throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); - } - } - - private static String badPositionIndexes(int start, int end, int size) { - if (start < 0 || start > size) { - return badPositionIndex(start, size, "start index"); - } - if (end < 0 || end > size) { - return badPositionIndex(end, size, "end index"); - } - // end < start - return format("end index (%s) must not be less than start index (%s)", end, start); - } - - /** - * Substitutes each {@code %s} in {@code template} with an argument. These are matched by - * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than - * placeholders, the unmatched arguments will be appended to the end of the formatted message in - * square braces. - * - * @param template a non-null string containing 0 or more {@code %s} placeholders. - * @param args the arguments to be substituted into the message template. Arguments are converted - * to strings using {@link String#valueOf(Object)}. Arguments can be null. - */ - // Note that this is somewhat-improperly used from Verify.java as well. - static String format(String template, Object... args) { - template = String.valueOf(template); // null -> "null" - - // start substituting the arguments into the '%s' placeholders - StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); - int templateStart = 0; - int i = 0; - while (i < args.length) { - int placeholderStart = template.indexOf("%s", templateStart); - if (placeholderStart == -1) { - break; - } - builder.append(template.substring(templateStart, placeholderStart)); - builder.append(args[i++]); - templateStart = placeholderStart + 2; - } - builder.append(template.substring(templateStart)); - - // if we run out of placeholders, append the extra args in square braces - if (i < args.length) { - builder.append(" ["); - builder.append(args[i++]); - while (i < args.length) { - builder.append(", "); - builder.append(args[i++]); - } - builder.append(']'); - } - - return builder.toString(); - } -} \ No newline at end of file From 78823da8a6c22772182fe12f4b0cf6aad3b78e61 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 24 Jan 2015 01:45:19 +0000 Subject: [PATCH 28/37] Replaced homebrew Base64 implementation with Apache Commons Codec (closes #122) --- .../snowplow/tracker/Base64.java | 261 ------------------ .../snowplow/tracker/Util.java | 13 +- 2 files changed, 6 insertions(+), 268 deletions(-) delete mode 100644 src/main/java/com/snowplowanalytics/snowplow/tracker/Base64.java diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/Base64.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Base64.java deleted file mode 100644 index 1975fb79..00000000 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/Base64.java +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Copyright 2005-2013 Karl Roberts - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of his contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -package com.snowplowanalytics.snowplow.tracker; - -import java.io.UnsupportedEncodingException; - -/** - * Author: karl roberts - * Date: 2-Mar-2005 - * Time: 15:34:26 - * - * Thanks to Tom Daley who posted the - * Base 64encode algorithm at - * http://www.javaworld.com/javaworld/javatips/jw-javatip36-p2.html - * allowing me to create the decoding - * - * the Base64 encoding can be represented by - * - * @author jkyr - * - */ -public class Base64 { - - public static final String DEFAULT_ENCODING = "UTF-8"; - - /* - * The methods of this class are static. Do not instantiate this class. Use - * its static methods to get the encoded/decoded results - */ - public static String encode(byte[] byteData) throws UnsupportedEncodingException { - return encode(byteData, DEFAULT_ENCODING); - } - public static String encode(byte[] byteData, String encoding) throws UnsupportedEncodingException { - if(byteData == null) { throw new IllegalArgumentException("byteData cannot be null"); } - return new String(_encode(byteData),encoding); - } - - public static byte[] encode(String string) throws UnsupportedEncodingException { - return encode(string, DEFAULT_ENCODING); - } - - public static byte[] encode(String string, String encoding) throws UnsupportedEncodingException { - if(string == null) { throw new IllegalArgumentException("string cannot be null"); } - return _encode(string.getBytes(encoding)); - } - - public final static byte[] _encode(byte[] byteData) { - /* If we received a null argument, exit this method. */ - if (byteData == null) { throw new IllegalArgumentException("byteData cannot be null"); } - - /* - * Declare working variables including an array of bytes that will - * contain the encoded data to be returned to the caller. Note that the - * encoded array is about 1/3 larger than the input. This is because - * every group of 3 bytes is being encoded into 4 bytes. - */ - int iSrcIdx; // index into source (byteData) - int iDestIdx; // index into destination (byteDest) - // byte[] byteData = (byte[])byteData_in.clone(); - // byte[] byteData = byteData_in; - byte[] byteDest = new byte[((byteData.length + 2) / 3) * 4]; - - /* - * Walk through the input array, 24 bits at a time, converting them from - * 3 groups of 8 to 4 groups of 6 with two unset bits between. as per - * Base64 spec see - * http://www.javaworld.com/javaworld/javatips/jw-javatip36-p2.html for - * example explanation - */ - for (iSrcIdx = 0, iDestIdx = 0; iSrcIdx < byteData.length - 2; iSrcIdx += 3) { - byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx] >>> 2) & 077); - byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx + 1] >>> 4) & 017 | (byteData[iSrcIdx] << 4) & 077); - byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx + 2] >>> 6) & 003 | (byteData[iSrcIdx + 1] << 2) & 077); - byteDest[iDestIdx++] = (byte) (byteData[iSrcIdx + 2] & 077); - } - - /* - * If the number of bytes we received in the input array was not an even - * multiple of 3, convert the remaining 1 or 2 bytes. - */ - if (iSrcIdx < byteData.length) { - byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx] >>> 2) & 077); - if (iSrcIdx < byteData.length - 1) { - byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx + 1] >>> 4) & 017 | (byteData[iSrcIdx] << 4) & 077); - byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx + 1] << 2) & 077); - } else - byteDest[iDestIdx++] = (byte) ((byteData[iSrcIdx] << 4) & 077); - } - - /* - * Use the encoded data as indexes into the Base64 alphabet. (The Base64 - * alphabet is completely documented in RFC 1521.) - */ - for (iSrcIdx = 0; iSrcIdx < iDestIdx; iSrcIdx++) { - if (byteDest[iSrcIdx] < 26) - byteDest[iSrcIdx] = (byte) (byteDest[iSrcIdx] + 'A'); - else if (byteDest[iSrcIdx] < 52) - byteDest[iSrcIdx] = (byte) (byteDest[iSrcIdx] + 'a' - 26); - else if (byteDest[iSrcIdx] < 62) - byteDest[iSrcIdx] = (byte) (byteDest[iSrcIdx] + '0' - 52); - else if (byteDest[iSrcIdx] < 63) - byteDest[iSrcIdx] = '+'; - else - byteDest[iSrcIdx] = '/'; - } - - /* Pad any unused bytes in the destination string with '=' characters. */ - for (; iSrcIdx < byteDest.length; iSrcIdx++) - byteDest[iSrcIdx] = '='; - - return byteDest; - } - - public static String decode(byte[] encoded) throws UnsupportedEncodingException { - return decode(encoded, DEFAULT_ENCODING); - } - - public static String decode(byte[] encoded, String encoding) throws UnsupportedEncodingException { - if(encoded == null) { throw new IllegalArgumentException("encoded cannot be null"); } - return new String(_decode(encoded), encoding); - } - - public final static byte[] decode(String encoded) throws UnsupportedEncodingException { - return decode(encoded,DEFAULT_ENCODING); - } - - public final static byte[] decode(String encoded, String encoding) throws IllegalArgumentException, UnsupportedEncodingException { - if(null == encoded) { throw new IllegalArgumentException("encoded cannot be null"); } - return _decode(encoded.getBytes(encoding)); - } - - public final static byte[] _decode(byte[] byteData) throws IllegalArgumentException { - /* If we received a null argument, exit this method. */ - if (byteData == null) { throw new IllegalArgumentException("byteData cannot be null"); } - - /* - * Declare working variables including an array of bytes that will - * contain the decoded data to be returned to the caller. Note that the - * decoded array is about 3/4 smaller than the input. This is because - * every group of 4 bytes is being encoded into 3 bytes. - */ - int iSrcIdx; // index into source (byteData) - int reviSrcIdx; // index from end of the src array (byteData) - int iDestIdx; // index into destination (byteDest) - byte[] byteTemp = new byte[byteData.length]; - - /* - * remove any '=' chars from the end of the byteData they would have - * been padding to make it up to groups of 4 bytes note that I don't - * need to remove it just make sure that when progressing throug array - * we don't go past reviSrcIdx ;-) - */ - for (reviSrcIdx = byteData.length; reviSrcIdx -1 > 0 && byteData[reviSrcIdx -1] == '='; reviSrcIdx--) { - ; // do nothing. I'm just interested in value of reviSrcIdx - } - - /* sanity check */ - if (reviSrcIdx -1 == 0) { return null; /* ie all padding */ } - - /* - * Set byteDest, this is smaller than byteData due to 4 -> 3 byte munge. - * Note that this is an integer division! This fact is used in the logic - * l8r. to make sure we don't fall out of the array and create an - * OutOfBoundsException and also in handling the remainder - */ - byte byteDest[] = new byte[((reviSrcIdx * 3) / 4)]; - - /* - * Convert from Base64 alphabet to encoded data (The Base64 alphabet is - * completely documented in RFC 1521.) The order of the testing is - * important as I use the '<' operator which looks at the hex value of - * these ASCII chars. So convert from the smallest up - * - * do all of this in a new array so as not to edit the original input - */ - for (iSrcIdx = 0; iSrcIdx < reviSrcIdx; iSrcIdx++) { - if (byteData[iSrcIdx] == '+') - byteTemp[iSrcIdx] = 62; - else if (byteData[iSrcIdx] == '/') - byteTemp[iSrcIdx] = 63; - else if (byteData[iSrcIdx] < '0' + 10) - byteTemp[iSrcIdx] = (byte) (byteData[iSrcIdx] + 52 - '0'); - else if (byteData[iSrcIdx] < ('A' + 26)) - byteTemp[iSrcIdx] = (byte) (byteData[iSrcIdx] - 'A'); - else if (byteData[iSrcIdx] < 'a' + 26) - byteTemp[iSrcIdx] = (byte) (byteData[iSrcIdx] + 26 - 'a'); - } - - /* - * 4bytes -> 3bytes munge Walk through the input array, 32 bits at a - * time, converting them from 4 groups of 6 to 3 groups of 8 removing - * the two unset most significant bits of each sorce byte as this was - * filler, as per Base64 spec. stop before potential buffer overun on - * byteDest, remember that byteDest is 3/4 (integer division) the size - * of input and won't necessary divide exactly (ie iDestIdx must be < - * (integer div byteDest.length / 3)*3 see - * http://www.javaworld.com/javaworld/javatips/jw-javatip36-p2.html for - * example - */ - for (iSrcIdx = 0, iDestIdx = 0; iSrcIdx < reviSrcIdx - && iDestIdx < ((byteDest.length / 3) * 3); iSrcIdx += 4) { - byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx] << 2) & 0xFC | (byteTemp[iSrcIdx + 1] >>> 4) & 0x03); - byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx + 1] << 4) & 0xF0 | (byteTemp[iSrcIdx + 2] >>> 2) & 0x0F); - byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx + 2] << 6) & 0xC0 | byteTemp[iSrcIdx + 3] & 0x3F); - } - - /* - * tidy up any remainders if iDestIdx >= ((byteDest.length / 3)*3) but - * iSrcIdx < reviSrcIdx then we have at most 2 extra destination bytes - * to fill and posiblr 3 input bytes yet to process - */ - if (iSrcIdx < reviSrcIdx) { - if (iSrcIdx < reviSrcIdx - 2) { - // "3 input bytes left" - byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx] << 2) & 0xFC | (byteTemp[iSrcIdx + 1] >>> 4) & 0x03); - byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx + 1] << 4) & 0xF0 | (byteTemp[iSrcIdx + 2] >>> 2) & 0x0F); - } else if (iSrcIdx < reviSrcIdx - 1) { - // "2 input bytes left" - byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx] << 2) & 0xFC | (byteTemp[iSrcIdx + 1] >>> 4) & 0x03); - } - /* - * wont have just one input byte left (unless input wasn't base64 - * encoded ) due to the for loop steps and array sizes, after "=" - * pad removed, but for compleatness - */ - else { - throw new IllegalArgumentException("Warning: 1 input bytes left to process. This was not Base64 input"); - } - } - return byteDest; - } - -} // that's all folks! \ No newline at end of file diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/Util.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Util.java index f19a57af..43e37784 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/Util.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Util.java @@ -16,14 +16,18 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.codec.binary.Base64; + import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.Random; import java.util.UUID; public class Util { private static ObjectMapper sObjectMapper = new ObjectMapper(); + + private static Base64 sBase64 = new Base64(true); // URL-safe variant + public static ObjectMapper defaultMapper() { return sObjectMapper; } @@ -58,12 +62,7 @@ public static String getTimestamp() { * Some use Base64 encoding */ public static String base64Encode(String string) { - try { - return Base64.encode(string.getBytes()); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return null; + return sBase64.encodeBase64String(string.getBytes()); } public static String getEventId() { From 7f71dac48c540d85b46c2d867907d535ae7d5588 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 24 Jan 2015 01:48:09 +0000 Subject: [PATCH 29/37] Removed deprecated add() methods from Payload interface (closes #72) --- .../tracker/payload/SchemaPayload.java | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java index 9a988fc0..d4bf5df2 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/SchemaPayload.java @@ -80,47 +80,6 @@ public SchemaPayload setData(Object data) { return this; } - @Deprecated - @Override - public void add(String key, String value) { - /* - * We intentionally do nothing because we do not want our SchemaPayload - * to do anything except accept a 'data' and 'schema' - */ - LOGGER.debug("add(String, String) method called: Doing nothing."); - } - - @Deprecated - @Override - public void add(String key, Object value) { - /* - * We intentionally do nothing because we do not want our SchemaPayload - * to do anything except accept a 'data' and 'schema' - */ - LOGGER.debug("add(String, Object) method called: Doing nothing."); - } - - @Deprecated - @Override - public void addMap(Map map) { - /* - * We intentionally do nothing because we do not want our SchemaPayload - * to do anything except accept a 'data' and 'schema' - */ - LOGGER.debug("addMap(Map) method called: Doing nothing."); - } - - @Deprecated - @Override - public void addMap(Map map, Boolean base64_encoded, String type_encoded, - String type_no_encoded) { - /* - * We intentionally do nothing because we do not want our SchemaPayload - * to do anything except accept a 'data' and 'schema' - */ - LOGGER.debug("addMap(Map, Boolean, String, String) method called: Doing nothing."); - } - public Map getMap() { HashMap map = new HashMap(); try { From 0145e019dfcc37ba29e4d5ed2188ff9877858393 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 24 Jan 2015 10:56:22 +0000 Subject: [PATCH 30/37] Relocated add() methods from Payload into TrackerPayload (closes #126) --- .../snowplow/tracker/Tracker.java | 12 +++---- .../snowplow/tracker/payload/Payload.java | 34 ++----------------- .../tracker/payload/TrackerPayload.java | 31 ++++++++++++++--- .../snowplow/tracker/TrackerPayloadTest.java | 10 +++--- 4 files changed, 41 insertions(+), 46 deletions(-) diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java index 58ee4b09..299d4605 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Tracker.java @@ -88,7 +88,7 @@ public Tracker(Emitter emitter, Subject subject, String namespace, String appId, * @param timestamp Optional user-provided timestamp for the event * @return A completed Payload */ - protected Payload completePayload(Payload payload, List context, + protected Payload completePayload(TrackerPayload payload, List context, long timestamp) { payload.add(Parameter.PLATFORM, this.platform.toString()); payload.add(Parameter.APPID, this.appId); @@ -191,7 +191,7 @@ public void trackPageView(String pageUrl, String pageTitle, String referrer, Preconditions.checkArgument(!pageTitle.isEmpty(), "pageTitle cannot be empty"); Preconditions.checkArgument(!referrer.isEmpty(), "referrer cannot be empty"); - Payload payload = new TrackerPayload(); + TrackerPayload payload = new TrackerPayload(); payload.add(Parameter.EVENT, Constants.EVENT_PAGE_VIEW); payload.add(Parameter.PAGE_URL, pageUrl); payload.add(Parameter.PAGE_TITLE, pageTitle); @@ -259,7 +259,7 @@ public void trackStructuredEvent(String category, String action, String label, S Preconditions.checkArgument(!category.isEmpty(), "category cannot be empty"); Preconditions.checkArgument(!action.isEmpty(), "action cannot be empty"); - Payload payload = new TrackerPayload(); + TrackerPayload payload = new TrackerPayload(); payload.add(Parameter.EVENT, Constants.EVENT_STRUCTURED); payload.add(Parameter.SE_CATEGORY, category); payload.add(Parameter.SE_ACTION, action); @@ -314,7 +314,7 @@ public void trackUnstructuredEvent(SchemaPayload eventData, long timestamp) { */ public void trackUnstructuredEvent(SchemaPayload eventData, List context, long timestamp) { - Payload payload = new TrackerPayload(); + TrackerPayload payload = new TrackerPayload(); SchemaPayload envelope = new SchemaPayload(); envelope.setSchema(Constants.SCHEMA_UNSTRUCT_EVENT); @@ -355,7 +355,7 @@ protected void trackEcommerceTransactionItem(String order_id, String sku, Double Preconditions.checkArgument(!category.isEmpty(), "category cannot be empty"); Preconditions.checkArgument(!currency.isEmpty(), "currency cannot be empty"); - Payload payload = new TrackerPayload(); + TrackerPayload payload = new TrackerPayload(); payload.add(Parameter.EVENT, Constants.EVENT_ECOMM_ITEM); payload.add(Parameter.TI_ITEM_ID, order_id); payload.add(Parameter.TI_ITEM_SKU, sku); @@ -465,7 +465,7 @@ public void trackEcommerceTransaction(String order_id, Double total_value, Strin Preconditions.checkArgument(!country.isEmpty(), "country cannot be empty"); Preconditions.checkArgument(!currency.isEmpty(), "currency cannot be empty"); - Payload payload = new TrackerPayload(); + TrackerPayload payload = new TrackerPayload(); payload.add(Parameter.EVENT, Constants.EVENT_ECOMM); payload.add(Parameter.TR_ID, order_id); payload.add(Parameter.TR_TOTAL, Double.toString(total_value)); diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/Payload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/Payload.java index b656a862..642b5e36 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/Payload.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/Payload.java @@ -25,42 +25,14 @@ * Payload interface * The Payload is used to store all the parameters and configurations that are used * to send data via the HTTP GET/POST request. + * + * It allows the code for buffering events for sending to be agnostic of the event + * format (either a TrackerPayload or a SchemaPayload). * @version 0.5.0 * @author Jonathan Almeida */ public interface Payload { - /** - * Add a basic parameter. - * @param key The parameter key - * @param value The parameter value as a String - */ - public void add(String key, String value); - - /** - * Add a basic parameter. - * @param key The parameter key - * @param value The parameter value - */ - public void add(String key, Object value); - - /** - * Add all the mappings from the specified map. The effect is the equivalent to that of calling - * add(String key, Object value) for each mapping for each key. - * @param map Mappings to be stored in this map - */ - public void addMap(Map map); - - /** - * Add a map to the Payload with a key dependent on the base 64 encoding option you choose using the - * two keys provided. - * @param map Mapping to be stored - * @param base64_encoded The option you choose to encode the data - * @param type_encoded The key that would be set if the encoding option was set to true - * @param type_no_encoded They key that would be set if the encoding option was set to false - */ - public void addMap(Map map, Boolean base64_encoded, String type_encoded, String type_no_encoded); - /** * Returns the Payload as a HashMap. * @return A HashMap diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/TrackerPayload.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/TrackerPayload.java index cce1927f..562538e7 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/TrackerPayload.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/payload/TrackerPayload.java @@ -35,7 +35,11 @@ public class TrackerPayload implements Payload { private final Logger LOGGER = LoggerFactory.getLogger(TrackerPayload.class); private ObjectNode objectNode = objectMapper.createObjectNode(); - @Override + /** + * Add a basic parameter. + * @param key The parameter key + * @param value The parameter value as a String + */ public void add(String key, String value) { if (value == null || value.isEmpty()) { LOGGER.debug("kv-value is empty. Returning out without adding key.."); @@ -46,7 +50,13 @@ public void add(String key, String value) { objectNode.put(key, value); } - @Override + /** + * Add a basic parameter. + * @param key The parameter key + * @param value The parameter value + */ + // TODO: remove this. Tracker Payload is all Strings, + // so we shouldn't be passing in Objects public void add(String key, Object value) { if (value == null) { LOGGER.debug("kv-value is empty. Returning out without adding key.."); @@ -61,7 +71,13 @@ public void add(String key, Object value) { } } - @Override + /** + * Add all the mappings from the specified map. The effect is the equivalent to that of calling + * add(String key, Object value) for each mapping for each key. + * @param map Mappings to be stored in this map + */ + // TODO: remove this unless we have a good reason to add + // a uni-typed Map public void addMap(Map map) { // Return if we don't have a map if (map == null) { @@ -75,7 +91,14 @@ public void addMap(Map map) { } } - @Override + /** + * Add a map to the Payload with a key dependent on the base 64 encoding option you choose using the + * two keys provided. + * @param map Mapping to be stored + * @param base64_encoded The option you choose to encode the data + * @param type_encoded The key that would be set if the encoding option was set to true + * @param type_no_encoded They key that would be set if the encoding option was set to false + */ public void addMap(Map map, Boolean base64_encoded, String type_encoded, String type_no_encoded) { // Return if we don't have a map if (map == null) { diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java index 6423363d..17d083b0 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerPayloadTest.java @@ -16,7 +16,7 @@ public class TrackerPayloadTest { @Test public void testAddString() throws Exception { - Payload payload = new TrackerPayload(); + TrackerPayload payload = new TrackerPayload(); payload.add("foo", "bar"); String res = "{\"foo\":\"bar\"}"; @@ -25,7 +25,7 @@ public void testAddString() throws Exception { @Test public void testAddObject() throws Exception { - Payload payload = new TrackerPayload(); + TrackerPayload payload = new TrackerPayload(); Map map = new HashMap(); map.put("foo", "bar"); map.put("more foo", "more bar"); @@ -43,7 +43,7 @@ public void testAddMap() throws Exception { bar.add("somebar2"); foo.put("myKey", "my Value"); foo.put("mehh", bar); - Payload payload = new TrackerPayload(); + TrackerPayload payload = new TrackerPayload(); payload.addMap(foo); String res = "{\"myKey\":\"my Value\",\"mehh\":[\"somebar\",\"somebar2\"]}"; @@ -58,7 +58,7 @@ public void testAddMapNotEncoding() throws Exception { bar.add("somebar2"); foo.put("myKey", "my Value"); foo.put("mehh", bar); - Payload payload = new TrackerPayload(); + TrackerPayload payload = new TrackerPayload(); payload.addMap(foo, false, "cx", "co"); String res = "{\"co\":\"{\\\"myKey\\\":\\\"my Value\\\",\\\"mehh\\\":[\\\"somebar\\\",\\\"somebar2\\\"]}\"}"; @@ -73,7 +73,7 @@ public void testAddMapEncoding() throws Exception { bar.add("somebar2"); foo.put("myKey", "my Value"); foo.put("mehh", bar); - Payload payload = new TrackerPayload(); + TrackerPayload payload = new TrackerPayload(); payload.addMap(foo, true, "cx", "co"); String res = "{\"cx\":\"eyJteUtleSI6Im15IFZhbHVlIiwibWVoaCI6WyJzb21lYmFyIiwic29tZWJhcjIiXX0=\"}"; From 3c33e344afed7e961f1c0fa0f6435866764b8192 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 24 Jan 2015 16:39:22 +0000 Subject: [PATCH 31/37] Updated Emitter and Tracker tests to use WireMock (closes #40) --- build.gradle | 5 + .../snowplow/tracker/EmitterTest.java | 43 +++++++-- .../snowplow/tracker/TrackerTest.java | 93 ++++++++++++++++++- 3 files changed, 130 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index 06059104..f65f6f74 100644 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,8 @@ targetCompatibility = '1.6' repositories { // Use 'maven central' for resolving our dependencies mavenCentral() + // Use 'jcenter' for resolving testing dependencies + jcenter() } dependencies { @@ -44,7 +46,10 @@ dependencies { // Preconditions compile 'com.google.guava:guava:17.0' + // Testing libraries testCompile 'junit:junit:4.11' + testCompile 'com.github.tomakehurst:wiremock:1.53' + testCompile 'org.skyscreamer:jsonassert:1.2.3' } diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java index ed0e7839..db1aadf7 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/EmitterTest.java @@ -3,15 +3,23 @@ import com.snowplowanalytics.snowplow.tracker.emitter.*; import com.snowplowanalytics.snowplow.tracker.payload.Payload; import com.snowplowanalytics.snowplow.tracker.payload.TrackerPayload; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import org.junit.Rule; import org.junit.Test; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import static com.github.tomakehurst.wiremock.client.WireMock.*; + public class EmitterTest { - private static String testURL = "d3rkrsqld9gmqf.cloudfront.net"; + @Rule + public WireMockRule wireMockRule = new WireMockRule(); + + private static String testURL = "localhost:8080"; @Test public void testEmitterConstructor() throws Exception { @@ -36,26 +44,33 @@ public void testFlushGet() throws Exception { emitter.addToBuffer(payload); emitter.flushBuffer(); + + verify(getRequestedFor(urlEqualTo("/i?test=testFlushBuffer"))); } @Test public void testFlushPost() throws Exception { - Emitter emitter = new Emitter(testURL, HttpMethod.POST, null); + Emitter emitter = new Emitter(testURL, HttpMethod.POST); - TrackerPayload payload; + TrackerPayload payload = new TrackerPayload(); LinkedHashMap foo = new LinkedHashMap(); ArrayList bar = new ArrayList(); - bar.add("somebar"); - bar.add("somebar"); - foo.put("test", "testMaxBuffer"); - foo.put("mehh", bar); - payload = new TrackerPayload(); + payload.add("someValue", "someKey"); + ArrayList anArray = new ArrayList(); + anArray.add("value1"); + anArray.add("value2"); + payload.add("values", anArray.toString()); payload.addMap(foo); emitter.addToBuffer(payload); - emitter.flushBuffer(); + + verify(postRequestedFor(urlEqualTo("/com.snowplowanalytics.snowplow/tp2")) + .withHeader("Content-Type", equalTo("application/json; charset=utf-8")) + .withRequestBody(equalToJson("{\"schema\":\"iglu:com.snowplowanalytics.snowplow/" + + "payload_data/jsonschema/1-0-0\",\"data\":[{\"someValue\":\"someKey\"," + + "\"values\":\"[value1, value2]\"}]}"))); } @Test @@ -67,10 +82,14 @@ public void testBufferOption() throws Exception { @Test public void testFlushBuffer() throws Exception { + stubFor(get(urlEqualTo("/i?test=testFlushBuffer")) + .willReturn(aResponse() + .withStatus(200))); + Emitter emitter = new Emitter(testURL, HttpMethod.GET, new RequestCallback() { @Override public void onSuccess(int successCount) { - System.out.println("Buffer length for POST/GET:" + successCount); + System.out.println("Buffer length for successful POST/GET:" + successCount); } @Override @@ -91,6 +110,8 @@ public void onFailure(int successCount, List failedEvent) { emitter.addToBuffer(payload); } emitter.flushBuffer(); + + verify(getRequestedFor(urlEqualTo("/i?test=testFlushBuffer"))); } @Test @@ -105,6 +126,8 @@ public void testMaxBuffer() throws Exception { payload.addMap(foo); emitter.addToBuffer(payload); + + verify(getRequestedFor(urlEqualTo("/i?test=testFlushBuffer"))); } } } \ No newline at end of file diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java index f25e292c..74a3e906 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java @@ -5,15 +5,24 @@ import com.snowplowanalytics.snowplow.tracker.emitter.HttpMethod; import com.snowplowanalytics.snowplow.tracker.emitter.RequestMethod; import com.snowplowanalytics.snowplow.tracker.payload.SchemaPayload; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; import java.util.*; import static org.junit.Assert.assertEquals; +import static com.github.tomakehurst.wiremock.client.WireMock.*; public class TrackerTest { - private static String TESTURL = "d3rkrsqld9gmqf.cloudfront.net"; + @Rule + public WireMockRule wireMockRule = new WireMockRule(); + + private static String TESTURL = "localhost:8080"; @Test public void testDefaultPlatform() throws Exception { @@ -71,6 +80,7 @@ public void testTrackPageView2() throws Exception { public void testTrackPageView3() throws Exception { Emitter emitter = new Emitter(TESTURL, HttpMethod.POST); Subject subject = new Subject(); + subject.setTimezone("Etc/UTC"); subject.setViewPort(320, 480); Tracker tracker = new Tracker(emitter, subject, "AF003", "cloudfront", false); emitter.setRequestMethod(RequestMethod.Asynchronous); @@ -86,6 +96,19 @@ public void testTrackPageView3() throws Exception { tracker.trackPageView("www.mypage.com", "My Page", "www.me.com", contextList); emitter.flushBuffer(); + + verify(postRequestedFor(urlEqualTo("/com.snowplowanalytics.snowplow/tp2")) + .withHeader("Content-Type", equalTo("application/json; charset=utf-8")) + .withRequestBody(equalToJson("{\"schema\":\"iglu:com.snowplowanalytics." + + "snowplow/payload_data/jsonschema/1-0-0\",\"data\":[{\"e\":\"pv\"," + + "\"url\":\"www.mypage.com\",\"page\":\"My Page\",\"refr\":" + + "\"www.me.com\",\"aid\":\"cloudfront\",\"tna\":\"AF003\"," + + "\"tv\":\"java-0.6.0\",\"co\":\"{\\\"schema\\\":" + + "\\\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\\\"," + + "\\\"data\\\":[{\\\"schema\\\":\\\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\\\"," + + "\\\"data\\\":{\\\"someContextKey\\\":\\\"testTrackPageView3\\\"}}]}\"," + + "\"tz\":\"Etc/UTC\",\"p\":\"pc\",\"vp\":\"320x480\"}]}", + JSONCompareMode.LENIENT))); } @Test @@ -155,6 +178,43 @@ public void testTrackEcommerceTransaction() throws Exception { "Delaware", "US", "USD", transactionItemLinkedList); emitter.flushBuffer(); + + // Verifying this JSON: + // { + // "schema": "iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-0", + // "data": [{ + // "e": "ti", + // "ti_id": "order-8", + // "ti_sk": "no_sku", + // "ti_nm": "Big Order", + // "ti_ca": "Food", + // "ti_pr": "34.0", + // "ti_qu": "1.0", + // "ti_cu": "USD", + // "tna": "AF003", + // "tv": "java-0.6.0", + // "dtm": "1414607597877", + // "co": "{\"schema\":\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\",\"data\":[{\"schema\":\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\",\"data\":{\"someContextKey\":\"testTrackPageView2\"}}]}" + // }, { + // "e": "tr", + // "tr_id": "order-7", + // "tr_tt": "25.0", + // "tr_af": "no_affiliate", + // "tr_tx": "0.0", + // "tr_sh": "0.0", + // "tr_ci": "Dover", + // "tr_st": "Delaware", + // "tr_co": "US", + // "tr_cu": "USD", + // "tna": "AF003", + // "tv": "java-0.6.0", + // "dtm": "1414607597877" + // }] + // } + verify(postRequestedFor(urlEqualTo("/com.snowplowanalytics.snowplow/tp2")) + .withHeader("Content-Type", equalTo("application/json; charset=utf-8")) + .withRequestBody(equalToJson("{\"schema\":\"iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-0\",\"data\":[{\"e\":\"ti\",\"ti_id\":\"order-8\",\"ti_sk\":\"no_sku\",\"ti_nm\":\"Big Order\",\"ti_ca\":\"Food\",\"ti_pr\":\"34.0\",\"ti_qu\":\"1.0\",\"ti_cu\":\"USD\",\"aid\":\"cloudfront\",\"tna\":\"AF003\",\"tv\":\"java-0.6.0\",\"co\":\"{\\\"schema\\\":\\\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\\\",\\\"data\\\":[{\\\"schema\\\":\\\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\\\",\\\"data\\\":{\\\"someContextKey\\\":\\\"testTrackPageView2\\\"}}]}\"},{\"e\":\"tr\",\"tr_id\":\"order-7\",\"tr_tt\":\"25.0\",\"tr_af\":\"no_affiliate\",\"tr_tx\":\"0.0\",\"tr_sh\":\"0.0\",\"tr_ci\":\"Dover\",\"tr_st\":\"Delaware\",\"tr_co\":\"US\",\"tr_cu\":\"USD\",\"aid\":\"cloudfront\",\"tna\":\"AF003\",\"tv\":\"java-0.6.0\"}]}", + JSONCompareMode.LENIENT))); } @Test @@ -176,6 +236,7 @@ public void testTrackEcommerceTransaction3() throws Exception { public void testTrackScreenView() throws Exception { Emitter emitter = new Emitter(TESTURL, HttpMethod.POST); Subject subject = new Subject(); + subject.setTimezone("Etc/UTC"); subject.setViewPort(320, 480); Tracker tracker = new Tracker(emitter, subject, "AF003", "cloudfront", false); emitter.setRequestMethod(RequestMethod.Asynchronous); @@ -190,6 +251,36 @@ public void testTrackScreenView() throws Exception { contextList.add(context); tracker.trackScreenView(null, "screen_1", contextList, 0); + + // Verifying this JSON: + // { + // "schema": "iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-0", + // "data": [{ + // "e": "ue", + // "ue_pr": "{\"schema\":\"iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0\",\"data\":{\"schema\":\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\",\"data\":{\"id\":\"screen_1\"}}}", + // "tna": "AF003", + // "tv": "java-0.6.0", + // "co": "{\"schema\":\"iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0\",\"data\":[{\"schema\":\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\",\"data\":{\"someContextKey\":\"testTrackPageView2\"}}]}", + // "tz": "Etc/UTC", + // "p": "pc", + // "vp": "320x480" + // }] + // } + verify(postRequestedFor(urlEqualTo("/com.snowplowanalytics.snowplow/tp2")) + .withHeader("Content-Type", equalTo("application/json; charset=utf-8")) + .withRequestBody(equalToJson("{\"schema\":\"iglu:com.snowplowanalytics.snowplow/" + + "payload_data/jsonschema/1-0-0\",\"data\":[{\"e\":\"ue\",\"ue_pr\":" + + "\"{\\\"schema\\\":\\\"iglu:com.snowplowanalytics.snowplow/" + + "unstruct_event/jsonschema/1-0-0\\\",\\\"data\\\":{\\\"schema\\\":" + + "\\\"iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0\\\"," + + "\\\"data\\\":{\\\"id\\\":\\\"screen_1\\\"}}}\",\"aid\":\"cloudfront\"," + + "\"tna\":\"AF003\",\"tv\":\"java-0.6.0\",\"co\":\"{\\\"schema\\\":" + + "\\\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\\\"," + + "\\\"data\\\":[{\\\"schema\\\":" + + "\\\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\\\"," + + "\\\"data\\\":{\\\"someContextKey\\\":\\\"testTrackPageView2\\\"}}]}\"," + + "\"tz\":\"Etc/UTC\",\"p\":\"pc\",\"vp\":\"320x480\"}]}", + JSONCompareMode.LENIENT))); } @Test From 7c1ce9c44347a6d247dbf4ed84e88304edae20bb Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 24 Jan 2015 17:53:29 +0000 Subject: [PATCH 32/37] Added Java 6 and 8 to Travis build matrix (closes #132) --- .travis.yml | 2 ++ .../com/snowplowanalytics/snowplow/tracker/UtilTest.java | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ca6ca2da..be5602ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: java jdk: + - openjdk6 - openjdk7 - oraclejdk7 + - oraclejdk8 diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java index 31d25def..4d6dd290 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/UtilTest.java @@ -10,6 +10,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +// JSONassert +import org.skyscreamer.jsonassert.JSONAssert; +import org.json.JSONException; + public class UtilTest { @Test public void testGetTimestamp() { @@ -32,7 +36,7 @@ public void testMapToJsonNode() { } @Test - public void testMapToJsonNode2() { + public void testMapToJsonNode2() throws JSONException { Map map = new HashMap(); map.put("foo", "bar"); @@ -44,6 +48,7 @@ public void testMapToJsonNode2() { JsonNode node = Util.mapToJsonNode(map); - assertEquals("{\"list\":[\"some\",\"stuff\"],\"foo\":\"bar\"}", node.toString()); + // Have to stringify because JSONAssert works with json.org, not Jackson + JSONAssert.assertEquals("{\"list\":[\"some\",\"stuff\"],\"foo\":\"bar\"}", node.toString(), false); } } From 3c94d367eee52bfd0e35418b0452954b3c148438 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 24 Jan 2015 17:57:15 +0000 Subject: [PATCH 33/37] Added Release button to README (closes #129) Added License button to README (closes #128) --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4d8808d2..8911094f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Java Analytics for Snowplow -[ ![Build Status] [travis-image] ] [travis] +[ ![Build Status] [travis-image] ] [travis] [ ![Release] [release-image] ] [releases] [ ![License] [license-image] ] [license] ## Overview @@ -40,6 +40,15 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +[travis]: https://travis-ci.org/snowplow/snowplow-java-tracker +[travis-image]: https://travis-ci.org/snowplow/snowplow-java-tracker.svg?branch=master + +[release-image]: http://img.shields.io/badge/release-0.6.0-blue.svg?style=flat +[releases]: https://github.com/snowplow/snowplow-java-tracker/releases + +[license-image]: http://img.shields.io/badge/license-Apache--2-blue.svg?style=flat +[license]: http://www.apache.org/licenses/LICENSE-2.0 + [java]: http://www.java.com/en/ [snowplow]: http://snowplowanalytics.com @@ -57,8 +66,3 @@ limitations under the License. [setup]: https://github.com/snowplow/snowplow/wiki/Java-Tracker-Setup [roadmap]: https://github.com/snowplow/snowplow/wiki/Java-Tracker-Roadmap [contributing]: https://github.com/snowplow/snowplow/wiki/Java-Tracker-Contributing - -[travis]: https://travis-ci.org/snowplow/snowplow-java-tracker -[travis-image]: https://travis-ci.org/snowplow/snowplow-java-tracker.svg?branch=master - -[license]: http://www.apache.org/licenses/LICENSE-2.0 From 52de6d1ad513023200652ae0985edf25dba1c4af Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Fri, 23 Jan 2015 16:24:18 +0000 Subject: [PATCH 34/37] Wrote CHANGELOG for 0.7.0 --- CHANGELOG | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1fa1ae08..4276c576 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,15 @@ -Java 0.?.? (?) --------------- -Merged root and core module +Java 0.7.0 (2015-01-xx) +----------------------- +Consolidated Tracker Core module into Java Tracker, thanks @dstendardi! (#116) +Removed war packaging from Gradle build, thanks @dstendardi! (#117) +Updated Emitter and Tracker tests to use WireMock, thanks @jonalmeida! (#40) +Added Java 6 and 8 to Travis build matrix (#132) +Removed deprecated add() methods from SchemaPayload (#72) +Relocated add() methods from Payload into TrackerPayload (#126) +Added Guava back as a dependency (#123) +Replaced homebrew Base64 implementation with Apache Commons Codec (#122) +Added Release button to README (#129) +Added License button to README (#128) Java 0.6.0 (2014-12-27) ----------------------- From e59dbc2876276a85d786723c37b6d208f1c92062 Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 24 Jan 2015 18:30:32 +0000 Subject: [PATCH 35/37] Bumped version to 0.7.0 --- README.md | 2 +- build.gradle | 2 +- .../snowplowanalytics/snowplow/tracker/Version.java | 4 ++-- .../snowplow/tracker/TrackerTest.java | 12 ++++++------ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8911094f..a01e9050 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ limitations under the License. [travis]: https://travis-ci.org/snowplow/snowplow-java-tracker [travis-image]: https://travis-ci.org/snowplow/snowplow-java-tracker.svg?branch=master -[release-image]: http://img.shields.io/badge/release-0.6.0-blue.svg?style=flat +[release-image]: http://img.shields.io/badge/release-0.7.0-blue.svg?style=flat [releases]: https://github.com/snowplow/snowplow-java-tracker/releases [license-image]: http://img.shields.io/badge/license-Apache--2-blue.svg?style=flat diff --git a/build.gradle b/build.gradle index f65f6f74..92de4e08 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ apply plugin: 'idea' group = 'com.snowplowanalytics' -version = '0.6.0' +version = '0.7.0' sourceCompatibility = '1.6' targetCompatibility = '1.6' repositories { diff --git a/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java b/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java index caa7be1b..a75e033b 100644 --- a/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java +++ b/src/main/java/com/snowplowanalytics/snowplow/tracker/Version.java @@ -15,6 +15,6 @@ // DO NOT EDIT. AUTO-GENERATED. public class Version { - static final String TRACKER = "java-0.6.0"; - static final String VERSION = "0.6.0"; + static final String TRACKER = "java-0.7.0"; + static final String VERSION = "0.7.0"; } diff --git a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java index 74a3e906..3a24fe64 100644 --- a/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java +++ b/src/test/java/com/snowplowanalytics/snowplow/tracker/TrackerTest.java @@ -103,7 +103,7 @@ public void testTrackPageView3() throws Exception { "snowplow/payload_data/jsonschema/1-0-0\",\"data\":[{\"e\":\"pv\"," + "\"url\":\"www.mypage.com\",\"page\":\"My Page\",\"refr\":" + "\"www.me.com\",\"aid\":\"cloudfront\",\"tna\":\"AF003\"," + - "\"tv\":\"java-0.6.0\",\"co\":\"{\\\"schema\\\":" + + "\"tv\":\"java-0.7.0\",\"co\":\"{\\\"schema\\\":" + "\\\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\\\"," + "\\\"data\\\":[{\\\"schema\\\":\\\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\\\"," + "\\\"data\\\":{\\\"someContextKey\\\":\\\"testTrackPageView3\\\"}}]}\"," + @@ -192,7 +192,7 @@ public void testTrackEcommerceTransaction() throws Exception { // "ti_qu": "1.0", // "ti_cu": "USD", // "tna": "AF003", - // "tv": "java-0.6.0", + // "tv": "java-0.7.0", // "dtm": "1414607597877", // "co": "{\"schema\":\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\",\"data\":[{\"schema\":\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\",\"data\":{\"someContextKey\":\"testTrackPageView2\"}}]}" // }, { @@ -207,13 +207,13 @@ public void testTrackEcommerceTransaction() throws Exception { // "tr_co": "US", // "tr_cu": "USD", // "tna": "AF003", - // "tv": "java-0.6.0", + // "tv": "java-0.7.0", // "dtm": "1414607597877" // }] // } verify(postRequestedFor(urlEqualTo("/com.snowplowanalytics.snowplow/tp2")) .withHeader("Content-Type", equalTo("application/json; charset=utf-8")) - .withRequestBody(equalToJson("{\"schema\":\"iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-0\",\"data\":[{\"e\":\"ti\",\"ti_id\":\"order-8\",\"ti_sk\":\"no_sku\",\"ti_nm\":\"Big Order\",\"ti_ca\":\"Food\",\"ti_pr\":\"34.0\",\"ti_qu\":\"1.0\",\"ti_cu\":\"USD\",\"aid\":\"cloudfront\",\"tna\":\"AF003\",\"tv\":\"java-0.6.0\",\"co\":\"{\\\"schema\\\":\\\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\\\",\\\"data\\\":[{\\\"schema\\\":\\\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\\\",\\\"data\\\":{\\\"someContextKey\\\":\\\"testTrackPageView2\\\"}}]}\"},{\"e\":\"tr\",\"tr_id\":\"order-7\",\"tr_tt\":\"25.0\",\"tr_af\":\"no_affiliate\",\"tr_tx\":\"0.0\",\"tr_sh\":\"0.0\",\"tr_ci\":\"Dover\",\"tr_st\":\"Delaware\",\"tr_co\":\"US\",\"tr_cu\":\"USD\",\"aid\":\"cloudfront\",\"tna\":\"AF003\",\"tv\":\"java-0.6.0\"}]}", + .withRequestBody(equalToJson("{\"schema\":\"iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-0\",\"data\":[{\"e\":\"ti\",\"ti_id\":\"order-8\",\"ti_sk\":\"no_sku\",\"ti_nm\":\"Big Order\",\"ti_ca\":\"Food\",\"ti_pr\":\"34.0\",\"ti_qu\":\"1.0\",\"ti_cu\":\"USD\",\"aid\":\"cloudfront\",\"tna\":\"AF003\",\"tv\":\"java-0.7.0\",\"co\":\"{\\\"schema\\\":\\\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\\\",\\\"data\\\":[{\\\"schema\\\":\\\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\\\",\\\"data\\\":{\\\"someContextKey\\\":\\\"testTrackPageView2\\\"}}]}\"},{\"e\":\"tr\",\"tr_id\":\"order-7\",\"tr_tt\":\"25.0\",\"tr_af\":\"no_affiliate\",\"tr_tx\":\"0.0\",\"tr_sh\":\"0.0\",\"tr_ci\":\"Dover\",\"tr_st\":\"Delaware\",\"tr_co\":\"US\",\"tr_cu\":\"USD\",\"aid\":\"cloudfront\",\"tna\":\"AF003\",\"tv\":\"java-0.7.0\"}]}", JSONCompareMode.LENIENT))); } @@ -259,7 +259,7 @@ public void testTrackScreenView() throws Exception { // "e": "ue", // "ue_pr": "{\"schema\":\"iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0\",\"data\":{\"schema\":\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\",\"data\":{\"id\":\"screen_1\"}}}", // "tna": "AF003", - // "tv": "java-0.6.0", + // "tv": "java-0.7.0", // "co": "{\"schema\":\"iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0\",\"data\":[{\"schema\":\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\",\"data\":{\"someContextKey\":\"testTrackPageView2\"}}]}", // "tz": "Etc/UTC", // "p": "pc", @@ -274,7 +274,7 @@ public void testTrackScreenView() throws Exception { "unstruct_event/jsonschema/1-0-0\\\",\\\"data\\\":{\\\"schema\\\":" + "\\\"iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0\\\"," + "\\\"data\\\":{\\\"id\\\":\\\"screen_1\\\"}}}\",\"aid\":\"cloudfront\"," + - "\"tna\":\"AF003\",\"tv\":\"java-0.6.0\",\"co\":\"{\\\"schema\\\":" + + "\"tna\":\"AF003\",\"tv\":\"java-0.7.0\",\"co\":\"{\\\"schema\\\":" + "\\\"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0\\\"," + "\\\"data\\\":[{\\\"schema\\\":" + "\\\"iglu:com.snowplowanalytics.snowplow/example/jsonschema/1-0-0\\\"," + From 321981b232f3018e1b24c6795bf321089b184d9d Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 24 Jan 2015 18:56:00 +0000 Subject: [PATCH 36/37] Finalized release date --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 4276c576..67d6ddaf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -Java 0.7.0 (2015-01-xx) +Java 0.7.0 (2015-01-24) ----------------------- Consolidated Tracker Core module into Java Tracker, thanks @dstendardi! (#116) Removed war packaging from Gradle build, thanks @dstendardi! (#117) From b919af238017e61a2b8ab56aa98d7d359bc9430e Mon Sep 17 00:00:00 2001 From: Alex Dean Date: Sat, 24 Jan 2015 19:19:08 +0000 Subject: [PATCH 37/37] Hardcoded artifactId to prevent vagrant folder being used (closes #138) --- CHANGELOG | 1 + build.gradle | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 67d6ddaf..2e64686e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Java 0.7.0 (2015-01-24) ----------------------- Consolidated Tracker Core module into Java Tracker, thanks @dstendardi! (#116) Removed war packaging from Gradle build, thanks @dstendardi! (#117) +Hardcoded artifactId to prevent vagrant folder being used (#138) Updated Emitter and Tracker tests to use WireMock, thanks @jonalmeida! (#40) Added Java 6 and 8 to Travis build matrix (#132) Removed deprecated add() methods from SchemaPayload (#72) diff --git a/build.gradle b/build.gradle index 92de4e08..81539ae4 100644 --- a/build.gradle +++ b/build.gradle @@ -61,6 +61,7 @@ task sourceJar(type: Jar, dependsOn: 'generateSources') { publishing { publications { mavenJava(MavenPublication) { + artifactId 'snowplow-java-tracker' from components.java artifact sourceJar {