Skip to content

Commit ee33566

Browse files
authored
Add feature analytics
2 parents df7b3cc + e463570 commit ee33566

File tree

9 files changed

+415
-8
lines changed

9 files changed

+415
-8
lines changed

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +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.Analytics;
89
import com.cloudinary.utils.ObjectUtils;
910
import com.cloudinary.utils.StringUtils;
1011

@@ -45,7 +46,7 @@ public class Cloudinary {
4546
private AbstractUploaderStrategy uploaderStrategy;
4647
private AbstractApiStrategy apiStrategy;
4748
private String userAgent = USER_AGENT_PREFIX+"/"+ VERSION + " "+USER_AGENT_JAVA_VERSION;
48-
49+
public Analytics analytics = new Analytics();
4950
public Uploader uploader() {
5051
return new Uploader(this, uploaderStrategy);
5152
}
@@ -153,6 +154,14 @@ public void setUserAgent(String prefix, String version){
153154
userAgent = prefix+"/"+ version + " ("+USER_AGENT_PREFIX+ " "+VERSION+") " + USER_AGENT_JAVA_VERSION;
154155
}
155156

157+
/**
158+
* Set the analytics object that will be sent with every URL generation call.
159+
* @param analytics - the analytics object to set
160+
*/
161+
public void setAnalytics(Analytics analytics) {
162+
this.analytics = analytics;
163+
}
164+
156165
/**
157166
* Verifies that Cloudinary notification request is genuine by checking its signature.
158167
*

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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.util.regex.Pattern;
1414
import java.util.zip.CRC32;
1515

16+
import com.cloudinary.utils.Analytics;
1617
import com.cloudinary.utils.Base64Coder;
1718
import com.cloudinary.utils.ObjectUtils;
1819
import com.cloudinary.utils.StringUtils;
@@ -417,6 +418,17 @@ public String generate(String source) {
417418
} catch (MalformedURLException ignored) {
418419
}
419420
}
421+
if (cloudinary.config.analytics != null && cloudinary.config.analytics) {
422+
try {
423+
URL tempUrl = new URL(url);
424+
// if any other query param already exist on the URL do not add analytics query param.
425+
if (tempUrl.getQuery() == null) {
426+
String path = tempUrl.getPath();
427+
url = url + "?" + cloudinary.analytics.toQueryParam();
428+
}
429+
} catch (MalformedURLException ignored) {
430+
}
431+
}
420432
return url;
421433
}
422434

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