From cd2fc064ce98cbf54a2121da67c01621313886f1 Mon Sep 17 00:00:00 2001 From: Daniel Marcos Date: Tue, 9 Jan 2024 13:59:31 +0100 Subject: [PATCH 01/40] Add missing display_name parameter to update resource --- cloudinary-core/src/main/java/com/cloudinary/Util.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Util.java b/cloudinary-core/src/main/java/com/cloudinary/Util.java index 19ae2c71..99fa608c 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Util.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Util.java @@ -166,6 +166,9 @@ public static final void processWriteParameters(Map options, Map if (options.get("unique_display_name") != null) { params.put("unique_display_name", options.get("unique_display_name")); } + if (options.get("display_name") != null) { + params.put("display_name", options.get("display_name")); + } putObject("ocr", options, params); putObject("raw_convert", options, params); putObject("categorization", options, params); From 36039520710e4fef7ee6e148a95471d27e1c1953 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Sun, 14 Jan 2024 09:15:58 +0200 Subject: [PATCH 02/40] Update analytics token --- .../java/com/cloudinary/utils/Analytics.java | 23 +++++++++++++++++-- .../cloudinary/analytics/AnalyticsTest.java | 20 +++++++++------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/utils/Analytics.java b/cloudinary-core/src/main/java/com/cloudinary/utils/Analytics.java index b0027889..d734377e 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/utils/Analytics.java +++ b/cloudinary-core/src/main/java/com/cloudinary/utils/Analytics.java @@ -8,7 +8,7 @@ public class Analytics { private String sdkTokenQueryKey = "_a"; //sdkTokenQueryKey private String sdkQueryDelimiter = "="; - public String algoVersion = "C"; + public String algoVersion = "D"; public String prodcut = "A"; public String SDKCode = ""; // Java = G, Android = F public String SDKSemver = ""; // Calculate the SDK version . @@ -67,12 +67,19 @@ private String versionArrayToString(String[] versions) throws Exception { return getPaddedString(StringUtils.join(versions, ".")); } + private String versionArrayToOsString(String[] versions) throws Exception { + if (versions.length > 2) { + versions = Arrays.copyOf(versions, versions.length - 1); + } + return getOsVersionString(StringUtils.join(versions, ".")); + } + private String getOsType() { return (osType != null) ? osType : "Z"; //System.getProperty("os.name"); } private String getOsVersion() throws Exception { - return (osVersion != null) ? versionArrayToString(osVersion.split("\\.")) : versionArrayToString(System.getProperty("os.version").split("\\.")); + return (osVersion != null) ? versionArrayToOsString(osVersion.split("\\.")) : versionArrayToString(System.getProperty("os.version").split("\\.")); } private String getSDKType() { @@ -91,6 +98,18 @@ private String getSDKVersion() throws Exception { return getPaddedString(SDKSemver); } + private String getOsVersionString(String string) throws Exception { + String[] parts = string.split("\\."); + String result = ""; + for(int i = 0 ; i < parts.length ; i++) { + int num = Integer.parseInt(parts[i]); + String binaryString = Integer.toBinaryString(num); + binaryString = StringUtils.padStart(binaryString, 6, '0'); + result = result + Base64Map.values.get(binaryString); + } + return result; + } + private String getPaddedString(String string) throws Exception { String paddedReversedSemver = ""; int parts = string.split("\\.").length; diff --git a/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java b/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java index fa277c15..7b4369a0 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java @@ -29,19 +29,19 @@ public void testEncodeVersion() { analytics.setSDKSemver("1.24.0"); analytics.setTechVersion("12.0.0"); String result = analytics.toQueryParam(); - Assert.assertEquals(result, "_a=CAGAlhAMZAA0"); + Assert.assertEquals(result, "_a=DAGAlhAMZAA0"); analytics.setSDKSemver("12.0"); result = analytics.toQueryParam(); - Assert.assertEquals(result, "_a=CAGAMAMZAA0"); + Assert.assertEquals(result, "_a=DAGAMAMZAA0"); analytics.setSDKSemver("43.21.26"); result = analytics.toQueryParam(); - Assert.assertEquals(result, "_a=CAG///AMZAA0"); + Assert.assertEquals(result, "_a=DAG///AMZAA0"); analytics.setSDKSemver("0.0.0"); result = analytics.toQueryParam(); - Assert.assertEquals(result, "_a=CAGAAAAMZAA0"); + Assert.assertEquals(result, "_a=DAGAAAAMZAA0"); analytics.setSDKSemver("43.21.27"); result = analytics.toQueryParam(); @@ -53,7 +53,11 @@ public void testEncodeVersion() { public void testToQueryParam() { Analytics analytics = new Analytics("F", "2.0.0", "1.8.0", "Z", "1.34.0"); String result = analytics.toQueryParam(); - Assert.assertEquals(result, "_a=CAFAACMhZ1J0"); + Assert.assertEquals(result, "_a=DAFAACMhZBi0"); + + analytics = new Analytics("F", "2.0.0", "1.8.0", "Z", "16.3"); + result = analytics.toQueryParam(); + Assert.assertEquals(result, "_a=DAFAACMhZQD0"); } @Test @@ -61,7 +65,7 @@ public void testUrlWithAnalytics() { cloudinary.config.analytics = true; cloudinary.setAnalytics(new Analytics("F", "2.0.0", "1.8.0", "Z", "1.34.0")); String url = cloudinary.url().generate("test"); - Assert.assertEquals(url, "http://res.cloudinary.com/test123/image/upload/test?_a=CAFAACMhZ1J0"); + Assert.assertEquals(url, "http://res.cloudinary.com/test123/image/upload/test?_a=DAFAACMhZBi0"); } @Test @@ -89,7 +93,7 @@ public void testUrlWithNoAnalyticsNullAndTrue() { cloudinary.analytics.setSDKSemver("1.30.0"); cloudinary.analytics.setTechVersion("12.0.0"); String url = cloudinary.url().generate("test"); - Assert.assertEquals(url, "http://res.cloudinary.com/test123/image/upload/test?_a=CAGAu5AMZAA0"); + Assert.assertEquals(url, "http://res.cloudinary.com/test123/image/upload/test?_a=DAGAu5AMZAA0"); } @Test @@ -97,7 +101,7 @@ public void testMiscAnalyticsObject() { cloudinary.config.analytics = true; Analytics analytics = new Analytics("Z", "1.24.0", "12.0.0", "Z", "1.34.0"); String result = analytics.toQueryParam(); - Assert.assertEquals(result, "_a=CAZAlhAMZ1J0"); + Assert.assertEquals(result, "_a=DAZAlhAMZBi0"); } @Test From c109e5e36a3e9cacf35bc8e6ee6eddaacb54b7cb Mon Sep 17 00:00:00 2001 From: adimiz1 Date: Sun, 14 Jan 2024 09:24:19 +0200 Subject: [PATCH 03/40] Version 1.37.0 --- CHANGELOG.md | 6 ++++++ README.md | 6 +++--- .../src/main/java/com/cloudinary/Cloudinary.java | 2 +- gradle.properties | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dce59e1a..72a14fd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +1.37.0 / 2024-01-14 +=================== + +* Update analytics token +* Add missing display name parameter + 1.36.0 / 2023-12-04 =================== diff --git a/README.md b/README.md index c40b5901..12989c75 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ For the complete documentation, see the [Java SDK Guide](https://cloudinary.com/ ## Version Support | SDK Version | Java 6+ | |----------------|---------| -| 1.1.0 - 1.36.0 | V | +| 1.1.0 - 1.37.0 | V | ## Installation The cloudinary_java library is available in [Maven Central](https://mvnrepository.com/artifact/com.cloudinary/cloudinary-core). To use it, add the following dependency to your pom.xml : @@ -35,8 +35,8 @@ The cloudinary_java library is available in [Maven Central](https://mvnrepositor ```xml com.cloudinary - cloudinary-http44 - 1.36.0 + cloudinary-http45 + 1.37.0 ``` diff --git a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java index a35bdc2b..3d1b7168 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java @@ -38,7 +38,7 @@ public class Cloudinary { public final static String AKAMAI_SHARED_CDN = "res.cloudinary.com"; public final static String SHARED_CDN = AKAMAI_SHARED_CDN; - public final static String VERSION = "1.36.0"; + public final static String VERSION = "1.37.0"; static String USER_AGENT_PREFIX = "CloudinaryJava"; public final static String USER_AGENT_JAVA_VERSION = "(Java " + System.getProperty("java.version") + ")"; diff --git a/gradle.properties b/gradle.properties index 7050ae5f..2202f4f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ developerEmail=info@cloudinary.com # These two properties must use these exact names to be compatible with 'gradle install' plugin. group=com.cloudinary -version=1.36.0 +version=1.37.0 gnsp.disableApplyOnlyOnRootProjectEnforcement=true From 0476ad62e14a0dc87ecf2c2636e3e7972c4fbac1 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Thu, 15 Feb 2024 07:50:28 +0200 Subject: [PATCH 04/40] Add `notification_url` support to rename and destroy --- cloudinary-core/src/main/java/com/cloudinary/Uploader.java | 2 ++ .../java/com/cloudinary/test/AbstractUploaderTest.java | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Uploader.java b/cloudinary-core/src/main/java/com/cloudinary/Uploader.java index e9a6909a..d2ae11ea 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Uploader.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Uploader.java @@ -234,6 +234,7 @@ public Map destroy(String publicId, Map options) throws IOException { params.put("type", (String) options.get("type")); params.put("public_id", publicId); params.put("invalidate", ObjectUtils.asBoolean(options.get("invalidate"), false).toString()); + params.put("notification_url", (String) options.get("notification_url")); return callApi("destroy", params, options, null); } @@ -249,6 +250,7 @@ public Map rename(String fromPublicId, String toPublicId, Map options) throws IO params.put("to_type", options.get("to_type")); params.put("context", ObjectUtils.asBoolean(options.get("context"), false).toString()); params.put("metadata", ObjectUtils.asBoolean(options.get("metadata"), false).toString()); + params.put("notification_url", (String) options.get("notification_url")); return callApi("rename", params, options, null); } diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java index bf590e13..1c12748b 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java @@ -831,4 +831,11 @@ public void testUploadFolderDecoupling() { Assert.assertEquals(true, uploadParams.get("use_asset_folder_as_public_id_prefix")); Assert.assertEquals(true, uploadParams.get("visual_search")); } + + @Test + public void testNotificationUrl() { + Map options = asMap("notification_url", "https://www.test.com"); + Map uploadParams = Util.buildUploadParams(options); + Assert.assertEquals("https://www.test.com", uploadParams.get("notification_url")); + } } From b4694e7d1f5d8cc7894e980eb0fcc924f9a772c7 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Thu, 15 Feb 2024 15:52:02 +0200 Subject: [PATCH 05/40] Add analytics feature flag support --- .../java/com/cloudinary/utils/Analytics.java | 18 ++++++++++++----- .../cloudinary/analytics/AnalyticsTest.java | 20 +++++++++++++------ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/utils/Analytics.java b/cloudinary-core/src/main/java/com/cloudinary/utils/Analytics.java index d734377e..55001eb2 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/utils/Analytics.java +++ b/cloudinary-core/src/main/java/com/cloudinary/utils/Analytics.java @@ -16,15 +16,18 @@ public class Analytics { public String osType; public String osVersion; + public String featureFlag = "0"; + public Analytics() { - this("G", Cloudinary.VERSION,System.getProperty("java.version"), "Z", "0.0"); + this("G", Cloudinary.VERSION,System.getProperty("java.version"), "Z", "0.0", "0"); } - public Analytics(String sdkCode, String sdkVersion, String techVersion, String osType, String osVersion) { + public Analytics(String sdkCode, String sdkVersion, String techVersion, String osType, String osVersion, String featureFlag) { this.SDKCode = sdkCode; this.SDKSemver = sdkVersion; this.techVersion = techVersion; this.osType = osType; this.osVersion = osVersion; + this.featureFlag = featureFlag; } public Analytics setSDKCode(String SDKCode) { @@ -42,13 +45,18 @@ public Analytics setTechVersion(String techVersion) { return this; } + public Analytics setFeatureFlag(String flag) { + this.featureFlag = flag; + return this; + } + /** * Function turn analytics variables into viable query parameter. * @return query param with analytics values. */ public String toQueryParam() { try { - return sdkTokenQueryKey + sdkQueryDelimiter + getAlgorithmVersion() + prodcut + getSDKType() + getSDKVersion() + getTechVersion() + getOsType() + getOsVersion() + getSDKFeatureCode(); + return sdkTokenQueryKey + sdkQueryDelimiter + getAlgorithmVersion() + prodcut + getSDKType() + getSDKVersion() + getTechVersion() + getOsType() + getOsVersion() + getSDKFeatureFlag(); } catch (Exception e) { return sdkTokenQueryKey + sdkQueryDelimiter + "E"; } @@ -90,8 +98,8 @@ private String getAlgorithmVersion() { return algoVersion; } - private String getSDKFeatureCode() { - return "0"; + private String getSDKFeatureFlag() { + return featureFlag; } private String getSDKVersion() throws Exception { diff --git a/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java b/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java index 7b4369a0..6300947e 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java @@ -51,11 +51,11 @@ public void testEncodeVersion() { @Test public void testToQueryParam() { - Analytics analytics = new Analytics("F", "2.0.0", "1.8.0", "Z", "1.34.0"); + Analytics analytics = new Analytics("F", "2.0.0", "1.8.0", "Z", "1.34.0", "0"); String result = analytics.toQueryParam(); Assert.assertEquals(result, "_a=DAFAACMhZBi0"); - analytics = new Analytics("F", "2.0.0", "1.8.0", "Z", "16.3"); + analytics = new Analytics("F", "2.0.0", "1.8.0", "Z", "16.3", "0"); result = analytics.toQueryParam(); Assert.assertEquals(result, "_a=DAFAACMhZQD0"); } @@ -63,7 +63,7 @@ public void testToQueryParam() { @Test public void testUrlWithAnalytics() { cloudinary.config.analytics = true; - cloudinary.setAnalytics(new Analytics("F", "2.0.0", "1.8.0", "Z", "1.34.0")); + cloudinary.setAnalytics(new Analytics("F", "2.0.0", "1.8.0", "Z", "1.34.0", "0")); String url = cloudinary.url().generate("test"); Assert.assertEquals(url, "http://res.cloudinary.com/test123/image/upload/test?_a=DAFAACMhZBi0"); } @@ -99,7 +99,7 @@ public void testUrlWithNoAnalyticsNullAndTrue() { @Test public void testMiscAnalyticsObject() { cloudinary.config.analytics = true; - Analytics analytics = new Analytics("Z", "1.24.0", "12.0.0", "Z", "1.34.0"); + Analytics analytics = new Analytics("Z", "1.24.0", "12.0.0", "Z", "1.34.0", "0"); String result = analytics.toQueryParam(); Assert.assertEquals(result, "_a=DAZAlhAMZBi0"); } @@ -107,7 +107,7 @@ public void testMiscAnalyticsObject() { @Test public void testErrorAnalytics() { cloudinary.config.analytics = true; - Analytics analytics = new Analytics("Z", "1.24.0", "0", "Z", "1.34.0"); + Analytics analytics = new Analytics("Z", "1.24.0", "0", "Z", "1.34.0", "0"); String result = analytics.toQueryParam(); Assert.assertEquals(result, "_a=E"); } @@ -120,13 +120,21 @@ public void testUrlNoAnalyticsWithQueryParams() { cloudinary.config.cloudName = "test123"; cloudinary.config.analytics = true; - cloudinary.setAnalytics(new Analytics("F", "2.0.0", System.getProperty("java.version"), "Z", System.getProperty("os.version"))); + cloudinary.setAnalytics(new Analytics("F", "2.0.0", System.getProperty("java.version"), "Z", System.getProperty("os.version"), "0")); cloudinary.config.privateCdn = true; String url = cloudinary.url().signed(true).type("authenticated").generate("test"); assertEquals(url,"http://test123-res.cloudinary.com/image/authenticated/test?__cld_token__=st=11111111~exp=11111411~hmac=735a49389a72ac0b90d1a84ac5d43facd1a9047f153b39e914747ef6ed195e53"); cloudinary.config.privateCdn = false; } + @Test + public void testFeatureFlag() { + Analytics analytics = new Analytics("F", "2.0.0", "1.8.0", "Z", "1.34.0", "0"); + analytics.setFeatureFlag("F"); + String result = analytics.toQueryParam(); + Assert.assertEquals(result, "_a=DAFAACMhZBiF"); + } + @After public void tearDown() { cloudinary.config.analytics = false; From c1abb9169c1a5e5b58932db314e45fd436a7f9bf Mon Sep 17 00:00:00 2001 From: adimiz1 Date: Sun, 18 Feb 2024 08:22:05 +0200 Subject: [PATCH 06/40] Version 1.38.0 --- CHANGELOG.md | 5 +++++ README.md | 4 ++-- cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java | 2 +- gradle.properties | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72a14fd8..0a520f7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +1.38.0 / 2024-02-18 +=================== + +* Add `notification_url` support to rename and destroy + 1.37.0 / 2024-01-14 =================== diff --git a/README.md b/README.md index 12989c75..b4eb9244 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ For the complete documentation, see the [Java SDK Guide](https://cloudinary.com/ ## Version Support | SDK Version | Java 6+ | |----------------|---------| -| 1.1.0 - 1.37.0 | V | +| 1.1.0 - 1.38.0 | V | ## Installation The cloudinary_java library is available in [Maven Central](https://mvnrepository.com/artifact/com.cloudinary/cloudinary-core). To use it, add the following dependency to your pom.xml : @@ -36,7 +36,7 @@ The cloudinary_java library is available in [Maven Central](https://mvnrepositor com.cloudinary cloudinary-http45 - 1.37.0 + 1.38.0 ``` diff --git a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java index 3d1b7168..af553631 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java @@ -38,7 +38,7 @@ public class Cloudinary { public final static String AKAMAI_SHARED_CDN = "res.cloudinary.com"; public final static String SHARED_CDN = AKAMAI_SHARED_CDN; - public final static String VERSION = "1.37.0"; + public final static String VERSION = "1.38.0"; static String USER_AGENT_PREFIX = "CloudinaryJava"; public final static String USER_AGENT_JAVA_VERSION = "(Java " + System.getProperty("java.version") + ")"; diff --git a/gradle.properties b/gradle.properties index 2202f4f5..b3933bac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ developerEmail=info@cloudinary.com # These two properties must use these exact names to be compatible with 'gradle install' plugin. group=com.cloudinary -version=1.37.0 +version=1.38.0 gnsp.disableApplyOnlyOnRootProjectEnforcement=true From 923594a12484bc86279d6d05f488093a1e12a499 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:04:20 +0200 Subject: [PATCH 07/40] Add restrictions field to metadata (#312) --- .../cloudinary/metadata/MetadataField.java | 9 +++++ .../com/cloudinary/metadata/Restrictions.java | 40 +++++++++++++++++++ .../test/AbstractStructuredMetadataTest.java | 24 +++++++++-- 3 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 cloudinary-core/src/main/java/com/cloudinary/metadata/Restrictions.java diff --git a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java index bae2b6c7..7dee301f 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java +++ b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java @@ -16,6 +16,7 @@ public class MetadataField extends JSONObject { public static final String MANDATORY = "mandatory"; public static final String TYPE = "type"; public static final String VALIDATION = "validation"; + public static final String RESTRICTIONS = "restrictions"; public MetadataField(MetadataFieldType type) { put(TYPE, type.toString()); @@ -130,4 +131,12 @@ public MetadataDataSource getDataSource() { public void setDataSource(MetadataDataSource dataSource) { put("datasource", dataSource); } + + /** + * Set the restrictions rules of this field. + * @param restrictions The rules to set. + */ + public void setRestrictions(Restrictions restrictions) { + put(RESTRICTIONS, restrictions.toHash()); + } } \ No newline at end of file diff --git a/cloudinary-core/src/main/java/com/cloudinary/metadata/Restrictions.java b/cloudinary-core/src/main/java/com/cloudinary/metadata/Restrictions.java new file mode 100644 index 00000000..25d80d12 --- /dev/null +++ b/cloudinary-core/src/main/java/com/cloudinary/metadata/Restrictions.java @@ -0,0 +1,40 @@ +package com.cloudinary.metadata; + +import java.util.HashMap; + +/** + * Represents the restrictions metadata field. + */ +public class Restrictions { + + private final HashMap restrictions = new HashMap(); + + /** + * Set the custom field into restrictions. + * @param key The key of the field. + * @param value The value of the field. + */ + public Restrictions setRestriction(String key, Object value) { + restrictions.put(key, value); + return this; + } + + /** + * Set the read only ui field. + * @param value The read only ui value. + */ + public Restrictions setReadOnlyUI(Boolean value) { + return setRestriction("readonly_ui", value); + } + + /** + * Set the read only ui field to true. + */ + public Restrictions setReadOnlyUI() { + return this.setReadOnlyUI(true); + } + + public HashMap toHash() { + return restrictions; + } +} diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java index b6e541a7..bb8f1b9b 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java @@ -72,6 +72,18 @@ public void testCreateMetadata() throws Exception { assertEquals(setField.getLabel(), result.get("label")); } + @Test + public void testFieldRestrictions() throws Exception { + StringMetadataField stringField = newFieldInstance("testCreateMetadata_3"); + stringField.setRestrictions(new Restrictions().setReadOnlyUI()); + + ApiResponse result = api.addMetadataField(stringField); + assertNotNull(result); + Map restrictions = (Map) result.get("restrictions"); + assertNotNull(restrictions); + assertTrue((Boolean) restrictions.get("readonly_ui")); + } + @Test public void testDateFieldDefaultValueValidation() throws Exception { // now minus 3 days hours. @@ -130,13 +142,17 @@ public void testGetMetadata() throws Exception { @Test public void testUpdateField() throws Exception { - ApiResponse fieldResult = addFieldToAccount(newFieldInstance("testUpdateField")); + StringMetadataField metadataField = newFieldInstance("testUpdateField"); + ApiResponse fieldResult = addFieldToAccount(metadataField); assertNotEquals("new_def", fieldResult.get("default_value")); - StringMetadataField field = new StringMetadataField(); - field.setDefaultValue("new_def"); - ApiResponse result = api.updateMetadataField(fieldResult.get("external_id").toString(), field); + metadataField.setDefaultValue("new_def"); + metadataField.setRestrictions(new Restrictions().setReadOnlyUI()); + ApiResponse result = api.updateMetadataField(fieldResult.get("external_id").toString(), metadataField); assertNotNull(result); assertEquals("new_def", result.get("default_value")); + Map restrictions = (Map) result.get("restrictions"); + assertNotNull(restrictions); + assertTrue((Boolean)restrictions.get("readonly_ui")); } @Test From 09e0719c7750233890f0c75026dab10828363a4b Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Wed, 6 Mar 2024 14:17:28 +0200 Subject: [PATCH 08/40] Add access key management --- .../com/cloudinary/provisioning/Account.java | 56 +++++++++++++++++++ .../test/AbstractAccountApiTest.java | 41 ++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/cloudinary-core/src/main/java/com/cloudinary/provisioning/Account.java b/cloudinary-core/src/main/java/com/cloudinary/provisioning/Account.java index 55860aa5..c149e5dc 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/provisioning/Account.java +++ b/cloudinary-core/src/main/java/com/cloudinary/provisioning/Account.java @@ -14,8 +14,10 @@ public class Account { private static final String CLOUDINARY_ACCOUNT_URL = "CLOUDINARY_ACCOUNT_URL"; public static final String PROVISIONING = "provisioning"; public static final String ACCOUNTS = "accounts"; + public static final String SUB_ACCOUNTS = "sub_accounts"; public static final String USERS = "users"; public static final String USER_GROUPS = "user_groups"; + public static final String ACCESS_KEYS = "access_keys"; private final AccountConfiguration configuration; private final String accountId; @@ -619,6 +621,60 @@ public ApiResponse userGroupUsers(String groupId, Map options) t return callAccountApi(Api.HttpMethod.GET, uri, Collections.emptyMap(), options); } + /** + * Lists the access keys belonging to this sub account id. + * @param subAccountId The id of the user group. + * @param options Generic advanced options map, see online documentation. + * @return The list of access keys in that sub account id. + * @throws Exception If the request fails. + */ + public ApiResponse getAccessKeys(String subAccountId, Map options) throws Exception { + List uri = Arrays.asList(PROVISIONING, ACCOUNTS, accountId, SUB_ACCOUNTS, subAccountId); + return callAccountApi(Api.HttpMethod.GET, uri, Collections.emptyMap(), options); + } + + /** + * Creates a new access key for this sub account id. + * @param subAccountId The id of the user group. + * @param name The name for the access key. + * @param enabled Access key's status (enabled or disabled). + * @param options Generic advanced options map, see online documentation. + * @return The created access key. + * @throws Exception If the request fails. + */ + public ApiResponse createAccessKey(String subAccountId, String name, Boolean enabled, Map options) throws Exception { + List uri = Arrays.asList(PROVISIONING, ACCOUNTS, accountId, SUB_ACCOUNTS, subAccountId, ACCESS_KEYS); + return callAccountApi(Api.HttpMethod.POST, uri, ObjectUtils.asMap("name", name, "enabled", enabled), options); + } + + /** + * Updates an existing access key for this sub account id. + * @param subAccountId The id of the user group. + * @param accessKey The key of the access key. + * @param name The name for the access key. + * @param enabled Access key's status (enabled or disabled). + * @param options Generic advanced options map, see online documentation. + * @return The updated access key. + * @throws Exception If the request fails. + */ + public ApiResponse updateAccessKey(String subAccountId, String accessKey, String name, Boolean enabled, Map options) throws Exception { + List uri = Arrays.asList(PROVISIONING, ACCOUNTS, accountId, SUB_ACCOUNTS, subAccountId, ACCESS_KEYS, accessKey); + return callAccountApi(Api.HttpMethod.PUT, uri, ObjectUtils.asMap("name", name, "enabled", enabled), options); + } + + /** + * Deletes an existing access key for this sub account id. + * @param subAccountId The id of the user group. + * @param accessKey The key of the access key. + * @param options Generic advanced options map, see online documentation. + * @return "message": "ok". + * @throws Exception If the request fails. + */ + public ApiResponse deleteAccessKey(String subAccountId, String accessKey, Map options) throws Exception { + List uri = Arrays.asList(PROVISIONING, ACCOUNTS, accountId, SUB_ACCOUNTS, subAccountId, ACCESS_KEYS, accessKey); + return callAccountApi(Api.HttpMethod.DELETE, uri, Collections.emptyMap(), options); + } + /** * Private helper method for users api calls * @param method Http method diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractAccountApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractAccountApiTest.java index 7513907a..5b8e9633 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractAccountApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractAccountApiTest.java @@ -423,6 +423,47 @@ public void testListUsersInGroup() throws Exception { deleteUser(user2Id); } + @Test + public void testGetAccessKeys() throws Exception { + ApiResponse createResult = createSubAccount(); + ApiResponse result = account.getAccessKeys((String) createResult.get("id"), ObjectUtils.emptyMap()); + assertNotNull(result); + } + + @Test + public void testCreateNewAccessKey() throws Exception { + ApiResponse createResult = createSubAccount(); + String name = randomLetters(); + ApiResponse result = account.createAccessKey((String)createResult.get("id"), name, true, ObjectUtils.emptyMap()); + assertNotNull(result); + assertTrue((Boolean) result.get("enabled")); + } + + @Test + public void testUpdateAccessKey() throws Exception { + ApiResponse createResult = createSubAccount(); + String name = randomLetters(); + ApiResponse result = account.createAccessKey((String)createResult.get("id"), name, false, ObjectUtils.emptyMap()); + assertNotNull(result); + + String updatedName = randomLetters(); + result = account.updateAccessKey((String)createResult.get("id"), (String) result.get("api_key"), updatedName, true, ObjectUtils.emptyMap()); + assertNotNull(result); + assertEquals(updatedName, result.get("name")); + assertTrue((Boolean) result.get("enabled")); + } + + @Test + public void testDeleteAccessKey() throws Exception { + ApiResponse createResult = createSubAccount(); + String name = randomLetters(); + ApiResponse result = account.createAccessKey((String)createResult.get("id"), name, false, ObjectUtils.emptyMap()); + assertNotNull(result); + + result = account.deleteAccessKey((String)createResult.get("id"), (String) result.get("api_key"), ObjectUtils.emptyMap()); + assertNotNull(result); + } + // Helpers private ApiResponse createGroup() throws Exception { From 959f98acd45da23f941c88f04a600271166ce1db Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Wed, 13 Mar 2024 13:08:16 +0200 Subject: [PATCH 09/40] Add selective response support --- .../src/main/java/com/cloudinary/Api.java | 33 ++++++++++++++----- .../src/main/java/com/cloudinary/Search.java | 12 +++++++ .../com/cloudinary/test/AbstractApiTest.java | 27 +++++++++++++++ .../cloudinary/test/AbstractSearchTest.java | 12 +++++++ 4 files changed, 75 insertions(+), 9 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index 828b821b..24df4a05 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -87,8 +87,10 @@ public ApiResponse resources(Map options) throws Exception { uri.add(resourceType); if (type != null) uri.add(type); - - ApiResponse response = callApi(HttpMethod.GET, uri, ObjectUtils.only(options, "next_cursor", "direction", "max_results", "prefix", "tags", "context", "moderations", "start_at", "metadata"), options); + if(options.get("fields") != null) { + options.put("fields", StringUtils.join(ObjectUtils.asArray(options.get("fields")), ",")); + } + ApiResponse response = callApi(HttpMethod.GET, uri, ObjectUtils.only(options, "next_cursor", "direction", "max_results", "prefix", "tags", "context", "moderations", "start_at", "metadata", "fields"), options); return response; } @@ -106,8 +108,10 @@ public ApiResponse visualSearch(Map options) throws Exception { public ApiResponse resourcesByTag(String tag, Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); String resourceType = ObjectUtils.asString(options.get("resource_type"), "image"); - - ApiResponse response = callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, "tags", tag), ObjectUtils.only(options, "next_cursor", "direction", "max_results", "tags", "context", "moderations", "metadata"), options); + if(options.get("fields") != null) { + options.put("fields", StringUtils.join(ObjectUtils.asArray(options.get("fields")), ",")); + } + ApiResponse response = callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, "tags", tag), ObjectUtils.only(options, "next_cursor", "direction", "max_results", "tags", "context", "moderations", "metadata", "fields"), options); return response; } @@ -118,7 +122,10 @@ public ApiResponse resourcesByContext(String key, Map options) throws Exception public ApiResponse resourcesByContext(String key, String value, Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); String resourceType = ObjectUtils.asString(options.get("resource_type"), "image"); - Map params = ObjectUtils.only(options, "next_cursor", "direction", "max_results", "tags", "context", "moderations", "metadata"); + if(options.get("fields") != null) { + options.put("fields", StringUtils.join(ObjectUtils.asArray(options.get("fields")), ",")); + } + Map params = ObjectUtils.only(options, "next_cursor", "direction", "max_results", "tags", "context", "moderations", "metadata", "fields"); params.put("key", key); if (StringUtils.isNotBlank(value)) { params.put("value", value); @@ -128,7 +135,10 @@ public ApiResponse resourcesByContext(String key, String value, Map options) thr public ApiResponse resourceByAssetID(String assetId, Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); - Map params = ObjectUtils.only(options, "tags", "context", "moderations"); + if(options.get("fields") != null) { + options.put("fields", StringUtils.join(ObjectUtils.asArray(options.get("fields")), ",")); + } + Map params = ObjectUtils.only(options, "tags", "context", "moderations", "fields"); ApiResponse response = callApi(HttpMethod.GET, Arrays.asList("resources", assetId), params, options); return response; } @@ -142,7 +152,10 @@ public ApiResponse resourcesByAssetIDs(Iterable assetIds, Map options) t public ApiResponse resourcesByAssetFolder(String assetFolder, Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); - Map params = ObjectUtils.only(options, "next_cursor", "direction", "max_results", "tags", "context", "moderations"); + if(options.get("fields") != null) { + options.put("fields", StringUtils.join(ObjectUtils.asArray(options.get("fields")), ",")); + } + Map params = ObjectUtils.only(options, "next_cursor", "direction", "max_results", "tags", "context", "moderations", "fields"); params.put("asset_folder", assetFolder); ApiResponse response = callApi(HttpMethod.GET, Arrays.asList("resources/by_asset_folder"), params, options); return response; @@ -161,8 +174,10 @@ public ApiResponse resourcesByIds(Iterable publicIds, Map options) throw public ApiResponse resourcesByModeration(String kind, String status, Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); String resourceType = ObjectUtils.asString(options.get("resource_type"), "image"); - - ApiResponse response = callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, "moderations", kind, status), ObjectUtils.only(options, "next_cursor", "direction", "max_results", "tags", "context", "moderations", "metadata"), options); + if(options.get("fields") != null) { + options.put("fields", StringUtils.join(ObjectUtils.asArray(options.get("fields")), ",")); + } + ApiResponse response = callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, "moderations", kind, status), ObjectUtils.only(options, "next_cursor", "direction", "max_results", "tags", "context", "moderations", "metadata", "fields"), options); return response; } diff --git a/cloudinary-core/src/main/java/com/cloudinary/Search.java b/cloudinary-core/src/main/java/com/cloudinary/Search.java index 652e2cda..2ba3ac8b 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Search.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Search.java @@ -19,6 +19,7 @@ public class Search { private ArrayList aggregateParam; private ArrayList withFieldParam; private HashMap params; + private ArrayList fields; private int ttl = 300; @@ -28,6 +29,7 @@ public class Search { this.sortByParam = new ArrayList>(); this.aggregateParam = new ArrayList(); this.withFieldParam = new ArrayList(); + this.fields = new ArrayList(); } public Search ttl(int ttl) { @@ -76,6 +78,13 @@ public Search sortBy(String field, String dir) { return this; } + public Search fields(String field) { + if (!fields.contains(field)) { + fields.add(field); + } + return this; + } + public HashMap toQuery() { HashMap queryParams = new HashMap(this.params); if (withFieldParam.size() > 0) { @@ -87,6 +96,9 @@ public HashMap toQuery() { if(aggregateParam.size() > 0) { queryParams.put("aggregate", aggregateParam); } + if(fields.size() > 0) { + queryParams.put("fields", fields); + } return queryParams; } diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index 24cc490d..141b1ff3 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -181,6 +181,33 @@ public void test01ResourceTypes() throws Exception { assertThat(resource_types, hasItem("image")); } + @Test + public void testSingleSelectiveResponse() throws Exception { + Map options = new HashMap(); + options.put("fields", "width"); + Map result = api.resources(options); + List resources = (List) result.get("resources"); + assertNotNull(resources); + Map resource = resources.get(0); + assertNotNull(resource); + assertNotNull(resource.get("width")); + assertNull(resource.get("format")); + } + + @Test + public void testMultipleSelectiveResponse() throws Exception { + Map options = new HashMap(); + options.put("fields", new String[]{"width", "format"}); + Map result = api.resources(options); + List resources = (List) result.get("resources"); + assertNotNull(resources); + Map resource = resources.get(0); + assertNotNull(resource); + assertNotNull(resource.get("width")); + assertNotNull(resource.get("format")); + assertNull(resource.get("height")); + } + @Test public void test03ResourcesCursor() throws Exception { // should allow listing resources with cursor diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractSearchTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractSearchTest.java index 1d0a2094..5e30d26b 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractSearchTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractSearchTest.java @@ -177,4 +177,16 @@ public void testShouldBuildSearchUrl() throws Exception { cloudinaryToSearch.config.privateCdn = true; assertEquals(String.format("https://%s-res.cloudinary.com/search/%s/%d/%s", cloudinaryToSearch.config.cloudName, ttl300Signature, 300, base64Query), search.toUrl(300, "")); } + + @Test + public void testSearchWithSelectiveResponse() throws Exception { + Map result = cloudinary.search().expression(String.format("tags:%s", SEARCH_TAG)).fields("width").fields("height").execute(); + List resources = (List) result.get("resources"); + assertEquals(3, resources.size()); + Map resource = resources.get(0); + assertNotNull(resource); + assertNotNull(resource.get("width")); + assertNotNull(resource.get("height")); + assertNull(resource.get("format")); + } } \ No newline at end of file From 36d721803f6332b07a35cb12c355f05f85435cef Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:37:22 +0200 Subject: [PATCH 10/40] Add analyze api --- cloudinary-core/src/main/java/com/cloudinary/Api.java | 11 +++++++++++ .../cloudinary/strategies/AbstractApiStrategy.java | 10 +++++++--- .../main/java/com/cloudinary/http42/ApiStrategy.java | 5 +---- .../main/java/com/cloudinary/http43/ApiStrategy.java | 5 +---- .../main/java/com/cloudinary/http44/ApiStrategy.java | 5 +---- .../main/java/com/cloudinary/http45/ApiStrategy.java | 6 +----- .../java/com/cloudinary/test/AbstractApiTest.java | 8 ++++++++ 7 files changed, 30 insertions(+), 20 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index 24df4a05..f97ed09e 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -779,6 +779,17 @@ public ApiResponse reorderMetadataFields(String orderBy, String direction, Map o return callApi(HttpMethod.PUT, uri, map, options); } + public ApiResponse analyze(String inputType, String analysisType, String uri, Map options) throws Exception { + if (options == null || options.isEmpty()) options = ObjectUtils.asMap(); + List url = Arrays.asList("analysis", "analyze", inputType); + options.put("api_version", "v2"); + options.put("content_type", "json"); + final Map params = new HashMap(); + params.put("analysis_type", analysisType); + params.put("uri", uri); + return callApi(HttpMethod.POST, url, params, options); + } + private Map extractParams(Map options, List keys) { Map result = new HashMap(); for (String key : keys) { diff --git a/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java b/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java index 9e427c4a..2d5a514d 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java +++ b/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java @@ -5,6 +5,7 @@ import com.cloudinary.SmartUrlEncoder; import com.cloudinary.api.ApiResponse; import com.cloudinary.utils.Base64Coder; +import com.cloudinary.utils.ObjectUtils; import com.cloudinary.utils.StringUtils; import java.util.Arrays; import java.util.Map; @@ -17,9 +18,12 @@ public void init(Api api) { this.api = api; } - protected String createApiUrl (Iterable uri, String prefix, String cloudName){ - - String apiUrl = StringUtils.join(Arrays.asList(prefix, "v1_1", cloudName), "/"); + protected String createApiUrl (Iterable uri, Map options){ + String version = ObjectUtils.asString(options.get("api_version"), "v1_1"); + String prefix = ObjectUtils.asString(options.get("upload_prefix"), ObjectUtils.asString(this.api.cloudinary.config.uploadPrefix, "https://api.cloudinary.com")); + String cloudName = ObjectUtils.asString(options.get("cloud_name"), this.api.cloudinary.config.cloudName); + if (cloudName == null) throw new IllegalArgumentException("Must supply cloud_name"); + String apiUrl = StringUtils.join(Arrays.asList(prefix, version, cloudName), "/"); for (String component : uri) { component = SmartUrlEncoder.encode(component); apiUrl = apiUrl + "/" + component; diff --git a/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java b/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java index 6703448e..4a90ed86 100644 --- a/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java +++ b/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java @@ -34,9 +34,6 @@ public class ApiStrategy extends AbstractApiStrategy { public ApiResponse callApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); - String prefix = ObjectUtils.asString(options.get("upload_prefix"), ObjectUtils.asString(this.api.cloudinary.config.uploadPrefix, "https://api.cloudinary.com")); - String cloudName = ObjectUtils.asString(options.get("cloud_name"), this.api.cloudinary.config.cloudName); - if (cloudName == null) throw new IllegalArgumentException("Must supply cloud_name"); String apiKey = ObjectUtils.asString(options.get("api_key"), this.api.cloudinary.config.apiKey); String apiSecret = ObjectUtils.asString(options.get("api_secret"), this.api.cloudinary.config.apiSecret); String oauthToken = ObjectUtils.asString(options.get("oauth_token"), this.api.cloudinary.config.oauthToken); @@ -44,7 +41,7 @@ public ApiResponse callApi(HttpMethod method, Iterable uri, Map uri, Map uri, Map uri, Map Date: Thu, 28 Mar 2024 10:54:32 +0200 Subject: [PATCH 11/40] Add filename test to upload large --- .../main/java/com/cloudinary/test/AbstractUploaderTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java index 1c12748b..bddf48cc 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java @@ -571,11 +571,12 @@ public void testUploadLarge() throws Exception { assertEquals("raw", resource.get("resource_type")); assertTrue(resource.get("public_id").toString().startsWith("cldupload")); - resource = cloudinary.uploader().uploadLarge(new FileInputStream(temp), asMap("chunk_size", 5243000, "tags", tags)); + resource = cloudinary.uploader().uploadLarge(new FileInputStream(temp), asMap("filename", "test123", "chunk_size", 5243000, "tags", tags)); assertArrayEquals(tags, ((java.util.ArrayList) resource.get("tags")).toArray()); assertEquals("image", resource.get("resource_type")); assertEquals(1400, resource.get("width")); assertEquals(1400, resource.get("height")); + assertEquals("test123", resource.get("original_filename")); resource = cloudinary.uploader().uploadLarge(temp, asMap("chunk_size", 5880138, "tags", tags)); assertArrayEquals(tags, ((java.util.ArrayList) resource.get("tags")).toArray()); From 40941ecb3485c3fcd530293df20508e1fe229618 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Tue, 30 Apr 2024 07:19:28 +0300 Subject: [PATCH 12/40] Add rename folder api support --- .../src/main/java/com/cloudinary/Api.java | 12 ++++++++++++ .../java/com/cloudinary/test/AbstractApiTest.java | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index f97ed09e..c9b59d0e 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -790,6 +790,18 @@ public ApiResponse analyze(String inputType, String analysisType, String uri, Ma return callApi(HttpMethod.POST, url, params, options); } + public ApiResponse renameFolder(String path, String toPath, Map options) throws Exception { + if (options == null || options.isEmpty()) options = ObjectUtils.asMap(); + List url = Arrays.asList("folder_operations", "rename"); + + final Map params = new HashMap(); + params.put("path", path); + params.put("to_path", toPath); + + return callApi(HttpMethod.PUT, url, params, options); + + } + private Map extractParams(Map options, List keys) { Map result = new HashMap(); for (String key : keys) { diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index 15bbf17c..889b15f6 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -1267,4 +1267,15 @@ public void testVisualSearch() { Util.processWriteParameters(options, params); assertEquals(true, params.get("visual_search")); } + + @Test + @Ignore("Skip test till FD is enabled for test accounts") + public void testRenameFolder() throws Exception { + Map result = api.createFolder("apTestCreateFolder", null); + assertNotNull(result); + + String folderName = (String) result.get("path"); + Map response = api.renameFolder(folderName, "newFolderName", ObjectUtils.emptyMap()); + assertNotNull(response); + } } From bd829089b00690a694838fea30a99ab7cf55ae69 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Sun, 5 May 2024 08:20:15 +0300 Subject: [PATCH 13/40] Add delete backup asset version support --- .../src/main/java/com/cloudinary/Api.java | 19 ++++++++++++++++++ .../com/cloudinary/test/AbstractApiTest.java | 20 +++++++++++++++++++ .../com/cloudinary/test/helpers/Feature.java | 1 + 3 files changed, 40 insertions(+) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index c9b59d0e..daaa30df 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -802,6 +802,25 @@ public ApiResponse renameFolder(String path, String toPath, Map options) throws } + public ApiResponse deleteBackedUpAssets(String assetId, String[] versionIds, Map options) throws Exception { + if (options == null || options.isEmpty()) options = ObjectUtils.asMap(); + if (StringUtils.isEmpty(assetId)) { + throw new IllegalArgumentException("AssetId parameter is required"); + } + + if (versionIds == null || versionIds.length == 0) { + throw new IllegalArgumentException("VersionIds parameter is required"); + } + + List url = Arrays.asList("resources", "backup", assetId); + + Map params = new HashMap(); + params.put("version_ids[]", StringUtils.join(versionIds, "&")); + + return callApi(HttpMethod.DELETE, url, params, options); + + } + private Map extractParams(Map options, List keys) { Map result = new HashMap(); for (String key : keys) { diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index 889b15f6..7ffd138e 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -1278,4 +1278,24 @@ public void testRenameFolder() throws Exception { Map response = api.renameFolder(folderName, "newFolderName", ObjectUtils.emptyMap()); assertNotNull(response); } + + @Test + public void testDeleteBackedupAsset() throws Exception { + if (MockableTest.shouldTestFeature(Feature.BACKEDUP_ASSETS)) { + Map result = cloudinary.uploader().upload(SRC_TEST_IMAGE, ObjectUtils.asMap("backup", true)); + + String publicId = (String) result.get("public_id"); + String assetId = (String) result.get("asset_id"); + + ApiResponse getVersionsResp = api.resource(publicId, ObjectUtils.asMap("versions", true)); + List versions = (List) getVersionsResp.get("versions"); + String firstAssetVersion = (String) versions.get(0).get("version_id"); + ApiResponse response = api.deleteBackedUpAssets(assetId, new String[]{firstAssetVersion}, ObjectUtils.emptyMap()); + + assertNotNull(response); + assertEquals(response.get("asset_id"), assetId); + List deletedVersionIds = (List) response.get("deleted_version_ids"); + assertEquals(deletedVersionIds.get(0), firstAssetVersion); + } + } } diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java index 875f9b9f..aa4297c8 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java @@ -3,4 +3,5 @@ public class Feature { public static final String ALL = "all"; public static final String DYNAMIC_FOLDERS = "dynamic_folders"; + public static final String BACKEDUP_ASSETS = "backedup_assets"; } From 52d8f8feb029e4f5bedd403576c1e42a75f037dc Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Wed, 8 May 2024 11:34:25 +0300 Subject: [PATCH 14/40] Add config api call --- cloudinary-core/src/main/java/com/cloudinary/Api.java | 10 ++++++++++ .../main/java/com/cloudinary/test/AbstractApiTest.java | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index daaa30df..a79409f5 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -72,6 +72,16 @@ public ApiResponse usage(Map options) throws Exception { return callApi(HttpMethod.GET, uri, ObjectUtils.emptyMap(), options); } + public ApiResponse configuration(Map options) throws Exception { + if(options == null) options = ObjectUtils.emptyMap(); + + final List uri = new ArrayList(); + uri.add("config"); + + Map params = ObjectUtils.only(options, "settings"); + + return callApi(HttpMethod.GET, uri, params, options); + } public ApiResponse resourceTypes(Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index 7ffd138e..26726340 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -668,6 +668,13 @@ public void testRateLimits() throws Exception { Assert.assertNotEquals(0, result.apiRateLimit().getRemaining()); } + @Test + public void testConfiguration() throws Exception { + ApiResponse result = cloudinary.api().configuration(new ObjectUtils().asMap("settings", true)); + Map settings = (Map) result.get("settings"); + Assert.assertNotNull(settings.get("folder_mode")); + } + @Test public void test19Ping() throws Exception { // should support ping API call From 94825e3de8f05848e9913e58fcca70ebd442ffa5 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Thu, 9 May 2024 11:47:40 +0300 Subject: [PATCH 15/40] Fix rename folder endpoint --- cloudinary-core/src/main/java/com/cloudinary/Api.java | 5 ++--- .../src/main/java/com/cloudinary/test/AbstractApiTest.java | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index a79409f5..9af8639b 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -802,11 +802,10 @@ public ApiResponse analyze(String inputType, String analysisType, String uri, Ma public ApiResponse renameFolder(String path, String toPath, Map options) throws Exception { if (options == null || options.isEmpty()) options = ObjectUtils.asMap(); - List url = Arrays.asList("folder_operations", "rename"); + List url = Arrays.asList("folders", path); final Map params = new HashMap(); - params.put("path", path); - params.put("to_path", toPath); + params.put("to_folder", toPath); return callApi(HttpMethod.PUT, url, params, options); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index 26726340..cd1ccc88 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -1278,11 +1278,11 @@ public void testVisualSearch() { @Test @Ignore("Skip test till FD is enabled for test accounts") public void testRenameFolder() throws Exception { - Map result = api.createFolder("apTestCreateFolder", null); + Map result = api.createFolder("apiTestCreateFolder" + SUFFIX, null); assertNotNull(result); String folderName = (String) result.get("path"); - Map response = api.renameFolder(folderName, "newFolderName", ObjectUtils.emptyMap()); + Map response = api.renameFolder(folderName, "newFolderName" + SUFFIX, ObjectUtils.emptyMap()); assertNotNull(response); } From 922d69198908f84676be5882cab05868c27e686c Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Mon, 1 Jul 2024 13:48:58 +0300 Subject: [PATCH 16/40] Add conditional metadata rules api --- .../src/main/java/com/cloudinary/Api.java | 30 +++++++++ .../com/cloudinary/metadata/MetadataRule.java | 66 +++++++++++++++++++ .../metadata/MetadataRuleCondition.java | 58 ++++++++++++++++ .../metadata/MetadataRuleResult.java | 58 ++++++++++++++++ .../test/AbstractStructuredMetadataTest.java | 52 ++++++++++++++- .../com/cloudinary/test/helpers/Feature.java | 1 + 6 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRule.java create mode 100644 cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRuleCondition.java create mode 100644 cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRuleResult.java diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index 9af8639b..2899327d 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -7,6 +7,7 @@ import com.cloudinary.api.exceptions.*; import com.cloudinary.metadata.MetadataField; import com.cloudinary.metadata.MetadataDataSource; +import com.cloudinary.metadata.MetadataRule; import com.cloudinary.strategies.AbstractApiStrategy; import com.cloudinary.utils.ObjectUtils; import com.cloudinary.utils.StringUtils; @@ -789,6 +790,35 @@ public ApiResponse reorderMetadataFields(String orderBy, String direction, Map o return callApi(HttpMethod.PUT, uri, map, options); } + public ApiResponse listMetadataRules(Map options) throws Exception { + if (options == null || options.isEmpty()) options = ObjectUtils.asMap(); + final Map params = new HashMap(); + List uri = Arrays.asList("metadata_rules"); + return callApi(HttpMethod.GET, uri, params, options); + } + + public ApiResponse addMetadataRule(MetadataRule rule, Map options) throws Exception { + if (options == null || options.isEmpty()) options = ObjectUtils.asMap(); + options.put("content_type", "json"); + final Map params = rule.asMap(); + List uri = Arrays.asList("metadata_rules"); + return callApi(HttpMethod.POST, uri, params, options); + } + + public ApiResponse updateMetadataRule(String externalId, MetadataRule rule, Map options) throws Exception { + if (options == null || options.isEmpty()) options = ObjectUtils.asMap(); + options.put("content_type", "json"); + final Map params = rule.asMap(); + List uri = Arrays.asList("metadata_rules", externalId); + return callApi(HttpMethod.PUT, uri, params, options); + } + + public ApiResponse deleteMetadataRule(String externalId, Map options) throws Exception { + if (options == null || options.isEmpty()) options = ObjectUtils.asMap(); + List uri = Arrays.asList("metadata_rules", externalId); + return callApi(HttpMethod.DELETE, uri, ObjectUtils.emptyMap(), options); + } + public ApiResponse analyze(String inputType, String analysisType, String uri, Map options) throws Exception { if (options == null || options.isEmpty()) options = ObjectUtils.asMap(); List url = Arrays.asList("analysis", "analyze", inputType); diff --git a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRule.java b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRule.java new file mode 100644 index 00000000..65edbed4 --- /dev/null +++ b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRule.java @@ -0,0 +1,66 @@ +package com.cloudinary.metadata; + +import com.cloudinary.utils.ObjectUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class MetadataRule { + String metadataFieldId; + String name; + MetadataRuleCondition condition; + MetadataRuleResult result; + + public MetadataRule(String metadataFieldId, String name, MetadataRuleCondition condition, MetadataRuleResult result) { + this.metadataFieldId = metadataFieldId; + this.name = name; + this.condition = condition; + this.result = result; + } + + public String getMetadataFieldId() { + return metadataFieldId; + } + + public void setMetadataFieldId(String metadataFieldId) { + this.metadataFieldId = metadataFieldId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public MetadataRuleCondition getCondition() { + return condition; + } + + public void setCondition(MetadataRuleCondition condition) { + this.condition = condition; + } + + public MetadataRuleResult getResult() { + return result; + } + + public void setResult(MetadataRuleResult result) { + this.result = result; + } + + public Map asMap() { + Map map = new HashMap(); + map.put("metadata_field_id", getMetadataFieldId()); + map.put("name", getName()); + if (getCondition() != null) { + map.put("condition", ObjectUtils.toJSON(getCondition().asMap())); + } + if(getResult() != null) { + map.put("result", ObjectUtils.toJSON(getResult().asMap())); + } + return map; + } +} diff --git a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRuleCondition.java b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRuleCondition.java new file mode 100644 index 00000000..55e3a714 --- /dev/null +++ b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRuleCondition.java @@ -0,0 +1,58 @@ +package com.cloudinary.metadata; +import java.util.HashMap; +import java.util.Map; + +public class MetadataRuleCondition { + String metadata_field_id; + Boolean populated; + Map includes; + String equals; + + public MetadataRuleCondition(String metadata_field_id, Boolean populated, Map includes, String equals) { + this.metadata_field_id = metadata_field_id; + this.populated = populated; + this.includes = includes; + this.equals = equals; + } + + public String getMetadata_field_id() { + return metadata_field_id; + } + + public void setMetadata_field_id(String metadata_field_id) { + this.metadata_field_id = metadata_field_id; + } + + public Boolean getPopulated() { + return populated; + } + + public void setPopulated(Boolean populated) { + this.populated = populated; + } + + public Map getIncludes() { + return includes; + } + + public void setIncludes(Map includes) { + this.includes = includes; + } + + public String getEquals() { + return equals; + } + + public void setEquals(String equals) { + this.equals = equals; + } + + public Map asMap() { + Map result = new HashMap(4); + result.put("metadata_field_id", metadata_field_id); + result.put("populated", populated); + result.put("includes", includes); + result.put("equals", equals); + return result; + } +} diff --git a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRuleResult.java b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRuleResult.java new file mode 100644 index 00000000..2d4efff0 --- /dev/null +++ b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRuleResult.java @@ -0,0 +1,58 @@ +package com.cloudinary.metadata; + +import java.util.HashMap; +import java.util.Map; + +public class MetadataRuleResult { + Boolean enabled; + String activateValues; + String applyValues; + Boolean setMandatory; + + public MetadataRuleResult(Boolean enabled, String activateValues, String applyValues, Boolean setMandatory) { + this.enabled = enabled; + this.activateValues = activateValues; + this.applyValues = applyValues; + this.setMandatory = setMandatory; + } + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public String getActivateValues() { + return activateValues; + } + + public void setActivateValues(String activateValues) { + this.activateValues = activateValues; + } + + public String getApplyValues() { + return applyValues; + } + + public void setApplyValues(String applyValues) { + this.applyValues = applyValues; + } + + public Boolean getSetMandatory() { + return setMandatory; + } + + public void setSetMandatory(Boolean setMandatory) { + this.setMandatory = setMandatory; + } + public Map asMap() { + Map result = new HashMap(4); + result.put("enable", enabled); + result.put("activate_values", activateValues); + result.put("apply_values", applyValues); + result.put("mandatory", setMandatory); + return result; + } +} diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java index bb8f1b9b..d49ac7bb 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java @@ -6,6 +6,7 @@ import com.cloudinary.api.exceptions.BadRequest; import com.cloudinary.metadata.*; +import com.cloudinary.test.helpers.Feature; import com.cloudinary.utils.ObjectUtils; import org.hamcrest.Matchers; import org.junit.*; @@ -196,7 +197,7 @@ public void testReorderMetadataFieldsByLabel() throws Exception { AddStringField("some_value"); AddStringField("aaa"); AddStringField("zzz"); - + ApiResponse result = api.reorderMetadataFields("label", null, Collections.EMPTY_MAP); assertThat(getField(result, 0), Matchers.containsString("aaa")); @@ -309,6 +310,55 @@ public void testSetField() throws Exception { assertNotNull(result); assertEquals(PUBLIC_ID, ((List) result.get("public_ids")).get(0).toString()); } + + @Test + public void testListMetadataRules() throws Exception { + Assume.assumeTrue(MockableTest.shouldTestFeature(Feature.CONDITIONAL_METADATA_RULES)); + ApiResponse result = cloudinary.api().listMetadataRules(null); + assertNotNull(result); + } + + @Test + public void testAddMetadataRule() throws Exception { + Assume.assumeTrue(MockableTest.shouldTestFeature(Feature.CONDITIONAL_METADATA_RULES)); + SetMetadataField field = createSetField("test123"); + ApiResponse response = addFieldToAccount(field); + assertNotNull(response); + + String externalId = (String) response.get("external_id"); + MetadataRule rule = new MetadataRule(externalId, "category-employee", new MetadataRuleCondition("category", false, null, "employee"), new MetadataRuleResult(true, "all", null, null)); + ApiResponse result = cloudinary.api().addMetadataRule(rule, ObjectUtils.asMap()); + assertNotNull(result); + + String name = (String) result.get("name"); + assertEquals(name, "category-employee"); + } + + @Test + public void testUpdateMetadataRule() throws Exception { + Assume.assumeTrue(MockableTest.shouldTestFeature(Feature.CONDITIONAL_METADATA_RULES)); + ApiResponse response = cloudinary.api().listMetadataRules(null); + List metadataRules = (List) response.get("metadata_rules"); + assertNotNull(metadataRules); + String externalId = (String) ((Map) metadataRules.get(0)).get("external_id"); + + MetadataRule rule = new MetadataRule(null, "test_name", null, null); + ApiResponse result = cloudinary.api().updateMetadataRule(externalId, rule, ObjectUtils.asMap()); + assertNotNull(result); + } + + @Test + public void testDeleteMetadataRule() throws Exception { + Assume.assumeTrue(MockableTest.shouldTestFeature(Feature.CONDITIONAL_METADATA_RULES)); + ApiResponse response = cloudinary.api().listMetadataRules(null); + List metadataRules = (List) response.get("metadata_rules"); + assertNotNull(metadataRules); + String externalId = (String) ((Map) metadataRules.get(0)).get("external_id"); + + ApiResponse result = cloudinary.api().deleteMetadataRule(externalId, ObjectUtils.emptyMap()); + assertNotNull(result); + } + // Metadata test helpers private SetMetadataField createSetField(String labelPrefix) { SetMetadataField setField = new SetMetadataField(); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java index aa4297c8..2ced269c 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java @@ -4,4 +4,5 @@ public class Feature { public static final String ALL = "all"; public static final String DYNAMIC_FOLDERS = "dynamic_folders"; public static final String BACKEDUP_ASSETS = "backedup_assets"; + public static final String CONDITIONAL_METADATA_RULES = "conditional_metadata_rules"; } From 2caecfd0273bcfd2bb9cf6b572c9b5b3de37e78c Mon Sep 17 00:00:00 2001 From: adimiz1 Date: Sun, 14 Jul 2024 11:14:35 +0300 Subject: [PATCH 17/40] Version 1.39.0 --- CHANGELOG.md | 13 +++++++++++++ README.md | 4 ++-- .../src/main/java/com/cloudinary/Cloudinary.java | 2 +- gradle.properties | 2 +- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a520f7d..f4b4cc2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +1.39.0 / 2024-07-14 +=================== + +* Add conditional metadata rules api +* Fix rename folder endpoint +* Add config api call +* Add delete backup asset version support +* Add rename folder api support +* Add analyze api +* Add selective response support +* Add access key management +* Add restrictions field to metadata + 1.38.0 / 2024-02-18 =================== diff --git a/README.md b/README.md index b4eb9244..42a635c6 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ For the complete documentation, see the [Java SDK Guide](https://cloudinary.com/ ## Version Support | SDK Version | Java 6+ | |----------------|---------| -| 1.1.0 - 1.38.0 | V | +| 1.1.0 - 1.39.0 | V | ## Installation The cloudinary_java library is available in [Maven Central](https://mvnrepository.com/artifact/com.cloudinary/cloudinary-core). To use it, add the following dependency to your pom.xml : @@ -36,7 +36,7 @@ The cloudinary_java library is available in [Maven Central](https://mvnrepositor com.cloudinary cloudinary-http45 - 1.38.0 + 1.39.0 ``` diff --git a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java index af553631..24e6f692 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java @@ -38,7 +38,7 @@ public class Cloudinary { public final static String AKAMAI_SHARED_CDN = "res.cloudinary.com"; public final static String SHARED_CDN = AKAMAI_SHARED_CDN; - public final static String VERSION = "1.38.0"; + public final static String VERSION = "1.39.0"; static String USER_AGENT_PREFIX = "CloudinaryJava"; public final static String USER_AGENT_JAVA_VERSION = "(Java " + System.getProperty("java.version") + ")"; diff --git a/gradle.properties b/gradle.properties index b3933bac..e588ea7d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ developerEmail=info@cloudinary.com # These two properties must use these exact names to be compatible with 'gradle install' plugin. group=com.cloudinary -version=1.38.0 +version=1.39.0 gnsp.disableApplyOnlyOnRootProjectEnforcement=true From f4c574389c3689457743ddbd76436a4c35bfff31 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Mon, 15 Jul 2024 15:18:12 +0300 Subject: [PATCH 18/40] Add support for update metadata field set default disabled --- .../cloudinary/metadata/MetadataField.java | 9 ++++++ .../com/cloudinary/test/AbstractApiTest.java | 6 ++-- .../test/AbstractStructuredMetadataTest.java | 30 ++++++++++--------- .../cloudinary/test/AbstractUploaderTest.java | 2 +- .../cloudinary/test/MetadataTestHelper.java | 4 +-- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java index 7dee301f..4f3bdf33 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java +++ b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java @@ -17,6 +17,7 @@ public class MetadataField extends JSONObject { public static final String TYPE = "type"; public static final String VALIDATION = "validation"; public static final String RESTRICTIONS = "restrictions"; + public static final String DEFAULT_DISABLED = "default_disabled"; public MetadataField(MetadataFieldType type) { put(TYPE, type.toString()); @@ -139,4 +140,12 @@ public void setDataSource(MetadataDataSource dataSource) { public void setRestrictions(Restrictions restrictions) { put(RESTRICTIONS, restrictions.toHash()); } + + /** + * Set the value indicating whether the field should be disabled by default + * @param disabled The value to set. + */ + public void setDefaultDisabled(Boolean disabled) { + put(DEFAULT_DISABLED, disabled); + } } \ No newline at end of file diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index cd1ccc88..dd3802c9 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -415,7 +415,7 @@ public void testDeleteDerivedByTransformation() throws Exception { @Test public void testGetResourcesWithMetadata() throws Exception { String public_id = "api_,withMetadata" + SUFFIX; - String fieldId = MetadataTestHelper.addFieldToAccount(api, MetadataTestHelper.newFieldInstance("some_field" + SUFFIX)).get("external_id").toString(); + String fieldId = MetadataTestHelper.addFieldToAccount(api, MetadataTestHelper.newFieldInstance("some_field" + SUFFIX, true)).get("external_id").toString(); cloudinary.uploader().upload(SRC_TEST_IMAGE, ObjectUtils.asMap("public_id", public_id, "tags", UPLOAD_TAGS, @@ -761,8 +761,8 @@ public void testDetectionUpdate() { @Test public void testUpdateResourceClearInvalid() throws Exception { - String fieldId = MetadataTestHelper.addFieldToAccount(api, MetadataTestHelper.newFieldInstance("some_field3" + SUFFIX)).get("external_id").toString(); - String fieldId2 = MetadataTestHelper.addFieldToAccount(api, MetadataTestHelper.newFieldInstance("some_field4" + SUFFIX)).get("external_id").toString(); + String fieldId = MetadataTestHelper.addFieldToAccount(api, MetadataTestHelper.newFieldInstance("some_field3" + SUFFIX, true)).get("external_id").toString(); + String fieldId2 = MetadataTestHelper.addFieldToAccount(api, MetadataTestHelper.newFieldInstance("some_field4" + SUFFIX, true)).get("external_id").toString(); Map uploadResult = cloudinary.uploader().upload(SRC_TEST_IMAGE, ObjectUtils.asMap("tags", UPLOAD_TAGS, "metadata", ObjectUtils.asMap(fieldId, "test"))); Map apiResult = api.update((String) uploadResult.get("public_id"), ObjectUtils.asMap("clear_invalid", true, "metadata", ObjectUtils.asMap(fieldId2, "test2"))); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java index d49ac7bb..241ac47d 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java @@ -62,7 +62,7 @@ public void setUp() { @Test public void testCreateMetadata() throws Exception { - StringMetadataField stringField = newFieldInstance("testCreateMetadata_1"); + StringMetadataField stringField = newFieldInstance("testCreateMetadata_1", true); ApiResponse result = addFieldToAccount(stringField); assertNotNull(result); assertEquals(stringField.getLabel(), result.get("label")); @@ -75,7 +75,7 @@ public void testCreateMetadata() throws Exception { @Test public void testFieldRestrictions() throws Exception { - StringMetadataField stringField = newFieldInstance("testCreateMetadata_3"); + StringMetadataField stringField = newFieldInstance("testCreateMetadata_3", true); stringField.setRestrictions(new Restrictions().setReadOnlyUI()); ApiResponse result = api.addMetadataField(stringField); @@ -124,7 +124,7 @@ public void testDateFieldDefaultValueValidation() throws Exception { @Test public void testListFields() throws Exception { - StringMetadataField stringField = newFieldInstance("testListFields"); + StringMetadataField stringField = newFieldInstance("testListFields", true); addFieldToAccount(stringField); ApiResponse result = cloudinary.api().listMetadataFields(); @@ -135,7 +135,7 @@ public void testListFields() throws Exception { @Test public void testGetMetadata() throws Exception { - ApiResponse fieldResult = addFieldToAccount(newFieldInstance("testGetMetadata")); + ApiResponse fieldResult = addFieldToAccount(newFieldInstance("testGetMetadata", true)); ApiResponse result = api.metadataFieldByFieldId(fieldResult.get("external_id").toString()); assertNotNull(result); assertEquals(fieldResult.get("label"), result.get("label")); @@ -143,14 +143,16 @@ public void testGetMetadata() throws Exception { @Test public void testUpdateField() throws Exception { - StringMetadataField metadataField = newFieldInstance("testUpdateField"); + StringMetadataField metadataField = newFieldInstance("testUpdateField", false); ApiResponse fieldResult = addFieldToAccount(metadataField); assertNotEquals("new_def", fieldResult.get("default_value")); metadataField.setDefaultValue("new_def"); + metadataField.setDefaultDisabled(true); metadataField.setRestrictions(new Restrictions().setReadOnlyUI()); ApiResponse result = api.updateMetadataField(fieldResult.get("external_id").toString(), metadataField); assertNotNull(result); assertEquals("new_def", result.get("default_value")); + assertEquals(true, result.get("default_disabled")); Map restrictions = (Map) result.get("restrictions"); assertNotNull(restrictions); assertTrue((Boolean)restrictions.get("readonly_ui")); @@ -158,7 +160,7 @@ public void testUpdateField() throws Exception { @Test public void testDeleteField() throws Exception { - ApiResponse fieldResult = addFieldToAccount(newFieldInstance("testDeleteField")); + ApiResponse fieldResult = addFieldToAccount(newFieldInstance("testDeleteField", true)); ApiResponse result = api.deleteMetadataField(fieldResult.get("external_id").toString()); assertNotNull(result); assertEquals("ok", result.get("message")); @@ -219,14 +221,14 @@ private String getField(ApiResponse result, int index) { } private void AddStringField(String labelPrefix) throws Exception { - StringMetadataField field = newFieldInstance(labelPrefix); + StringMetadataField field = newFieldInstance(labelPrefix, true); ApiResponse fieldResult = addFieldToAccount(field); String fieldId = fieldResult.get("external_id").toString(); } @Test public void testUploadWithMetadata() throws Exception { - StringMetadataField field = newFieldInstance("testUploadWithMetadata"); + StringMetadataField field = newFieldInstance("testUploadWithMetadata", true); ApiResponse fieldResult = addFieldToAccount(field); String fieldId = fieldResult.get("external_id").toString(); Map metadata = Collections.singletonMap(fieldId, "123456"); @@ -239,7 +241,7 @@ public void testUploadWithMetadata() throws Exception { public void testExplicitWithMetadata() throws Exception { Map uploadResult = cloudinary.uploader().upload(SRC_TEST_IMAGE, asMap("tags", Arrays.asList(SDK_TEST_TAG, METADATA_UPLOADER_TAG))); String publicId = uploadResult.get("public_id").toString(); - StringMetadataField field = newFieldInstance("testExplicitWithMetadata"); + StringMetadataField field = newFieldInstance("testExplicitWithMetadata", true); ApiResponse fieldResult = addFieldToAccount(field); String fieldId = fieldResult.get("external_id").toString(); Map metadata = Collections.singletonMap(fieldId, "123456"); @@ -263,7 +265,7 @@ public void testExplicitWithMetadata() throws Exception { public void testUpdateWithMetadata() throws Exception { Map uploadResult = cloudinary.uploader().upload(SRC_TEST_IMAGE, asMap("tags", Arrays.asList(SDK_TEST_TAG, METADATA_UPLOADER_TAG))); String publicId = uploadResult.get("public_id").toString(); - StringMetadataField field = newFieldInstance("testUpdateWithMetadata"); + StringMetadataField field = newFieldInstance("testUpdateWithMetadata", true); ApiResponse fieldResult = addFieldToAccount(field); String fieldId = fieldResult.get("external_id").toString(); Map metadata = Collections.singletonMap(fieldId, "123456"); @@ -274,7 +276,7 @@ public void testUpdateWithMetadata() throws Exception { @Test public void testUploaderUpdateMetadata() throws Exception { - StringMetadataField field = newFieldInstance("testUploaderUpdateMetadata"); + StringMetadataField field = newFieldInstance("testUploaderUpdateMetadata", true); ApiResponse fieldResult = addFieldToAccount(field); String fieldId = fieldResult.get("external_id").toString(); Map result = cloudinary.uploader().updateMetadata(Collections.singletonMap(fieldId, "123456"), new String[]{PUBLIC_ID}, null); @@ -288,7 +290,7 @@ public void testUploaderUpdateMetadata() throws Exception { @Test public void testUploaderUpdateMetadataClearInvalid() throws Exception { - StringMetadataField field = newFieldInstance("testUploaderUpdateMetadata1"); + StringMetadataField field = newFieldInstance("testUploaderUpdateMetadata1", true); ApiResponse fieldResult = addFieldToAccount(field); String fieldId = fieldResult.get("external_id").toString(); Map result = cloudinary.uploader().updateMetadata(Collections.singletonMap(fieldId, "123456"), new String[]{PUBLIC_ID}, ObjectUtils.asMap("clear_invalid", true)); @@ -377,9 +379,9 @@ private SetMetadataField createSetField(String labelPrefix) { return setField; } - private StringMetadataField newFieldInstance(String labelPrefix) throws Exception { + private StringMetadataField newFieldInstance(String labelPrefix, Boolean mandatory) throws Exception { String label = labelPrefix + "_" + SUFFIX; - return MetadataTestHelper.newFieldInstance(label); + return MetadataTestHelper.newFieldInstance(label, mandatory); } private ApiResponse addFieldToAccount(MetadataField field) throws Exception { diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java index bddf48cc..99654c4e 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java @@ -236,7 +236,7 @@ public void testRenameShouldReturnContext() throws Exception { @Test public void testRenameShouldReturnMetadata() throws Exception { String label = "test" + SUFFIX; - StringMetadataField f = MetadataTestHelper.newFieldInstance(label); + StringMetadataField f = MetadataTestHelper.newFieldInstance(label, true); Map fieldResult = MetadataTestHelper.addFieldToAccount(cloudinary.api(), f); String fieldId = fieldResult.get("external_id").toString(); Map metadata = Collections.singletonMap(fieldId, "123456"); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/MetadataTestHelper.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/MetadataTestHelper.java index d130b282..cdb52487 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/MetadataTestHelper.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/MetadataTestHelper.java @@ -7,10 +7,10 @@ import com.cloudinary.metadata.StringMetadataField; public class MetadataTestHelper { - public static StringMetadataField newFieldInstance(String label) throws Exception { + public static StringMetadataField newFieldInstance(String label, Boolean mandatory) throws Exception { StringMetadataField field = new StringMetadataField(); field.setLabel(label); - field.setMandatory(true); + field.setMandatory(mandatory); field.setValidation(new MetadataValidation.StringLength(3, 9)); field.setDefaultValue("val_test"); return field; From 5553c36e22ecff46ced3db4a8c2157629816269f Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Tue, 30 Jul 2024 17:42:55 +0300 Subject: [PATCH 19/40] Implement major version requirements --- .../java/com/cloudinary/Configuration.java | 4 +- .../java/com/cloudinary/AuthTokenTest.java | 16 +-- .../cloudinary/analytics/AnalyticsTest.java | 16 +-- .../com/cloudinary/test/CloudinaryTest.java | 113 +++++++++--------- .../cloudinary/transformation/LayerTest.java | 6 +- .../cloudinary/test/AbstractUploaderTest.java | 2 + 6 files changed, 80 insertions(+), 77 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Configuration.java b/cloudinary-core/src/main/java/com/cloudinary/Configuration.java index b0dcc41f..07280d89 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Configuration.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Configuration.java @@ -114,7 +114,7 @@ public void update(Map config) { this.apiSecret = (String) config.get("api_secret"); this.secureDistribution = (String) config.get("secure_distribution"); this.cname = (String) config.get("cname"); - this.secure = ObjectUtils.asBoolean(config.get("secure"), false); + this.secure = ObjectUtils.asBoolean(config.get("secure"), true); this.privateCdn = ObjectUtils.asBoolean(config.get("private_cdn"), false); this.cdnSubdomain = ObjectUtils.asBoolean(config.get("cdn_subdomain"), false); this.shorten = ObjectUtils.asBoolean(config.get("shorten"), false); @@ -128,7 +128,7 @@ public void update(Map config) { this.loadStrategies = ObjectUtils.asBoolean(config.get("load_strategies"), true); this.timeout = ObjectUtils.asInteger(config.get("timeout"), 0); this.clientHints = ObjectUtils.asBoolean(config.get("client_hints"), false); - this.analytics = ObjectUtils.asBoolean(config.get("analytics"), null); + this.analytics = ObjectUtils.asBoolean(config.get("analytics"), true); Map tokenMap = (Map) config.get("auth_token"); if (tokenMap != null) { this.authToken = new AuthToken(tokenMap); diff --git a/cloudinary-core/src/test/java/com/cloudinary/AuthTokenTest.java b/cloudinary-core/src/test/java/com/cloudinary/AuthTokenTest.java index ca30479e..468c43bb 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/AuthTokenTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/AuthTokenTest.java @@ -32,7 +32,7 @@ public class AuthTokenTest { @Before public void setUp() { System.out.println("Running " + this.getClass().getName() + "." + currentTest.getMethodName()); - this.cloudinary = new Cloudinary("cloudinary://a:b@test123?load_strategies=false"); + this.cloudinary = new Cloudinary("cloudinary://a:b@test123?load_strategies=false&analytics=false"); final AuthToken authToken = new AuthToken(KEY).duration(300); authToken.startTime(11111111); // start time is set for test purposes cloudinary.config.authToken = authToken; @@ -74,28 +74,28 @@ public void testAuthenticatedUrl() { String message = "should add token if authToken is globally set and signed = true"; String url = cloudinary.url().signed(true).resourceType("image").type("authenticated").version("1486020273").generate("sample.jpg"); - assertEquals(message,"http://test123-res.cloudinary.com/image/authenticated/v1486020273/sample.jpg?__cld_token__=st=11111111~exp=11111411~hmac=8db0d753ee7bbb9e2eaf8698ca3797436ba4c20e31f44527e43b6a6e995cfdb3", url); + assertEquals(message,"https://test123-res.cloudinary.com/image/authenticated/v1486020273/sample.jpg?__cld_token__=st=11111111~exp=11111411~hmac=8db0d753ee7bbb9e2eaf8698ca3797436ba4c20e31f44527e43b6a6e995cfdb3", url); message = "should add token for 'public' resource"; url = cloudinary.url().signed(true).resourceType("image").type("public").version("1486020273").generate("sample.jpg"); - assertEquals(message,"http://test123-res.cloudinary.com/image/public/v1486020273/sample.jpg?__cld_token__=st=11111111~exp=11111411~hmac=c2b77d9f81be6d89b5d0ebc67b671557e88a40bcf03dd4a6997ff4b994ceb80e", url); + assertEquals(message,"https://test123-res.cloudinary.com/image/public/v1486020273/sample.jpg?__cld_token__=st=11111111~exp=11111411~hmac=c2b77d9f81be6d89b5d0ebc67b671557e88a40bcf03dd4a6997ff4b994ceb80e", url); message = "should not add token if signed is false"; url = cloudinary.url().resourceType("image").type("authenticated").version("1486020273").generate("sample.jpg"); - assertEquals(message,"http://test123-res.cloudinary.com/image/authenticated/v1486020273/sample.jpg", url); + assertEquals(message,"https://test123-res.cloudinary.com/image/authenticated/v1486020273/sample.jpg", url); message = "should not add token if authToken is globally set but null auth token is explicitly set and signed = true"; url = cloudinary.url().authToken(AuthToken.NULL_AUTH_TOKEN).signed(true).resourceType("image").type("authenticated").version("1486020273").generate("sample.jpg"); - assertEquals(message,"http://test123-res.cloudinary.com/image/authenticated/s--v2fTPYTu--/v1486020273/sample.jpg", url); + assertEquals(message,"https://test123-res.cloudinary.com/image/authenticated/s--v2fTPYTu--/v1486020273/sample.jpg", url); message = "explicit authToken should override global setting"; url = cloudinary.url().signed(true).authToken(new AuthToken(ALT_KEY).startTime(222222222).duration(100)).resourceType("image").type("authenticated").transformation(new Transformation().crop("scale").width(300)).generate("sample.jpg"); - assertEquals(message,"http://test123-res.cloudinary.com/image/authenticated/c_scale,w_300/sample.jpg?__cld_token__=st=222222222~exp=222222322~hmac=55cfe516530461213fe3b3606014533b1eca8ff60aeab79d1bb84c9322eebc1f", url); + assertEquals(message,"https://test123-res.cloudinary.com/image/authenticated/c_scale,w_300/sample.jpg?__cld_token__=st=222222222~exp=222222322~hmac=55cfe516530461213fe3b3606014533b1eca8ff60aeab79d1bb84c9322eebc1f", url); message = "should compute expiration as start time + duration"; url = cloudinary.url().signed(true).authToken(new AuthToken().startTime(11111111).duration(300)) .type("authenticated").version("1486020273").generate("sample.jpg"); - assertEquals(message,"http://test123-res.cloudinary.com/image/authenticated/v1486020273/sample.jpg?__cld_token__=st=11111111~exp=11111411~hmac=8db0d753ee7bbb9e2eaf8698ca3797436ba4c20e31f44527e43b6a6e995cfdb3", url); + assertEquals(message,"https://test123-res.cloudinary.com/image/authenticated/v1486020273/sample.jpg?__cld_token__=st=11111111~exp=11111411~hmac=8db0d753ee7bbb9e2eaf8698ca3797436ba4c20e31f44527e43b6a6e995cfdb3", url); } @@ -120,7 +120,7 @@ public void testTokenGeneration(){ public void testUrlInTag() { String message = "should add token to an image tag url"; String url = cloudinary.url().signed(true).resourceType("image").type("authenticated").version("1486020273").imageTag("sample.jpg"); - assertThat(url, Matchers.matchesPattern("")); } diff --git a/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java b/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java index 6300947e..e87143c6 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/analytics/AnalyticsTest.java @@ -65,26 +65,28 @@ public void testUrlWithAnalytics() { cloudinary.config.analytics = true; cloudinary.setAnalytics(new Analytics("F", "2.0.0", "1.8.0", "Z", "1.34.0", "0")); String url = cloudinary.url().generate("test"); - Assert.assertEquals(url, "http://res.cloudinary.com/test123/image/upload/test?_a=DAFAACMhZBi0"); + Assert.assertEquals(url, "https://res.cloudinary.com/test123/image/upload/test?_a=DAFAACMhZBi0"); } @Test public void testUrlWithNoAnalytics() { - String url = cloudinary.url().generate("test"); - Assert.assertEquals(url, "http://res.cloudinary.com/test123/image/upload/test"); + cloudinary.config.analytics = false; + String url = cloudinary.url().secure(true).generate("test"); + Assert.assertEquals(url, "https://res.cloudinary.com/test123/image/upload/test"); } @Test public void testUrlWithNoAnalyticsDefined() { cloudinary.config.analytics = false; String url = cloudinary.url().generate("test"); - Assert.assertEquals(url, "http://res.cloudinary.com/test123/image/upload/test"); + Assert.assertEquals(url, "https://res.cloudinary.com/test123/image/upload/test"); } @Test public void testUrlWithNoAnalyticsNull() { + cloudinary.config.analytics = false; String url = cloudinary.url().generate("test"); - Assert.assertEquals(url, "http://res.cloudinary.com/test123/image/upload/test"); + Assert.assertEquals(url, "https://res.cloudinary.com/test123/image/upload/test"); } @Test @@ -93,7 +95,7 @@ public void testUrlWithNoAnalyticsNullAndTrue() { cloudinary.analytics.setSDKSemver("1.30.0"); cloudinary.analytics.setTechVersion("12.0.0"); String url = cloudinary.url().generate("test"); - Assert.assertEquals(url, "http://res.cloudinary.com/test123/image/upload/test?_a=DAGAu5AMZAA0"); + Assert.assertEquals(url, "https://res.cloudinary.com/test123/image/upload/test?_a=DAGAu5AMZAA0"); } @Test @@ -123,7 +125,7 @@ public void testUrlNoAnalyticsWithQueryParams() { cloudinary.setAnalytics(new Analytics("F", "2.0.0", System.getProperty("java.version"), "Z", System.getProperty("os.version"), "0")); cloudinary.config.privateCdn = true; String url = cloudinary.url().signed(true).type("authenticated").generate("test"); - assertEquals(url,"http://test123-res.cloudinary.com/image/authenticated/test?__cld_token__=st=11111111~exp=11111411~hmac=735a49389a72ac0b90d1a84ac5d43facd1a9047f153b39e914747ef6ed195e53"); + assertEquals(url,"https://test123-res.cloudinary.com/image/authenticated/test?__cld_token__=st=11111111~exp=11111411~hmac=735a49389a72ac0b90d1a84ac5d43facd1a9047f153b39e914747ef6ed195e53"); cloudinary.config.privateCdn = false; } diff --git a/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java b/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java index f23acd60..0721acae 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java @@ -35,7 +35,7 @@ @RunWith(JUnitParamsRunner.class) public class CloudinaryTest { - private static final String DEFAULT_ROOT_PATH = "http://res.cloudinary.com/test123/"; + private static final String DEFAULT_ROOT_PATH = "https://res.cloudinary.com/test123/"; private static final String DEFAULT_UPLOAD_PATH = DEFAULT_ROOT_PATH + "image/upload/"; private static final String VIDEO_UPLOAD_PATH = DEFAULT_ROOT_PATH + "video/upload/"; private Cloudinary cloudinary; @@ -46,7 +46,7 @@ public class CloudinaryTest { @Before public void setUp() { System.out.println("Running " + this.getClass().getName() + "." + currentTest.getMethodName()); - this.cloudinary = new Cloudinary("cloudinary://a:b@test123?load_strategies=false"); + this.cloudinary = new Cloudinary("cloudinary://a:b@test123?load_strategies=false&analytics=false"); } @Test @@ -93,13 +93,13 @@ public void testCloudName() { public void testCloudNameOptions() { // should allow overriding cloud_name in options String result = cloudinary.url().cloudName("test321").generate("test"); - assertEquals("http://res.cloudinary.com/test321/image/upload/test", result); + assertEquals("https://res.cloudinary.com/test321/image/upload/test", result); } @Test public void testSecureDistribution() { // should use default secure distribution if secure=TRUE - String result = cloudinary.url().secure(true).generate("test"); + String result = cloudinary.url().generate("test"); assertEquals("https://res.cloudinary.com/test123/image/upload/test", result); } @@ -113,7 +113,7 @@ public void testTextLayerStyleIdentifierVariables() { new TextLayer().text("hello-world").textStyle("$style") )).generate("sample"); - assertEquals("http://res.cloudinary.com/test123/image/upload/$style_!Arial_12!/l_text:$style:hello-world/sample", url); + assertEquals("https://res.cloudinary.com/test123/image/upload/$style_!Arial_12!/l_text:$style:hello-world/sample", url); url = cloudinary.url().transformation( new Transformation() @@ -123,14 +123,14 @@ public void testTextLayerStyleIdentifierVariables() { new TextLayer().text("hello-world").textStyle(new Expression("$style")) )).generate("sample"); - assertEquals("http://res.cloudinary.com/test123/image/upload/$style_!Arial_12!/l_text:$style:hello-world/sample", url); + assertEquals("https://res.cloudinary.com/test123/image/upload/$style_!Arial_12!/l_text:$style:hello-world/sample", url); } @Test public void testSecureDistributionOverwrite() { // should allow overwriting secure distribution if secure=TRUE - String result = cloudinary.url().secure(true).secureDistribution("something.else.com").generate("test"); + String result = cloudinary.url().secureDistribution("something.else.com").generate("test"); assertEquals("https://something.else.com/test123/image/upload/test", result); } @@ -146,7 +146,6 @@ public void testSecureDistibution() { public void testSecureAkamai() { // should default to akamai if secure is given with private_cdn and no // secure_distribution - cloudinary.config.secure = true; cloudinary.config.privateCdn = true; String result = cloudinary.url().generate("test"); assertEquals("https://test123-res.cloudinary.com/image/upload/test", result); @@ -156,7 +155,6 @@ public void testSecureAkamai() { public void testSecureNonAkamai() { // should not add cloud_name if private_cdn and secure non akamai // secure_distribution - cloudinary.config.secure = true; cloudinary.config.privateCdn = true; cloudinary.config.secureDistribution = "something.cloudfront.net"; String result = cloudinary.url().generate("test"); @@ -168,7 +166,7 @@ public void testHttpPrivateCdn() { // should not add cloud_name if private_cdn and not secure cloudinary.config.privateCdn = true; String result = cloudinary.url().generate("test"); - assertEquals("http://test123-res.cloudinary.com/image/upload/test", result); + assertEquals("https://test123-res.cloudinary.com/image/upload/test", result); } @Test @@ -182,14 +180,14 @@ public void testFormat() { public void testType() { // should use type from options String result = cloudinary.url().type("facebook").generate("test"); - assertEquals("http://res.cloudinary.com/test123/image/facebook/test", result); + assertEquals("https://res.cloudinary.com/test123/image/facebook/test", result); } @Test public void testResourceType() { // should use resource_type from options String result = cloudinary.url().resourcType("raw").generate("test"); - assertEquals("http://res.cloudinary.com/test123/raw/upload/test", result); + assertEquals("https://res.cloudinary.com/test123/raw/upload/test", result); } @Test @@ -200,27 +198,27 @@ public void testIgnoreHttp() { result = cloudinary.url().type("asset").generate("http://test"); assertEquals("http://test", result); result = cloudinary.url().type("fetch").generate("http://test"); - assertEquals("http://res.cloudinary.com/test123/image/fetch/http://test", result); + assertEquals("https://res.cloudinary.com/test123/image/fetch/http://test", result); } @Test public void testFetch() { // should escape fetch urls String result = cloudinary.url().type("fetch").generate("http://blah.com/hello?a=b"); - assertEquals("http://res.cloudinary.com/test123/image/fetch/http://blah.com/hello%3Fa%3Db", result); + assertEquals("https://res.cloudinary.com/test123/image/fetch/http://blah.com/hello%3Fa%3Db", result); } @Test public void testCname() { // should support external cname - String result = cloudinary.url().cname("hello.com").generate("test"); + String result = cloudinary.url().cname("hello.com").secure(false).generate("test"); assertEquals("http://hello.com/test123/image/upload/test", result); } @Test public void testCnameSubdomain() { // should support external cname with cdn_subdomain on - String result = cloudinary.url().cname("hello.com").cdnSubdomain(true).generate("test"); + String result = cloudinary.url().cname("hello.com").cdnSubdomain(true).secure(false).generate("test"); assertEquals("http://a2.hello.com/test123/image/upload/test", result); } @@ -243,17 +241,17 @@ public void testDisallowUrlSuffixWithDot() { @Test public void testSupportUrlSuffixForPrivateCdn() { String actual = cloudinary.url().suffix("hello").privateCdn(true).generate("test"); - assertEquals("http://test123-res.cloudinary.com/images/test/hello", actual); + assertEquals("https://test123-res.cloudinary.com/images/test/hello", actual); actual = cloudinary.url().suffix("hello").privateCdn(true).transformation(new Transformation().angle(0)).generate("test"); - assertEquals("http://test123-res.cloudinary.com/images/a_0/test/hello", actual); + assertEquals("https://test123-res.cloudinary.com/images/a_0/test/hello", actual); } @Test public void testPutFormatAfterUrlSuffix() { String actual = cloudinary.url().suffix("hello").privateCdn(true).format("jpg").generate("test"); - assertEquals("http://test123-res.cloudinary.com/images/test/hello.jpg", actual); + assertEquals("https://test123-res.cloudinary.com/images/test/hello.jpg", actual); } @Test @@ -266,7 +264,7 @@ public void testNotSignTheUrlSuffix() { String expectedSignature = url.substring(matcher.start(), matcher.end()); String actual = cloudinary.url().format("jpg").privateCdn(true).signed(true).suffix("hello").generate("test"); - assertEquals("http://test123-res.cloudinary.com/images/" + expectedSignature + "/test/hello.jpg", actual); + assertEquals("https://test123-res.cloudinary.com/images/" + expectedSignature + "/test/hello.jpg", actual); url = cloudinary.url().format("jpg").signed(true).transformation(new Transformation().angle(0)).generate("test"); matcher = pattern.matcher(url); @@ -275,56 +273,56 @@ public void testNotSignTheUrlSuffix() { actual = cloudinary.url().format("jpg").privateCdn(true).signed(true).suffix("hello").transformation(new Transformation().angle(0)).generate("test"); - assertEquals("http://test123-res.cloudinary.com/images/" + expectedSignature + "/a_0/test/hello.jpg", actual); + assertEquals("https://test123-res.cloudinary.com/images/" + expectedSignature + "/a_0/test/hello.jpg", actual); } @Test public void testSignatureLength(){ String url = cloudinary.url().signed(true).generate("sample.jpg"); - assertEquals("http://res.cloudinary.com/test123/image/upload/s--v2fTPYTu--/sample.jpg", url); + assertEquals("https://res.cloudinary.com/test123/image/upload/s--v2fTPYTu--/sample.jpg", url); url = cloudinary.url().signed(true).longUrlSignature(true).generate("sample.jpg"); - assertEquals("http://res.cloudinary.com/test123/image/upload/s--2hbrSMPOjj5BJ4xV7SgFbRDevFaQNUFf--/sample.jpg", url); + assertEquals("https://res.cloudinary.com/test123/image/upload/s--2hbrSMPOjj5BJ4xV7SgFbRDevFaQNUFf--/sample.jpg", url); } @Test public void testSupportUrlSuffixForRawUploads() { String actual = cloudinary.url().suffix("hello").privateCdn(true).resourceType("raw").generate("test"); - assertEquals("http://test123-res.cloudinary.com/files/test/hello", actual); + assertEquals("https://test123-res.cloudinary.com/files/test/hello", actual); } @Test public void testSupportUrlSuffixForVideoUploads() { String actual = cloudinary.url().suffix("hello").privateCdn(true).resourceType("video").generate("test"); - assertEquals("http://test123-res.cloudinary.com/videos/test/hello", actual); + assertEquals("https://test123-res.cloudinary.com/videos/test/hello", actual); } @Test public void testSupportUrlSuffixForAuthenticatedImages() { String actual = cloudinary.url().suffix("hello").privateCdn(true).resourceType("image").type("authenticated").generate("test"); - assertEquals("http://test123-res.cloudinary.com/authenticated_images/test/hello", actual); + assertEquals("https://test123-res.cloudinary.com/authenticated_images/test/hello", actual); } @Test public void testSupportUrlSuffixForPrivateImages() { String actual = cloudinary.url().suffix("hello").privateCdn(true).resourceType("image").type("private").generate("test"); - assertEquals("http://test123-res.cloudinary.com/private_images/test/hello", actual); + assertEquals("https://test123-res.cloudinary.com/private_images/test/hello", actual); } @Test public void testSupportUseRootPathForPrivateCdn() { String actual = cloudinary.url().privateCdn(true).useRootPath(true).generate("test"); - assertEquals("http://test123-res.cloudinary.com/test", actual); + assertEquals("https://test123-res.cloudinary.com/test", actual); actual = cloudinary.url().privateCdn(true).transformation(new Transformation().angle(0)).useRootPath(true).generate("test"); - assertEquals("http://test123-res.cloudinary.com/a_0/test", actual); + assertEquals("https://test123-res.cloudinary.com/a_0/test", actual); } @Test public void testSupportUseRootPathTogetherWithUrlSuffixForPrivateCdn() { String actual = cloudinary.url().privateCdn(true).suffix("hello").useRootPath(true).generate("test"); - assertEquals("http://test123-res.cloudinary.com/test/hello", actual); + assertEquals("https://test123-res.cloudinary.com/test/hello", actual); } @@ -452,7 +450,7 @@ public void testNoEmptyTransformation() { public void testHttpEscape() { // should escape http urls String result = cloudinary.url().type("youtube").generate("http://www.youtube.com/watch?v=d9NF2edxy-M"); - assertEquals("http://res.cloudinary.com/test123/image/youtube/http://www.youtube.com/watch%3Fv%3Dd9NF2edxy-M", result); + assertEquals("https://res.cloudinary.com/test123/image/youtube/http://www.youtube.com/watch%3Fv%3Dd9NF2edxy-M", result); } @Test @@ -489,14 +487,14 @@ public void testAngle() { public void testFetchFormat() { // should support format for fetch urls String result = cloudinary.url().format("jpg").type("fetch").generate("http://cloudinary.com/images/old_logo.png"); - assertEquals("http://res.cloudinary.com/test123/image/fetch/f_jpg/http://cloudinary.com/images/old_logo.png", result); + assertEquals("https://res.cloudinary.com/test123/image/fetch/f_jpg/http://cloudinary.com/images/old_logo.png", result); } @Test public void testUseFetchFormat() { // should support use fetch format, adds the format but not an extension String result = cloudinary.url().format("jpg").useFetchFormat(true).generate("old_logo"); - assertEquals("http://res.cloudinary.com/test123/image/upload/f_jpg/old_logo", result); + assertEquals("https://res.cloudinary.com/test123/image/upload/f_jpg/old_logo", result); } @Test @@ -580,24 +578,24 @@ public void testOpacity() { public void testImageTag() { Transformation transformation = new Transformation().width(100).height(101).crop("crop"); String result = cloudinary.url().transformation(transformation).imageTag("test", asMap("alt", "my image")); - assertEquals("my image", result); + assertEquals("my image", result); transformation = new Transformation().width(0.9).height(0.9).crop("crop").responsiveWidth(true); result = cloudinary.url().transformation(transformation).imageTag("test", asMap("alt", "my image")); assertEquals( - "my image", + "my image", result); result = cloudinary.url().transformation(transformation).imageTag("test", asMap("alt", "my image", "class", "extra")); assertEquals( - "my image", + "my image", result); transformation = new Transformation().width("auto").crop("crop"); result = cloudinary.url().transformation(transformation).imageTag("test", asMap("alt", "my image", "responsive_placeholder", "blank")); assertEquals( - "my image", + "my image", result); result = cloudinary.url().transformation(transformation).imageTag("test", asMap("alt", "my image", "responsive_placeholder", "other.gif")); assertEquals( - "my image", + "my image", result); } @@ -614,12 +612,12 @@ public void testClientHints() { assertTrue(testTag.startsWith(" getUrlParameters(URI uri) throws UnsupportedEn @Test public void testUrlCloneConfig() { // verify that secure (from url.config) is cloned as well: - Url url = cloudinary.url().cloudName("cloud").format("frmt").publicId("123").secure(true); + Url url = cloudinary.url().cloudName("cloud").format("frmt").publicId("123"); assertEquals("https://res.cloudinary.com/cloud/image/upload/123.frmt", url.clone().generate()); } diff --git a/cloudinary-core/src/test/java/com/cloudinary/transformation/LayerTest.java b/cloudinary-core/src/test/java/com/cloudinary/transformation/LayerTest.java index d801c4dc..ca230f52 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/transformation/LayerTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/transformation/LayerTest.java @@ -12,14 +12,14 @@ * Created by amir on 03/11/2015. */ public class LayerTest { - private static final String DEFAULT_ROOT_PATH = "http://res.cloudinary.com/test123/"; + private static final String DEFAULT_ROOT_PATH = "https://res.cloudinary.com/test123/"; private static final String DEFAULT_UPLOAD_PATH = DEFAULT_ROOT_PATH + "image/upload/"; private static final String VIDEO_UPLOAD_PATH = DEFAULT_ROOT_PATH + "video/upload/"; private Cloudinary cloudinary; @Before public void setUp() { - this.cloudinary = new Cloudinary("cloudinary://a:b@test123?load_strategies=false"); + this.cloudinary = new Cloudinary("cloudinary://a:b@test123?load_strategies=false&analytics=false"); } @After @@ -46,7 +46,7 @@ public void testOverlay() { } @Test - public void testUnderlay() { + public void testUnderlay() { Transformation transformation = new Transformation().underlay("text:hello"); String result = cloudinary.url().transformation(transformation).generate("test"); assertEquals(DEFAULT_UPLOAD_PATH + "u_text:hello/test", result); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java index 99654c4e..8581ca30 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java @@ -41,6 +41,7 @@ abstract public class AbstractUploaderTest extends MockableTest { @BeforeClass public static void setUpClass() throws IOException { Cloudinary cloudinary = new Cloudinary(); + cloudinary.config.analytics = false; if (cloudinary.config.apiSecret == null) { System.err.println("Please setup environment for Upload test to run"); } @@ -89,6 +90,7 @@ public static void tearDownClass() { public void setUp() { System.out.println("Running " + this.getClass().getName() + "." + currentTest.getMethodName()); this.cloudinary = new Cloudinary(); + this.cloudinary.config.analytics = false; assumeNotNull(cloudinary.config.apiSecret); } From 238b54971b153b318b7ffc04823042fd1eb7d745 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Tue, 30 Jul 2024 17:48:55 +0300 Subject: [PATCH 20/40] Update minimum java version --- java_shared.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java_shared.gradle b/java_shared.gradle index d23a49b4..f7e6e550 100644 --- a/java_shared.gradle +++ b/java_shared.gradle @@ -1,5 +1,5 @@ -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 javadoc { options.encoding = 'UTF-8' From 232a2e538331c2d4011215dfe61b10fdf2d21b9e Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Tue, 30 Jul 2024 17:52:24 +0300 Subject: [PATCH 21/40] Remove deprecated functions --- .../main/java/com/cloudinary/Cloudinary.java | 5 ----- .../src/main/java/com/cloudinary/Uploader.java | 5 ----- .../transformation/AbstractLayerBuilder.java | 7 ------- .../cloudinary/transformation/Condition.java | 17 ----------------- .../cloudinary/transformation/LayerBuilder.java | 7 ------- .../transformation/SubtitlesLayerBuilder.java | 7 ------- .../transformation/TextLayerBuilder.java | 7 ------- .../com/cloudinary/test/CloudinaryTest.java | 9 +++++---- .../cloudinary/taglib/CloudinaryImageTag.java | 11 ----------- 9 files changed, 5 insertions(+), 70 deletions(-) delete mode 100644 cloudinary-core/src/main/java/com/cloudinary/transformation/AbstractLayerBuilder.java delete mode 100644 cloudinary-core/src/main/java/com/cloudinary/transformation/LayerBuilder.java delete mode 100644 cloudinary-core/src/main/java/com/cloudinary/transformation/SubtitlesLayerBuilder.java delete mode 100644 cloudinary-core/src/main/java/com/cloudinary/transformation/TextLayerBuilder.java diff --git a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java index 24e6f692..3f636d06 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java @@ -401,9 +401,4 @@ private String buildUrl(String base, Map params) throws Unsuppor } return urlBuilder.toString(); } - - @Deprecated - public static Map asMap(Object... values) { - return ObjectUtils.asMap(values); - } } diff --git a/cloudinary-core/src/main/java/com/cloudinary/Uploader.java b/cloudinary-core/src/main/java/com/cloudinary/Uploader.java index d2ae11ea..39b21950 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Uploader.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Uploader.java @@ -263,11 +263,6 @@ public Map explicit(String publicId, Map options) throws IOException { return callApi("explicit", params, options, null); } - @Deprecated - public Map generate_sprite(String tag, Map options) throws IOException { - return generateSprite(tag, options); - } - public Map generateSprite(String tag, Map options) throws IOException { if (options == null) options = Collections.singletonMap("tag", tag); diff --git a/cloudinary-core/src/main/java/com/cloudinary/transformation/AbstractLayerBuilder.java b/cloudinary-core/src/main/java/com/cloudinary/transformation/AbstractLayerBuilder.java deleted file mode 100644 index bcc2cfea..00000000 --- a/cloudinary-core/src/main/java/com/cloudinary/transformation/AbstractLayerBuilder.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.cloudinary.transformation; - -/** - * @deprecated - */ -public abstract class AbstractLayerBuilder extends AbstractLayer { -} diff --git a/cloudinary-core/src/main/java/com/cloudinary/transformation/Condition.java b/cloudinary-core/src/main/java/com/cloudinary/transformation/Condition.java index 35613813..234fd477 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/transformation/Condition.java +++ b/cloudinary-core/src/main/java/com/cloudinary/transformation/Condition.java @@ -65,27 +65,10 @@ public Condition initialDuration(String operator, Object value) { return predicate("idu", operator, value); } - - /** - * @deprecated Use {@link #faceCount(String, Object)} instead - */ - @Deprecated - public Condition faces(String operator, Object value) { - return faceCount(operator, value); - } - public Condition faceCount(String operator, Object value) { return predicate("fc", operator, value); } - /** - * @deprecated Use {@link #pageCount(String, Object)} instead - */ - @Deprecated - public Condition pages(String operator, Object value) { - return pageCount(operator, value); - } - public Condition pageCount(String operator, Object value) { return predicate("pc", operator, value); } diff --git a/cloudinary-core/src/main/java/com/cloudinary/transformation/LayerBuilder.java b/cloudinary-core/src/main/java/com/cloudinary/transformation/LayerBuilder.java deleted file mode 100644 index 5a4ea9df..00000000 --- a/cloudinary-core/src/main/java/com/cloudinary/transformation/LayerBuilder.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.cloudinary.transformation; - -/** - * @deprecated Use {@link Layer} instead - */ -public class LayerBuilder extends Layer { -} diff --git a/cloudinary-core/src/main/java/com/cloudinary/transformation/SubtitlesLayerBuilder.java b/cloudinary-core/src/main/java/com/cloudinary/transformation/SubtitlesLayerBuilder.java deleted file mode 100644 index 22a78625..00000000 --- a/cloudinary-core/src/main/java/com/cloudinary/transformation/SubtitlesLayerBuilder.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.cloudinary.transformation; - -/** - * @deprecated Use {@link SubtitlesLayer} instead - */ -public class SubtitlesLayerBuilder extends SubtitlesLayer { -} diff --git a/cloudinary-core/src/main/java/com/cloudinary/transformation/TextLayerBuilder.java b/cloudinary-core/src/main/java/com/cloudinary/transformation/TextLayerBuilder.java deleted file mode 100644 index 0db485ce..00000000 --- a/cloudinary-core/src/main/java/com/cloudinary/transformation/TextLayerBuilder.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.cloudinary.transformation; - -/** - * @deprecated Use {@link TextLayer} instead - */ -public class TextLayerBuilder extends TextLayer { -} diff --git a/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java b/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java index 0721acae..9e436183 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java @@ -146,6 +146,7 @@ public void testSecureDistibution() { public void testSecureAkamai() { // should default to akamai if secure is given with private_cdn and no // secure_distribution + cloudinary.config.secure = true; cloudinary.config.privateCdn = true; String result = cloudinary.url().generate("test"); assertEquals("https://test123-res.cloudinary.com/image/upload/test", result); @@ -155,6 +156,7 @@ public void testSecureAkamai() { public void testSecureNonAkamai() { // should not add cloud_name if private_cdn and secure non akamai // secure_distribution + cloudinary.config.secure = true; cloudinary.config.privateCdn = true; cloudinary.config.secureDistribution = "something.cloudfront.net"; String result = cloudinary.url().generate("test"); @@ -1209,10 +1211,9 @@ public void videoTagWithAuthTokenTest() { .type("upload") .authToken(new AuthToken("123456").duration(300)) .signed(true) -// .videoTag("sample", Cloudinary.asMap( -// "controls", true, -// "loop", true) - .videoTag("sample", asMap("controls", true, + .secure(true) + .videoTag("sample", ObjectUtils.asMap( + "controls", true, "loop", true) ); assert(actualTag.contains("cld_token")); diff --git a/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryImageTag.java b/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryImageTag.java index d3738278..2de25e3b 100644 --- a/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryImageTag.java +++ b/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryImageTag.java @@ -72,15 +72,4 @@ public String getExtraClasses() { public void setExtraClasses(String extraClasses) { this.extraClasses = extraClasses; } - - @Deprecated - public void setPublicId(String src) { - this.src = src; - } - - @Deprecated - public String getPublicId() { - return src; - } - } \ No newline at end of file From 178559ba3ea4a7afa2cc18aa3df17dca41ead86b Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Mon, 19 Aug 2024 12:13:04 +0300 Subject: [PATCH 22/40] Add derived next cursor support --- .../src/main/java/com/cloudinary/Api.java | 2 +- .../com/cloudinary/test/AbstractApiTest.java | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index 2899327d..19cd61d8 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -200,7 +200,7 @@ public ApiResponse resource(String public_id, Map options) throws Exception { ApiResponse response = callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, type, public_id), ObjectUtils.only(options, "exif", "colors", "faces", "coordinates", "image_metadata", "pages", "phash", "max_results", "quality_analysis", "cinemagraph_analysis", - "accessibility_analysis", "versions", "media_metadata"), options); + "accessibility_analysis", "versions", "media_metadata", "derived_next_cursor"), options); return response; } diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index dd3802c9..ad89074a 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -1305,4 +1305,29 @@ public void testDeleteBackedupAsset() throws Exception { assertEquals(deletedVersionIds.get(0), firstAssetVersion); } } + + @Test + public void testAllowDerivedNextCursor() throws Exception { + String publicId = "allowderivednextcursor_" + SUFFIX; + Map options = ObjectUtils.asMap("public_id", publicId, "eager", Arrays.asList( + new Transformation().width(100), + new Transformation().width(101), + new Transformation().width(102) + )); + + try { + cloudinary.uploader().upload(SRC_TEST_IMAGE, options); + ApiResponse res = api.resource(publicId, Collections.singletonMap("max_results", 1)); + String derivedNextCursor = res.get("derived_next_cursor").toString(); + assertNotNull(derivedNextCursor); + + ApiResponse res2 = api.resource(publicId, ObjectUtils.asMap("derived_next_cursor", derivedNextCursor, "max_results", 1)); + String derivedNextCursor2 = res2.get("derived_next_cursor").toString(); + assertNotNull(derivedNextCursor2); + + assertNotEquals(derivedNextCursor, derivedNextCursor2); + } finally { + cloudinary.uploader().destroy(publicId, Collections.singletonMap("invalidate", true)); + } + } } From 5e77cc58a0da6c8fd05c4b13ac7c6ab14fa7c350 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Mon, 9 Sep 2024 14:04:01 +0300 Subject: [PATCH 23/40] Update http client --- .travis.yml | 5 +- .../src/main/java/com/cloudinary/Api.java | 44 +++- .../main/java/com/cloudinary/Cloudinary.java | 10 +- .../com/cloudinary/provisioning/Account.java | 31 ++- .../strategies/AbstractApiStrategy.java | 33 +-- cloudinary-http42/build.gradle | 114 ---------- .../com/cloudinary/http42/ApiStrategy.java | 142 ------------ .../cloudinary/http42/UploaderStrategy.java | 120 ----------- .../java/com/cloudinary/test/ApiTest.java | 23 -- .../java/com/cloudinary/test/ContextTest.java | 4 - .../com/cloudinary/http43/ApiStrategy.java | 203 ----------------- .../java/com/cloudinary/http43/ApiUtils.java | 53 ----- .../cloudinary/http43/UploaderStrategy.java | 144 ------------- .../com/cloudinary/http43/api/Response.java | 69 ------ .../com/cloudinary/test/AccountApiTest.java | 4 - .../java/com/cloudinary/test/ApiTest.java | 33 --- .../com/cloudinary/test/FoldersApiTest.java | 4 - .../java/com/cloudinary/test/SearchTest.java | 4 - .../test/StreamingProfilesApiTest.java | 7 - .../test/StructuredMetadataTest.java | 4 - .../com/cloudinary/test/UploaderTest.java | 34 --- cloudinary-http44/build.gradle | 113 ---------- .../com/cloudinary/http44/ApiStrategy.java | 204 ------------------ .../java/com/cloudinary/http44/ApiUtils.java | 53 ----- .../cloudinary/http44/UploaderStrategy.java | 145 ------------- .../com/cloudinary/http44/api/Response.java | 69 ------ .../com/cloudinary/test/AccountApiTest.java | 4 - .../java/com/cloudinary/test/ApiTest.java | 32 --- .../java/com/cloudinary/test/ContextTest.java | 5 - .../com/cloudinary/test/FoldersApiTest.java | 4 - .../java/com/cloudinary/test/SearchTest.java | 4 - .../test/StreamingProfilesApiTest.java | 7 - .../test/StructuredMetadataTest.java | 4 - .../com/cloudinary/test/UploaderTest.java | 33 --- cloudinary-http45/build.gradle | 113 ---------- .../com/cloudinary/http45/ApiStrategy.java | 201 ----------------- .../java/com/cloudinary/http45/ApiUtils.java | 53 ----- .../cloudinary/http45/UploaderStrategy.java | 141 ------------ .../com/cloudinary/http45/api/Response.java | 69 ------ .../com/cloudinary/test/AccountApiTest.java | 4 - .../java/com/cloudinary/test/ApiTest.java | 32 --- .../java/com/cloudinary/test/ContextTest.java | 5 - .../com/cloudinary/test/FoldersApiTest.java | 4 - .../java/com/cloudinary/test/SearchTest.java | 4 - .../test/StreamingProfilesApiTest.java | 4 - .../test/StructuredMetadataTest.java | 4 - .../com/cloudinary/test/UploaderTest.java | 34 --- .../build.gradle | 8 +- .../com/cloudinary/http5/ApiStrategy.java | 163 ++++++++++++++ .../java/com/cloudinary/http5/ApiUtils.java | 71 ++++++ .../cloudinary/http5/UploaderStrategy.java | 155 +++++++++++++ .../com/cloudinary/http5}/api/Response.java | 37 ++-- .../com/cloudinary/test/AccountApiTest.java | 0 .../java/com/cloudinary/test/ApiTest.java | 45 ++++ .../java/com/cloudinary/test/ContextTest.java | 0 .../com/cloudinary/test/FoldersApiTest.java | 0 .../java/com/cloudinary/test/SearchTest.java | 0 .../test/StreamingProfilesApiTest.java | 0 .../test/StructuredMetadataTest.java | 0 .../com/cloudinary/test/UploaderTest.java | 2 +- samples/photo_album_gae/pom.xml | 4 +- settings.gradle | 6 +- 62 files changed, 536 insertions(+), 2385 deletions(-) delete mode 100644 cloudinary-http42/build.gradle delete mode 100644 cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java delete mode 100644 cloudinary-http42/src/main/java/com/cloudinary/http42/UploaderStrategy.java delete mode 100644 cloudinary-http42/src/test/java/com/cloudinary/test/ApiTest.java delete mode 100644 cloudinary-http42/src/test/java/com/cloudinary/test/ContextTest.java delete mode 100644 cloudinary-http43/src/main/java/com/cloudinary/http43/ApiStrategy.java delete mode 100644 cloudinary-http43/src/main/java/com/cloudinary/http43/ApiUtils.java delete mode 100644 cloudinary-http43/src/main/java/com/cloudinary/http43/UploaderStrategy.java delete mode 100644 cloudinary-http43/src/main/java/com/cloudinary/http43/api/Response.java delete mode 100644 cloudinary-http43/src/test/java/com/cloudinary/test/AccountApiTest.java delete mode 100644 cloudinary-http43/src/test/java/com/cloudinary/test/ApiTest.java delete mode 100644 cloudinary-http43/src/test/java/com/cloudinary/test/FoldersApiTest.java delete mode 100644 cloudinary-http43/src/test/java/com/cloudinary/test/SearchTest.java delete mode 100644 cloudinary-http43/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java delete mode 100644 cloudinary-http43/src/test/java/com/cloudinary/test/StructuredMetadataTest.java delete mode 100644 cloudinary-http43/src/test/java/com/cloudinary/test/UploaderTest.java delete mode 100644 cloudinary-http44/build.gradle delete mode 100644 cloudinary-http44/src/main/java/com/cloudinary/http44/ApiStrategy.java delete mode 100644 cloudinary-http44/src/main/java/com/cloudinary/http44/ApiUtils.java delete mode 100644 cloudinary-http44/src/main/java/com/cloudinary/http44/UploaderStrategy.java delete mode 100644 cloudinary-http44/src/main/java/com/cloudinary/http44/api/Response.java delete mode 100644 cloudinary-http44/src/test/java/com/cloudinary/test/AccountApiTest.java delete mode 100644 cloudinary-http44/src/test/java/com/cloudinary/test/ApiTest.java delete mode 100644 cloudinary-http44/src/test/java/com/cloudinary/test/ContextTest.java delete mode 100644 cloudinary-http44/src/test/java/com/cloudinary/test/FoldersApiTest.java delete mode 100644 cloudinary-http44/src/test/java/com/cloudinary/test/SearchTest.java delete mode 100644 cloudinary-http44/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java delete mode 100644 cloudinary-http44/src/test/java/com/cloudinary/test/StructuredMetadataTest.java delete mode 100644 cloudinary-http44/src/test/java/com/cloudinary/test/UploaderTest.java delete mode 100644 cloudinary-http45/build.gradle delete mode 100644 cloudinary-http45/src/main/java/com/cloudinary/http45/ApiStrategy.java delete mode 100644 cloudinary-http45/src/main/java/com/cloudinary/http45/ApiUtils.java delete mode 100644 cloudinary-http45/src/main/java/com/cloudinary/http45/UploaderStrategy.java delete mode 100644 cloudinary-http45/src/main/java/com/cloudinary/http45/api/Response.java delete mode 100644 cloudinary-http45/src/test/java/com/cloudinary/test/AccountApiTest.java delete mode 100644 cloudinary-http45/src/test/java/com/cloudinary/test/ApiTest.java delete mode 100644 cloudinary-http45/src/test/java/com/cloudinary/test/ContextTest.java delete mode 100644 cloudinary-http45/src/test/java/com/cloudinary/test/FoldersApiTest.java delete mode 100644 cloudinary-http45/src/test/java/com/cloudinary/test/SearchTest.java delete mode 100644 cloudinary-http45/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java delete mode 100644 cloudinary-http45/src/test/java/com/cloudinary/test/StructuredMetadataTest.java delete mode 100644 cloudinary-http45/src/test/java/com/cloudinary/test/UploaderTest.java rename {cloudinary-http43 => cloudinary-http5}/build.gradle (92%) create mode 100644 cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java create mode 100644 cloudinary-http5/src/main/java/com/cloudinary/http5/ApiUtils.java create mode 100644 cloudinary-http5/src/main/java/com/cloudinary/http5/UploaderStrategy.java rename {cloudinary-http42/src/main/java/com/cloudinary/http42 => cloudinary-http5/src/main/java/com/cloudinary/http5}/api/Response.java (72%) rename {cloudinary-http42 => cloudinary-http5}/src/test/java/com/cloudinary/test/AccountApiTest.java (100%) create mode 100644 cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java rename {cloudinary-http43 => cloudinary-http5}/src/test/java/com/cloudinary/test/ContextTest.java (100%) rename {cloudinary-http42 => cloudinary-http5}/src/test/java/com/cloudinary/test/FoldersApiTest.java (100%) rename {cloudinary-http42 => cloudinary-http5}/src/test/java/com/cloudinary/test/SearchTest.java (100%) rename {cloudinary-http42 => cloudinary-http5}/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java (100%) rename {cloudinary-http42 => cloudinary-http5}/src/test/java/com/cloudinary/test/StructuredMetadataTest.java (100%) rename {cloudinary-http42 => cloudinary-http5}/src/test/java/com/cloudinary/test/UploaderTest.java (97%) diff --git a/.travis.yml b/.travis.yml index 510d55ae..8a1fec22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,10 +18,7 @@ jdk: env: - MODULE=core - - MODULE=http42 - - MODULE=http43 - - MODULE=http44 - - MODULE=http45 + - MODULE=http5 branches: except: diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index 19cd61d8..9dbacde9 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -9,6 +9,7 @@ import com.cloudinary.metadata.MetadataDataSource; import com.cloudinary.metadata.MetadataRule; import com.cloudinary.strategies.AbstractApiStrategy; +import com.cloudinary.utils.Base64Coder; import com.cloudinary.utils.ObjectUtils; import com.cloudinary.utils.StringUtils; import org.cloudinary.json.JSONArray; @@ -40,7 +41,19 @@ public enum HttpMethod {GET, POST, PUT, DELETE;} private AbstractApiStrategy strategy; protected ApiResponse callApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { - return this.strategy.callApi(method, uri, params, options); + if (options == null) + options = ObjectUtils.emptyMap(); + + String apiKey = ObjectUtils.asString(options.get("api_key"), this.cloudinary.config.apiKey); + String apiSecret = ObjectUtils.asString(options.get("api_secret"), this.cloudinary.config.apiSecret); + String oauthToken = ObjectUtils.asString(options.get("oauth_token"), this.cloudinary.config.oauthToken); + + validateAuthorization(apiKey, apiSecret, oauthToken); + + + String authorizationHeader = getAuthorizationHeaderValue(apiKey, apiSecret, oauthToken); + String apiUrl = createApiUrl(uri, options); + return this.strategy.callApi(method, apiUrl, params, options, authorizationHeader); } public Api(Cloudinary cloudinary, AbstractApiStrategy strategy) { @@ -871,4 +884,33 @@ public ApiResponse deleteBackedUpAssets(String assetId, String[] versionIds, Map } return result; } + + protected void validateAuthorization(String apiKey, String apiSecret, String oauthToken) { + if (oauthToken == null) { + if (apiKey == null) throw new IllegalArgumentException("Must supply api_key"); + if (apiSecret == null) throw new IllegalArgumentException("Must supply api_secret"); + } + } + + protected String getAuthorizationHeaderValue(String apiKey, String apiSecret, String oauthToken) { + if (oauthToken != null){ + return "Bearer " + oauthToken; + } else { + return "Basic " + Base64Coder.encodeString(apiKey + ":" + apiSecret); + } + } + + protected String createApiUrl (Iterable uri, Map options){ + String version = ObjectUtils.asString(options.get("api_version"), "v1_1"); + String prefix = ObjectUtils.asString(options.get("upload_prefix"), ObjectUtils.asString(this.cloudinary.config.uploadPrefix, "https://api.cloudinary.com")); + String cloudName = ObjectUtils.asString(options.get("cloud_name"), this.cloudinary.config.cloudName); + if (cloudName == null) throw new IllegalArgumentException("Must supply cloud_name"); + String apiUrl = StringUtils.join(Arrays.asList(prefix, version, cloudName), "/"); + for (String component : uri) { + component = SmartUrlEncoder.encode(component); + apiUrl = apiUrl + "/" + component; + + } + return apiUrl; + } } diff --git a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java index 3f636d06..27b347ac 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java @@ -22,16 +22,10 @@ public class Cloudinary { private static List UPLOAD_STRATEGIES = new ArrayList(Arrays.asList( "com.cloudinary.android.UploaderStrategy", - "com.cloudinary.http42.UploaderStrategy", - "com.cloudinary.http43.UploaderStrategy", - "com.cloudinary.http44.UploaderStrategy", - "com.cloudinary.http45.UploaderStrategy")); + "com.cloudinary.http5.UploaderStrategy")); public static List API_STRATEGIES = new ArrayList(Arrays.asList( "com.cloudinary.android.ApiStrategy", - "com.cloudinary.http42.ApiStrategy", - "com.cloudinary.http43.ApiStrategy", - "com.cloudinary.http44.ApiStrategy", - "com.cloudinary.http45.ApiStrategy")); + "com.cloudinary.http5.ApiStrategy")); public final static String CF_SHARED_CDN = "d3jpl91pxevbkh.cloudfront.net"; public final static String OLD_AKAMAI_SHARED_CDN = "cloudinary-a.akamaihd.net"; diff --git a/cloudinary-core/src/main/java/com/cloudinary/provisioning/Account.java b/cloudinary-core/src/main/java/com/cloudinary/provisioning/Account.java index c149e5dc..1c545345 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/provisioning/Account.java +++ b/cloudinary-core/src/main/java/com/cloudinary/provisioning/Account.java @@ -4,7 +4,10 @@ import com.cloudinary.Cloudinary; import com.cloudinary.Util; import com.cloudinary.api.ApiResponse; +import com.cloudinary.utils.Base64Coder; import com.cloudinary.utils.ObjectUtils; +import com.cloudinary.utils.StringUtils; + import java.util.*; /** @@ -76,7 +79,25 @@ private ApiResponse callAccountApi(Api.HttpMethod method, List uri, Map< } Util.clearEmpty(params); - return api.getStrategy().callAccountApi(method, uri, params, options); + + if (options == null) { + options = ObjectUtils.emptyMap(); + } + + String prefix = ObjectUtils.asString(options.get("upload_prefix"), "https://api.cloudinary.com"); + String apiKey = ObjectUtils.asString(options.get("provisioning_api_key")); + if (apiKey == null) throw new IllegalArgumentException("Must supply provisioning_api_key"); + String apiSecret = ObjectUtils.asString(options.get("provisioning_api_secret")); + if (apiSecret == null) throw new IllegalArgumentException("Must supply provisioning_api_secret"); + + String apiUrl = StringUtils.join(Arrays.asList(prefix, "v1_1"), "/"); + for (String component : uri) { + apiUrl = apiUrl + "/" + component; + } + + String authorizationHeader = getAuthorizationHeaderValue(apiKey, apiSecret, null); + + return api.getStrategy().callAccountApi(method, apiUrl, params, options, authorizationHeader); } /** @@ -707,4 +728,12 @@ private Map verifyOptions(Map options) { return options; } + + protected String getAuthorizationHeaderValue(String apiKey, String apiSecret, String oauthToken) { + if (oauthToken != null){ + return "Bearer " + oauthToken; + } else { + return "Basic " + Base64Coder.encodeString(apiKey + ":" + apiSecret); + } + } } diff --git a/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java b/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java index 2d5a514d..8878bf2c 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java +++ b/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java @@ -18,37 +18,8 @@ public void init(Api api) { this.api = api; } - protected String createApiUrl (Iterable uri, Map options){ - String version = ObjectUtils.asString(options.get("api_version"), "v1_1"); - String prefix = ObjectUtils.asString(options.get("upload_prefix"), ObjectUtils.asString(this.api.cloudinary.config.uploadPrefix, "https://api.cloudinary.com")); - String cloudName = ObjectUtils.asString(options.get("cloud_name"), this.api.cloudinary.config.cloudName); - if (cloudName == null) throw new IllegalArgumentException("Must supply cloud_name"); - String apiUrl = StringUtils.join(Arrays.asList(prefix, version, cloudName), "/"); - for (String component : uri) { - component = SmartUrlEncoder.encode(component); - apiUrl = apiUrl + "/" + component; - - } - return apiUrl; - } - @SuppressWarnings("rawtypes") - public abstract ApiResponse callApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception; - - public abstract ApiResponse callAccountApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception; + public abstract ApiResponse callApi(HttpMethod method, String apiUrl, Map params, Map options, String authorizationHeader) throws Exception; - protected String getAuthorizationHeaderValue(String apiKey, String apiSecret, String oauthToken) { - if (oauthToken != null){ - return "Bearer " + oauthToken; - } else { - return "Basic " + Base64Coder.encodeString(apiKey + ":" + apiSecret); - } - } - - protected void validateAuthorization(String apiKey, String apiSecret, String oauthToken) { - if (oauthToken == null) { - if (apiKey == null) throw new IllegalArgumentException("Must supply api_key"); - if (apiSecret == null) throw new IllegalArgumentException("Must supply api_secret"); - } - } + public abstract ApiResponse callAccountApi(HttpMethod method, String apiUrl, Map params, Map options, String authorizationHeader) throws Exception; } diff --git a/cloudinary-http42/build.gradle b/cloudinary-http42/build.gradle deleted file mode 100644 index 7c94214b..00000000 --- a/cloudinary-http42/build.gradle +++ /dev/null @@ -1,114 +0,0 @@ -plugins { - id 'java-library' - id 'signing' - id 'maven-publish' - id 'io.codearte.nexus-staging' version '0.21.1' -} - -apply from: "../java_shared.gradle" - -task ciTest( type: Test ) { - useJUnit { - excludeCategories 'com.cloudinary.test.TimeoutTest' - if (System.getProperty("CLOUDINARY_ACCOUNT_URL") == "") { - exclude '**/AccountApiTest.class' - } - } -} - -dependencies { - compile project(':cloudinary-core') - compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.1' - compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.2.1' - compile group: 'org.apache.httpcomponents', name: 'httpcore', version: '4.2.1' - compile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.2.1' - testCompile project(':cloudinary-test-common') - testCompile group: 'org.hamcrest', name: 'java-hamcrest', version: '2.0.0.0' - testCompile group: 'pl.pragmatists', name: 'JUnitParams', version: '1.0.5' - testCompile group: 'junit', name: 'junit', version: '4.12' -} - -if (hasProperty("ossrhPassword")) { - - signing { - sign configurations.archives - } - - nexusStaging { - packageGroup = group - username = project.hasProperty("ossrhUsername") ? project.ext["ossrhUsername"] : "" - password = project.hasProperty("ossrhPassword") ? project.ext["ossrhPassword"] : "" - } - - publishing { - publications { - mavenJava(MavenPublication) { - from components.java - artifact sourcesJar - artifact javadocJar - pom { - name = 'Cloudinary Apache HTTP 4.2 Library' - packaging = 'jar' - groupId = publishGroupId - artifactId = 'cloudinary-http42' - description = publishDescription - url = githubUrl - licenses { - license { - name = licenseName - url = licenseUrl - } - } - - developers { - developer { - id = developerId - name = developerName - email = developerEmail - } - } - scm { - connection = scmConnection - developerConnection = scmDeveloperConnection - url = scmUrl - } - } - - pom.withXml { - def pomFile = file("${project.buildDir}/generated-pom.xml") - writeTo(pomFile) - def pomAscFile = signing.sign(pomFile).signatureFiles[0] - artifact(pomAscFile) { - classifier = null - extension = 'pom.asc' - } - } - - // create the signed artifacts - project.tasks.signArchives.signatureFiles.each { - artifact(it) { - def matcher = it.file =~ /-(sources|javadoc)\.jar\.asc$/ - if (matcher.find()) { - classifier = matcher.group(1) - } else { - classifier = null - } - extension = 'jar.asc' - } - } - } - } - - model { - tasks.generatePomFileForMavenJavaPublication { - destination = file("$buildDir/generated-pom.xml") - } - tasks.publishMavenJavaPublicationToMavenLocal { - dependsOn project.tasks.signArchives - } - tasks.publishMavenJavaPublicationToSonatypeRepository { - dependsOn project.tasks.signArchives - } - } - } -} diff --git a/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java b/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java deleted file mode 100644 index 4a90ed86..00000000 --- a/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.cloudinary.http42; - -import com.cloudinary.Api; -import com.cloudinary.Api.HttpMethod; -import com.cloudinary.Cloudinary; -import com.cloudinary.api.ApiResponse; -import com.cloudinary.api.exceptions.GeneralError; -import com.cloudinary.http42.api.Response; -import com.cloudinary.strategies.AbstractApiStrategy; -import com.cloudinary.utils.Base64Coder; -import com.cloudinary.utils.ObjectUtils; -import com.cloudinary.utils.StringUtils; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.*; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.conn.ClientConnectionManager; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpConnectionParams; -import org.apache.http.params.HttpParams; -import org.cloudinary.json.JSONException; -import org.cloudinary.json.JSONObject; - -import java.io.InputStream; -import java.lang.reflect.Constructor; -import java.net.URI; -import java.util.Arrays; -import java.util.Map; - -public class ApiStrategy extends AbstractApiStrategy { - - @SuppressWarnings({"rawtypes", "unchecked"}) - public ApiResponse callApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { - if (options == null) options = ObjectUtils.emptyMap(); - - String apiKey = ObjectUtils.asString(options.get("api_key"), this.api.cloudinary.config.apiKey); - String apiSecret = ObjectUtils.asString(options.get("api_secret"), this.api.cloudinary.config.apiSecret); - String oauthToken = ObjectUtils.asString(options.get("oauth_token"), this.api.cloudinary.config.oauthToken); - String contentType = ObjectUtils.asString(options.get("content_type"), "urlencoded"); - int timeout = ObjectUtils.asInteger(options.get("timeout"), this.api.cloudinary.config.timeout); - validateAuthorization(apiKey, apiSecret, oauthToken); - - String apiUrl = createApiUrl(uri, options); - - return getApiResponse(method, params, apiKey, apiSecret, oauthToken, contentType, timeout, apiUrl); - } - - @Override - public ApiResponse callAccountApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { - String prefix = ObjectUtils.asString(options.get("upload_prefix"), "https://api.cloudinary.com"); - String apiKey = ObjectUtils.asString(options.get("provisioning_api_key")); - if (apiKey == null) throw new IllegalArgumentException("Must supply provisioning_api_key"); - String apiSecret = ObjectUtils.asString(options.get("provisioning_api_secret")); - if (apiSecret == null) throw new IllegalArgumentException("Must supply provisioning_api_secret"); - String contentType = ObjectUtils.asString(options.get("content_type"), "urlencoded"); - int timeout = ObjectUtils.asInteger(options.get("timeout"), this.api.cloudinary.config.timeout); - - String apiUrl = StringUtils.join(Arrays.asList(prefix, "v1_1"), "/"); - for (String component : uri) { - apiUrl = apiUrl + "/" + component; - } - - return getApiResponse(method, params, apiKey, apiSecret, null, contentType, timeout, apiUrl); - } - - private ApiResponse getApiResponse(HttpMethod method, Map params, String apiKey, String apiSecret, String oauthToken, String contentType, int timeout, String apiUrl) throws Exception { - URIBuilder apiUrlBuilder = new URIBuilder(apiUrl); - if (!contentType.equals("json")) { - for (Map.Entry param : params.entrySet()) { - if (param.getValue() instanceof Iterable) { - for (String single : (Iterable) param.getValue()) { - apiUrlBuilder.addParameter(param.getKey() + "[]", single); - } - } else { - apiUrlBuilder.addParameter(param.getKey(), ObjectUtils.asString(param.getValue())); - } - } - } - - ClientConnectionManager connectionManager = (ClientConnectionManager) this.api.cloudinary.config.properties.get("connectionManager"); - - DefaultHttpClient client = new DefaultHttpClient(connectionManager); - if (timeout > 0) { - HttpParams httpParams = client.getParams(); - HttpConnectionParams.setConnectionTimeout(httpParams, timeout); - HttpConnectionParams.setSoTimeout(httpParams, timeout); - } - - URI apiUri = apiUrlBuilder.build(); - HttpUriRequest request = null; - switch (method) { - case GET: - request = new HttpGet(apiUri); - break; - case PUT: - request = new HttpPut(apiUri); - break; - case POST: - request = new HttpPost(apiUri); - break; - case DELETE: - request = new HttpDelete(apiUri); - break; - } - request.setHeader("Authorization", getAuthorizationHeaderValue(apiKey, apiSecret, oauthToken)); - request.setHeader("User-Agent", this.api.cloudinary.getUserAgent() + " ApacheHTTPComponents/4.2"); - if (contentType.equals("json")) { - JSONObject asJSON = ObjectUtils.toJSON(params); - StringEntity requestEntity = new StringEntity(asJSON.toString(), ContentType.APPLICATION_JSON); - ((HttpEntityEnclosingRequestBase) request).setEntity(requestEntity); - } - - HttpResponse response = client.execute(request); - - int code = response.getStatusLine().getStatusCode(); - InputStream responseStream = response.getEntity().getContent(); - String responseData = StringUtils.read(responseStream); - - Class exceptionClass = Api.CLOUDINARY_API_ERROR_CLASSES.get(code); - if (code != 200 && exceptionClass == null) { - throw new GeneralError("Server returned unexpected status code - " + code + " - " + responseData); - } - Map result; - - try { - JSONObject responseJSON = new JSONObject(responseData); - result = ObjectUtils.toMap(responseJSON); - } catch (JSONException e) { - throw new RuntimeException("Invalid JSON response from server " + e.getMessage()); - } - - if (code == 200) { - return new Response(response, result); - } else { - String message = (String) ((Map) result.get("error")).get("message"); - Constructor exceptionConstructor = exceptionClass.getConstructor(String.class); - throw exceptionConstructor.newInstance(message); - } - } - -} diff --git a/cloudinary-http42/src/main/java/com/cloudinary/http42/UploaderStrategy.java b/cloudinary-http42/src/main/java/com/cloudinary/http42/UploaderStrategy.java deleted file mode 100644 index 0e38365d..00000000 --- a/cloudinary-http42/src/main/java/com/cloudinary/http42/UploaderStrategy.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.cloudinary.http42; - -import com.cloudinary.Cloudinary; -import com.cloudinary.ProgressCallback; -import com.cloudinary.Util; -import com.cloudinary.strategies.AbstractUploaderStrategy; -import com.cloudinary.utils.ObjectUtils; -import com.cloudinary.utils.StringUtils; -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.ClientConnectionManager; -import org.apache.http.conn.params.ConnRoutePNames; -import org.apache.http.entity.mime.HttpMultipartMode; -import org.apache.http.entity.mime.MultipartEntity; -import org.apache.http.entity.mime.content.ByteArrayBody; -import org.apache.http.entity.mime.content.FileBody; -import org.apache.http.entity.mime.content.StringBody; -import org.apache.http.impl.client.DefaultHttpClient; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.Map; - -public class UploaderStrategy extends AbstractUploaderStrategy { - - @SuppressWarnings({"rawtypes", "unchecked"}) - @Override - public Map callApi(String action, Map params, Map options, Object file, ProgressCallback progressCallback) throws IOException { - if (progressCallback != null){ - throw new IllegalArgumentException("Progress callback is not supported"); - } - - // initialize options if passed as null - if (options == null) { - options = ObjectUtils.emptyMap(); - } - - boolean returnError = ObjectUtils.asBoolean(options.get("return_error"), false); - - if (requiresSigning(action, options)) { - uploader.signRequestParams(params, options); - } else { - Util.clearEmpty(params); - } - - String apiUrl = buildUploadUrl(action, options); - - ClientConnectionManager connectionManager = (ClientConnectionManager) this.uploader.cloudinary().config.properties.get("connectionManager"); - HttpClient client = new DefaultHttpClient(connectionManager); - - // If the configuration specifies a proxy then apply it to the client - if (uploader.cloudinary().config.proxyHost != null && uploader.cloudinary().config.proxyPort != 0) { - HttpHost proxy = new HttpHost(uploader.cloudinary().config.proxyHost, uploader.cloudinary().config.proxyPort); - client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); - } - - HttpPost postMethod = new HttpPost(apiUrl); - postMethod.setHeader("User-Agent", this.cloudinary().getUserAgent() + " ApacheHTTPComponents/4.2"); - - Map extraHeaders = (Map) options.get("extra_headers"); - if (extraHeaders != null) { - for (Map.Entry header : extraHeaders.entrySet()) { - postMethod.setHeader(header.getKey(), header.getValue()); - } - } - - Charset utf8 = Charset.forName("UTF-8"); - - MultipartEntity multipart = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null, StandardCharsets.UTF_8); - // Remove blank parameters - for (Map.Entry param : params.entrySet()) { - if (param.getValue() instanceof Collection) { - for (Object value : (Collection) param.getValue()) { - multipart.addPart(param.getKey() + "[]", new StringBody(ObjectUtils.asString(value), utf8)); - } - } else { - String value = param.getValue().toString(); - if (StringUtils.isNotBlank(value)) { - multipart.addPart(param.getKey(), new StringBody(value, utf8)); - } - } - } - if(file instanceof String && !(StringUtils.isRemoteUrl((String)file))){ - File _file = new File((String) file); - if (!_file.isFile() && !_file.canRead()) { - throw new IOException("File not found or unreadable: " + file); - } - file = _file; - } - - String filename = (String) options.get("filename"); - if (file instanceof File) { - multipart.addPart("file", new FileBody((File) file, filename, "application/octet-stream", null)); - } else if (file instanceof String) { - multipart.addPart("file", new StringBody((String) file, utf8)); - } else if (file instanceof byte[]) { - if (filename == null) filename = "file"; - multipart.addPart("file", new ByteArrayBody((byte[]) file, filename)); - } else if (file == null) { - // no-problem - } else { - throw new IOException("Unrecognized file parameter " + file); - } - postMethod.setEntity(multipart); - - HttpResponse response = client.execute(postMethod); - int code = response.getStatusLine().getStatusCode(); - InputStream responseStream = response.getEntity().getContent(); - String responseData = StringUtils.read(responseStream); - - return processResponse(returnError, code, responseData); - } - -} diff --git a/cloudinary-http42/src/test/java/com/cloudinary/test/ApiTest.java b/cloudinary-http42/src/test/java/com/cloudinary/test/ApiTest.java deleted file mode 100644 index b3fa3556..00000000 --- a/cloudinary-http42/src/test/java/com/cloudinary/test/ApiTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.cloudinary.test; - -import org.apache.http.conn.ConnectTimeoutException; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ApiTest extends AbstractApiTest { - @Category(TimeoutTest.class) - @Test(expected = ConnectTimeoutException.class) - public void testTimeoutException() throws Exception { - // should allow listing resources - Map options = new HashMap(); - options.put("timeout", Integer.valueOf(1)); - - Map result = api.resources(options); - Map resource = findByAttr((List) result.get("resources"), "public_id", "api_test"); - - } -} diff --git a/cloudinary-http42/src/test/java/com/cloudinary/test/ContextTest.java b/cloudinary-http42/src/test/java/com/cloudinary/test/ContextTest.java deleted file mode 100644 index 1c126299..00000000 --- a/cloudinary-http42/src/test/java/com/cloudinary/test/ContextTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class ContextTest extends AbstractContextTest { -} diff --git a/cloudinary-http43/src/main/java/com/cloudinary/http43/ApiStrategy.java b/cloudinary-http43/src/main/java/com/cloudinary/http43/ApiStrategy.java deleted file mode 100644 index 0d619e11..00000000 --- a/cloudinary-http43/src/main/java/com/cloudinary/http43/ApiStrategy.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.cloudinary.http43; - -import com.cloudinary.Api; -import com.cloudinary.Api.HttpMethod; -import com.cloudinary.Cloudinary; -import com.cloudinary.api.ApiResponse; -import com.cloudinary.api.exceptions.GeneralError; -import com.cloudinary.http43.api.Response; -import com.cloudinary.utils.Base64Coder; -import com.cloudinary.utils.ObjectUtils; -import com.cloudinary.utils.StringUtils; -import org.apache.http.Consts; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.*; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; -import org.cloudinary.json.JSONException; -import org.cloudinary.json.JSONObject; - -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Constructor; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import static com.cloudinary.http43.ApiUtils.prepareParams; -import static com.cloudinary.http43.ApiUtils.setTimeouts; - -public class ApiStrategy extends com.cloudinary.strategies.AbstractApiStrategy { - - private CloseableHttpClient client = null; - - @Override - public void init(Api api) { - super.init(api); - - HttpClientBuilder clientBuilder = HttpClients.custom(); - clientBuilder.useSystemProperties().setUserAgent(this.api.cloudinary.getUserAgent() + " ApacheHTTPComponents/4.3"); - - // If the configuration specifies a proxy then apply it to the client - if (api.cloudinary.config.proxyHost != null && api.cloudinary.config.proxyPort != 0) { - HttpHost proxy = new HttpHost(api.cloudinary.config.proxyHost, api.cloudinary.config.proxyPort); - clientBuilder.setProxy(proxy); - } - - HttpClientConnectionManager connectionManager = (HttpClientConnectionManager) api.cloudinary.config.properties.get("connectionManager"); - if (connectionManager != null) { - clientBuilder.setConnectionManager(connectionManager); - } - - int timeout = this.api.cloudinary.config.timeout; - if (timeout > 0) { - RequestConfig config = RequestConfig.custom() - .setSocketTimeout(timeout * 1000) - .setConnectTimeout(timeout * 1000) - .build(); - clientBuilder.setDefaultRequestConfig(config); - } - - this.client = clientBuilder.build(); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public ApiResponse callApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { - if (options == null) - options = ObjectUtils.emptyMap(); - - String apiKey = ObjectUtils.asString(options.get("api_key"), this.api.cloudinary.config.apiKey); - String apiSecret = ObjectUtils.asString(options.get("api_secret"), this.api.cloudinary.config.apiSecret); - String oauthToken = ObjectUtils.asString(options.get("oauth_token"), this.api.cloudinary.config.oauthToken); - - validateAuthorization(apiKey, apiSecret, oauthToken); - - String apiUrl = createApiUrl(uri, options); - HttpUriRequest request = prepareRequest(method, apiUrl, params, options); - - request.setHeader("Authorization", getAuthorizationHeaderValue(apiKey, apiSecret, oauthToken)); - - return getApiResponse(request); - } - - private ApiResponse getApiResponse(HttpUriRequest request) throws Exception { - String responseData = null; - int code = 0; - CloseableHttpResponse response = client.execute(request); - try { - code = response.getStatusLine().getStatusCode(); - final HttpEntity entity = response.getEntity(); - responseData = StringUtils.read(entity.getContent()); - EntityUtils.consume(entity); - } finally { - response.close(); - } - - Class exceptionClass = Api.CLOUDINARY_API_ERROR_CLASSES.get(code); - if (code != 200 && exceptionClass == null) { - throw new GeneralError("Server returned unexpected status code - " + code + " - " + responseData); - } - Map result; - - try { - JSONObject responseJSON = new JSONObject(responseData); - result = ObjectUtils.toMap(responseJSON); - } catch (JSONException e) { - throw new RuntimeException("Invalid JSON response from server " + e.getMessage()); - } - - if (code == 200) { - return new Response(response, result); - } else { - String message = (String) ((Map) result.get("error")).get("message"); - Constructor exceptionConstructor = exceptionClass.getConstructor(String.class); - throw exceptionConstructor.newInstance(message); - } - } - - @Override - public ApiResponse callAccountApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { - if (options == null) - options = ObjectUtils.emptyMap(); - - String prefix = ObjectUtils.asString(options.get("upload_prefix"), "https://api.cloudinary.com"); - String apiKey = ObjectUtils.asString(options.get("provisioning_api_key")); - if (apiKey == null) throw new IllegalArgumentException("Must supply provisioning_api_key"); - String apiSecret = ObjectUtils.asString(options.get("provisioning_api_secret")); - if (apiSecret == null) throw new IllegalArgumentException("Must supply provisioning_api_secret"); - - String apiUrl = StringUtils.join(Arrays.asList(prefix, "v1_1"), "/"); - for (String component : uri) { - apiUrl = apiUrl + "/" + component; - } - - HttpUriRequest request = prepareRequest(method, apiUrl, params, options); - - request.setHeader("Authorization", "Basic " + Base64Coder.encodeString(apiKey + ":" + apiSecret)); - - return getApiResponse(request); - } - - /** - * Prepare a request with the URL and parameters based on the HTTP method used - * - * @param method the HTTP method: GET, PUT, POST, DELETE - * @param apiUrl the cloudinary API URI - * @param params the parameters to pass to the server - * @return an HTTP request - * @throws URISyntaxException - * @throws UnsupportedEncodingException - */ - private HttpUriRequest prepareRequest(HttpMethod method, String apiUrl, Map params, Map options) throws URISyntaxException, UnsupportedEncodingException { - URI apiUri; - HttpRequestBase request; - - String contentType = ObjectUtils.asString(options.get("content_type"), "urlencoded"); - URIBuilder apiUrlBuilder = new URIBuilder(apiUrl); - HashMap unboxedParams = new HashMap(params); - - if (method == HttpMethod.GET) { - apiUrlBuilder.setParameters(prepareParams(params)); - apiUri = apiUrlBuilder.build(); - request = new HttpGet(apiUri); - } else { - apiUri = apiUrlBuilder.build(); - switch (method) { - case PUT: - request = new HttpPut(apiUri); - break; - case DELETE: //uses HttpPost instead of HttpDelete - unboxedParams.put("_method","delete"); - //continue with POST - case POST: - request = new HttpPost(apiUri); - break; - default: - throw new IllegalArgumentException("Unknown HTTP method"); - } - if (contentType.equals("json")) { - JSONObject asJSON = ObjectUtils.toJSON(unboxedParams); - StringEntity requestEntity = new StringEntity(asJSON.toString(), ContentType.APPLICATION_JSON); - ((HttpEntityEnclosingRequestBase) request).setEntity(requestEntity); - } else { - ((HttpEntityEnclosingRequestBase) request).setEntity(new UrlEncodedFormEntity(prepareParams(unboxedParams), Consts.UTF_8)); - } - } - - setTimeouts(request, options); - return request; - } - - -} diff --git a/cloudinary-http43/src/main/java/com/cloudinary/http43/ApiUtils.java b/cloudinary-http43/src/main/java/com/cloudinary/http43/ApiUtils.java deleted file mode 100644 index 0356934b..00000000 --- a/cloudinary-http43/src/main/java/com/cloudinary/http43/ApiUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.cloudinary.http43; - -import com.cloudinary.utils.ObjectUtils; -import org.apache.http.NameValuePair; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.message.BasicNameValuePair; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class ApiUtils { - - public static void setTimeouts(HttpRequestBase request, Map options) { - RequestConfig config= request.getConfig(); - final RequestConfig.Builder builder; - if (config != null) { - builder = RequestConfig.copy(config); - } else { - builder = RequestConfig.custom(); - } - Integer timeout = (Integer) options.get("timeout"); - if(timeout != null) { - builder.setSocketTimeout(timeout); - } - Integer connectionRequestTimeout = (Integer) options.get("connection_request_timeout"); - if(connectionRequestTimeout != null) { - builder.setConnectionRequestTimeout(connectionRequestTimeout); - } - Integer connectTimeout = (Integer) options.get("connect_timeout"); - if(connectTimeout != null) { - builder.setConnectTimeout(connectTimeout); - } - request.setConfig(builder.build()); - } - - static List prepareParams(Map params) { - List requestParams = new ArrayList(params.size()); - for (Map.Entry param : params.entrySet()) { - if (param.getValue() instanceof Iterable) { - for (Object single : (Iterable) param.getValue()) { - requestParams.add(new BasicNameValuePair(param.getKey() + "[]", ObjectUtils.asString(single))); - } - } else { - requestParams.add(new BasicNameValuePair(param.getKey(), ObjectUtils.asString(param.getValue()))); - } - } - - - return requestParams; - } -} diff --git a/cloudinary-http43/src/main/java/com/cloudinary/http43/UploaderStrategy.java b/cloudinary-http43/src/main/java/com/cloudinary/http43/UploaderStrategy.java deleted file mode 100644 index 88ce4b90..00000000 --- a/cloudinary-http43/src/main/java/com/cloudinary/http43/UploaderStrategy.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.cloudinary.http43; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.Map; - -import com.cloudinary.ProgressCallback; -import org.apache.http.HttpHost; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.mime.HttpMultipartMode; -import org.apache.http.entity.mime.MIME; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.cloudinary.json.JSONException; -import org.cloudinary.json.JSONObject; - -import com.cloudinary.Cloudinary; -import com.cloudinary.Uploader; -import com.cloudinary.Util; -import com.cloudinary.strategies.AbstractUploaderStrategy; -import com.cloudinary.utils.ObjectUtils; -import com.cloudinary.utils.StringUtils; - -public class UploaderStrategy extends AbstractUploaderStrategy { - - private CloseableHttpClient client = null; - - @Override - public void init(Uploader uploader) { - super.init(uploader); - - HttpClientBuilder clientBuilder = HttpClients.custom(); - clientBuilder.useSystemProperties().setUserAgent(this.cloudinary().getUserAgent() + " ApacheHTTPComponents/4.3"); - - // If the configuration specifies a proxy then apply it to the client - if (cloudinary().config.proxyHost != null && cloudinary().config.proxyPort != 0) { - HttpHost proxy = new HttpHost(cloudinary().config.proxyHost, cloudinary().config.proxyPort); - clientBuilder.setProxy(proxy); - } - - HttpClientConnectionManager connectionManager = (HttpClientConnectionManager) cloudinary().config.properties.get("connectionManager"); - if (connectionManager != null) { - clientBuilder.setConnectionManager(connectionManager); - } - - this.client = clientBuilder.build(); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - @Override - public Map callApi(String action, Map params, Map options, Object file, ProgressCallback progressCallback) throws IOException { - if (progressCallback != null){ - throw new IllegalArgumentException("Progress callback is not supported"); - } - - // initialize options if passed as null - if (options == null) { - options = ObjectUtils.emptyMap(); - } - - boolean returnError = ObjectUtils.asBoolean(options.get("return_error"), false); - - if (requiresSigning(action, options)) { - uploader.signRequestParams(params, options); - } else { - Util.clearEmpty(params); - } - - String apiUrl = buildUploadUrl(action, options); - - HttpPost postMethod = new HttpPost(apiUrl); - ApiUtils.setTimeouts(postMethod, options); - - Map extraHeaders = (Map) options.get("extra_headers"); - if (extraHeaders != null) { - for (Map.Entry header : extraHeaders.entrySet()) { - postMethod.setHeader(header.getKey(), header.getValue()); - } - } - - MultipartEntityBuilder multipart = MultipartEntityBuilder.create(); - multipart.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); - multipart.setCharset(StandardCharsets.UTF_8); - ContentType contentType = ContentType.MULTIPART_FORM_DATA.withCharset(MIME.UTF8_CHARSET); - // Remove blank parameters - for (Map.Entry param : params.entrySet()) { - if (param.getValue() instanceof Collection) { - for (Object value : (Collection) param.getValue()) { - multipart.addTextBody(param.getKey() + "[]", ObjectUtils.asString(value), contentType); - } - } else { - String value = param.getValue().toString(); - if (StringUtils.isNotBlank(value)) { - multipart.addTextBody(param.getKey(), value, contentType); - } - } - } - - if(file instanceof String && !(StringUtils.isRemoteUrl((String)file))){ - File _file = new File((String) file); - if (!_file.isFile() && !_file.canRead()) { - throw new IOException("File not found or unreadable: " + file); - } - file = _file; - } - String filename = (String) options.get("filename"); - if (file instanceof File) { - if (filename == null) filename = ((File) file).getName(); - multipart.addBinaryBody("file", (File) file, ContentType.APPLICATION_OCTET_STREAM, filename); - } else if (file instanceof String) { - multipart.addTextBody("file", (String) file, contentType); - } else if (file instanceof byte[]) { - if (filename == null) filename = "file"; - multipart.addBinaryBody("file", (byte[]) file, ContentType.APPLICATION_OCTET_STREAM, filename); - } else if (file == null) { - // no-problem - } else { - throw new IOException("Unrecognized file parameter " + file); - } - postMethod.setEntity(multipart.build()); - - String responseData = null; - int code = 0; - CloseableHttpResponse response = client.execute(postMethod); - try { - code = response.getStatusLine().getStatusCode(); - InputStream responseStream = response.getEntity().getContent(); - responseData = StringUtils.read(responseStream); - } finally { - response.close(); - } - - return processResponse(returnError, code, responseData); - } - -} diff --git a/cloudinary-http43/src/main/java/com/cloudinary/http43/api/Response.java b/cloudinary-http43/src/main/java/com/cloudinary/http43/api/Response.java deleted file mode 100644 index 51cd9219..00000000 --- a/cloudinary-http43/src/main/java/com/cloudinary/http43/api/Response.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.cloudinary.http43.api; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.http.Header; -import org.apache.http.HttpResponse; - -import com.cloudinary.api.ApiResponse; -import com.cloudinary.api.RateLimit; -import com.cloudinary.utils.StringUtils; - -@SuppressWarnings("rawtypes") -public class Response extends HashMap implements ApiResponse { - private static final long serialVersionUID = -5458609797599845837L; - private HttpResponse response = null; - - @SuppressWarnings("unchecked") - public Response(HttpResponse response, Map result) { - super(result); - this.response = response; - } - - public HttpResponse getRawHttpResponse() { - return this.response; - } - - private static final Pattern RATE_LIMIT_REGEX = Pattern - .compile("X-FEATURE(\\w*)RATELIMIT(-LIMIT|-RESET|-REMAINING)", Pattern.CASE_INSENSITIVE); - private static final String RFC1123_PATTERN = "EEE, dd MMM yyyyy HH:mm:ss z"; - private static final DateFormat RFC1123 = new SimpleDateFormat(RFC1123_PATTERN, Locale.ENGLISH); - - public Map rateLimits() throws java.text.ParseException { - Header[] headers = this.response.getAllHeaders(); - Map limits = new HashMap(); - for (Header header : headers) { - Matcher m = RATE_LIMIT_REGEX.matcher(header.getName()); - if (m.matches()) { - String limitName = "Api"; - RateLimit limit = null; - if (!StringUtils.isEmpty(m.group(1))) { - limitName = m.group(1); - } - limit = limits.get(limitName); - if (limit == null) { - limit = new RateLimit(); - } - if (m.group(2).equalsIgnoreCase("-limit")) { - limit.setLimit(Long.parseLong(header.getValue())); - } else if (m.group(2).equalsIgnoreCase("-remaining")) { - limit.setRemaining(Long.parseLong(header.getValue())); - } else if (m.group(2).equalsIgnoreCase("-reset")) { - limit.setReset(RFC1123.parse(header.getValue())); - } - limits.put(limitName, limit); - } - } - return limits; - } - - public RateLimit apiRateLimit() throws java.text.ParseException { - return rateLimits().get("Api"); - } -} diff --git a/cloudinary-http43/src/test/java/com/cloudinary/test/AccountApiTest.java b/cloudinary-http43/src/test/java/com/cloudinary/test/AccountApiTest.java deleted file mode 100644 index 573a12e5..00000000 --- a/cloudinary-http43/src/test/java/com/cloudinary/test/AccountApiTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class AccountApiTest extends AbstractAccountApiTest { -} diff --git a/cloudinary-http43/src/test/java/com/cloudinary/test/ApiTest.java b/cloudinary-http43/src/test/java/com/cloudinary/test/ApiTest.java deleted file mode 100644 index 530b644f..00000000 --- a/cloudinary-http43/src/test/java/com/cloudinary/test/ApiTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.cloudinary.test; - -import com.cloudinary.api.ApiResponse; -import com.cloudinary.utils.ObjectUtils; -import org.apache.http.conn.ConnectTimeoutException; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import java.net.SocketTimeoutException; -import java.util.Map; - -public class ApiTest extends AbstractApiTest { - @Category(TimeoutTest.class) - @Test(expected = ConnectTimeoutException.class) - public void testConnectTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "connect_timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } - - @Category(TimeoutTest.class) - @Test(expected = SocketTimeoutException.class) - public void testTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } - -} diff --git a/cloudinary-http43/src/test/java/com/cloudinary/test/FoldersApiTest.java b/cloudinary-http43/src/test/java/com/cloudinary/test/FoldersApiTest.java deleted file mode 100644 index 971bcf39..00000000 --- a/cloudinary-http43/src/test/java/com/cloudinary/test/FoldersApiTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class FoldersApiTest extends AbstractFoldersApiTest { -} diff --git a/cloudinary-http43/src/test/java/com/cloudinary/test/SearchTest.java b/cloudinary-http43/src/test/java/com/cloudinary/test/SearchTest.java deleted file mode 100644 index 16a4708c..00000000 --- a/cloudinary-http43/src/test/java/com/cloudinary/test/SearchTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class SearchTest extends AbstractSearchTest { -} diff --git a/cloudinary-http43/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java b/cloudinary-http43/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java deleted file mode 100644 index 4e763579..00000000 --- a/cloudinary-http43/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.cloudinary.test; - -/** - * Created by amir on 25/10/2016. - */ -public class StreamingProfilesApiTest extends AbstractStreamingProfilesApiTest { -} diff --git a/cloudinary-http43/src/test/java/com/cloudinary/test/StructuredMetadataTest.java b/cloudinary-http43/src/test/java/com/cloudinary/test/StructuredMetadataTest.java deleted file mode 100644 index 900da239..00000000 --- a/cloudinary-http43/src/test/java/com/cloudinary/test/StructuredMetadataTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class StructuredMetadataTest extends AbstractStructuredMetadataTest { -} \ No newline at end of file diff --git a/cloudinary-http43/src/test/java/com/cloudinary/test/UploaderTest.java b/cloudinary-http43/src/test/java/com/cloudinary/test/UploaderTest.java deleted file mode 100644 index efbf9190..00000000 --- a/cloudinary-http43/src/test/java/com/cloudinary/test/UploaderTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.cloudinary.test; - -import com.cloudinary.api.ApiResponse; -import com.cloudinary.utils.ObjectUtils; -import org.apache.http.conn.ConnectTimeoutException; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import java.net.SocketTimeoutException; -import java.util.Map; - -public class UploaderTest extends AbstractUploaderTest { - - @Category(TimeoutTest.class) - @Test(expected = ConnectTimeoutException.class) - public void testConnectTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "connect_timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } - - @Category(TimeoutTest.class) - @Test(expected = SocketTimeoutException.class) - public void testTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } - -} \ No newline at end of file diff --git a/cloudinary-http44/build.gradle b/cloudinary-http44/build.gradle deleted file mode 100644 index a4c51ed8..00000000 --- a/cloudinary-http44/build.gradle +++ /dev/null @@ -1,113 +0,0 @@ -plugins { - id 'java-library' - id 'signing' - id 'maven-publish' - id 'io.codearte.nexus-staging' version '0.21.1' -} - -apply from: "../java_shared.gradle" - -task ciTest( type: Test ) { - useJUnit { - excludeCategories 'com.cloudinary.test.TimeoutTest' - if (System.getProperty("CLOUDINARY_ACCOUNT_URL") == "") { - exclude '**/AccountApiTest.class' - } - } -} - -dependencies { - compile project(':cloudinary-core') - compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.1' - compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.4' - compile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.4' - testCompile project(':cloudinary-test-common') - testCompile group: 'org.hamcrest', name: 'java-hamcrest', version: '2.0.0.0' - testCompile group: 'pl.pragmatists', name: 'JUnitParams', version: '1.0.5' - testCompile group: 'junit', name: 'junit', version: '4.12' -} - -if (hasProperty("ossrhPassword")) { - - signing { - sign configurations.archives - } - - nexusStaging { - packageGroup = group - username = project.hasProperty("ossrhUsername") ? project.ext["ossrhUsername"] : "" - password = project.hasProperty("ossrhPassword") ? project.ext["ossrhPassword"] : "" - } - - publishing { - publications { - mavenJava(MavenPublication) { - from components.java - artifact sourcesJar - artifact javadocJar - pom { - name = 'Cloudinary Apache HTTP 4.4 Library' - packaging = 'jar' - groupId = publishGroupId - artifactId = 'cloudinary-http44' - description = publishDescription - url = githubUrl - licenses { - license { - name = licenseName - url = licenseUrl - } - } - - developers { - developer { - id = developerId - name = developerName - email = developerEmail - } - } - scm { - connection = scmConnection - developerConnection = scmDeveloperConnection - url = scmUrl - } - } - - pom.withXml { - def pomFile = file("${project.buildDir}/generated-pom.xml") - writeTo(pomFile) - def pomAscFile = signing.sign(pomFile).signatureFiles[0] - artifact(pomAscFile) { - classifier = null - extension = 'pom.asc' - } - } - - // create the signed artifacts - project.tasks.signArchives.signatureFiles.each { - artifact(it) { - def matcher = it.file =~ /-(sources|javadoc)\.jar\.asc$/ - if (matcher.find()) { - classifier = matcher.group(1) - } else { - classifier = null - } - extension = 'jar.asc' - } - } - } - } - - model { - tasks.generatePomFileForMavenJavaPublication { - destination = file("$buildDir/generated-pom.xml") - } - tasks.publishMavenJavaPublicationToMavenLocal { - dependsOn project.tasks.signArchives - } - tasks.publishMavenJavaPublicationToSonatypeRepository { - dependsOn project.tasks.signArchives - } - } - } -} diff --git a/cloudinary-http44/src/main/java/com/cloudinary/http44/ApiStrategy.java b/cloudinary-http44/src/main/java/com/cloudinary/http44/ApiStrategy.java deleted file mode 100644 index b74f1dd7..00000000 --- a/cloudinary-http44/src/main/java/com/cloudinary/http44/ApiStrategy.java +++ /dev/null @@ -1,204 +0,0 @@ -package com.cloudinary.http44; - -import com.cloudinary.Api; -import com.cloudinary.Api.HttpMethod; -import com.cloudinary.Cloudinary; -import com.cloudinary.api.ApiResponse; -import com.cloudinary.api.exceptions.GeneralError; -import com.cloudinary.http44.api.Response; -import com.cloudinary.utils.Base64Coder; -import com.cloudinary.utils.ObjectUtils; -import com.cloudinary.utils.StringUtils; -import org.apache.http.Consts; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.NameValuePair; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.*; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; -import org.cloudinary.json.JSONException; -import org.cloudinary.json.JSONObject; - -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Constructor; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.cloudinary.http44.ApiUtils.prepareParams; -import static com.cloudinary.http44.ApiUtils.setTimeouts; - -public class ApiStrategy extends com.cloudinary.strategies.AbstractApiStrategy { - - private CloseableHttpClient client = null; - - @Override - public void init(Api api) { - super.init(api); - - HttpClientBuilder clientBuilder = HttpClients.custom(); - clientBuilder.useSystemProperties().setUserAgent(this.api.cloudinary.getUserAgent() + " ApacheHTTPComponents/4.4"); - - // If the configuration specifies a proxy then apply it to the client - if (api.cloudinary.config.proxyHost != null && api.cloudinary.config.proxyPort != 0) { - HttpHost proxy = new HttpHost(api.cloudinary.config.proxyHost, api.cloudinary.config.proxyPort); - clientBuilder.setProxy(proxy); - } - - HttpClientConnectionManager connectionManager = (HttpClientConnectionManager) api.cloudinary.config.properties.get("connectionManager"); - if (connectionManager != null) { - clientBuilder.setConnectionManager(connectionManager); - } - - int timeout = this.api.cloudinary.config.timeout; - if (timeout > 0) { - RequestConfig config = RequestConfig.custom() - .setSocketTimeout(timeout * 1000) - .setConnectTimeout(timeout * 1000) - .build(); - clientBuilder.setDefaultRequestConfig(config); - } - - this.client = clientBuilder.build(); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public ApiResponse callApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { - if (options == null) - options = ObjectUtils.emptyMap(); - - String apiKey = ObjectUtils.asString(options.get("api_key"), this.api.cloudinary.config.apiKey); - String apiSecret = ObjectUtils.asString(options.get("api_secret"), this.api.cloudinary.config.apiSecret); - String oauthToken = ObjectUtils.asString(options.get("oauth_token"), this.api.cloudinary.config.oauthToken); - - validateAuthorization(apiKey, apiSecret, oauthToken); - - String apiUrl = createApiUrl(uri, options); - HttpUriRequest request = prepareRequest(method, apiUrl, params, options); - - request.setHeader("Authorization", getAuthorizationHeaderValue(apiKey, apiSecret, oauthToken)); - - return getApiResponse(request); - } - - private ApiResponse getApiResponse(HttpUriRequest request) throws Exception { - String responseData = null; - int code = 0; - CloseableHttpResponse response = client.execute(request); - try { - code = response.getStatusLine().getStatusCode(); - final HttpEntity entity = response.getEntity(); - responseData = StringUtils.read(entity.getContent()); - EntityUtils.consume(entity); - } finally { - response.close(); - } - - Class exceptionClass = Api.CLOUDINARY_API_ERROR_CLASSES.get(code); - if (code != 200 && exceptionClass == null) { - throw new GeneralError("Server returned unexpected status code - " + code + " - " + responseData); - } - Map result; - - try { - JSONObject responseJSON = new JSONObject(responseData); - result = ObjectUtils.toMap(responseJSON); - } catch (JSONException e) { - throw new RuntimeException("Invalid JSON response from server " + e.getMessage()); - } - - if (code == 200) { - return new Response(response, result); - } else { - String message = (String) ((Map) result.get("error")).get("message"); - Constructor exceptionConstructor = exceptionClass.getConstructor(String.class); - throw exceptionConstructor.newInstance(message); - } - } - - @Override - public ApiResponse callAccountApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { - if (options == null) - options = ObjectUtils.emptyMap(); - - String prefix = ObjectUtils.asString(options.get("upload_prefix"), "https://api.cloudinary.com"); - String apiKey = ObjectUtils.asString(options.get("provisioning_api_key")); - if (apiKey == null) throw new IllegalArgumentException("Must supply provisioning_api_key"); - String apiSecret = ObjectUtils.asString(options.get("provisioning_api_secret")); - if (apiSecret == null) throw new IllegalArgumentException("Must supply provisioning_api_secret"); - - String apiUrl = StringUtils.join(Arrays.asList(prefix, "v1_1"), "/"); - for (String component : uri) { - apiUrl = apiUrl + "/" + component; - } - - HttpUriRequest request = prepareRequest(method, apiUrl, params, options); - - request.setHeader("Authorization", getAuthorizationHeaderValue(apiKey, apiSecret, null)); - - return getApiResponse(request); - } - - /** - * Prepare a request with the URL and parameters based on the HTTP method used - * - * @param method the HTTP method: GET, PUT, POST, DELETE - * @param apiUrl the cloudinary API URI - * @param params the parameters to pass to the server - * @return an HTTP request - * @throws URISyntaxException - * @throws UnsupportedEncodingException - */ - private HttpUriRequest prepareRequest(HttpMethod method, String apiUrl, Map params, Map options) throws URISyntaxException, UnsupportedEncodingException { - URI apiUri; - HttpRequestBase request; - - String contentType = ObjectUtils.asString(options.get("content_type"), "urlencoded"); - URIBuilder apiUrlBuilder = new URIBuilder(apiUrl); - List urlEncodedParams = prepareParams(params); - - if (method == HttpMethod.GET) { - apiUrlBuilder.setParameters(prepareParams(params)); - apiUri = apiUrlBuilder.build(); - request = new HttpGet(apiUri); - } else { - Map paramsCopy = new HashMap((Map) params); - apiUri = apiUrlBuilder.build(); - switch (method) { - case PUT: - request = new HttpPut(apiUri); - break; - case DELETE: //uses HttpPost instead of HttpDelete - paramsCopy.put("_method", "delete"); - //continue with POST - case POST: - request = new HttpPost(apiUri); - break; - default: - throw new IllegalArgumentException("Unknown HTTP method"); - } - if (contentType.equals("json")) { - JSONObject asJSON = ObjectUtils.toJSON(paramsCopy); - StringEntity requestEntity = new StringEntity(asJSON.toString(), ContentType.APPLICATION_JSON); - ((HttpEntityEnclosingRequestBase) request).setEntity(requestEntity); - } else { - ((HttpEntityEnclosingRequestBase) request).setEntity(new UrlEncodedFormEntity(prepareParams(paramsCopy), Consts.UTF_8)); - } - } - - setTimeouts(request, options); - return request; - } -} diff --git a/cloudinary-http44/src/main/java/com/cloudinary/http44/ApiUtils.java b/cloudinary-http44/src/main/java/com/cloudinary/http44/ApiUtils.java deleted file mode 100644 index 1a3da83f..00000000 --- a/cloudinary-http44/src/main/java/com/cloudinary/http44/ApiUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.cloudinary.http44; - -import com.cloudinary.utils.ObjectUtils; -import org.apache.http.NameValuePair; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.message.BasicNameValuePair; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class ApiUtils { - - public static void setTimeouts(HttpRequestBase request, Map options) { - RequestConfig config= request.getConfig(); - final RequestConfig.Builder builder; - if (config != null) { - builder = RequestConfig.copy(config); - } else { - builder = RequestConfig.custom(); - } - Integer timeout = (Integer) options.get("timeout"); - if(timeout != null) { - builder.setSocketTimeout(timeout); - } - Integer connectionRequestTimeout = (Integer) options.get("connection_request_timeout"); - if(connectionRequestTimeout != null) { - builder.setConnectionRequestTimeout(connectionRequestTimeout); - } - Integer connectTimeout = (Integer) options.get("connect_timeout"); - if(connectTimeout != null) { - builder.setConnectTimeout(connectTimeout); - } - request.setConfig(builder.build()); - } - - static List prepareParams(Map params) { - List requestParams = new ArrayList(params.size()); - for (Map.Entry param : params.entrySet()) { - if (param.getValue() instanceof Iterable) { - for (Object single : (Iterable) param.getValue()) { - requestParams.add(new BasicNameValuePair(param.getKey() + "[]", ObjectUtils.asString(single))); - } - } else { - requestParams.add(new BasicNameValuePair(param.getKey(), ObjectUtils.asString(param.getValue()))); - } - } - - - return requestParams; - } -} diff --git a/cloudinary-http44/src/main/java/com/cloudinary/http44/UploaderStrategy.java b/cloudinary-http44/src/main/java/com/cloudinary/http44/UploaderStrategy.java deleted file mode 100644 index 3afc8bce..00000000 --- a/cloudinary-http44/src/main/java/com/cloudinary/http44/UploaderStrategy.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.cloudinary.http44; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.Map; - -import com.cloudinary.ProgressCallback; -import org.apache.http.HttpHost; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.mime.HttpMultipartMode; -import org.apache.http.entity.mime.MIME; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.cloudinary.json.JSONException; -import org.cloudinary.json.JSONObject; - -import com.cloudinary.Cloudinary; -import com.cloudinary.Uploader; -import com.cloudinary.Util; -import com.cloudinary.strategies.AbstractUploaderStrategy; -import com.cloudinary.utils.ObjectUtils; -import com.cloudinary.utils.StringUtils; - -public class UploaderStrategy extends AbstractUploaderStrategy { - - private CloseableHttpClient client = null; - - @Override - public void init(Uploader uploader) { - super.init(uploader); - - HttpClientBuilder clientBuilder = HttpClients.custom(); - clientBuilder.useSystemProperties().setUserAgent(this.cloudinary().getUserAgent() + " ApacheHTTPComponents/4.4"); - - // If the configuration specifies a proxy then apply it to the client - if (cloudinary().config.proxyHost != null && cloudinary().config.proxyPort != 0) { - HttpHost proxy = new HttpHost(cloudinary().config.proxyHost, cloudinary().config.proxyPort); - clientBuilder.setProxy(proxy); - } - - HttpClientConnectionManager connectionManager = (HttpClientConnectionManager) cloudinary().config.properties.get("connectionManager"); - if (connectionManager != null) { - clientBuilder.setConnectionManager(connectionManager); - } - - this.client = clientBuilder.build(); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - @Override - public Map callApi(String action, Map params, Map options, Object file, ProgressCallback progressCallback) throws IOException { - if (progressCallback != null){ - throw new IllegalArgumentException("Progress callback is not supported"); - } - - // initialize options if passed as null - if (options == null) { - options = ObjectUtils.emptyMap(); - } - - boolean returnError = ObjectUtils.asBoolean(options.get("return_error"), false); - - if (requiresSigning(action, options)) { - uploader.signRequestParams(params, options); - } else { - Util.clearEmpty(params); - } - - String apiUrl = buildUploadUrl(action, options); - - HttpPost postMethod = new HttpPost(apiUrl); - ApiUtils.setTimeouts(postMethod, options); - - Map extraHeaders = (Map) options.get("extra_headers"); - if (extraHeaders != null) { - for (Map.Entry header : extraHeaders.entrySet()) { - postMethod.setHeader(header.getKey(), header.getValue()); - } - } - - MultipartEntityBuilder multipart = MultipartEntityBuilder.create(); - multipart.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); - multipart.setCharset(StandardCharsets.UTF_8); - ContentType contentType = ContentType.MULTIPART_FORM_DATA.withCharset(MIME.UTF8_CHARSET); - // Remove blank parameters - for (Map.Entry param : params.entrySet()) { - if (param.getValue() instanceof Collection) { - for (Object value : (Collection) param.getValue()) { - multipart.addTextBody(param.getKey() + "[]", ObjectUtils.asString(value), contentType); - } - } else { - String value = param.getValue().toString(); - if (StringUtils.isNotBlank(value)) { - multipart.addTextBody(param.getKey(), value, contentType); - } - } - } - - if (file instanceof String && !StringUtils.isRemoteUrl((String) file)) { - File _file = new File((String) file); - if (!_file.isFile() && !_file.canRead()) { - throw new IOException("File not found or unreadable: " + file); - } - file = _file; - } - String filename = (String) options.get("filename"); - if (file instanceof File) { - if (filename == null) filename = ((File) file).getName(); - multipart.addBinaryBody("file", (File) file, ContentType.APPLICATION_OCTET_STREAM, filename); - } else if (file instanceof String) { - multipart.addTextBody("file", (String) file, contentType); - } else if (file instanceof byte[]) { - if (filename == null) filename = "file"; - multipart.addBinaryBody("file", (byte[]) file, ContentType.APPLICATION_OCTET_STREAM, filename); - } else if (file == null) { - // no-problem - } else { - throw new IOException("Unrecognized file parameter " + file); - } - postMethod.setEntity(multipart.build()); - - String responseData = null; - int code = 0; - CloseableHttpResponse response = client.execute(postMethod); - try { - code = response.getStatusLine().getStatusCode(); - InputStream responseStream = response.getEntity().getContent(); - responseData = StringUtils.read(responseStream); - } finally { - response.close(); - } - - Map result = processResponse(returnError, code, responseData); - return result; - } -} diff --git a/cloudinary-http44/src/main/java/com/cloudinary/http44/api/Response.java b/cloudinary-http44/src/main/java/com/cloudinary/http44/api/Response.java deleted file mode 100644 index 0036d453..00000000 --- a/cloudinary-http44/src/main/java/com/cloudinary/http44/api/Response.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.cloudinary.http44.api; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.http.Header; -import org.apache.http.HttpResponse; - -import com.cloudinary.api.ApiResponse; -import com.cloudinary.api.RateLimit; -import com.cloudinary.utils.StringUtils; - -@SuppressWarnings("rawtypes") -public class Response extends HashMap implements ApiResponse { - private static final long serialVersionUID = -5458609797599845837L; - private HttpResponse response = null; - - @SuppressWarnings("unchecked") - public Response(HttpResponse response, Map result) { - super(result); - this.response = response; - } - - public HttpResponse getRawHttpResponse() { - return this.response; - } - - private static final Pattern RATE_LIMIT_REGEX = Pattern - .compile("X-FEATURE(\\w*)RATELIMIT(-LIMIT|-RESET|-REMAINING)", Pattern.CASE_INSENSITIVE); - private static final String RFC1123_PATTERN = "EEE, dd MMM yyyyy HH:mm:ss z"; - private static final DateFormat RFC1123 = new SimpleDateFormat(RFC1123_PATTERN, Locale.ENGLISH); - - public Map rateLimits() throws java.text.ParseException { - Header[] headers = this.response.getAllHeaders(); - Map limits = new HashMap(); - for (Header header : headers) { - Matcher m = RATE_LIMIT_REGEX.matcher(header.getName()); - if (m.matches()) { - String limitName = "Api"; - RateLimit limit = null; - if (!StringUtils.isEmpty(m.group(1))) { - limitName = m.group(1); - } - limit = limits.get(limitName); - if (limit == null) { - limit = new RateLimit(); - } - if (m.group(2).equalsIgnoreCase("-limit")) { - limit.setLimit(Long.parseLong(header.getValue())); - } else if (m.group(2).equalsIgnoreCase("-remaining")) { - limit.setRemaining(Long.parseLong(header.getValue())); - } else if (m.group(2).equalsIgnoreCase("-reset")) { - limit.setReset(RFC1123.parse(header.getValue())); - } - limits.put(limitName, limit); - } - } - return limits; - } - - public RateLimit apiRateLimit() throws java.text.ParseException { - return rateLimits().get("Api"); - } -} diff --git a/cloudinary-http44/src/test/java/com/cloudinary/test/AccountApiTest.java b/cloudinary-http44/src/test/java/com/cloudinary/test/AccountApiTest.java deleted file mode 100644 index 573a12e5..00000000 --- a/cloudinary-http44/src/test/java/com/cloudinary/test/AccountApiTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class AccountApiTest extends AbstractAccountApiTest { -} diff --git a/cloudinary-http44/src/test/java/com/cloudinary/test/ApiTest.java b/cloudinary-http44/src/test/java/com/cloudinary/test/ApiTest.java deleted file mode 100644 index c39a89e2..00000000 --- a/cloudinary-http44/src/test/java/com/cloudinary/test/ApiTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.cloudinary.test; - -import com.cloudinary.api.ApiResponse; -import com.cloudinary.utils.ObjectUtils; -import org.apache.http.conn.ConnectTimeoutException; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import java.net.SocketTimeoutException; -import java.util.Map; - -public class ApiTest extends AbstractApiTest { - @Category(TimeoutTest.class) - @Test(expected = ConnectTimeoutException.class) - public void testConnectTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "connect_timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } - - @Category(TimeoutTest.class) - @Test(expected = SocketTimeoutException.class) - public void testTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } -} diff --git a/cloudinary-http44/src/test/java/com/cloudinary/test/ContextTest.java b/cloudinary-http44/src/test/java/com/cloudinary/test/ContextTest.java deleted file mode 100644 index 4841e9f6..00000000 --- a/cloudinary-http44/src/test/java/com/cloudinary/test/ContextTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.cloudinary.test; - -public class ContextTest extends AbstractContextTest { - -} \ No newline at end of file diff --git a/cloudinary-http44/src/test/java/com/cloudinary/test/FoldersApiTest.java b/cloudinary-http44/src/test/java/com/cloudinary/test/FoldersApiTest.java deleted file mode 100644 index 971bcf39..00000000 --- a/cloudinary-http44/src/test/java/com/cloudinary/test/FoldersApiTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class FoldersApiTest extends AbstractFoldersApiTest { -} diff --git a/cloudinary-http44/src/test/java/com/cloudinary/test/SearchTest.java b/cloudinary-http44/src/test/java/com/cloudinary/test/SearchTest.java deleted file mode 100644 index 16a4708c..00000000 --- a/cloudinary-http44/src/test/java/com/cloudinary/test/SearchTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class SearchTest extends AbstractSearchTest { -} diff --git a/cloudinary-http44/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java b/cloudinary-http44/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java deleted file mode 100644 index 4e763579..00000000 --- a/cloudinary-http44/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.cloudinary.test; - -/** - * Created by amir on 25/10/2016. - */ -public class StreamingProfilesApiTest extends AbstractStreamingProfilesApiTest { -} diff --git a/cloudinary-http44/src/test/java/com/cloudinary/test/StructuredMetadataTest.java b/cloudinary-http44/src/test/java/com/cloudinary/test/StructuredMetadataTest.java deleted file mode 100644 index 8cc186f4..00000000 --- a/cloudinary-http44/src/test/java/com/cloudinary/test/StructuredMetadataTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class StructuredMetadataTest extends AbstractStructuredMetadataTest { -} diff --git a/cloudinary-http44/src/test/java/com/cloudinary/test/UploaderTest.java b/cloudinary-http44/src/test/java/com/cloudinary/test/UploaderTest.java deleted file mode 100644 index 4734707c..00000000 --- a/cloudinary-http44/src/test/java/com/cloudinary/test/UploaderTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.cloudinary.test; - -import com.cloudinary.api.ApiResponse; -import com.cloudinary.utils.ObjectUtils; -import org.apache.http.conn.ConnectTimeoutException; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import java.net.SocketTimeoutException; -import java.util.Map; - -public class UploaderTest extends AbstractUploaderTest { - - @Category(TimeoutTest.class) - @Test(expected = ConnectTimeoutException.class) - public void testConnectTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "connect_timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } - - @Category(TimeoutTest.class) - @Test(expected = SocketTimeoutException.class) - public void testTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } -} diff --git a/cloudinary-http45/build.gradle b/cloudinary-http45/build.gradle deleted file mode 100644 index f4b7613d..00000000 --- a/cloudinary-http45/build.gradle +++ /dev/null @@ -1,113 +0,0 @@ -plugins { - id 'java-library' - id 'signing' - id 'maven-publish' - id 'io.codearte.nexus-staging' version '0.21.1' -} - -apply from: "../java_shared.gradle" - -task ciTest( type: Test ) { - useJUnit { - excludeCategories 'com.cloudinary.test.TimeoutTest' - if (System.getProperty("CLOUDINARY_ACCOUNT_URL") == "") { - exclude '**/AccountApiTest.class' - } - } -} - -dependencies { - compile project(':cloudinary-core') - compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.1' - compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.13' - compile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.5.13' - testCompile project(':cloudinary-test-common') - testCompile group: 'org.hamcrest', name: 'java-hamcrest', version: '2.0.0.0' - testCompile group: 'pl.pragmatists', name: 'JUnitParams', version: '1.0.5' - testCompile group: 'junit', name: 'junit', version: '4.12' -} - -if (hasProperty("ossrhPassword")) { - - signing { - sign configurations.archives - } - - nexusStaging { - packageGroup = group - username = project.hasProperty("ossrhUsername") ? project.ext["ossrhUsername"] : "" - password = project.hasProperty("ossrhPassword") ? project.ext["ossrhPassword"] : "" - } - - publishing { - publications { - mavenJava(MavenPublication) { - from components.java - artifact sourcesJar - artifact javadocJar - pom { - name = 'Cloudinary Apache HTTP 4.5 Library' - packaging = 'jar' - groupId = publishGroupId - artifactId = 'cloudinary-http45' - description = publishDescription - url = githubUrl - licenses { - license { - name = licenseName - url = licenseUrl - } - } - - developers { - developer { - id = developerId - name = developerName - email = developerEmail - } - } - scm { - connection = scmConnection - developerConnection = scmDeveloperConnection - url = scmUrl - } - } - - pom.withXml { - def pomFile = file("${project.buildDir}/generated-pom.xml") - writeTo(pomFile) - def pomAscFile = signing.sign(pomFile).signatureFiles[0] - artifact(pomAscFile) { - classifier = null - extension = 'pom.asc' - } - } - - // create the signed artifacts - project.tasks.signArchives.signatureFiles.each { - artifact(it) { - def matcher = it.file =~ /-(sources|javadoc)\.jar\.asc$/ - if (matcher.find()) { - classifier = matcher.group(1) - } else { - classifier = null - } - extension = 'jar.asc' - } - } - } - } - - model { - tasks.generatePomFileForMavenJavaPublication { - destination = file("$buildDir/generated-pom.xml") - } - tasks.publishMavenJavaPublicationToMavenLocal { - dependsOn project.tasks.signArchives - } - tasks.publishMavenJavaPublicationToSonatypeRepository { - dependsOn project.tasks.signArchives - } - } - } -} diff --git a/cloudinary-http45/src/main/java/com/cloudinary/http45/ApiStrategy.java b/cloudinary-http45/src/main/java/com/cloudinary/http45/ApiStrategy.java deleted file mode 100644 index b4e8673a..00000000 --- a/cloudinary-http45/src/main/java/com/cloudinary/http45/ApiStrategy.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.cloudinary.http45; - -import com.cloudinary.Api; -import com.cloudinary.Api.HttpMethod; -import com.cloudinary.Cloudinary; -import com.cloudinary.api.ApiResponse; -import com.cloudinary.api.exceptions.GeneralError; -import com.cloudinary.http45.api.Response; -import com.cloudinary.utils.Base64Coder; -import com.cloudinary.utils.ObjectUtils; -import com.cloudinary.utils.StringUtils; -import org.apache.http.Consts; -import org.apache.http.HttpHost; -import org.apache.http.NameValuePair; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.*; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.cloudinary.json.JSONException; -import org.cloudinary.json.JSONObject; - -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Constructor; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.cloudinary.http45.ApiUtils.prepareParams; -import static com.cloudinary.http45.ApiUtils.setTimeouts; - -public class ApiStrategy extends com.cloudinary.strategies.AbstractApiStrategy { - - private CloseableHttpClient client = null; - - @Override - public void init(Api api) { - super.init(api); - - HttpClientBuilder clientBuilder = HttpClients.custom(); - clientBuilder.useSystemProperties().setUserAgent(this.api.cloudinary.getUserAgent() + " ApacheHTTPComponents/4.5"); - - // If the configuration specifies a proxy then apply it to the client - if (api.cloudinary.config.proxyHost != null && api.cloudinary.config.proxyPort != 0) { - HttpHost proxy = new HttpHost(api.cloudinary.config.proxyHost, api.cloudinary.config.proxyPort); - clientBuilder.setProxy(proxy); - } - - HttpClientConnectionManager connectionManager = (HttpClientConnectionManager) api.cloudinary.config.properties.get("connectionManager"); - if (connectionManager != null) { - clientBuilder.setConnectionManager(connectionManager); - } - - int timeout = this.api.cloudinary.config.timeout; - if (timeout > 0) { - RequestConfig config = RequestConfig.custom() - .setSocketTimeout(timeout * 1000) - .setConnectTimeout(timeout * 1000) - .build(); - clientBuilder.setDefaultRequestConfig(config); - } - - this.client = clientBuilder.build(); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public ApiResponse callApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { - if (options == null) - options = ObjectUtils.emptyMap(); - - String apiKey = ObjectUtils.asString(options.get("api_key"), this.api.cloudinary.config.apiKey); - String apiSecret = ObjectUtils.asString(options.get("api_secret"), this.api.cloudinary.config.apiSecret); - String oauthToken = ObjectUtils.asString(options.get("oauth_token"), this.api.cloudinary.config.oauthToken); - - validateAuthorization(apiKey, apiSecret, oauthToken); - - String apiUrl = createApiUrl(uri, options); - HttpUriRequest request = prepareRequest(method, apiUrl, params, options); - - request.setHeader("Authorization", getAuthorizationHeaderValue(apiKey, apiSecret, oauthToken)); - - return getApiResponse(request); - } - - private ApiResponse getApiResponse(HttpUriRequest request) throws Exception { - String responseData = null; - int code = 0; - CloseableHttpResponse response = client.execute(request); - try { - code = response.getStatusLine().getStatusCode(); - InputStream responseStream = response.getEntity().getContent(); - responseData = StringUtils.read(responseStream); - } finally { - response.close(); - } - - Class exceptionClass = Api.CLOUDINARY_API_ERROR_CLASSES.get(code); - if (code != 200 && exceptionClass == null) { - throw new GeneralError("Server returned unexpected status code - " + code + " - " + responseData); - } - Map result; - - try { - JSONObject responseJSON = new JSONObject(responseData); - result = ObjectUtils.toMap(responseJSON); - } catch (JSONException e) { - throw new RuntimeException("Invalid JSON response from server " + e.getMessage()); - } - - if (code == 200) { - return new Response(response, result); - } else { - String message = (String) ((Map) result.get("error")).get("message"); - Constructor exceptionConstructor = exceptionClass.getConstructor(String.class); - throw exceptionConstructor.newInstance(message); - } - } - - @Override - public ApiResponse callAccountApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception { - if (options == null) - options = ObjectUtils.emptyMap(); - - String prefix = ObjectUtils.asString(options.get("upload_prefix"), "https://api.cloudinary.com"); - String apiKey = ObjectUtils.asString(options.get("provisioning_api_key")); - if (apiKey == null) throw new IllegalArgumentException("Must supply provisioning_api_key"); - String apiSecret = ObjectUtils.asString(options.get("provisioning_api_secret")); - if (apiSecret == null) throw new IllegalArgumentException("Must supply provisioning_api_secret"); - - String apiUrl = StringUtils.join(Arrays.asList(prefix, "v1_1"), "/"); - for (String component : uri) { - apiUrl = apiUrl + "/" + component; - } - - HttpUriRequest request = prepareRequest(method, apiUrl, params, options); - - request.setHeader("Authorization", getAuthorizationHeaderValue(apiKey, apiSecret, null)); - - return getApiResponse(request); - } - - /** - * Prepare a request with the URL and parameters based on the HTTP method used - * - * @param method the HTTP method: GET, PUT, POST, DELETE - * @param apiUrl the cloudinary API URI - * @param params the parameters to pass to the server - * @return an HTTP request - * @throws URISyntaxException - * @throws UnsupportedEncodingException - */ - private HttpUriRequest prepareRequest(HttpMethod method, String apiUrl, Map params, Map options) throws URISyntaxException, UnsupportedEncodingException { - URI apiUri; - HttpRequestBase request; - - String contentType = ObjectUtils.asString(options.get("content_type"), "urlencoded"); - URIBuilder apiUrlBuilder = new URIBuilder(apiUrl); - List urlEncodedParams = prepareParams(params); - - if (method == HttpMethod.GET) { - apiUrlBuilder.setParameters(prepareParams(params)); - apiUri = apiUrlBuilder.build(); - request = new HttpGet(apiUri); - } else { - Map paramsCopy = new HashMap((Map) params); - apiUri = apiUrlBuilder.build(); - switch (method) { - case PUT: - request = new HttpPut(apiUri); - break; - case DELETE: //uses HttpPost instead of HttpDelete - paramsCopy.put("_method", "delete"); - //continue with POST - case POST: - request = new HttpPost(apiUri); - break; - default: - throw new IllegalArgumentException("Unknown HTTP method"); - } - if (contentType.equals("json")) { - JSONObject asJSON = ObjectUtils.toJSON(paramsCopy); - StringEntity requestEntity = new StringEntity(asJSON.toString(), ContentType.APPLICATION_JSON); - ((HttpEntityEnclosingRequestBase) request).setEntity(requestEntity); - } else { - ((HttpEntityEnclosingRequestBase) request).setEntity(new UrlEncodedFormEntity(prepareParams(paramsCopy), Consts.UTF_8)); - } - } - - setTimeouts(request, options); - return request; - } -} diff --git a/cloudinary-http45/src/main/java/com/cloudinary/http45/ApiUtils.java b/cloudinary-http45/src/main/java/com/cloudinary/http45/ApiUtils.java deleted file mode 100644 index 6639b9cc..00000000 --- a/cloudinary-http45/src/main/java/com/cloudinary/http45/ApiUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.cloudinary.http45; - -import com.cloudinary.utils.ObjectUtils; -import org.apache.http.NameValuePair; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.message.BasicNameValuePair; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class ApiUtils { - - public static void setTimeouts(HttpRequestBase request, Map options) { - RequestConfig config= request.getConfig(); - final RequestConfig.Builder builder; - if (config != null) { - builder = RequestConfig.copy(config); - } else { - builder = RequestConfig.custom(); - } - Integer timeout = (Integer) options.get("timeout"); - if(timeout != null) { - builder.setSocketTimeout(timeout); - } - Integer connectionRequestTimeout = (Integer) options.get("connection_request_timeout"); - if(connectionRequestTimeout != null) { - builder.setConnectionRequestTimeout(connectionRequestTimeout); - } - Integer connectTimeout = (Integer) options.get("connect_timeout"); - if(connectTimeout != null) { - builder.setConnectTimeout(connectTimeout); - } - request.setConfig(builder.build()); - } - - static List prepareParams(Map params) { - List requestParams = new ArrayList(params.size()); - for (Map.Entry param : params.entrySet()) { - if (param.getValue() instanceof Iterable) { - for (Object single : (Iterable) param.getValue()) { - requestParams.add(new BasicNameValuePair(param.getKey() + "[]", ObjectUtils.asString(single))); - } - } else { - requestParams.add(new BasicNameValuePair(param.getKey(), ObjectUtils.asString(param.getValue()))); - } - } - - - return requestParams; - } -} diff --git a/cloudinary-http45/src/main/java/com/cloudinary/http45/UploaderStrategy.java b/cloudinary-http45/src/main/java/com/cloudinary/http45/UploaderStrategy.java deleted file mode 100644 index f4712515..00000000 --- a/cloudinary-http45/src/main/java/com/cloudinary/http45/UploaderStrategy.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.cloudinary.http45; - -import com.cloudinary.Cloudinary; -import com.cloudinary.ProgressCallback; -import com.cloudinary.Uploader; -import com.cloudinary.Util; -import com.cloudinary.strategies.AbstractUploaderStrategy; -import com.cloudinary.utils.ObjectUtils; -import com.cloudinary.utils.StringUtils; -import org.apache.http.HttpHost; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.mime.HttpMultipartMode; -import org.apache.http.entity.mime.MIME; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.Map; - -public class UploaderStrategy extends AbstractUploaderStrategy { - - private CloseableHttpClient client = null; - - @Override - public void init(Uploader uploader) { - super.init(uploader); - - HttpClientBuilder clientBuilder = HttpClients.custom(); - clientBuilder.useSystemProperties().setUserAgent(cloudinary().getUserAgent() + " ApacheHTTPComponents/4.5"); - - // If the configuration specifies a proxy then apply it to the client - if (cloudinary().config.proxyHost != null && cloudinary().config.proxyPort != 0) { - HttpHost proxy = new HttpHost(cloudinary().config.proxyHost, cloudinary().config.proxyPort); - clientBuilder.setProxy(proxy); - } - - HttpClientConnectionManager connectionManager = (HttpClientConnectionManager) cloudinary().config.properties.get("connectionManager"); - if (connectionManager != null) { - clientBuilder.setConnectionManager(connectionManager); - } - - this.client = clientBuilder.build(); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - @Override - public Map callApi(String action, Map params, Map options, Object file, ProgressCallback progressCallback) throws IOException { - if (progressCallback != null){ - throw new IllegalArgumentException("Progress callback is not supported"); - } - - // initialize options if passed as null - if (options == null) { - options = ObjectUtils.emptyMap(); - } - - boolean returnError = ObjectUtils.asBoolean(options.get("return_error"), false); - - if (requiresSigning(action, options)) { - uploader.signRequestParams(params, options); - } else { - Util.clearEmpty(params); - } - - String apiUrl = buildUploadUrl(action, options); - - HttpPost postMethod = new HttpPost(apiUrl); - ApiUtils.setTimeouts(postMethod, options); - - Map extraHeaders = (Map) options.get("extra_headers"); - if (extraHeaders != null) { - for (Map.Entry header : extraHeaders.entrySet()) { - postMethod.setHeader(header.getKey(), header.getValue()); - } - } - - MultipartEntityBuilder multipart = MultipartEntityBuilder.create(); - multipart.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); - multipart.setCharset(StandardCharsets.UTF_8); - ContentType contentType = ContentType.MULTIPART_FORM_DATA.withCharset(MIME.UTF8_CHARSET); - // Remove blank parameters - for (Map.Entry param : params.entrySet()) { - if (param.getValue() instanceof Collection) { - for (Object value : (Collection) param.getValue()) { - multipart.addTextBody(param.getKey() + "[]", ObjectUtils.asString(value), contentType); - } - } else { - String value = param.getValue().toString(); - if (StringUtils.isNotBlank(value)) { - multipart.addTextBody(param.getKey(), value, contentType); - } - } - } - - if (file instanceof String && !StringUtils.isRemoteUrl((String) file)) { - File _file = new File((String) file); - if (!_file.isFile() && !_file.canRead()) { - throw new IOException("File not found or unreadable: " + file); - } - file = _file; - } - String filename = (String) options.get("filename"); - if (file instanceof File) { - if (filename == null) filename = ((File) file).getName(); - multipart.addBinaryBody("file", (File) file, ContentType.APPLICATION_OCTET_STREAM, filename); - } else if (file instanceof String) { - multipart.addTextBody("file", (String) file, contentType); - } else if (file instanceof byte[]) { - if (filename == null) filename = "file"; - multipart.addBinaryBody("file", (byte[]) file, ContentType.APPLICATION_OCTET_STREAM, filename); - } else if (file == null) { - // no-problem - } else { - throw new IOException("Unrecognized file parameter " + file); - } - postMethod.setEntity(multipart.build()); - - String responseData = null; - int code = 0; - CloseableHttpResponse response = client.execute(postMethod); - try { - code = response.getStatusLine().getStatusCode(); - InputStream responseStream = response.getEntity().getContent(); - responseData = StringUtils.read(responseStream); - } finally { - response.close(); - } - - Map result = processResponse(returnError, code, responseData); - return result; - } -} diff --git a/cloudinary-http45/src/main/java/com/cloudinary/http45/api/Response.java b/cloudinary-http45/src/main/java/com/cloudinary/http45/api/Response.java deleted file mode 100644 index 08121401..00000000 --- a/cloudinary-http45/src/main/java/com/cloudinary/http45/api/Response.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.cloudinary.http45.api; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.http.Header; -import org.apache.http.HttpResponse; - -import com.cloudinary.api.ApiResponse; -import com.cloudinary.api.RateLimit; -import com.cloudinary.utils.StringUtils; - -@SuppressWarnings("rawtypes") -public class Response extends HashMap implements ApiResponse { - private static final long serialVersionUID = -5458609797599845837L; - private HttpResponse response = null; - - @SuppressWarnings("unchecked") - public Response(HttpResponse response, Map result) { - super(result); - this.response = response; - } - - public HttpResponse getRawHttpResponse() { - return this.response; - } - - private static final Pattern RATE_LIMIT_REGEX = Pattern - .compile("X-FEATURE(\\w*)RATELIMIT(-LIMIT|-RESET|-REMAINING)", Pattern.CASE_INSENSITIVE); - private static final String RFC1123_PATTERN = "EEE, dd MMM yyyyy HH:mm:ss z"; - private static final DateFormat RFC1123 = new SimpleDateFormat(RFC1123_PATTERN, Locale.ENGLISH); - - public Map rateLimits() throws java.text.ParseException { - Header[] headers = this.response.getAllHeaders(); - Map limits = new HashMap(); - for (Header header : headers) { - Matcher m = RATE_LIMIT_REGEX.matcher(header.getName()); - if (m.matches()) { - String limitName = "Api"; - RateLimit limit = null; - if (!StringUtils.isEmpty(m.group(1))) { - limitName = m.group(1); - } - limit = limits.get(limitName); - if (limit == null) { - limit = new RateLimit(); - } - if (m.group(2).equalsIgnoreCase("-limit")) { - limit.setLimit(Long.parseLong(header.getValue())); - } else if (m.group(2).equalsIgnoreCase("-remaining")) { - limit.setRemaining(Long.parseLong(header.getValue())); - } else if (m.group(2).equalsIgnoreCase("-reset")) { - limit.setReset(RFC1123.parse(header.getValue())); - } - limits.put(limitName, limit); - } - } - return limits; - } - - public RateLimit apiRateLimit() throws java.text.ParseException { - return rateLimits().get("Api"); - } -} diff --git a/cloudinary-http45/src/test/java/com/cloudinary/test/AccountApiTest.java b/cloudinary-http45/src/test/java/com/cloudinary/test/AccountApiTest.java deleted file mode 100644 index 573a12e5..00000000 --- a/cloudinary-http45/src/test/java/com/cloudinary/test/AccountApiTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class AccountApiTest extends AbstractAccountApiTest { -} diff --git a/cloudinary-http45/src/test/java/com/cloudinary/test/ApiTest.java b/cloudinary-http45/src/test/java/com/cloudinary/test/ApiTest.java deleted file mode 100644 index c39a89e2..00000000 --- a/cloudinary-http45/src/test/java/com/cloudinary/test/ApiTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.cloudinary.test; - -import com.cloudinary.api.ApiResponse; -import com.cloudinary.utils.ObjectUtils; -import org.apache.http.conn.ConnectTimeoutException; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import java.net.SocketTimeoutException; -import java.util.Map; - -public class ApiTest extends AbstractApiTest { - @Category(TimeoutTest.class) - @Test(expected = ConnectTimeoutException.class) - public void testConnectTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "connect_timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } - - @Category(TimeoutTest.class) - @Test(expected = SocketTimeoutException.class) - public void testTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } -} diff --git a/cloudinary-http45/src/test/java/com/cloudinary/test/ContextTest.java b/cloudinary-http45/src/test/java/com/cloudinary/test/ContextTest.java deleted file mode 100644 index 4841e9f6..00000000 --- a/cloudinary-http45/src/test/java/com/cloudinary/test/ContextTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.cloudinary.test; - -public class ContextTest extends AbstractContextTest { - -} \ No newline at end of file diff --git a/cloudinary-http45/src/test/java/com/cloudinary/test/FoldersApiTest.java b/cloudinary-http45/src/test/java/com/cloudinary/test/FoldersApiTest.java deleted file mode 100644 index 971bcf39..00000000 --- a/cloudinary-http45/src/test/java/com/cloudinary/test/FoldersApiTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class FoldersApiTest extends AbstractFoldersApiTest { -} diff --git a/cloudinary-http45/src/test/java/com/cloudinary/test/SearchTest.java b/cloudinary-http45/src/test/java/com/cloudinary/test/SearchTest.java deleted file mode 100644 index 16a4708c..00000000 --- a/cloudinary-http45/src/test/java/com/cloudinary/test/SearchTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class SearchTest extends AbstractSearchTest { -} diff --git a/cloudinary-http45/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java b/cloudinary-http45/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java deleted file mode 100644 index 6a2e8a31..00000000 --- a/cloudinary-http45/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class StreamingProfilesApiTest extends AbstractStreamingProfilesApiTest { -} diff --git a/cloudinary-http45/src/test/java/com/cloudinary/test/StructuredMetadataTest.java b/cloudinary-http45/src/test/java/com/cloudinary/test/StructuredMetadataTest.java deleted file mode 100644 index 8cc186f4..00000000 --- a/cloudinary-http45/src/test/java/com/cloudinary/test/StructuredMetadataTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.cloudinary.test; - -public class StructuredMetadataTest extends AbstractStructuredMetadataTest { -} diff --git a/cloudinary-http45/src/test/java/com/cloudinary/test/UploaderTest.java b/cloudinary-http45/src/test/java/com/cloudinary/test/UploaderTest.java deleted file mode 100644 index efbf9190..00000000 --- a/cloudinary-http45/src/test/java/com/cloudinary/test/UploaderTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.cloudinary.test; - -import com.cloudinary.api.ApiResponse; -import com.cloudinary.utils.ObjectUtils; -import org.apache.http.conn.ConnectTimeoutException; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import java.net.SocketTimeoutException; -import java.util.Map; - -public class UploaderTest extends AbstractUploaderTest { - - @Category(TimeoutTest.class) - @Test(expected = ConnectTimeoutException.class) - public void testConnectTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "connect_timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } - - @Category(TimeoutTest.class) - @Test(expected = SocketTimeoutException.class) - public void testTimeoutParameter() throws Exception { - // should allow listing resources - Map options = ObjectUtils.asMap( - "max_results", 500, - "timeout", 1); - ApiResponse result = cloudinary.api().resources(options); - } - -} \ No newline at end of file diff --git a/cloudinary-http43/build.gradle b/cloudinary-http5/build.gradle similarity index 92% rename from cloudinary-http43/build.gradle rename to cloudinary-http5/build.gradle index 47fe4701..177ecdfa 100644 --- a/cloudinary-http43/build.gradle +++ b/cloudinary-http5/build.gradle @@ -19,8 +19,8 @@ task ciTest( type: Test ) { dependencies { compile project(':cloudinary-core') compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.1' - compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.1' - compile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.3' + api group: 'org.apache.httpcomponents.client5', name: 'httpclient5', version: '5.3.1' + api group: 'org.apache.httpcomponents.core5', name: 'httpcore5', version: '5.2.5' testCompile project(':cloudinary-test-common') testCompile group: 'org.hamcrest', name: 'java-hamcrest', version: '2.0.0.0' testCompile group: 'pl.pragmatists', name: 'JUnitParams', version: '1.0.5' @@ -46,10 +46,10 @@ if (hasProperty("ossrhPassword")) { artifact sourcesJar artifact javadocJar pom { - name = 'Cloudinary Apache HTTP 4.3 Library' + name = 'Cloudinary Apache HTTP 5 Library' packaging = 'jar' groupId = publishGroupId - artifactId = 'cloudinary-http43' + artifactId = 'cloudinary-http5' description = publishDescription url = githubUrl licenses { diff --git a/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java b/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java new file mode 100644 index 00000000..2852225d --- /dev/null +++ b/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java @@ -0,0 +1,163 @@ +package com.cloudinary.http5; + + +import com.cloudinary.Api; +import com.cloudinary.api.ApiResponse; +import com.cloudinary.api.exceptions.GeneralError; +import com.cloudinary.http5.api.Response; +import com.cloudinary.strategies.AbstractApiStrategy; +import com.cloudinary.utils.ObjectUtils; +import com.cloudinary.utils.StringUtils; +import org.apache.hc.client5.http.classic.methods.*; +import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.net.URIBuilder; +import org.cloudinary.json.JSONException; +import org.cloudinary.json.JSONObject; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static com.cloudinary.http5.ApiUtils.prepareParams; +import static com.cloudinary.http5.ApiUtils.setTimeouts; + +public class ApiStrategy extends AbstractApiStrategy { + + private static final String APACHE_HTTP_CLIENT_VERSION = System.getProperty("apache.http.client.version", "5.3.1"); + + private CloseableHttpClient client; + + @Override + public void init(Api api) { + super.init(api); + + this.client = HttpClients.custom() + .setUserAgent(this.api.cloudinary.getUserAgent() + " ApacheHttpClient/" + APACHE_HTTP_CLIENT_VERSION) + .build(); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public ApiResponse callApi(Api.HttpMethod method, String apiUrl, Map params, Map options, String autorizationHeader) throws Exception { + HttpUriRequestBase request = prepareRequest(method, apiUrl, params, options); + + request.setHeader("Authorization", autorizationHeader); + + return getApiResponse(request); + } + + private ApiResponse getApiResponse(HttpUriRequestBase request) throws Exception { + String responseData = null; + int code = 0; + CloseableHttpResponse response; + try { + response = client.execute(request); + code = response.getCode(); + HttpEntity entity = response.getEntity(); + if (entity != null) { + responseData = EntityUtils.toString(entity, StandardCharsets.UTF_8); + } + } catch (IOException e) { + throw new GeneralError("Error executing request: " + e.getMessage()); + } + + if (code != 200) { + Map result; + try { + JSONObject responseJSON = new JSONObject(responseData); + result = ObjectUtils.toMap(responseJSON); + } catch (JSONException e) { + throw new RuntimeException("Invalid JSON response from server " + e.getMessage()); + } + + // Extract the error message from the result map + String message = (String) ((Map) result.get("error")).get("message"); + + // Get the appropriate exception class based on status code + Class exceptionClass = Api.CLOUDINARY_API_ERROR_CLASSES.get(code); + if (exceptionClass != null) { + Constructor exceptionConstructor = exceptionClass.getConstructor(String.class); + throw exceptionConstructor.newInstance(message); + } else { + throw new GeneralError("Server returned unexpected status code - " + code + " - " + responseData); + } + } + + Map result; + try { + JSONObject responseJSON = new JSONObject(responseData); + result = ObjectUtils.toMap(responseJSON); + } catch (JSONException e) { + throw new RuntimeException("Invalid JSON response from server " + e.getMessage()); + } + + return new Response(response, result); + } + + @Override + public ApiResponse callAccountApi(Api.HttpMethod method, String apiUrl, Map params, Map options, String authorizationHeader) throws Exception { + // Prepare the request + HttpUriRequestBase request = prepareRequest(method, apiUrl, params, options); + + // Add authorization header + + request.setHeader("Authorization", authorizationHeader); + + // Execute the request and return the response + return getApiResponse(request); + } + + private HttpUriRequestBase prepareRequest(Api.HttpMethod method, String apiUrl, Map params, Map options) throws URISyntaxException { + HttpUriRequestBase request; + + String contentType = ObjectUtils.asString(options.get("content_type"), "urlencoded"); + + switch (method) { + case GET: + URIBuilder uriBuilder = new URIBuilder(apiUrl); + for (NameValuePair param : prepareParams(params)) { + uriBuilder.addParameter(param.getName(), param.getValue()); + } + request = new HttpGet(uriBuilder.toString()); + break; + case POST: + request = new HttpPost(apiUrl); + setEntity((HttpUriRequestBase) request, params, contentType); + break; + case PUT: + request = new HttpPut(apiUrl); + setEntity((HttpUriRequestBase) request, params, contentType); + break; + case DELETE: + request = new HttpDelete(apiUrl); + setEntity((HttpUriRequestBase) request, params, contentType); + break; + default: + throw new IllegalArgumentException("Unknown HTTP method"); + } + setTimeouts(request, options); + return request; + } + + private void setEntity(HttpUriRequestBase request, Map params, String contentType) { + if ("json".equals(contentType)) { + JSONObject json = ObjectUtils.toJSON(params); + StringEntity entity = new StringEntity(json.toString(), StandardCharsets.UTF_8); + request.setEntity(entity); + request.setHeader("Content-Type", "application/json"); + } else { + List formParams = prepareParams(params); + request.setEntity(new UrlEncodedFormEntity(formParams, StandardCharsets.UTF_8)); + } + } +} diff --git a/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiUtils.java b/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiUtils.java new file mode 100644 index 00000000..af67a1e8 --- /dev/null +++ b/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiUtils.java @@ -0,0 +1,71 @@ +package com.cloudinary.http5; + +import com.cloudinary.utils.ObjectUtils; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.message.BasicNameValuePair; +import org.apache.hc.core5.util.Timeout; +import org.cloudinary.json.JSONObject; + +import java.util.*; + +public class ApiUtils { + + public static void setTimeouts(HttpUriRequestBase request, Map options) { + RequestConfig config = request.getConfig(); + final RequestConfig.Builder builder; + + if (config != null) { + builder = RequestConfig.copy(config); + } else { + builder = RequestConfig.custom(); + } + + Integer timeout = (Integer) options.get("timeout"); + if (timeout != null) { + builder.setResponseTimeout(Timeout.ofSeconds(timeout)); + } + + Integer connectionRequestTimeout = (Integer) options.get("connection_request_timeout"); + if (connectionRequestTimeout != null) { + builder.setConnectionRequestTimeout(Timeout.ofSeconds(connectionRequestTimeout)); + } + + Integer connectTimeout = (Integer) options.get("connect_timeout"); + if (connectTimeout != null) { + builder.setConnectTimeout(Timeout.ofSeconds(connectTimeout)); + } + + request.setConfig(builder.build()); + } + + + public static List prepareParams(Map params) { + List requestParams = new ArrayList<>(); + + for (Map.Entry param : params.entrySet()) { + String key = param.getKey(); + Object value = param.getValue(); + + if (value instanceof Iterable) { + // If the value is an Iterable, handle each item individually + for (Object single : (Iterable) value) { + requestParams.add(new BasicNameValuePair(key + "[]", ObjectUtils.asString(single))); + } + } else if (value instanceof Map) { + // Convert Map to JSON string manually to avoid empty object issues + JSONObject jsonObject = new JSONObject(); + for (Map.Entry entry : ((Map) value).entrySet()) { + jsonObject.put(entry.getKey().toString(), entry.getValue()); + } + requestParams.add(new BasicNameValuePair(key, jsonObject.toString())); + } else { + // Handle simple key-value pairs + requestParams.add(new BasicNameValuePair(key, ObjectUtils.asString(value))); + } + } + + return requestParams; + } +} diff --git a/cloudinary-http5/src/main/java/com/cloudinary/http5/UploaderStrategy.java b/cloudinary-http5/src/main/java/com/cloudinary/http5/UploaderStrategy.java new file mode 100644 index 00000000..5f87cbd8 --- /dev/null +++ b/cloudinary-http5/src/main/java/com/cloudinary/http5/UploaderStrategy.java @@ -0,0 +1,155 @@ +package com.cloudinary.http5; + +import com.cloudinary.ProgressCallback; +import com.cloudinary.Uploader; +import com.cloudinary.Util; +import com.cloudinary.strategies.AbstractUploaderStrategy; +import com.cloudinary.utils.ObjectUtils; +import com.cloudinary.utils.StringUtils; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.entity.mime.ByteArrayBody; +import org.apache.hc.client5.http.entity.mime.FileBody; +import org.apache.hc.client5.http.entity.mime.HttpMultipartMode; +import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.EntityUtils; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Map; + +public class UploaderStrategy extends AbstractUploaderStrategy { + + private static final String APACHE_HTTP_CLIENT_VERSION = System.getProperty("apache.http.client.version", "5.3.1"); + + private CloseableHttpClient client; + + @Override + public void init(Uploader uploader) { + super.init(uploader); + + this.client = HttpClients.custom() + .setUserAgent(cloudinary().getUserAgent() + " ApacheHttpClient/" + APACHE_HTTP_CLIENT_VERSION) + .build(); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + public Map callApi(String action, Map params, Map options, Object file, ProgressCallback progressCallback) throws IOException { + if (progressCallback != null) { + throw new IllegalArgumentException("Progress callback is not supported"); + } + + // Initialize options if passed as null + if (options == null) { + options = ObjectUtils.emptyMap(); + } + + boolean returnError = ObjectUtils.asBoolean(options.get("return_error"), false); + + if (requiresSigning(action, options)) { + uploader.signRequestParams(params, options); + } else { + Util.clearEmpty(params); + } + + String apiUrl = buildUploadUrl(action, options); + + // Prepare the request + HttpUriRequestBase request = prepareRequest(apiUrl, params, options, file); + + // Execute the request and handle the response + String responseData; + int code; + + try (CloseableHttpResponse response = client.execute(request)) { + code = response.getCode(); + responseData = EntityUtils.toString(response.getEntity()); + } catch (ParseException e) { + throw new RuntimeException(e); + } + + // Process and return the response + return processResponse(returnError, code, responseData); + } + + private HttpUriRequestBase prepareRequest(String apiUrl, Map params, Map options, Object file) throws IOException { + HttpPost request = new HttpPost(apiUrl); + + MultipartEntityBuilder multipartBuilder = MultipartEntityBuilder.create() + .setCharset(StandardCharsets.UTF_8).setMode(HttpMultipartMode.LEGACY); + + // Add text parameters + for (Map.Entry param : params.entrySet()) { + if (param.getValue() instanceof Collection) { + for (Object value : (Collection) param.getValue()) { + multipartBuilder.addTextBody(param.getKey() + "[]", ObjectUtils.asString(value), ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)); + } + } else { + String value = param.getValue().toString(); + if (StringUtils.isNotBlank(value)) { + multipartBuilder.addTextBody(param.getKey(), value, ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)); + } + } + } + + // Add file part + addFilePart(multipartBuilder, file, options); + + request.setEntity(multipartBuilder.build()); + + // Add extra headers if provided + Map extraHeaders = (Map) options.get("extra_headers"); + if (extraHeaders != null) { + for (Map.Entry header : extraHeaders.entrySet()) { + request.addHeader(header.getKey(), header.getValue()); + } + } + + return request; + } + + + private void addFilePart(MultipartEntityBuilder multipartBuilder, Object file, Map options) throws IOException { + String filename = (String) options.get("filename"); + + if (file instanceof String && !StringUtils.isRemoteUrl((String) file)) { + File _file = new File((String) file); + if (!_file.isFile() || !_file.canRead()) { + throw new IOException("File not found or unreadable: " + file); + } + file = _file; + } + + if (file instanceof File) { + if (filename == null) { + filename = ((File) file).getName(); + } + // Encode filename properly + filename = new String(filename.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); + + // Create FileBody with correct filename encoding + FileBody fileBody = new FileBody((File) file, ContentType.APPLICATION_OCTET_STREAM, filename); + multipartBuilder.addPart("file", fileBody); + } else if (file instanceof String) { + multipartBuilder.addTextBody("file", (String) file, ContentType.TEXT_PLAIN); + } else if (file instanceof byte[]) { + if (filename == null) { + filename = "file"; + } + ByteArrayBody byteArrayBody = new ByteArrayBody((byte[]) file, ContentType.APPLICATION_OCTET_STREAM, filename); + multipartBuilder.addPart("file", byteArrayBody); + } else if (file == null) { + // No file to add + } else { + throw new IOException("Unrecognized file parameter " + file); + } + } +} diff --git a/cloudinary-http42/src/main/java/com/cloudinary/http42/api/Response.java b/cloudinary-http5/src/main/java/com/cloudinary/http5/api/Response.java similarity index 72% rename from cloudinary-http42/src/main/java/com/cloudinary/http42/api/Response.java rename to cloudinary-http5/src/main/java/com/cloudinary/http5/api/Response.java index 87de8299..fd7b0980 100644 --- a/cloudinary-http42/src/main/java/com/cloudinary/http42/api/Response.java +++ b/cloudinary-http5/src/main/java/com/cloudinary/http5/api/Response.java @@ -1,7 +1,12 @@ -package com.cloudinary.http42.api; +package com.cloudinary.http5.api; -import java.text.DateFormat; +import com.cloudinary.api.ApiResponse; +import com.cloudinary.api.RateLimit; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpResponse; import java.text.ParseException; + +import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.Locale; @@ -9,20 +14,12 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.http.Header; -import org.apache.http.HttpResponse; - -import com.cloudinary.api.ApiResponse; -import com.cloudinary.api.RateLimit; -import com.cloudinary.utils.StringUtils; - -@SuppressWarnings("rawtypes") public class Response extends HashMap implements ApiResponse { private static final long serialVersionUID = -5458609797599845837L; - private HttpResponse response = null; + private final HttpResponse response; @SuppressWarnings("unchecked") - public Response(HttpResponse response, Map result) { + public Response(HttpResponse response, Map result) { super(result); this.response = response; } @@ -32,25 +29,21 @@ public HttpResponse getRawHttpResponse() { } private static final Pattern RATE_LIMIT_REGEX = Pattern - .compile("X-FEATURE(\\w*)RATELIMIT(-LIMIT|-RESET|-REMAINING)", Pattern.CASE_INSENSITIVE); - private static final String RFC1123_PATTERN = "EEE, dd MMM yyyyy HH:mm:ss z"; + .compile("X-FEATURE(\\w*)RATELIMIT(-LIMIT|-RESET|-REMAINING)", Pattern.CASE_INSENSITIVE); + private static final String RFC1123_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z"; private static final DateFormat RFC1123 = new SimpleDateFormat(RFC1123_PATTERN, Locale.ENGLISH); public Map rateLimits() throws ParseException { - Header[] headers = this.response.getAllHeaders(); - Map limits = new HashMap(); + Header[] headers = this.response.getHeaders(); + Map limits = new HashMap<>(); for (Header header : headers) { Matcher m = RATE_LIMIT_REGEX.matcher(header.getName()); if (m.matches()) { String limitName = "Api"; - RateLimit limit = null; - if (!StringUtils.isEmpty(m.group(1))) { + RateLimit limit = limits.getOrDefault(limitName, new RateLimit()); + if (!m.group(1).isEmpty()) { limitName = m.group(1); } - limit = limits.get(limitName); - if (limit == null) { - limit = new RateLimit(); - } if (m.group(2).equalsIgnoreCase("-limit")) { limit.setLimit(Long.parseLong(header.getValue())); } else if (m.group(2).equalsIgnoreCase("-remaining")) { diff --git a/cloudinary-http42/src/test/java/com/cloudinary/test/AccountApiTest.java b/cloudinary-http5/src/test/java/com/cloudinary/test/AccountApiTest.java similarity index 100% rename from cloudinary-http42/src/test/java/com/cloudinary/test/AccountApiTest.java rename to cloudinary-http5/src/test/java/com/cloudinary/test/AccountApiTest.java diff --git a/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java b/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java new file mode 100644 index 00000000..a2f3c89f --- /dev/null +++ b/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java @@ -0,0 +1,45 @@ +package com.cloudinary.test; + +import com.cloudinary.api.ApiResponse; +import com.cloudinary.utils.ObjectUtils; +import org.apache.hc.core5.util.Timeout; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import java.util.Map; + + +public class ApiTest extends AbstractApiTest { + + @Category(TimeoutTest.class) + @Test(expected = Exception.class) + public void testConnectTimeoutParameter() throws Exception { + Map options = ObjectUtils.asMap( + "max_results", 500, + "connect_timeout", 0.2); + + try { + System.out.println("Setting connect timeout to 100 ms"); + ApiResponse result = cloudinary.api().resources(options); + System.out.println("Request completed without timeout"); + } catch (Exception e) { + throw new Exception("Connection timeout", e); + } + } + + @Category(TimeoutTest.class) + @Test(expected = Exception.class) + public void testTimeoutParameter() throws Exception { + // Set a very short request timeout to trigger a timeout exception + Map options = ObjectUtils.asMap( + "max_results", 500, + "timeout", Timeout.ofMilliseconds(1000)); // Set the timeout to 1 second + + try { + ApiResponse result = cloudinary.api().resources(options); + } catch (Exception e) { + // Convert IOException to SocketTimeoutException if appropriate + throw new Exception("Socket timeout"); + } + } +} + diff --git a/cloudinary-http43/src/test/java/com/cloudinary/test/ContextTest.java b/cloudinary-http5/src/test/java/com/cloudinary/test/ContextTest.java similarity index 100% rename from cloudinary-http43/src/test/java/com/cloudinary/test/ContextTest.java rename to cloudinary-http5/src/test/java/com/cloudinary/test/ContextTest.java diff --git a/cloudinary-http42/src/test/java/com/cloudinary/test/FoldersApiTest.java b/cloudinary-http5/src/test/java/com/cloudinary/test/FoldersApiTest.java similarity index 100% rename from cloudinary-http42/src/test/java/com/cloudinary/test/FoldersApiTest.java rename to cloudinary-http5/src/test/java/com/cloudinary/test/FoldersApiTest.java diff --git a/cloudinary-http42/src/test/java/com/cloudinary/test/SearchTest.java b/cloudinary-http5/src/test/java/com/cloudinary/test/SearchTest.java similarity index 100% rename from cloudinary-http42/src/test/java/com/cloudinary/test/SearchTest.java rename to cloudinary-http5/src/test/java/com/cloudinary/test/SearchTest.java diff --git a/cloudinary-http42/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java b/cloudinary-http5/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java similarity index 100% rename from cloudinary-http42/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java rename to cloudinary-http5/src/test/java/com/cloudinary/test/StreamingProfilesApiTest.java diff --git a/cloudinary-http42/src/test/java/com/cloudinary/test/StructuredMetadataTest.java b/cloudinary-http5/src/test/java/com/cloudinary/test/StructuredMetadataTest.java similarity index 100% rename from cloudinary-http42/src/test/java/com/cloudinary/test/StructuredMetadataTest.java rename to cloudinary-http5/src/test/java/com/cloudinary/test/StructuredMetadataTest.java diff --git a/cloudinary-http42/src/test/java/com/cloudinary/test/UploaderTest.java b/cloudinary-http5/src/test/java/com/cloudinary/test/UploaderTest.java similarity index 97% rename from cloudinary-http42/src/test/java/com/cloudinary/test/UploaderTest.java rename to cloudinary-http5/src/test/java/com/cloudinary/test/UploaderTest.java index 712b0ffd..50c2a6ed 100644 --- a/cloudinary-http42/src/test/java/com/cloudinary/test/UploaderTest.java +++ b/cloudinary-http5/src/test/java/com/cloudinary/test/UploaderTest.java @@ -2,4 +2,4 @@ public class UploaderTest extends AbstractUploaderTest { -} +} \ No newline at end of file diff --git a/samples/photo_album_gae/pom.xml b/samples/photo_album_gae/pom.xml index d730e1f5..9be3ebf6 100644 --- a/samples/photo_album_gae/pom.xml +++ b/samples/photo_album_gae/pom.xml @@ -42,8 +42,8 @@ com.cloudinary - cloudinary-http42 - 1.4.1 + cloudinary-http5 + 2.0.0 org.springframework diff --git a/settings.gradle b/settings.gradle index 174cb41d..004842ea 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,8 +1,6 @@ rootProject.name = 'cloudinary-parent' include ':cloudinary-core' include ':cloudinary-taglib' +include ':cloudinary-http5' include ':cloudinary-test-common' -include ':cloudinary-http42' -include ':cloudinary-http43' -include ':cloudinary-http44' -include ':cloudinary-http45' + From 6bb07c2ca8bad7163d08df3c3d257acccde6bd0f Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Thu, 12 Sep 2024 07:54:01 +0300 Subject: [PATCH 24/40] Add `auto_chaptering` and `auto_transcription` to upload API --- .../src/main/java/com/cloudinary/Util.java | 9 ++++++++- .../cloudinary/test/AbstractUploaderTest.java | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Util.java b/cloudinary-core/src/main/java/com/cloudinary/Util.java index 99fa608c..c5fcb1f0 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Util.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Util.java @@ -11,7 +11,8 @@ public class Util { static final String[] BOOLEAN_UPLOAD_OPTIONS = new String[]{"backup", "exif", "faces", "colors", "image_metadata", "use_filename", "unique_filename", "eager_async", "invalidate", "discard_original_filename", "overwrite", "phash", "return_delete_token", "async", "quality_analysis", "cinemagraph_analysis", - "accessibility_analysis", "use_filename_as_display_name", "use_asset_folder_as_public_id_prefix", "unique_display_name", "media_metadata", "visual_search"}; + "accessibility_analysis", "use_filename_as_display_name", "use_asset_folder_as_public_id_prefix", "unique_display_name", "media_metadata", "visual_search", + "auto_chaptering", "auto_transcription"}; @SuppressWarnings({"rawtypes", "unchecked"}) public static final Map buildUploadParams(Map options) { @@ -184,6 +185,12 @@ public static final void processWriteParameters(Map options, Map if(options.get("visual_search") != null) { params.put("visual_search", options.get("visual_search")); } + if(options.get("auto_chaptering") != null) { + params.put("auto_chaptering", options.get("auto_chaptering")); + } + if(options.get("auto_transcription") != null) { + params.put("auto_transcription", options.get("auto_transcription")); + } } protected static String encodeAccessControl(Object accessControl) { diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java index 8581ca30..19098f6c 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java @@ -841,4 +841,20 @@ public void testNotificationUrl() { Map uploadParams = Util.buildUploadParams(options); Assert.assertEquals("https://www.test.com", uploadParams.get("notification_url")); } + + @Test + public void testAutoChaptering() throws Exception { + Map result = cloudinary.uploader().upload(SRC_TEST_VIDEO, asMap( + "resource_type", "video", "auto_chaptering", true)); + assert(result != null); + assertNotNull(result.get("playback_url")); + } + + @Test + public void testAutoTranscription() throws Exception { + Map result = cloudinary.uploader().upload(SRC_TEST_VIDEO, asMap( + "resource_type", "video", "auto_transcription", true)); + assert(result != null); + assertNotNull(result.get("playback_url")); + } } From 94f8977106b394bab5c2d61dc3cb0fc154df6b0f Mon Sep 17 00:00:00 2001 From: adimiz1 Date: Sun, 29 Sep 2024 15:09:20 +0300 Subject: [PATCH 25/40] Version 2.0.0 --- CHANGELOG.md | 9 +++++++++ README.md | 11 +++++++---- .../src/main/java/com/cloudinary/Cloudinary.java | 2 +- gradle.properties | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4b4cc2c..bc13fee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +2.0.0 / 2024-09-29 +================== + +* Bump minimum Java version to 8 +* Secure true by default +* Add `auto_chaptering` and `auto_transcription` to upload API +* New Http client +* Add support for update metadata field set default disabled + 1.39.0 / 2024-07-14 =================== diff --git a/README.md b/README.md index 42a635c6..4e44ba97 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,12 @@ For the complete documentation, see the [Java SDK Guide](https://cloudinary.com/ - [Upload assets to cloud](https://cloudinary.com/documentation/java_image_and_video_upload) ## Version Support -| SDK Version | Java 6+ | -|----------------|---------| -| 1.1.0 - 1.39.0 | V | +| SDK Version | Java 6+ | Java 8 | +|----------------|---------|--------| +| 1.1.0 - 1.39.0 | V | | +| 2.0.0 | | V | + + ## Installation The cloudinary_java library is available in [Maven Central](https://mvnrepository.com/artifact/com.cloudinary/cloudinary-core). To use it, add the following dependency to your pom.xml : @@ -36,7 +39,7 @@ The cloudinary_java library is available in [Maven Central](https://mvnrepositor com.cloudinary cloudinary-http45 - 1.39.0 + 2.0.0 ``` diff --git a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java index 27b347ac..9bdbe122 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java @@ -32,7 +32,7 @@ public class Cloudinary { public final static String AKAMAI_SHARED_CDN = "res.cloudinary.com"; public final static String SHARED_CDN = AKAMAI_SHARED_CDN; - public final static String VERSION = "1.39.0"; + public final static String VERSION = "2.0.0"; static String USER_AGENT_PREFIX = "CloudinaryJava"; public final static String USER_AGENT_JAVA_VERSION = "(Java " + System.getProperty("java.version") + ")"; diff --git a/gradle.properties b/gradle.properties index e588ea7d..c15a7578 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ developerEmail=info@cloudinary.com # These two properties must use these exact names to be compatible with 'gradle install' plugin. group=com.cloudinary -version=1.39.0 +version=2.0.0 gnsp.disableApplyOnlyOnRootProjectEnforcement=true From 43d8e9ac0c7f073017d9c4b566c9566dea95f205 Mon Sep 17 00:00:00 2001 From: adimiz1 Date: Sun, 29 Sep 2024 15:39:43 +0300 Subject: [PATCH 26/40] Fix publish script --- build.gradle | 4 ++-- cloudinary-core/build.gradle | 4 ++-- cloudinary-http5/build.gradle | 4 ++-- cloudinary-taglib/build.gradle | 4 ++-- cloudinary-test-common/build.gradle | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index ebe374c8..5b9d6f04 100644 --- a/build.gradle +++ b/build.gradle @@ -20,8 +20,8 @@ nexusPublishing { } repositories { sonatype { - username = project.hasProperty("ossrhUsername") ? project.ext["ossrhUsername"] : "" - password = project.hasProperty("ossrhPassword") ? project.ext["ossrhPassword"] : "" + username = project.hasProperty("ossrhToken") ? project.ext["ossrhToken"] : "" + password = project.hasProperty("ossrhTokenPassword") ? project.ext["ossrhTokenPassword"] : "" } } } diff --git a/cloudinary-core/build.gradle b/cloudinary-core/build.gradle index 37246e23..01ac348b 100644 --- a/cloudinary-core/build.gradle +++ b/cloudinary-core/build.gradle @@ -23,8 +23,8 @@ if (hasProperty("ossrhPassword")) { nexusStaging { packageGroup = group - username = project.hasProperty("ossrhUsername") ? project.ext["ossrhUsername"] : "" - password = project.hasProperty("ossrhPassword") ? project.ext["ossrhPassword"] : "" + username = project.hasProperty("ossrhToken") ? project.ext["ossrhToken"] : "" + password = project.hasProperty("ossrhTokenPassword") ? project.ext["ossrhTokenPassword"] : "" } publishing { diff --git a/cloudinary-http5/build.gradle b/cloudinary-http5/build.gradle index 177ecdfa..b58b6c36 100644 --- a/cloudinary-http5/build.gradle +++ b/cloudinary-http5/build.gradle @@ -35,8 +35,8 @@ if (hasProperty("ossrhPassword")) { nexusStaging { packageGroup = group - username = project.hasProperty("ossrhUsername") ? project.ext["ossrhUsername"] : "" - password = project.hasProperty("ossrhPassword") ? project.ext["ossrhPassword"] : "" + username = project.hasProperty("ossrhToken") ? project.ext["ossrhToken"] : "" + password = project.hasProperty("ossrhTokenPassword") ? project.ext["ossrhTokenPassword"] : "" } publishing { diff --git a/cloudinary-taglib/build.gradle b/cloudinary-taglib/build.gradle index 6db5af30..16b200f3 100644 --- a/cloudinary-taglib/build.gradle +++ b/cloudinary-taglib/build.gradle @@ -30,8 +30,8 @@ if (hasProperty("ossrhPassword")) { nexusStaging { packageGroup = group - username = project.hasProperty("ossrhUsername") ? project.ext["ossrhUsername"] : "" - password = project.hasProperty("ossrhPassword") ? project.ext["ossrhPassword"] : "" + username = project.hasProperty("ossrhToken") ? project.ext["ossrhToken"] : "" + password = project.hasProperty("ossrhTokenPassword") ? project.ext["ossrhTokenPassword"] : "" } publishing { diff --git a/cloudinary-test-common/build.gradle b/cloudinary-test-common/build.gradle index 31a8bae2..daa5ce83 100644 --- a/cloudinary-test-common/build.gradle +++ b/cloudinary-test-common/build.gradle @@ -24,8 +24,8 @@ if (hasProperty("ossrhPassword")) { nexusStaging { packageGroup = group - username = project.hasProperty("ossrhUsername") ? project.ext["ossrhUsername"] : "" - password = project.hasProperty("ossrhPassword") ? project.ext["ossrhPassword"] : "" + username = project.hasProperty("ossrhToken") ? project.ext["ossrhToken"] : "" + password = project.hasProperty("ossrhTokenPassword") ? project.ext["ossrhTokenPassword"] : "" } publishing { From ab8f466972f0763c9230b683a5986e539a129cab Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:57:29 +0200 Subject: [PATCH 27/40] Make utility classes proper utilities --- .../src/main/java/com/cloudinary/SmartUrlEncoder.java | 4 +++- cloudinary-core/src/main/java/com/cloudinary/Util.java | 4 +++- .../src/main/java/com/cloudinary/utils/Base64Map.java | 4 +++- .../src/main/java/com/cloudinary/utils/HtmlEscape.java | 3 ++- .../src/main/java/com/cloudinary/utils/ObjectUtils.java | 4 +++- .../src/main/java/com/cloudinary/utils/StringUtils.java | 4 +++- .../src/main/java/com/cloudinary/http5/ApiUtils.java | 3 ++- cloudinary-taglib/src/main/java/com/cloudinary/Singleton.java | 3 ++- .../src/main/java/com/cloudinary/test/AbstractApiTest.java | 2 +- .../src/main/java/com/cloudinary/test/MetadataTestHelper.java | 4 +++- .../src/main/java/com/cloudinary/test/helpers/Feature.java | 4 +++- 11 files changed, 28 insertions(+), 11 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/SmartUrlEncoder.java b/cloudinary-core/src/main/java/com/cloudinary/SmartUrlEncoder.java index bcd8f654..2f20414f 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/SmartUrlEncoder.java +++ b/cloudinary-core/src/main/java/com/cloudinary/SmartUrlEncoder.java @@ -3,7 +3,9 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -public class SmartUrlEncoder { +public final class SmartUrlEncoder { + private SmartUrlEncoder() {} + public static String encode(String input) { try { return URLEncoder.encode(input, "UTF-8").replace("%2F", "/").replace("%3A", ":").replace("+", "%20"); diff --git a/cloudinary-core/src/main/java/com/cloudinary/Util.java b/cloudinary-core/src/main/java/com/cloudinary/Util.java index c5fcb1f0..f81da3cc 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Util.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Util.java @@ -8,7 +8,9 @@ import java.security.NoSuchAlgorithmException; import java.util.*; -public class Util { +public final class Util { + private Util() {} + static final String[] BOOLEAN_UPLOAD_OPTIONS = new String[]{"backup", "exif", "faces", "colors", "image_metadata", "use_filename", "unique_filename", "eager_async", "invalidate", "discard_original_filename", "overwrite", "phash", "return_delete_token", "async", "quality_analysis", "cinemagraph_analysis", "accessibility_analysis", "use_filename_as_display_name", "use_asset_folder_as_public_id_prefix", "unique_display_name", "media_metadata", "visual_search", diff --git a/cloudinary-core/src/main/java/com/cloudinary/utils/Base64Map.java b/cloudinary-core/src/main/java/com/cloudinary/utils/Base64Map.java index d5e755f9..f9948974 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/utils/Base64Map.java +++ b/cloudinary-core/src/main/java/com/cloudinary/utils/Base64Map.java @@ -3,7 +3,9 @@ import java.util.HashMap; import java.util.Map; -public class Base64Map { +public final class Base64Map { + private Base64Map() {} + public static Map values; static { diff --git a/cloudinary-core/src/main/java/com/cloudinary/utils/HtmlEscape.java b/cloudinary-core/src/main/java/com/cloudinary/utils/HtmlEscape.java index 2be36583..39ba901e 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/utils/HtmlEscape.java +++ b/cloudinary-core/src/main/java/com/cloudinary/utils/HtmlEscape.java @@ -16,7 +16,8 @@ * this program code. */ -public class HtmlEscape { +public final class HtmlEscape { + private HtmlEscape() {} private static char[] hex = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; diff --git a/cloudinary-core/src/main/java/com/cloudinary/utils/ObjectUtils.java b/cloudinary-core/src/main/java/com/cloudinary/utils/ObjectUtils.java index 437c04db..2dc607f6 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/utils/ObjectUtils.java +++ b/cloudinary-core/src/main/java/com/cloudinary/utils/ObjectUtils.java @@ -11,7 +11,9 @@ import java.util.*; -public class ObjectUtils { +public final class ObjectUtils { + private ObjectUtils() {} + /** * Formats a Date as an ISO-8601 string representation. * @param date Date to format diff --git a/cloudinary-core/src/main/java/com/cloudinary/utils/StringUtils.java b/cloudinary-core/src/main/java/com/cloudinary/utils/StringUtils.java index 0d25bacb..f8a21231 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/utils/StringUtils.java +++ b/cloudinary-core/src/main/java/com/cloudinary/utils/StringUtils.java @@ -8,7 +8,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class StringUtils { +public final class StringUtils { + private StringUtils() {} + public static final String EMPTY = ""; /** diff --git a/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiUtils.java b/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiUtils.java index af67a1e8..040fd714 100644 --- a/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiUtils.java +++ b/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiUtils.java @@ -10,7 +10,8 @@ import java.util.*; -public class ApiUtils { +public final class ApiUtils { + private ApiUtils() {} public static void setTimeouts(HttpUriRequestBase request, Map options) { RequestConfig config = request.getConfig(); diff --git a/cloudinary-taglib/src/main/java/com/cloudinary/Singleton.java b/cloudinary-taglib/src/main/java/com/cloudinary/Singleton.java index a3767492..5c11458f 100644 --- a/cloudinary-taglib/src/main/java/com/cloudinary/Singleton.java +++ b/cloudinary-taglib/src/main/java/com/cloudinary/Singleton.java @@ -10,7 +10,8 @@ * * @author jpollak */ -public class Singleton { +public final class Singleton { + private Singleton() {} private static Cloudinary cloudinary; diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index ad89074a..e5ae3703 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -670,7 +670,7 @@ public void testRateLimits() throws Exception { @Test public void testConfiguration() throws Exception { - ApiResponse result = cloudinary.api().configuration(new ObjectUtils().asMap("settings", true)); + ApiResponse result = cloudinary.api().configuration(ObjectUtils.asMap("settings", true)); Map settings = (Map) result.get("settings"); Assert.assertNotNull(settings.get("folder_mode")); } diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/MetadataTestHelper.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/MetadataTestHelper.java index cdb52487..2a128c7f 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/MetadataTestHelper.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/MetadataTestHelper.java @@ -6,7 +6,9 @@ import com.cloudinary.metadata.MetadataValidation; import com.cloudinary.metadata.StringMetadataField; -public class MetadataTestHelper { +public final class MetadataTestHelper { + private MetadataTestHelper() {} + public static StringMetadataField newFieldInstance(String label, Boolean mandatory) throws Exception { StringMetadataField field = new StringMetadataField(); field.setLabel(label); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java index 2ced269c..b66bd303 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/helpers/Feature.java @@ -1,6 +1,8 @@ package com.cloudinary.test.helpers; -public class Feature { +public final class Feature { + private Feature() {} + public static final String ALL = "all"; public static final String DYNAMIC_FOLDERS = "dynamic_folders"; public static final String BACKEDUP_ASSETS = "backedup_assets"; From c4d7b2926fe1789237672485b6ab026415ca509f Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Mon, 21 Oct 2024 22:33:00 +0200 Subject: [PATCH 28/40] Remove unused imports --- cloudinary-core/src/main/java/com/cloudinary/AuthToken.java | 3 --- cloudinary-core/src/main/java/com/cloudinary/Search.java | 1 - cloudinary-core/src/main/java/com/cloudinary/Url.java | 1 - .../src/main/java/com/cloudinary/metadata/MetadataRule.java | 1 - .../java/com/cloudinary/strategies/AbstractApiStrategy.java | 5 ----- .../src/test/java/com/cloudinary/AuthTokenTest.java | 2 -- .../src/test/java/com/cloudinary/test/CloudinaryTest.java | 1 - .../src/main/java/com/cloudinary/http5/ApiStrategy.java | 2 -- .../main/java/com/cloudinary/taglib/CloudinaryImageTag.java | 4 ---- .../main/java/com/cloudinary/taglib/CloudinaryVideoTag.java | 1 - .../java/com/cloudinary/test/AbstractAccountApiTest.java | 1 - .../main/java/com/cloudinary/test/AbstractSearchTest.java | 3 --- .../main/java/com/cloudinary/test/AbstractUploaderTest.java | 2 -- .../src/main/java/cloudinary/lib/PhotoUploadValidator.java | 6 ------ .../main/java/cloudinary/controllers/PhotoController.java | 1 - .../src/main/java/cloudinary/lib/PhotoUploadValidator.java | 6 ------ 16 files changed, 40 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/AuthToken.java b/cloudinary-core/src/main/java/com/cloudinary/AuthToken.java index aa8cf213..a5114dd3 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/AuthToken.java +++ b/cloudinary-core/src/main/java/com/cloudinary/AuthToken.java @@ -5,13 +5,10 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import java.nio.charset.Charset; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.*; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** diff --git a/cloudinary-core/src/main/java/com/cloudinary/Search.java b/cloudinary-core/src/main/java/com/cloudinary/Search.java index 2ba3ac8b..369830c6 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Search.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Search.java @@ -6,7 +6,6 @@ import com.cloudinary.utils.StringUtils; import org.cloudinary.json.JSONObject; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; diff --git a/cloudinary-core/src/main/java/com/cloudinary/Url.java b/cloudinary-core/src/main/java/com/cloudinary/Url.java index 6517bd28..5365c996 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Url.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Url.java @@ -13,7 +13,6 @@ import java.util.regex.Pattern; import java.util.zip.CRC32; -import com.cloudinary.utils.Analytics; import com.cloudinary.utils.Base64Coder; import com.cloudinary.utils.ObjectUtils; import com.cloudinary.utils.StringUtils; diff --git a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRule.java b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRule.java index 65edbed4..4df82ded 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRule.java +++ b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataRule.java @@ -2,7 +2,6 @@ import com.cloudinary.utils.ObjectUtils; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; diff --git a/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java b/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java index 8878bf2c..0342f5bc 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java +++ b/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java @@ -2,12 +2,7 @@ import com.cloudinary.Api; import com.cloudinary.Api.HttpMethod; -import com.cloudinary.SmartUrlEncoder; import com.cloudinary.api.ApiResponse; -import com.cloudinary.utils.Base64Coder; -import com.cloudinary.utils.ObjectUtils; -import com.cloudinary.utils.StringUtils; -import java.util.Arrays; import java.util.Map; diff --git a/cloudinary-core/src/test/java/com/cloudinary/AuthTokenTest.java b/cloudinary-core/src/test/java/com/cloudinary/AuthTokenTest.java index 468c43bb..49fd8d35 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/AuthTokenTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/AuthTokenTest.java @@ -1,6 +1,5 @@ package com.cloudinary; -import com.cloudinary.utils.Analytics; import com.cloudinary.utils.ObjectUtils; import org.hamcrest.CoreMatchers; @@ -11,7 +10,6 @@ import org.junit.Test; import org.junit.rules.TestName; -import java.io.UnsupportedEncodingException; import java.util.Calendar; import java.util.Collections; import java.util.Map; diff --git a/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java b/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java index 9e436183..b43a2bc8 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java @@ -18,7 +18,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.Type; -import java.lang.reflect.ParameterizedType; import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; diff --git a/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java b/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java index 2852225d..40171489 100644 --- a/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java +++ b/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java @@ -7,7 +7,6 @@ import com.cloudinary.http5.api.Response; import com.cloudinary.strategies.AbstractApiStrategy; import com.cloudinary.utils.ObjectUtils; -import com.cloudinary.utils.StringUtils; import org.apache.hc.client5.http.classic.methods.*; import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; @@ -25,7 +24,6 @@ import java.lang.reflect.Constructor; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; -import java.util.Arrays; import java.util.List; import java.util.Map; diff --git a/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryImageTag.java b/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryImageTag.java index 2de25e3b..8b253533 100644 --- a/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryImageTag.java +++ b/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryImageTag.java @@ -4,12 +4,8 @@ import java.util.HashMap; import java.util.Map; -import javax.servlet.ServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; -import javax.servlet.jsp.PageContext; -import javax.servlet.jsp.tagext.DynamicAttributes; -import javax.servlet.jsp.tagext.SimpleTagSupport; import com.cloudinary.*; diff --git a/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryVideoTag.java b/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryVideoTag.java index 9ed803ee..ec2adb54 100644 --- a/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryVideoTag.java +++ b/cloudinary-taglib/src/main/java/com/cloudinary/taglib/CloudinaryVideoTag.java @@ -1,7 +1,6 @@ package com.cloudinary.taglib; import java.io.IOException; -import java.util.HashMap; import java.util.Map; import javax.servlet.jsp.JspException; diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractAccountApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractAccountApiTest.java index 5b8e9633..7852f96b 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractAccountApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractAccountApiTest.java @@ -15,7 +15,6 @@ import static java.util.Collections.singletonMap; import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.*; -import static org.junit.Assume.assumeTrue; public abstract class AbstractAccountApiTest extends MockableTest { private static Random rand = new Random(); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractSearchTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractSearchTest.java index 5e30d26b..e6bf5d6e 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractSearchTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractSearchTest.java @@ -1,9 +1,7 @@ package com.cloudinary.test; import com.cloudinary.Cloudinary; -import com.cloudinary.Configuration; import com.cloudinary.Search; -import com.cloudinary.api.ApiResponse; import com.cloudinary.utils.ObjectUtils; import org.junit.*; import org.junit.rules.TestName; @@ -13,7 +11,6 @@ import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.core.AllOf.allOf; import static org.junit.Assert.*; import static org.junit.Assume.assumeNotNull; diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java index 19098f6c..5de797fa 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java @@ -1,7 +1,6 @@ package com.cloudinary.test; import com.cloudinary.*; -import com.cloudinary.api.ApiResponse; import com.cloudinary.metadata.StringMetadataField; import com.cloudinary.test.rules.RetryRule; import com.cloudinary.utils.ObjectUtils; @@ -13,7 +12,6 @@ import java.io.*; import java.net.HttpURLConnection; import java.net.URL; -import java.net.URLEncoder; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; diff --git a/samples/photo_album/src/main/java/cloudinary/lib/PhotoUploadValidator.java b/samples/photo_album/src/main/java/cloudinary/lib/PhotoUploadValidator.java index 2bcdc56d..0a389e02 100644 --- a/samples/photo_album/src/main/java/cloudinary/lib/PhotoUploadValidator.java +++ b/samples/photo_album/src/main/java/cloudinary/lib/PhotoUploadValidator.java @@ -1,16 +1,10 @@ package cloudinary.lib; import cloudinary.models.PhotoUpload; -import com.cloudinary.Cloudinary; -import com.cloudinary.Singleton; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - public class PhotoUploadValidator implements Validator { public boolean supports(Class clazz) { return PhotoUpload.class.equals(clazz); diff --git a/samples/photo_album_gae/src/main/java/cloudinary/controllers/PhotoController.java b/samples/photo_album_gae/src/main/java/cloudinary/controllers/PhotoController.java index 53e8b537..7a6438a8 100644 --- a/samples/photo_album_gae/src/main/java/cloudinary/controllers/PhotoController.java +++ b/samples/photo_album_gae/src/main/java/cloudinary/controllers/PhotoController.java @@ -2,7 +2,6 @@ import cloudinary.lib.PhotoUploadValidator; import cloudinary.models.PhotoUpload; -import com.cloudinary.Cloudinary; import com.cloudinary.utils.ObjectUtils; import com.cloudinary.Singleton; import org.springframework.stereotype.Controller; diff --git a/samples/photo_album_gae/src/main/java/cloudinary/lib/PhotoUploadValidator.java b/samples/photo_album_gae/src/main/java/cloudinary/lib/PhotoUploadValidator.java index 2bcdc56d..0a389e02 100644 --- a/samples/photo_album_gae/src/main/java/cloudinary/lib/PhotoUploadValidator.java +++ b/samples/photo_album_gae/src/main/java/cloudinary/lib/PhotoUploadValidator.java @@ -1,16 +1,10 @@ package cloudinary.lib; import cloudinary.models.PhotoUpload; -import com.cloudinary.Cloudinary; -import com.cloudinary.Singleton; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - public class PhotoUploadValidator implements Validator { public boolean supports(Class clazz) { return PhotoUpload.class.equals(clazz); From 3a0e000b4fd72dd6833e4bbba0500532fb31ed4e Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Thu, 16 Jan 2025 11:00:49 +0200 Subject: [PATCH 29/40] Fix upload preset tests --- cloudinary-core/src/main/java/com/cloudinary/Api.java | 4 ++-- .../src/main/java/com/cloudinary/test/AbstractApiTest.java | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index 9dbacde9..d09df997 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -338,7 +338,7 @@ public ApiResponse updateUploadPreset(String name, Map options) throws Exception if (options == null) options = ObjectUtils.emptyMap(); Map params = Util.buildUploadParams(options); Util.clearEmpty(params); - params.putAll(ObjectUtils.only(options, "unsigned", "disallow_public_id", "live")); + params.putAll(ObjectUtils.only(options, "unsigned", "disallow_public_id")); return callApi(HttpMethod.PUT, Arrays.asList("upload_presets", name), params, options); } @@ -346,7 +346,7 @@ public ApiResponse createUploadPreset(Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); Map params = Util.buildUploadParams(options); Util.clearEmpty(params); - params.putAll(ObjectUtils.only(options, "name", "unsigned", "disallow_public_id", "live")); + params.putAll(ObjectUtils.only(options, "name", "unsigned", "disallow_public_id")); return callApi(HttpMethod.POST, Arrays.asList("upload_presets"), params, options); } diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index e5ae3703..9ec8746f 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -825,14 +825,13 @@ public void testGetUploadPreset() throws Exception { String[] tags = {"a", "b", "c"}; Map context = ObjectUtils.asMap("a", "b", "c", "d"); Map result = api.createUploadPreset(ObjectUtils.asMap("unsigned", true, "folder", "folder", "transformation", EXPLICIT_TRANSFORMATION, "tags", tags, "context", - context, "live", true, "use_asset_folder_as_public_id_prefix", true)); + context, "use_asset_folder_as_public_id_prefix", true)); String name = result.get("name").toString(); Map preset = api.uploadPreset(name, ObjectUtils.emptyMap()); assertEquals(preset.get("name"), name); assertEquals(Boolean.TRUE, preset.get("unsigned")); Map settings = (Map) preset.get("settings"); assertEquals(settings.get("folder"), "folder"); - assertEquals(settings.get("live"), Boolean.TRUE); assertEquals(settings.get("use_asset_folder_as_public_id_prefix"), true); Map outTransformation = (Map) ((java.util.ArrayList) settings.get("transformation")).get(0); assertEquals(outTransformation.get("width"), 100); @@ -866,13 +865,12 @@ public void testUpdateUploadPreset() throws Exception { String name = api.createUploadPreset(ObjectUtils.asMap("folder", "folder")).get("name").toString(); Map preset = api.uploadPreset(name, ObjectUtils.emptyMap()); Map settings = (Map) preset.get("settings"); - settings.putAll(ObjectUtils.asMap("colors", true, "unsigned", true, "disallow_public_id", true, "live", true, "eval",AbstractUploaderTest.SRC_TEST_EVAL)); + settings.putAll(ObjectUtils.asMap("colors", true, "unsigned", true, "disallow_public_id", true, "eval",AbstractUploaderTest.SRC_TEST_EVAL)); api.updateUploadPreset(name, settings); settings.remove("unsigned"); preset = api.uploadPreset(name, ObjectUtils.emptyMap()); assertEquals(name, preset.get("name")); assertEquals(Boolean.TRUE, preset.get("unsigned")); - assertEquals(settings.get("live"), Boolean.TRUE); assertEquals(settings, preset.get("settings")); api.deleteUploadPreset(name, ObjectUtils.emptyMap()); From 0f456e8a14b2f3957bc8fdd75373446bd6927144 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Thu, 16 Jan 2025 12:51:41 +0200 Subject: [PATCH 30/40] Update Cloudinary constructor --- .../main/java/com/cloudinary/Cloudinary.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java index 9bdbe122..b802d26d 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java @@ -85,22 +85,21 @@ private void loadStrategies() { } public Cloudinary(Map config) { - this.config = new Configuration(config); - loadStrategies(); + this(new Configuration(config)); } public Cloudinary(String cloudinaryUrl) { - this.config = Configuration.from(cloudinaryUrl); - loadStrategies(); + this(Configuration.from(cloudinaryUrl)); } public Cloudinary() { - String cloudinaryUrl = System.getProperty("CLOUDINARY_URL", System.getenv("CLOUDINARY_URL")); - if (cloudinaryUrl != null) { - this.config = Configuration.from(cloudinaryUrl); - } else { - this.config = new Configuration(); - } + this(System.getProperty("CLOUDINARY_URL", System.getenv("CLOUDINARY_URL")) != null + ? Configuration.from(System.getProperty("CLOUDINARY_URL", System.getenv("CLOUDINARY_URL"))) + : new Configuration()); + } + + public Cloudinary(Configuration config) { + this.config = config; loadStrategies(); } From fad1ed50956b21206706750c06f5f4d38c5cb82d Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Thu, 16 Jan 2025 12:52:01 +0200 Subject: [PATCH 31/40] Fix and test register upload + api strategies --- .../src/main/java/com/cloudinary/Cloudinary.java | 6 +++--- .../java/com/cloudinary/test/CloudinaryTest.java | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java index b802d26d..f70f8965 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java @@ -20,7 +20,7 @@ @SuppressWarnings({"rawtypes", "unchecked"}) public class Cloudinary { - private static List UPLOAD_STRATEGIES = new ArrayList(Arrays.asList( + public static List UPLOAD_STRATEGIES = new ArrayList(Arrays.asList( "com.cloudinary.android.UploaderStrategy", "com.cloudinary.http5.UploaderStrategy")); public static List API_STRATEGIES = new ArrayList(Arrays.asList( @@ -59,14 +59,14 @@ public SearchFolders searchFolders() { public static void registerUploaderStrategy(String className) { if (!UPLOAD_STRATEGIES.contains(className)) { - UPLOAD_STRATEGIES.add(className); + UPLOAD_STRATEGIES.add(0, className); } } public static void registerAPIStrategy(String className) { if (!API_STRATEGIES.contains(className)) { - API_STRATEGIES.add(className); + API_STRATEGIES.add(0, className); } } diff --git a/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java b/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java index b43a2bc8..18064976 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java @@ -1464,6 +1464,20 @@ public void testDownloadBackedupAsset() throws UnsupportedEncodingException, URI assertNotNull(params.get("timestamp")); } + @Test + public void testRegisterUploaderStrategy() { + String className = "myUploadStrategy"; + Cloudinary.registerUploaderStrategy(className); + assertEquals(className, Cloudinary.UPLOAD_STRATEGIES.get(0)); + } + + @Test + public void testRegisterApiStrategy() { + String className = "myApiStrategy"; + Cloudinary.registerAPIStrategy(className); + assertEquals(className, Cloudinary.API_STRATEGIES.get(0)); + } + private void assertFieldsEqual(Object a, Object b) throws IllegalAccessException { assertEquals("Two objects must be the same class", a.getClass(), b.getClass()); Field[] fields = a.getClass().getFields(); From 98f0260ce1b4e0fc965ce16c09e8956a35a2e022 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Mon, 20 Jan 2025 08:10:00 +0200 Subject: [PATCH 32/40] Fix Http client 5.0 init (#369) --- .../com/cloudinary/http5/ApiStrategy.java | 38 +++++++++++++++++-- .../java/com/cloudinary/test/ApiTest.java | 38 ++++++++++++++++++- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java b/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java index 40171489..9c0145e9 100644 --- a/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java +++ b/cloudinary-http5/src/main/java/com/cloudinary/http5/ApiStrategy.java @@ -8,15 +8,20 @@ import com.cloudinary.strategies.AbstractApiStrategy; import com.cloudinary.utils.ObjectUtils; import org.apache.hc.client5.http.classic.methods.*; +import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.io.HttpClientConnectionManager; import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.NameValuePair; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.net.URIBuilder; +import org.apache.hc.core5.util.Timeout; import org.cloudinary.json.JSONException; import org.cloudinary.json.JSONObject; @@ -36,15 +41,42 @@ public class ApiStrategy extends AbstractApiStrategy { private CloseableHttpClient client; - @Override public void init(Api api) { super.init(api); - this.client = HttpClients.custom() - .setUserAgent(this.api.cloudinary.getUserAgent() + " ApacheHttpClient/" + APACHE_HTTP_CLIENT_VERSION) + HttpClientBuilder clientBuilder = HttpClients.custom(); + clientBuilder.useSystemProperties().setUserAgent(this.api.cloudinary.getUserAgent() + " ApacheHttpClient/" + APACHE_HTTP_CLIENT_VERSION); + + HttpClientConnectionManager connectionManager = (HttpClientConnectionManager) api.cloudinary.config.properties.get("connectionManager"); + if (connectionManager != null) { + clientBuilder.setConnectionManager(connectionManager); + } + + RequestConfig requestConfig = buildRequestConfig(); + + client = clientBuilder + .setDefaultRequestConfig(requestConfig) .build(); } + public RequestConfig buildRequestConfig() { + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); + + if (api.cloudinary.config.proxyHost != null && api.cloudinary.config.proxyPort != 0) { + HttpHost proxy = new HttpHost(api.cloudinary.config.proxyHost, api.cloudinary.config.proxyPort); + requestConfigBuilder.setProxy(proxy); + } + + int timeout = this.api.cloudinary.config.timeout; + if (timeout > 0) { + requestConfigBuilder.setResponseTimeout(Timeout.ofSeconds(timeout)) + .setConnectionRequestTimeout(Timeout.ofSeconds(timeout)) + .setConnectTimeout(Timeout.ofSeconds(timeout)); + } + + return requestConfigBuilder.build(); + } + @SuppressWarnings({"rawtypes", "unchecked"}) public ApiResponse callApi(Api.HttpMethod method, String apiUrl, Map params, Map options, String autorizationHeader) throws Exception { HttpUriRequestBase request = prepareRequest(method, apiUrl, params, options); diff --git a/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java b/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java index a2f3c89f..4735d89f 100644 --- a/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java +++ b/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java @@ -1,15 +1,50 @@ package com.cloudinary.test; +import com.cloudinary.Cloudinary; import com.cloudinary.api.ApiResponse; +import com.cloudinary.http5.ApiStrategy; import com.cloudinary.utils.ObjectUtils; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.util.Timeout; import org.junit.Test; import org.junit.experimental.categories.Category; + import java.util.Map; public class ApiTest extends AbstractApiTest { + @Test + public void testBuildRequestConfig_withProxyAndTimeout() { + Cloudinary cloudinary = new Cloudinary("cloudinary://test:test@test.com"); + cloudinary.config.proxyHost = "127.0.0.1"; + cloudinary.config.proxyPort = 8080; + cloudinary.config.timeout = 15; + + RequestConfig requestConfig = ((ApiStrategy)cloudinary.api().getStrategy()).buildRequestConfig(); + + assert(requestConfig.getProxy() != null); + HttpHost proxy = requestConfig.getProxy(); + assert("127.0.0.1" == proxy.getHostName()); + assert(8080 == proxy.getPort()); + + assert(15000 == requestConfig.getConnectionRequestTimeout().toMilliseconds()); + assert(15000 == requestConfig.getResponseTimeout().toMilliseconds()); + } + + @Test + public void testBuildRequestConfig_withoutProxy() { + Cloudinary cloudinary = new Cloudinary("cloudinary://test:test@test.com"); + cloudinary.config.timeout = 10; + + RequestConfig requestConfig = ((ApiStrategy)cloudinary.api().getStrategy()).buildRequestConfig(); + + assert(requestConfig.getProxy() == null); + assert(10000 == requestConfig.getConnectionRequestTimeout().toMilliseconds()); + assert(10000 == requestConfig.getResponseTimeout().toMilliseconds()); + } + @Category(TimeoutTest.class) @Test(expected = Exception.class) public void testConnectTimeoutParameter() throws Exception { @@ -41,5 +76,4 @@ public void testTimeoutParameter() throws Exception { throw new Exception("Socket timeout"); } } -} - +} \ No newline at end of file From 209037e99016bb76067a52cea33e2098502ac868 Mon Sep 17 00:00:00 2001 From: Adi Mizrahi Date: Mon, 20 Jan 2025 12:17:20 +0200 Subject: [PATCH 33/40] Version 2.1.0 --- CHANGELOG.md | 8 ++++++++ README.md | 4 ++-- .../src/main/java/com/cloudinary/Cloudinary.java | 2 +- gradle.properties | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc13fee5..ffe151ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +2.1.0 / 2025-01-20 +================== + +* Fix Http client proxy +* Fix Http client system properties support +* Add Cloudinary constructor for `Configuration` +* Fix Register strategy functions + 2.0.0 / 2024-09-29 ================== diff --git a/README.md b/README.md index 4e44ba97..74e77daa 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ For the complete documentation, see the [Java SDK Guide](https://cloudinary.com/ | SDK Version | Java 6+ | Java 8 | |----------------|---------|--------| | 1.1.0 - 1.39.0 | V | | -| 2.0.0 | | V | +| 2.0.0+ | | V | @@ -39,7 +39,7 @@ The cloudinary_java library is available in [Maven Central](https://mvnrepositor com.cloudinary cloudinary-http45 - 2.0.0 + 2.1.0 ``` diff --git a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java index f70f8965..aa156ec2 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java @@ -32,7 +32,7 @@ public class Cloudinary { public final static String AKAMAI_SHARED_CDN = "res.cloudinary.com"; public final static String SHARED_CDN = AKAMAI_SHARED_CDN; - public final static String VERSION = "2.0.0"; + public final static String VERSION = "2.1.0"; static String USER_AGENT_PREFIX = "CloudinaryJava"; public final static String USER_AGENT_JAVA_VERSION = "(Java " + System.getProperty("java.version") + ")"; diff --git a/gradle.properties b/gradle.properties index c15a7578..6ce82a60 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ developerEmail=info@cloudinary.com # These two properties must use these exact names to be compatible with 'gradle install' plugin. group=com.cloudinary -version=2.0.0 +version=2.1.0 gnsp.disableApplyOnlyOnRootProjectEnforcement=true From 4e7d91f77ae8f4a9c45e6439dac39caafde72815 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Mon, 27 Jan 2025 08:06:28 +0200 Subject: [PATCH 34/40] Add delete resources by assetids --- .../src/main/java/com/cloudinary/Api.java | 7 +++++++ .../java/com/cloudinary/test/AbstractApiTest.java | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index d09df997..0885ab13 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -240,6 +240,13 @@ public ApiResponse deleteResources(Iterable publicIds, Map options) thro return callApi(HttpMethod.DELETE, Arrays.asList("resources", resourceType, type), params, options); } + public ApiResponse deleteResourcesByAssetIds(Iterable assetIds, Map options) throws Exception { + if (options == null) options = ObjectUtils.emptyMap(); + Map params = ObjectUtils.only(options, "keep_original", "invalidate", "next_cursor", "transformations"); + params.put("asset_ids", assetIds); + return callApi(HttpMethod.DELETE, Arrays.asList("resources"), params, options); + } + public ApiResponse deleteDerivedByTransformation(Iterable publicIds, List transformations, Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); String resourceType = ObjectUtils.asString(options.get("resource_type"), "image"); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index 9ec8746f..4a73ff73 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -464,6 +464,20 @@ public void test09DeleteResources() throws Exception { api.resource(public_id, ObjectUtils.emptyMap()); } + @Test(expected = NotFound.class) + public void test10DeleteResourcesByAssetsIds() throws Exception { + String public_id = "api_,test4" + SUFFIX; + cloudinary.uploader().upload(SRC_TEST_IMAGE, ObjectUtils.asMap("public_id", public_id, "tags", UPLOAD_TAGS)); + Map resource = api.resource(public_id, ObjectUtils.emptyMap()); + assertNotNull(resource); + String assetId = (String)resource.get("asset_id"); + ApiResponse response = api.deleteResourcesByAssetIds(Arrays.asList(assetId), ObjectUtils.emptyMap()); + assertNotNull(response); + assertNotNull(response.get("deleted")); + assertNotNull(response.get("deleted_counts")); + api.resource(public_id, ObjectUtils.emptyMap()); + } + @Test(expected = NotFound.class) public void test09aDeleteResourcesByPrefix() throws Exception { // should allow deleting resources From a8284ebc8f0ae98760405d6454706e97a341529f Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:15:18 +0200 Subject: [PATCH 35/40] Add allow dynamic list to List Metadata field --- .../java/com/cloudinary/metadata/MetadataField.java | 7 +++++++ .../test/AbstractStructuredMetadataTest.java | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java index 4f3bdf33..7fe81c43 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java +++ b/cloudinary-core/src/main/java/com/cloudinary/metadata/MetadataField.java @@ -18,6 +18,7 @@ public class MetadataField extends JSONObject { public static final String VALIDATION = "validation"; public static final String RESTRICTIONS = "restrictions"; public static final String DEFAULT_DISABLED = "default_disabled"; + public static final String ALLOW_DYNAMIC_LIST_VALUES = "allow_dynamic_list_values"; public MetadataField(MetadataFieldType type) { put(TYPE, type.toString()); @@ -148,4 +149,10 @@ public void setRestrictions(Restrictions restrictions) { public void setDefaultDisabled(Boolean disabled) { put(DEFAULT_DISABLED, disabled); } + + /** + * Set the value indicating whether the dynamic list values should allow + * @param allowDynamicListValues The value to set. + */ + public void setAllowDynamicListValues(Boolean allowDynamicListValues) {put(ALLOW_DYNAMIC_LIST_VALUES, allowDynamicListValues);} } \ No newline at end of file diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java index 241ac47d..60467685 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java @@ -73,6 +73,15 @@ public void testCreateMetadata() throws Exception { assertEquals(setField.getLabel(), result.get("label")); } + @Test + public void testCreateSetMetadataWithAllowDynamicListValues() throws Exception { + SetMetadataField setField = createSetField("testCreateMetadata_2"); + ApiResponse result = cloudinary.api().addMetadataField(setField); + assertNotNull(result); + assertEquals(setField.getLabel(), result.get("label")); + assertEquals(true, result.get("allow_dynamic_list_values")); + } + @Test public void testFieldRestrictions() throws Exception { StringMetadataField stringField = newFieldInstance("testCreateMetadata_3", true); @@ -367,6 +376,7 @@ private SetMetadataField createSetField(String labelPrefix) { String label = labelPrefix + "_" + SUFFIX; setField.setLabel(label); setField.setMandatory(false); + setField.setAllowDynamicListValues(true); setField.setValidation(new MetadataValidation.StringLength(3, 99)); setField.setDefaultValue(Arrays.asList("id2", "id3")); setField.setValidation(null); From 61a5c905e84a24af5e328268b8444e7290b2f27e Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Wed, 29 Jan 2025 15:42:59 +0200 Subject: [PATCH 36/40] Add restore by asset ids api call --- .../src/main/java/com/cloudinary/Api.java | 8 ++++++ .../com/cloudinary/test/AbstractApiTest.java | 26 +++++++++++++++++++ .../test/AbstractStructuredMetadataTest.java | 2 +- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index 0885ab13..0cbab208 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -393,6 +393,14 @@ public ApiResponse restore(Iterable publicIds, Map options) throws Excep return response; } + public ApiResponse restoreByAssetIds(Iterable assetIds, Map options) throws Exception { + if (options == null) + options = ObjectUtils.emptyMap(); + Map params = new HashMap(); + params.put("asset_ids", assetIds); + return callApi(HttpMethod.POST, Arrays.asList("resources", "restore"), params, options); + } + public ApiResponse uploadMappings(Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index 4a73ff73..5c854d75 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -971,6 +971,32 @@ public void testRestore() throws Exception { assertEquals(resource.get("bytes"), 3381); } + @Test + public void testRestoreByAssetIds() throws Exception { + + // Upload + cloudinary.uploader().upload(SRC_TEST_IMAGE, + ObjectUtils.asMap("public_id", API_TEST_RESTORE, "backup", true, "tags", UPLOAD_TAGS)); + Map resource = api.resource(API_TEST_RESTORE, ObjectUtils.emptyMap()); + assertEquals(resource.get("bytes"), 3381); + + //Delete + api.deleteResources(Collections.singletonList(API_TEST_RESTORE), ObjectUtils.emptyMap()); + resource = api.resource(API_TEST_RESTORE, ObjectUtils.emptyMap()); + String assetId = (String) resource.get("asset_id"); + assertEquals(resource.get("bytes"), 0); + assertNotNull(assetId); + assertTrue((Boolean) resource.get("placeholder")); + + //Restore + Map response = api.restoreByAssetIds(Collections.singletonList(assetId), ObjectUtils.emptyMap()); + Map info = (Map) response.get(assetId); + assertNotNull(info); + assertEquals(info.get("bytes"), 3381); + resource = api.resource(API_TEST_RESTORE, ObjectUtils.emptyMap()); + assertEquals(resource.get("bytes"), 3381); + } + @Test public void testRestoreDifferentVersionsOfDeletedAsset() throws Exception { final String TEST_RESOURCE_PUBLIC_ID = "api_test_restore_different_versions_single_asset" + SUFFIX; diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java index 60467685..b1137fb4 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractStructuredMetadataTest.java @@ -75,7 +75,7 @@ public void testCreateMetadata() throws Exception { @Test public void testCreateSetMetadataWithAllowDynamicListValues() throws Exception { - SetMetadataField setField = createSetField("testCreateMetadata_2"); + SetMetadataField setField = createSetField("testCreateMetadata_4"); ApiResponse result = cloudinary.api().addMetadataField(setField); assertNotNull(result); assertEquals(setField.getLabel(), result.get("label")); From c646ad486e1beb156e94da729da9da3550bbe891 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Thu, 30 Jan 2025 14:36:53 +0200 Subject: [PATCH 37/40] Fix Uploader strategy --- .../cloudinary/http5/UploaderStrategy.java | 37 ++++++++++++++++++- .../java/com/cloudinary/test/ApiTest.java | 27 +++++++++++++- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/cloudinary-http5/src/main/java/com/cloudinary/http5/UploaderStrategy.java b/cloudinary-http5/src/main/java/com/cloudinary/http5/UploaderStrategy.java index 5f87cbd8..589dff5b 100644 --- a/cloudinary-http5/src/main/java/com/cloudinary/http5/UploaderStrategy.java +++ b/cloudinary-http5/src/main/java/com/cloudinary/http5/UploaderStrategy.java @@ -8,16 +8,21 @@ import com.cloudinary.utils.StringUtils; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.entity.mime.ByteArrayBody; import org.apache.hc.client5.http.entity.mime.FileBody; import org.apache.hc.client5.http.entity.mime.HttpMultipartMode; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.io.HttpClientConnectionManager; import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.ParseException; import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.util.Timeout; import java.io.File; import java.io.IOException; @@ -35,11 +40,39 @@ public class UploaderStrategy extends AbstractUploaderStrategy { public void init(Uploader uploader) { super.init(uploader); - this.client = HttpClients.custom() - .setUserAgent(cloudinary().getUserAgent() + " ApacheHttpClient/" + APACHE_HTTP_CLIENT_VERSION) + HttpClientBuilder clientBuilder = HttpClients.custom(); + clientBuilder.useSystemProperties().setUserAgent(cloudinary().getUserAgent() + " ApacheHttpClient/" + APACHE_HTTP_CLIENT_VERSION); + + HttpClientConnectionManager connectionManager = (HttpClientConnectionManager) cloudinary().config.properties.get("connectionManager"); + if (connectionManager != null) { + clientBuilder.setConnectionManager(connectionManager); + } + + RequestConfig requestConfig = buildRequestConfig(); + + client = clientBuilder + .setDefaultRequestConfig(requestConfig) .build(); } + public RequestConfig buildRequestConfig() { + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); + + if (cloudinary().config.proxyHost != null && cloudinary().config.proxyPort != 0) { + HttpHost proxy = new HttpHost(cloudinary().config.proxyHost, cloudinary().config.proxyPort); + requestConfigBuilder.setProxy(proxy); + } + + int timeout = cloudinary().config.timeout; + if (timeout > 0) { + requestConfigBuilder.setResponseTimeout(Timeout.ofSeconds(timeout)) + .setConnectionRequestTimeout(Timeout.ofSeconds(timeout)) + .setConnectTimeout(Timeout.ofSeconds(timeout)); + } + + return requestConfigBuilder.build(); + } + @SuppressWarnings({"rawtypes", "unchecked"}) @Override public Map callApi(String action, Map params, Map options, Object file, ProgressCallback progressCallback) throws IOException { diff --git a/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java b/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java index 4735d89f..53da8866 100644 --- a/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java +++ b/cloudinary-http5/src/test/java/com/cloudinary/test/ApiTest.java @@ -11,6 +11,9 @@ import org.junit.experimental.categories.Category; import java.util.Map; +import java.util.UUID; + +import static com.cloudinary.utils.ObjectUtils.asMap; public class ApiTest extends AbstractApiTest { @@ -48,7 +51,7 @@ public void testBuildRequestConfig_withoutProxy() { @Category(TimeoutTest.class) @Test(expected = Exception.class) public void testConnectTimeoutParameter() throws Exception { - Map options = ObjectUtils.asMap( + Map options = asMap( "max_results", 500, "connect_timeout", 0.2); @@ -65,7 +68,7 @@ public void testConnectTimeoutParameter() throws Exception { @Test(expected = Exception.class) public void testTimeoutParameter() throws Exception { // Set a very short request timeout to trigger a timeout exception - Map options = ObjectUtils.asMap( + Map options = asMap( "max_results", 500, "timeout", Timeout.ofMilliseconds(1000)); // Set the timeout to 1 second @@ -76,4 +79,24 @@ public void testTimeoutParameter() throws Exception { throw new Exception("Socket timeout"); } } + + @Category(TimeoutTest.class) + @Test(expected = Exception.class) + public void testUploaderTimeoutParameter() throws Exception { + Cloudinary cloudinary = new Cloudinary("cloudinary://test:test@test.com"); + cloudinary.config.uploadPrefix = "https://10.255.255.1"; + String publicId = UUID.randomUUID().toString(); + // Set a very short request timeout to trigger a timeout exception + Map options = asMap( + "max_results", 500, + "timeout", Timeout.ofMilliseconds(10)); // Set the timeout to 1 second + + try { + Map result = cloudinary.uploader().addContext(asMap("caption", "new caption"), new String[]{publicId, "no-such-id"}, options); + } catch (Exception e) { + // Convert IOException to SocketTimeoutException if appropriate + throw new Exception("Socket timeout"); + } + } + } \ No newline at end of file From a9e77cd2ee94b4ec8562f8c5a731accad64c0134 Mon Sep 17 00:00:00 2001 From: Adi Mizrahi Date: Sun, 2 Feb 2025 14:15:48 +0200 Subject: [PATCH 38/40] Version 2.2.0 --- CHANGELOG.md | 8 ++++++++ README.md | 2 +- .../src/main/java/com/cloudinary/Cloudinary.java | 2 +- gradle.properties | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffe151ac..ba03059e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +2.2.0 / 2025-02-02 +================== + +* Fix Uploader strategy +* Add restore assets by asset ids +* Add allow dynamic list parameter +* Add delete resources by asset ids + 2.1.0 / 2025-01-20 ================== diff --git a/README.md b/README.md index 74e77daa..f5659de0 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ The cloudinary_java library is available in [Maven Central](https://mvnrepositor com.cloudinary cloudinary-http45 - 2.1.0 + 2.2.0 ``` diff --git a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java index aa156ec2..19c0c3b8 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Cloudinary.java @@ -32,7 +32,7 @@ public class Cloudinary { public final static String AKAMAI_SHARED_CDN = "res.cloudinary.com"; public final static String SHARED_CDN = AKAMAI_SHARED_CDN; - public final static String VERSION = "2.1.0"; + public final static String VERSION = "2.2.0"; static String USER_AGENT_PREFIX = "CloudinaryJava"; public final static String USER_AGENT_JAVA_VERSION = "(Java " + System.getProperty("java.version") + ")"; diff --git a/gradle.properties b/gradle.properties index 6ce82a60..aaea4f1d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ developerEmail=info@cloudinary.com # These two properties must use these exact names to be compatible with 'gradle install' plugin. group=com.cloudinary -version=2.1.0 +version=2.2.0 gnsp.disableApplyOnlyOnRootProjectEnforcement=true From 45a218aeafd01b273d183b21264be7d8f69d1576 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:39:28 +0200 Subject: [PATCH 39/40] Add skip backup parameter to delete folder api --- .../src/main/java/com/cloudinary/Api.java | 4 +++- .../com/cloudinary/test/AbstractFoldersApiTest.java | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index 0cbab208..4a01933f 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -660,8 +660,10 @@ public ApiResponse updateResourcesAccessModeByTag(String accessMode, String tag, * @throws Exception When the folder isn't empty or doesn't exist. */ public ApiResponse deleteFolder(String folder, Map options) throws Exception { + if (options == null || options.isEmpty()) options = ObjectUtils.asMap(); List uri = Arrays.asList("folders", folder); - return callApi(HttpMethod.DELETE, uri, Collections.emptyMap(), options); + Map params = ObjectUtils.only(options, "skip_backup"); + return callApi(HttpMethod.DELETE, uri, params, options); } /** diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractFoldersApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractFoldersApiTest.java index a0478bad..a8835046 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractFoldersApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractFoldersApiTest.java @@ -85,4 +85,17 @@ public void testSubFolderWithParams() throws Exception { ApiResponse result = api.deleteFolder(rootFolderName, null); assertTrue(((List) result.get("deleted")).contains(rootFolderName)); } + + @Test + public void testDeleteFolderWithSkipBackup() throws Exception { + //Create + String rootFolderName = "deleteFolderWithSkipBackup" + SUFFIX; + assertTrue((Boolean) api.createFolder(rootFolderName, null).get("success")); + + //Delete + ApiResponse result = api.deleteFolder(rootFolderName, ObjectUtils.asMap("skip_backup", "true")); + assertTrue(((List) result.get("deleted")).contains(rootFolderName)); + + + } } From bae86bc9717c8ef8f09d28c58de8966c72232540 Mon Sep 17 00:00:00 2001 From: adimiz1 <95848801+adimiz1@users.noreply.github.com> Date: Wed, 5 Feb 2025 13:00:49 +0200 Subject: [PATCH 40/40] Fix build single resource params --- .../src/main/java/com/cloudinary/Api.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index 4a01933f..c84be0d6 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -162,7 +162,7 @@ public ApiResponse resourceByAssetID(String assetId, Map options) throws Excepti if(options.get("fields") != null) { options.put("fields", StringUtils.join(ObjectUtils.asArray(options.get("fields")), ",")); } - Map params = ObjectUtils.only(options, "tags", "context", "moderations", "fields"); + Map params = buildResourceDetailParams(options); ApiResponse response = callApi(HttpMethod.GET, Arrays.asList("resources", assetId), params, options); return response; } @@ -209,15 +209,19 @@ public ApiResponse resource(String public_id, Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); String resourceType = ObjectUtils.asString(options.get("resource_type"), "image"); String type = ObjectUtils.asString(options.get("type"), "upload"); + Map params = buildResourceDetailParams(options); - ApiResponse response = callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, type, public_id), - ObjectUtils.only(options, "exif", "colors", "faces", "coordinates", - "image_metadata", "pages", "phash", "max_results", "quality_analysis", "cinemagraph_analysis", - "accessibility_analysis", "versions", "media_metadata", "derived_next_cursor"), options); + ApiResponse response = callApi(HttpMethod.GET, Arrays.asList("resources", resourceType, type, public_id), params, options); return response; } + private Map buildResourceDetailParams(Map options) { + return ObjectUtils.only(options, "exif", "colors", "faces", "coordinates", + "image_metadata", "pages", "phash", "max_results", "quality_analysis", "cinemagraph_analysis", + "accessibility_analysis", "versions", "media_metadata", "derived_next_cursor"); + } + public ApiResponse update(String public_id, Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); String resourceType = ObjectUtils.asString(options.get("resource_type"), "image");