Skip to content

Commit c187007

Browse files
authored
Add support for forcing a version when generating URLs.
* Add `forceUrl` boolean to `Url` and `Configuration` * Add missing fields to configuration and fix to/from map.
1 parent 58ee182 commit c187007

File tree

4 files changed

+109
-23
lines changed

4 files changed

+109
-23
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,20 @@ public AuthToken(Map options) {
5656
this.acl = (String) options.get("acl");
5757
this.duration = ObjectUtils.asLong(options.get("duration"), 0L);
5858
}
59+
}
60+
61+
public Map<String,Object> asMap(){
62+
Map<String,Object> result = new HashMap<String, Object>();
63+
64+
result.put("tokenName", this.tokenName);
65+
result.put("key", this.key);
66+
result.put("startTime", this.startTime);
67+
result.put("expiration", this.expiration);
68+
result.put("ip", this.ip);
69+
result.put("acl", this.acl);
70+
result.put("duration", this.duration);
5971

72+
return result;
6073
}
6174

6275
/**

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

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,12 @@ public class Configuration {
4040
public boolean loadStrategies = true;
4141
public boolean clientHints = false;
4242
public AuthToken authToken;
43+
public boolean forceVersion = true;
4344

4445
public Configuration() {
4546
}
4647

47-
private Configuration(String cloudName, String apiKey, String apiSecret, String secureDistribution, String cname, String uploadPrefix, boolean secure, boolean privateCdn, boolean cdnSubdomain, boolean shorten, String callback, String proxyHost, int proxyPort, Boolean secureCdnSubdomain, boolean useRootPath) {
48-
this(cloudName, apiKey, apiSecret, secureDistribution, cname, uploadPrefix, secure, privateCdn, cdnSubdomain, shorten, callback, proxyHost, proxyPort, secureCdnSubdomain, useRootPath, 0, true);
49-
}
50-
51-
private Configuration(String cloudName, String apiKey, String apiSecret, String secureDistribution, String cname, String uploadPrefix, boolean secure, boolean privateCdn, boolean cdnSubdomain, boolean shorten, String callback, String proxyHost, int proxyPort, Boolean secureCdnSubdomain, boolean useRootPath, int timeout, boolean loadStrategies) {
48+
private Configuration(String cloudName, String apiKey, String apiSecret, String secureDistribution, String cname, String uploadPrefix, boolean secure, boolean privateCdn, boolean cdnSubdomain, boolean shorten, String callback, String proxyHost, int proxyPort, Boolean secureCdnSubdomain, boolean useRootPath, int timeout, boolean loadStrategies, boolean forceVersion) {
5249
this.cloudName = cloudName;
5350
this.apiKey = apiKey;
5451
this.apiSecret = apiSecret;
@@ -66,6 +63,7 @@ private Configuration(String cloudName, String apiKey, String apiSecret, String
6663
this.useRootPath = useRootPath;
6764
this.timeout = 0;
6865
this.loadStrategies = loadStrategies;
66+
this.forceVersion = forceVersion;
6967
}
7068

7169
@SuppressWarnings("rawtypes")
@@ -97,6 +95,11 @@ public void update(Map config) {
9795
if (tokenMap != null) {
9896
this.authToken = new AuthToken(tokenMap);
9997
}
98+
this.forceVersion = ObjectUtils.asBoolean(config.get("force_version"), true);
99+
Map properties = (Map) config.get("properties");
100+
if (properties != null) {
101+
this.properties.putAll(properties);
102+
}
100103
}
101104

102105
@SuppressWarnings("rawtypes")
@@ -121,8 +124,10 @@ public Map<String, Object> asMap() {
121124
map.put("timeout", timeout);
122125
map.put("client_hints", clientHints);
123126
if (authToken != null) {
124-
map.put("auth_token", authToken.copy());
127+
map.put("auth_token", authToken.asMap());
125128
}
129+
map.put("force_version", forceVersion);
130+
map.put("properties", new HashMap<String,Object>(properties));
126131
return map;
127132
}
128133

@@ -148,6 +153,9 @@ public Configuration(Configuration other) {
148153
if (other.authToken != null) {
149154
this.authToken = other.authToken.copy();
150155
}
156+
this.forceVersion = other.forceVersion;
157+
this.loadStrategies = other.loadStrategies;
158+
this.properties.putAll(other.properties);
151159
}
152160

153161
/**
@@ -253,6 +261,7 @@ public static class Builder {
253261
private int timeout;
254262
private boolean clientHints = false;
255263
private AuthToken authToken;
264+
private boolean forceVersion = true;
256265

257266
/**
258267
* Set the HTTP connection timeout.
@@ -269,7 +278,7 @@ public Builder setTimeout(int timeout) {
269278
* Creates a {@link Configuration} with the arguments supplied to this builder
270279
*/
271280
public Configuration build() {
272-
final Configuration configuration = new Configuration(cloudName, apiKey, apiSecret, secureDistribution, cname, uploadPrefix, secure, privateCdn, cdnSubdomain, shorten, callback, proxyHost, proxyPort, secureCdnSubdomain, useRootPath, timeout, loadStrategies);
281+
final Configuration configuration = new Configuration(cloudName, apiKey, apiSecret, secureDistribution, cname, uploadPrefix, secure, privateCdn, cdnSubdomain, shorten, callback, proxyHost, proxyPort, secureCdnSubdomain, useRootPath, timeout, loadStrategies, forceVersion);
273282
configuration.clientHints = clientHints;
274283
return configuration;
275284
}
@@ -383,6 +392,10 @@ public Builder setAuthToken(AuthToken authToken) {
383392
this.authToken = authToken;
384393
return this;
385394
}
395+
public Builder setForceVersion(boolean forceVersion) {
396+
this.forceVersion = forceVersion;
397+
return this;
398+
}
386399

387400
/**
388401
* Initialize builder from existing {@link Configuration}
@@ -410,6 +423,7 @@ public Builder from(Configuration other) {
410423
this.timeout = other.timeout;
411424
this.clientHints = other.clientHints;
412425
this.authToken = other.authToken == null ? null : other.authToken.copy();
426+
this.forceVersion = other.forceVersion;
413427
return this;
414428
}
415429
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ public class Url {
3939
Transformation posterTransformation = null;
4040
String posterSource = null;
4141
Url posterUrl = null;
42-
boolean forceVersion = true;
4342

4443
private static final String CL_BLANK = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
4544
public static final String[] DEFAULT_VIDEO_SOURCE_TYPES = {"webm", "mp4", "ogv"};
@@ -322,7 +321,7 @@ public Url poster(Object poster) {
322321
* @return This same Url instance for chaining.
323322
*/
324323
public Url forceVersion(boolean forceVersion){
325-
this.forceVersion = forceVersion;
324+
this.config.forceVersion = forceVersion;
326325
return this;
327326
}
328327

@@ -371,7 +370,7 @@ public String generate(String source) {
371370
source = finalizedSource[0];
372371
String sourceToSign = finalizedSource[1];
373372

374-
if (forceVersion && sourceToSign.contains("/") && !StringUtils.hasVersionString(sourceToSign) &&
373+
if (this.config.forceVersion && sourceToSign.contains("/") && !StringUtils.hasVersionString(sourceToSign) &&
375374
!httpSource && StringUtils.isEmpty(version)) {
376375
version = "1";
377376
}

cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515

1616
import java.io.IOException;
1717
import java.io.UnsupportedEncodingException;
18+
import java.lang.reflect.Field;
19+
import java.lang.reflect.Modifier;
20+
import java.lang.reflect.Type;
1821
import java.net.URI;
1922
import java.net.URLDecoder;
2023
import java.util.*;
@@ -44,29 +47,29 @@ public void setUp() {
4447
}
4548

4649
@Test
47-
public void testUrlSuffixWithDotOrSlash(){
50+
public void testUrlSuffixWithDotOrSlash() {
4851
Boolean[] errors = new Boolean[4];
4952
try {
5053
cloudinary.url().suffix("dsfdfd.adsfad").generate("publicId");
51-
} catch (IllegalArgumentException e){
54+
} catch (IllegalArgumentException e) {
5255
errors[0] = true;
5356
}
5457

5558
try {
5659
cloudinary.url().suffix("dsfdfd/adsfad").generate("publicId");
57-
} catch (IllegalArgumentException e){
60+
} catch (IllegalArgumentException e) {
5861
errors[1] = true;
5962
}
6063

6164
try {
6265
cloudinary.url().suffix("dsfd.fd/adsfad").generate("publicId");
63-
} catch (IllegalArgumentException e){
66+
} catch (IllegalArgumentException e) {
6467
errors[2] = true;
6568
}
6669

6770
try {
6871
cloudinary.url().suffix("dsfdfdaddsfad").generate("publicId");
69-
} catch (IllegalArgumentException e){
72+
} catch (IllegalArgumentException e) {
7073
errors[3] = true;
7174
}
7275

@@ -75,6 +78,7 @@ public void testUrlSuffixWithDotOrSlash(){
7578
assertTrue(errors[2]);
7679
assertNull(errors[3]);
7780
}
81+
7882
@Test
7983
public void testCloudName() {
8084
// should use cloud_name from config
@@ -573,7 +577,7 @@ public void testFolders() {
573577
}
574578

575579
@Test
576-
public void testFoldersWithExcludeVersion(){
580+
public void testFoldersWithExcludeVersion() {
577581
// should not add version if the user turned off forceVersion
578582
String result = cloudinary.url().forceVersion(false).generate("folder/test");
579583
assertEquals(DEFAULT_UPLOAD_PATH + "folder/test", result);
@@ -582,7 +586,7 @@ public void testFoldersWithExcludeVersion(){
582586
result = cloudinary.url().forceVersion(false).version("1234").generate("folder/test");
583587
assertEquals(DEFAULT_UPLOAD_PATH + "v1234/folder/test", result);
584588

585-
// should add version no value specified for forceVersion:
589+
// should add version if no value specified for forceVersion:
586590
result = cloudinary.url().generate("folder/test");
587591
assertEquals(DEFAULT_UPLOAD_PATH + "v1/folder/test", result);
588592

@@ -1160,11 +1164,11 @@ public void testFps() {
11601164
assertEquals("fps_24", t.generate());
11611165
t = new Transformation().fps("-24");
11621166
assertEquals("fps_-24", t.generate());
1163-
t = new Transformation().fps(24,29.97);
1167+
t = new Transformation().fps(24, 29.97);
11641168
assertEquals("fps_24-29.97", t.generate());
1165-
t = new Transformation().fps(24,null);
1169+
t = new Transformation().fps(24, null);
11661170
assertEquals("fps_24-", t.generate());
1167-
t = new Transformation().fps(null,29.97);
1171+
t = new Transformation().fps(null, 29.97);
11681172
assertEquals("fps_-29.97", t.generate());
11691173
}
11701174

@@ -1180,14 +1184,14 @@ public void testKeyframeInterval() {
11801184
}
11811185

11821186
@Test
1183-
public void testCustomFunction(){
1187+
public void testCustomFunction() {
11841188
assertEquals("fn_wasm:blur_wasm", new Transformation().customFunction(wasm("blur_wasm")).generate());
11851189
assertEquals("fn_remote:aHR0cHM6Ly9kZjM0cmE0YS5leGVjdXRlLWFwaS51cy13ZXN0LTIuYW1hem9uYXdzLmNvbS9kZWZhdWx0L2Nsb3VkaW5hcnlGdW5jdGlvbg==",
11861190
new Transformation().customFunction(remote("https://df34ra4a.execute-api.us-west-2.amazonaws.com/default/cloudinaryFunction")).generate());
11871191
}
11881192

11891193
@Test
1190-
public void testCustomPreFunction(){
1194+
public void testCustomPreFunction() {
11911195
assertEquals("fn_pre:wasm:blur_wasm", new Transformation().customPreFunction(wasm("blur_wasm")).generate());
11921196
assertEquals("fn_pre:remote:aHR0cHM6Ly9kZjM0cmE0YS5leGVjdXRlLWFwaS51cy13ZXN0LTIuYW1hem9uYXdzLmNvbS9kZWZhdWx0L2Nsb3VkaW5hcnlGdW5jdGlvbg==",
11931197
new Transformation().customPreFunction(remote("https://df34ra4a.execute-api.us-west-2.amazonaws.com/default/cloudinaryFunction")).generate());
@@ -1208,9 +1212,65 @@ public static Map<String, String> getUrlParameters(URI uri) throws UnsupportedEn
12081212
}
12091213

12101214
@Test
1211-
public void testUrlCloneConfig(){
1215+
public void testUrlCloneConfig() {
12121216
// verify that secure (from url.config) is cloned as well:
12131217
Url url = cloudinary.url().cloudName("cloud").format("frmt").publicId("123").secure(true);
12141218
assertEquals("https://res.cloudinary.com/cloud/image/upload/123.frmt", url.clone().generate());
12151219
}
1220+
1221+
@Test
1222+
public void testConfiguration() throws IllegalAccessException {
1223+
Configuration config = new Configuration();
1224+
randomizeFields(config);
1225+
Map<String, Object> map = config.asMap();
1226+
Configuration copy = new Configuration(map);
1227+
assertFieldsEqual(config, copy);
1228+
1229+
copy = new Configuration(config);
1230+
assertFieldsEqual(config, copy);
1231+
}
1232+
1233+
private void assertFieldsEqual(Object a, Object b) throws IllegalAccessException {
1234+
assertEquals("Two objects must be the same class", a.getClass(), b.getClass());
1235+
Field[] fields = a.getClass().getFields();
1236+
for (Field field : fields) {
1237+
assertEquals("Field " + field.getName() + " should have equal values", field.get(a), field.get(b));
1238+
}
1239+
}
1240+
1241+
private void randomizeFields(Object instance) throws IllegalAccessException {
1242+
Random rand = new Random();
1243+
Field[] fields = instance.getClass().getDeclaredFields();
1244+
for (Field field : fields) {
1245+
setRandomValue(rand, field, instance);
1246+
}
1247+
}
1248+
1249+
private void setRandomValue(Random rand, Field field, Object instance) throws IllegalAccessException {
1250+
field.setAccessible(true);
1251+
Type fieldType = field.getGenericType();
1252+
if (Modifier.isFinal(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) {
1253+
return;
1254+
}
1255+
1256+
if (fieldType.equals(boolean.class) || fieldType.equals(Boolean.class)) {
1257+
field.set(instance, rand.nextBoolean());
1258+
} else if (fieldType.equals(int.class) || fieldType.equals(Integer.class)) {
1259+
field.set(instance, rand.nextInt());
1260+
} else if (fieldType.equals(long.class) || fieldType.equals(Long.class)) {
1261+
field.set(instance, rand.nextLong());
1262+
} else if (fieldType.equals(String.class)) {
1263+
field.set(instance, cloudinary.randomPublicId());
1264+
} else if (fieldType.equals(AuthToken.class)) {
1265+
AuthToken authToken = new AuthToken();
1266+
randomizeFields(authToken);
1267+
field.set(instance, authToken);
1268+
} else if (field.get(instance) instanceof HashMap) {
1269+
Map<String, Object> map = new HashMap<String, Object>();
1270+
map.put(cloudinary.randomPublicId(), rand.nextInt());
1271+
field.set(instance, map);
1272+
} else {
1273+
throw new IllegalArgumentException("Object have unexpected field type, randomizing not supported: " + field.getName() + ", type: " + field.getType().getSimpleName());
1274+
}
1275+
}
12161276
}

0 commit comments

Comments
 (0)