From 4bfb945a08267d6b2038363ad6024690f9a91d9a Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 27 Jun 2024 12:21:09 +0200 Subject: [PATCH 1/7] Exclude dependabot "push" events from codeql Analysis --- .github/workflows/codeql-analysis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index debd498..efb0bc4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,7 +13,8 @@ jobs: analyse: name: Analyse runs-on: ubuntu-latest - if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + # dependeabot has on push events only read-only access, but codeql requires write access + if: ${{ !(github.actor == 'dependabot[bot]' && contains(fromJSON('["push"]'), github.event_name)) }} steps: - uses: actions/checkout@v4 with: @@ -30,4 +31,4 @@ jobs: - name: Build run: mvn -B compile - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 \ No newline at end of file + uses: github/codeql-action/analyze@v3 From aad9c043ec0bfe352263b044ca1f1b928621ff89 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 1 Jul 2024 11:21:14 +0200 Subject: [PATCH 2/7] add display method interface --- .../integrations/common/DisplayName.java | 21 ++++++++++++++++ .../common/NamedServiceProvider.java | 24 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/main/java/org/cryptomator/integrations/common/DisplayName.java create mode 100644 src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java diff --git a/src/main/java/org/cryptomator/integrations/common/DisplayName.java b/src/main/java/org/cryptomator/integrations/common/DisplayName.java new file mode 100644 index 0000000..f34321e --- /dev/null +++ b/src/main/java/org/cryptomator/integrations/common/DisplayName.java @@ -0,0 +1,21 @@ +package org.cryptomator.integrations.common; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.jetbrains.annotations.ApiStatus; + +/** + * A humanreadable name of the annotated class. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@ApiStatus.Experimental +public @interface DisplayName { + String value(); + +} diff --git a/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java b/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java new file mode 100644 index 0000000..1404c5b --- /dev/null +++ b/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java @@ -0,0 +1,24 @@ +package org.cryptomator.integrations.common; + +/** + * A service provider with a specific, human-readable name. + * + */ +public interface NamedServiceProvider { + + /** + * Get the name of this service provider. + * @implNote The default implementation looks for the {@link DisplayName} annotation and uses its value. If the annotation is not present, it falls back to the qualified class name. + * @return The name of the service provider + * + * @see DisplayName + */ + default public String getName() { + var displayName = this.getClass().getAnnotation(DisplayName.class); + if(displayName != null) { + return displayName.value(); + } else { + return this.getClass().getName(); + } + } +} From 750bb022e381619496cac402072f94a50dec9dfa Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 11 Jul 2024 16:09:37 +0200 Subject: [PATCH 3/7] refactor to make localization an own annotation --- .../integrations/common/DisplayName.java | 5 +-- .../common/LocalizedDisplayName.java | 34 ++++++++++++++ .../common/NamedServiceProvider.java | 44 +++++++++++-------- 3 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 src/main/java/org/cryptomator/integrations/common/LocalizedDisplayName.java diff --git a/src/main/java/org/cryptomator/integrations/common/DisplayName.java b/src/main/java/org/cryptomator/integrations/common/DisplayName.java index f34321e..61afd53 100644 --- a/src/main/java/org/cryptomator/integrations/common/DisplayName.java +++ b/src/main/java/org/cryptomator/integrations/common/DisplayName.java @@ -1,13 +1,13 @@ package org.cryptomator.integrations.common; +import org.jetbrains.annotations.ApiStatus; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.jetbrains.annotations.ApiStatus; - /** * A humanreadable name of the annotated class. */ @@ -17,5 +17,4 @@ @ApiStatus.Experimental public @interface DisplayName { String value(); - } diff --git a/src/main/java/org/cryptomator/integrations/common/LocalizedDisplayName.java b/src/main/java/org/cryptomator/integrations/common/LocalizedDisplayName.java new file mode 100644 index 0000000..ff8e325 --- /dev/null +++ b/src/main/java/org/cryptomator/integrations/common/LocalizedDisplayName.java @@ -0,0 +1,34 @@ +package org.cryptomator.integrations.common; + +import org.jetbrains.annotations.ApiStatus; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A humanreadable, localized name of the annotated class. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@ApiStatus.Experimental +public @interface LocalizedDisplayName { + + /** + * Name of the localization bundle, where the display name is loaded from. + * + * @return Name of the localization bundle + */ + String bundle(); + + /** + * The localization key containing the display name. + * + * @return Localization key to use + */ + String key(); + +} diff --git a/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java b/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java index 1404c5b..d9b47e2 100644 --- a/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java +++ b/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java @@ -1,24 +1,32 @@ package org.cryptomator.integrations.common; +import java.util.ResourceBundle; + /** - * A service provider with a specific, human-readable name. - * + * A service provider with a human-readable, possibly localized name. */ public interface NamedServiceProvider { - - /** - * Get the name of this service provider. - * @implNote The default implementation looks for the {@link DisplayName} annotation and uses its value. If the annotation is not present, it falls back to the qualified class name. - * @return The name of the service provider - * - * @see DisplayName - */ - default public String getName() { - var displayName = this.getClass().getAnnotation(DisplayName.class); - if(displayName != null) { - return displayName.value(); - } else { - return this.getClass().getName(); - } - } + + /** + * Get the name of this service provider. + * + * @return The name of the service provider + * @implNote The default implementation looks first for a {@link LocalizedDisplayName} and loads the name from the specified resource bundle/key. If the annotation is not present, the code looks for {@link DisplayName} and uses its value. If none of the former annotations are present, it falls back to the qualified class name. + * @see DisplayName + * @see LocalizedDisplayName + */ + default String getName() { + var localizedDisplayName = this.getClass().getAnnotation(LocalizedDisplayName.class); + if (localizedDisplayName != null) { + return ResourceBundle.getBundle(localizedDisplayName.bundle()) // + .getString(localizedDisplayName.key()); + } + + var displayName = this.getClass().getAnnotation(DisplayName.class); + if (displayName != null) { + return displayName.value(); + } else { + return this.getClass().getName(); + } + } } From de3997aa881e8bc85c1b9c3d0be6f68e7c1f3748 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 11 Jul 2024 16:43:02 +0200 Subject: [PATCH 4/7] doc doc doc --- .../org/cryptomator/integrations/common/DisplayName.java | 5 +++++ .../integrations/common/LocalizedDisplayName.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/org/cryptomator/integrations/common/DisplayName.java b/src/main/java/org/cryptomator/integrations/common/DisplayName.java index 61afd53..7389220 100644 --- a/src/main/java/org/cryptomator/integrations/common/DisplayName.java +++ b/src/main/java/org/cryptomator/integrations/common/DisplayName.java @@ -10,6 +10,11 @@ /** * A humanreadable name of the annotated class. + *

+ * Checked in the default implementation of the {@link NamedServiceProvider#getName()} with lower priority. + * + * @see NamedServiceProvider + * @see LocalizedDisplayName */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/src/main/java/org/cryptomator/integrations/common/LocalizedDisplayName.java b/src/main/java/org/cryptomator/integrations/common/LocalizedDisplayName.java index ff8e325..3a05603 100644 --- a/src/main/java/org/cryptomator/integrations/common/LocalizedDisplayName.java +++ b/src/main/java/org/cryptomator/integrations/common/LocalizedDisplayName.java @@ -10,6 +10,11 @@ /** * A humanreadable, localized name of the annotated class. + *

+ * Checked in the default implementation of the {@link NamedServiceProvider#getName()} with highest priority. + * + * @see NamedServiceProvider + * @see DisplayName */ @Documented @Retention(RetentionPolicy.RUNTIME) From def56feafa0c1e91eba0949a9eab71f479a37d16 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 11 Jul 2024 16:44:37 +0200 Subject: [PATCH 5/7] implement and document fallback strategy --- .../common/NamedServiceProvider.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java b/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java index d9b47e2..c9344a0 100644 --- a/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java +++ b/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java @@ -1,5 +1,8 @@ package org.cryptomator.integrations.common; +import org.slf4j.LoggerFactory; + +import java.util.MissingResourceException; import java.util.ResourceBundle; /** @@ -11,15 +14,22 @@ public interface NamedServiceProvider { * Get the name of this service provider. * * @return The name of the service provider - * @implNote The default implementation looks first for a {@link LocalizedDisplayName} and loads the name from the specified resource bundle/key. If the annotation is not present, the code looks for {@link DisplayName} and uses its value. If none of the former annotations are present, it falls back to the qualified class name. + * @implNote The default implementation looks first for a {@link LocalizedDisplayName} and loads the name from the specified resource bundle/key. If the annotation is not present or loading the resource throws an exception, the code looks for {@link DisplayName} and uses its value. If none of the former annotations are present, it falls back to the qualified class name. * @see DisplayName * @see LocalizedDisplayName */ default String getName() { var localizedDisplayName = this.getClass().getAnnotation(LocalizedDisplayName.class); if (localizedDisplayName != null) { - return ResourceBundle.getBundle(localizedDisplayName.bundle()) // - .getString(localizedDisplayName.key()); + try { + return ResourceBundle.getBundle(localizedDisplayName.bundle()) // + .getString(localizedDisplayName.key()); + } catch (MissingResourceException e) { + var clazz = this.getClass(); + var logger = LoggerFactory.getLogger(clazz); + logger.warn("Failed to load localized display name for {}. Falling back to not-localized display name/class name.", clazz.getName()); + logger.debug("Reason for failure of {}.", clazz.getName(), e); + } } var displayName = this.getClass().getAnnotation(DisplayName.class); From 9508ee5ea4d344a3c538a51621a53044c47f199b Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 11 Jul 2024 17:17:10 +0200 Subject: [PATCH 6/7] one line logging --- .../cryptomator/integrations/common/NamedServiceProvider.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java b/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java index c9344a0..692192b 100644 --- a/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java +++ b/src/main/java/org/cryptomator/integrations/common/NamedServiceProvider.java @@ -27,8 +27,7 @@ default String getName() { } catch (MissingResourceException e) { var clazz = this.getClass(); var logger = LoggerFactory.getLogger(clazz); - logger.warn("Failed to load localized display name for {}. Falling back to not-localized display name/class name.", clazz.getName()); - logger.debug("Reason for failure of {}.", clazz.getName(), e); + logger.warn("Failed to load localized display name for {}. Falling back to not-localized display name/class name.", clazz.getName(), e); } } From d1c262304121d25dec1bd8aac3d23c3d54ae993d Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 12 Jul 2024 13:09:39 +0200 Subject: [PATCH 7/7] make quickAccessService a named SPI --- .../integrations/quickaccess/QuickAccessService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cryptomator/integrations/quickaccess/QuickAccessService.java b/src/main/java/org/cryptomator/integrations/quickaccess/QuickAccessService.java index cc6b1f3..bf084b2 100644 --- a/src/main/java/org/cryptomator/integrations/quickaccess/QuickAccessService.java +++ b/src/main/java/org/cryptomator/integrations/quickaccess/QuickAccessService.java @@ -1,6 +1,7 @@ package org.cryptomator.integrations.quickaccess; import org.cryptomator.integrations.common.IntegrationsLoader; +import org.cryptomator.integrations.common.NamedServiceProvider; import org.jetbrains.annotations.Blocking; import org.jetbrains.annotations.NotNull; @@ -13,7 +14,7 @@ * @apiNote On purpose this service does not define, what an "link to a quick access area" is. The defintion depends on the OS. For example, the quick access area can be the home screen/desktop and the link would be an icon leading to the linked path. */ @FunctionalInterface -public interface QuickAccessService { +public interface QuickAccessService extends NamedServiceProvider { /** * Creates an entry in the quick access area.