Skip to content

Commit ea3c262

Browse files
committed
Add Analytics support
1 parent b650f8e commit ea3c262

File tree

11 files changed

+373
-57
lines changed

11 files changed

+373
-57
lines changed

cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import com.cloudinary.strategies.AbstractApiStrategy;
66
import com.cloudinary.strategies.AbstractUploaderStrategy;
77
import com.cloudinary.strategies.StrategyLoader;
8-
import com.cloudinary.utils.AnalyticsUtils;
8+
import com.cloudinary.utils.Analytics;
99
import com.cloudinary.utils.ObjectUtils;
1010
import com.cloudinary.utils.StringUtils;
1111

@@ -46,7 +46,7 @@ public class Cloudinary {
4646
private AbstractUploaderStrategy uploaderStrategy;
4747
private AbstractApiStrategy apiStrategy;
4848
private String userAgent = USER_AGENT_PREFIX+"/"+ VERSION + " "+USER_AGENT_JAVA_VERSION;
49-
49+
public Analytics analytics;
5050
public Uploader uploader() {
5151
return new Uploader(this, uploaderStrategy);
5252
}
@@ -155,11 +155,12 @@ public void setUserAgent(String prefix, String version){
155155
}
156156

157157
/**
158-
* Set the analytics token that will be sent with every URL generate call
159-
* @param token - the analytics token to be set
158+
* Set the prefix and version for the user agent that will be sent with every API call
159+
* a userAgent is built from `prefix/version (additional data)`
160+
* @param analytics - the analytics objec to set
160161
*/
161-
public void setAnalyticsToken(String token) {
162-
AnalyticsUtils.token = token;
162+
public void setAnalytics(Analytics analytics) {
163+
this.analytics = analytics;
163164
}
164165

165166
/**

cloudinary-core/src/main/java/com/cloudinary/Configuration.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public class Configuration {
4848
public boolean longUrlSignature = DEFAULT_IS_LONG_SIGNATURE;
4949
public SignatureAlgorithm signatureAlgorithm = DEFAULT_SIGNATURE_ALGORITHM;
5050
public String oauthToken = null;
51-
51+
public Boolean analytics;
5252
public Configuration() {
5353
}
5454

@@ -73,7 +73,8 @@ private Configuration(
7373
boolean forceVersion,
7474
boolean longUrlSignature,
7575
SignatureAlgorithm signatureAlgorithm,
76-
String oauthToken) {
76+
String oauthToken,
77+
boolean analytics) {
7778
this.cloudName = cloudName;
7879
this.apiKey = apiKey;
7980
this.apiSecret = apiSecret;
@@ -95,6 +96,7 @@ private Configuration(
9596
this.longUrlSignature = longUrlSignature;
9697
this.signatureAlgorithm = signatureAlgorithm;
9798
this.oauthToken = oauthToken;
99+
this.analytics = analytics;
98100
}
99101

100102
@SuppressWarnings("rawtypes")
@@ -122,6 +124,7 @@ public void update(Map config) {
122124
this.loadStrategies = ObjectUtils.asBoolean(config.get("load_strategies"), true);
123125
this.timeout = ObjectUtils.asInteger(config.get("timeout"), 0);
124126
this.clientHints = ObjectUtils.asBoolean(config.get("client_hints"), false);
127+
this.analytics = ObjectUtils.asBoolean(config.get("analytics"), null);
125128
Map tokenMap = (Map) config.get("auth_token");
126129
if (tokenMap != null) {
127130
this.authToken = new AuthToken(tokenMap);
@@ -134,6 +137,7 @@ public void update(Map config) {
134137
this.longUrlSignature = ObjectUtils.asBoolean(config.get("long_url_signature"), DEFAULT_IS_LONG_SIGNATURE);
135138
this.signatureAlgorithm = SignatureAlgorithm.valueOf(ObjectUtils.asString(config.get(CONFIG_PROP_SIGNATURE_ALGORITHM), DEFAULT_SIGNATURE_ALGORITHM.name()));
136139
this.oauthToken = (String) config.get("oauth_token");
140+
137141
}
138142

139143
@SuppressWarnings("rawtypes")
@@ -165,6 +169,7 @@ public Map<String, Object> asMap() {
165169
map.put("long_url_signature", longUrlSignature);
166170
map.put(CONFIG_PROP_SIGNATURE_ALGORITHM, signatureAlgorithm.toString());
167171
map.put("oauth_token", oauthToken);
172+
map.put("analytics", analytics);
168173
return map;
169174
}
170175

@@ -196,6 +201,7 @@ public Configuration(Configuration other) {
196201
this.longUrlSignature = other.longUrlSignature;
197202
this.signatureAlgorithm = other.signatureAlgorithm;
198203
this.oauthToken = other.oauthToken;
204+
this.analytics = other.analytics;
199205
}
200206

201207
/**
@@ -308,6 +314,7 @@ public static class Builder {
308314
private boolean longUrlSignature = DEFAULT_IS_LONG_SIGNATURE;
309315
private SignatureAlgorithm signatureAlgorithm = DEFAULT_SIGNATURE_ALGORITHM;
310316
private String oauthToken = null;
317+
private boolean analytics;
311318

312319
/**
313320
* Set the HTTP connection timeout.
@@ -345,7 +352,8 @@ public Configuration build() {
345352
forceVersion,
346353
longUrlSignature,
347354
signatureAlgorithm,
348-
oauthToken);
355+
oauthToken,
356+
analytics);
349357
configuration.clientHints = clientHints;
350358
return configuration;
351359
}
@@ -450,6 +458,11 @@ public Builder setLoadStrategies(boolean loadStrategies) {
450458
return this;
451459
}
452460

461+
public Builder setAnalytics(boolean analytics) {
462+
this.analytics = analytics;
463+
return this;
464+
}
465+
453466
public Builder setClientHints(boolean clientHints) {
454467
this.clientHints = clientHints;
455468
return this;
@@ -509,6 +522,7 @@ public Builder from(Configuration other) {
509522
this.longUrlSignature = other.longUrlSignature;
510523
this.signatureAlgorithm = other.signatureAlgorithm;
511524
this.oauthToken = other.oauthToken;
525+
this.analytics = other.analytics;
512526
return this;
513527
}
514528
}

cloudinary-core/src/main/java/com/cloudinary/Url.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import java.util.regex.Pattern;
1414
import java.util.zip.CRC32;
1515

16-
import com.cloudinary.utils.AnalyticsUtils;
16+
import com.cloudinary.utils.Analytics;
1717
import com.cloudinary.utils.Base64Coder;
1818
import com.cloudinary.utils.ObjectUtils;
1919
import com.cloudinary.utils.StringUtils;
@@ -409,6 +409,7 @@ public String generate(String source) {
409409
String join = StringUtils.join(new String[]{prefix, finalResourceType, signature, transformationStr, version, source}, "/");
410410
String url = StringUtils.mergeSlashesInUrl(join);
411411

412+
412413
if (signUrl && authToken != null && !authToken.equals(AuthToken.NULL_AUTH_TOKEN)) {
413414
try {
414415
URL tempUrl = new URL(url);
@@ -418,9 +419,14 @@ public String generate(String source) {
418419
} catch (MalformedURLException ignored) {
419420
}
420421
}
421-
if (AnalyticsUtils.token != null) {
422-
if(!AnalyticsUtils.checkIfQueryParamExist(url)) {
423-
url = (new StringBuilder()).append(url).append(AnalyticsUtils.analyticsPrefix).append(AnalyticsUtils.token).toString();
422+
if (cloudinary.analytics != null && cloudinary.config.analytics) {
423+
try {
424+
URL tempUrl = new URL(url);
425+
if (tempUrl.getQuery() == null) {
426+
String path = tempUrl.getPath();
427+
url = url + "?" + cloudinary.analytics.toQueryParam();
428+
}
429+
} catch (MalformedURLException ignored) {
424430
}
425431
}
426432
return url;
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package com.cloudinary.utils;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
6+
public class Analytics {
7+
private String sdkTokenQueryKey = "_a="; //sdkTokenQueryKey
8+
public String algoVersion = "A";
9+
public String SDKCode = ""; // Java = G, Android = F
10+
public String SDKSemver = ""; // Calculate the SDK version .
11+
public String techVersion = ""; // Calculate the Java version.
12+
public void Analytics() {
13+
// initilaize with Java values.
14+
// From Android pick the values.
15+
}
16+
17+
public Analytics() {}
18+
public Analytics(String sdkCode, String sdkVersion, String techVersion) {
19+
this.SDKCode = sdkCode;
20+
this.SDKSemver = sdkVersion;
21+
this.techVersion = techVersion;
22+
}
23+
24+
public Analytics setSDKCode(String SDKCode) {
25+
this.SDKCode = SDKCode;
26+
return this;
27+
}
28+
29+
public Analytics setSDKSemver(String SDKSemver) {
30+
this.SDKSemver = SDKSemver;
31+
return this;
32+
}
33+
34+
public Analytics setTechVersion(String techVersion) {
35+
this.techVersion = techVersion;
36+
return this;
37+
}
38+
39+
/**
40+
* Function turn analytics variables into viable query parameter.
41+
* @return query param with analytics values.
42+
*/
43+
public String toQueryParam() {
44+
try {
45+
return sdkTokenQueryKey + getAlgorithmVersion() + getSDKType() + getSDKVersion() + getTechVersion() + getSDKFeatureCode();
46+
} catch (Exception e) {
47+
return sdkTokenQueryKey + "E";
48+
}
49+
}
50+
51+
private String getTechVersion() throws Exception {
52+
String[] techVersionString = techVersion.split("_");
53+
String[] versions = techVersionString[0].split("\\.");
54+
if (versions.length > 2) {
55+
versions = Arrays.copyOf(versions, versions.length - 1);
56+
}
57+
return getPaddedString(StringUtils.join(versions, "."));
58+
}
59+
60+
private String getSDKType() {
61+
return SDKCode;
62+
}
63+
64+
private String getAlgorithmVersion() {
65+
return "A";
66+
}
67+
68+
private String getSDKFeatureCode() {
69+
return "0";
70+
}
71+
72+
private String getSDKVersion() throws Exception {
73+
return getPaddedString(SDKSemver);
74+
}
75+
76+
private String getPaddedString(String string) throws Exception {
77+
String paddedReversedSemver = "";
78+
int parts = string.split("\\.").length;
79+
int paddedStringLength = parts * 6;
80+
try {
81+
paddedReversedSemver = reverseVersion(string);
82+
} catch (Exception e) {
83+
throw new Exception("Error");
84+
}
85+
int num = Integer.parseInt(StringUtils.join(paddedReversedSemver.split("\\."),""));
86+
87+
String paddedBinary = StringUtils.padStart(Integer.toBinaryString(num), paddedStringLength, '0');
88+
89+
if (paddedBinary.length() % 6 != 0) {
90+
throw new Exception("Error");
91+
}
92+
93+
String result = "";
94+
List<String> resultList = StringUtils.usingPattern(paddedBinary,6);
95+
int i = 0;
96+
while (i < resultList.size()) {
97+
result = result + Base64Map.values.get(resultList.get(i));
98+
i++;
99+
}
100+
return result;
101+
}
102+
103+
private String reverseVersion(String SDKSemver) throws Exception {
104+
if (SDKSemver.split("\\.").length < 2) {
105+
throw new Exception("invalid semVer, must have at least two segments");
106+
}
107+
String[] versionArray = SDKSemver.split("\\.");
108+
for (int i = 0 ; i < versionArray.length; i ++) {
109+
versionArray[i] = StringUtils.padStart(versionArray[i], 2, '0');
110+
}
111+
return StringUtils.join(StringUtils.reverseStringArray(versionArray), ".");
112+
}
113+
}

cloudinary-core/src/main/java/com/cloudinary/utils/AnalyticsUtils.java

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.cloudinary.utils;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
public class Base64Map {
7+
public static Map<String, String> values;
8+
9+
static {
10+
values = new HashMap<>();
11+
values.put("000000", "A");
12+
values.put("000001", "B");
13+
values.put("000010", "C");
14+
values.put("000011", "D");
15+
values.put("000100", "E");
16+
values.put("000101", "F");
17+
values.put("000110", "G");
18+
values.put("000111", "H");
19+
values.put("001000", "I");
20+
values.put("001001", "J");
21+
values.put("001010", "K");
22+
values.put("001011", "L");
23+
values.put("001100", "M");
24+
values.put("001101", "N");
25+
values.put("001110", "O");
26+
values.put("001111", "P");
27+
values.put("010000", "Q");
28+
values.put("010001", "R");
29+
values.put("010010", "S");
30+
values.put("010011", "T");
31+
values.put("010100", "U");
32+
values.put("010101", "V");
33+
values.put("010110", "W");
34+
values.put("010111", "X");
35+
values.put("011000", "Y");
36+
values.put("011001", "Z");
37+
values.put("011010", "a");
38+
values.put("011011", "b");
39+
values.put("011100", "c");
40+
values.put("011101", "d");
41+
values.put("011110", "e");
42+
values.put("011111", "f");
43+
values.put("100000","g");
44+
values.put("100001","h");
45+
values.put("100010","i");
46+
values.put("100011","j");
47+
values.put("100100","k");
48+
values.put("100101","l");
49+
values.put("100110","m");
50+
values.put("100111","n");
51+
values.put("101000","o");
52+
values.put("101001","p");
53+
values.put("101010","q");
54+
values.put("101011","r");
55+
values.put("101100","s");
56+
values.put("101101","t");
57+
values.put("101110","u");
58+
values.put("101111","v");
59+
values.put("110000","w");
60+
values.put("110001","x");
61+
values.put("110010","y");
62+
values.put("110011","z");
63+
values.put("110100","0");
64+
values.put("110101","1");
65+
values.put("110110","2");
66+
values.put("110111","3");
67+
values.put("111000","4");
68+
values.put("111001","5");
69+
values.put("111010","6");
70+
values.put("111011","7");
71+
values.put("111100","8");
72+
values.put("111101","9");
73+
values.put("111110","+");
74+
values.put("111111","/");
75+
}
76+
}

0 commit comments

Comments
 (0)