Skip to content

Commit 7b4d701

Browse files
committed
Merge branch 'release/1.3.1'
2 parents b58ecc6 + 2b905cd commit 7b4d701

File tree

9 files changed

+149
-32
lines changed

9 files changed

+149
-32
lines changed

.github/dependabot.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "maven"
4+
directory: "/"
5+
schedule:
6+
interval: "monthly"
7+
day: "monday"
8+
time: "06:00"
9+
timezone: "Etc/UTC"
10+
groups:
11+
java-test-dependencies:
12+
patterns:
13+
- "org.junit.jupiter:*"
14+
- "org.mockito:*"
15+
maven-build-plugins:
16+
patterns:
17+
- "org.apache.maven.plugins:*"
18+
- "org.sonatype.plugins:nexus-staging-maven-plugin"
19+
java-production-dependencies:
20+
patterns:
21+
- "*"
22+
exclude-patterns:
23+
- "org.apache.maven.plugins:*"
24+
- "org.sonatype.plugins:nexus-staging-maven-plugin"
25+
- "org.junit.jupiter:*"
26+
- "org.mockito:*"
27+
28+
29+
- package-ecosystem: "github-actions"
30+
directory: "/" # even for `.github/workflows`
31+
schedule:
32+
interval: "monthly"
33+
groups:
34+
github-actions:
35+
patterns:
36+
- "*"
37+
labels:
38+
- "ci"

.github/workflows/build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ jobs:
77
runs-on: ubuntu-latest
88
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
99
steps:
10-
- uses: actions/checkout@v3
11-
- uses: actions/setup-java@v3
10+
- uses: actions/checkout@v4
11+
- uses: actions/setup-java@v4
1212
with:
1313
distribution: 'temurin'
1414
java-version: 17
@@ -19,7 +19,7 @@ jobs:
1919
- name: Build and Test
2020
id: buildAndTest
2121
run: mvn -B clean install
22-
- uses: actions/upload-artifact@v3
22+
- uses: actions/upload-artifact@v4
2323
with:
2424
name: artifacts
2525
path: target/*.jar

.github/workflows/codeql-analysis.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@ jobs:
1515
runs-on: ubuntu-latest
1616
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
1717
steps:
18-
- uses: actions/checkout@v3
18+
- uses: actions/checkout@v4
1919
with:
2020
fetch-depth: 2
21-
- uses: actions/setup-java@v3
21+
- uses: actions/setup-java@v4
2222
with:
2323
distribution: 'temurin'
2424
java-version: 17
2525
cache: 'maven'
2626
- name: Initialize CodeQL
27-
uses: github/codeql-action/init@v2
27+
uses: github/codeql-action/init@v3
2828
with:
2929
languages: java
3030
- name: Build
3131
run: mvn -B compile
3232
- name: Perform CodeQL Analysis
33-
uses: github/codeql-action/analyze@v2
33+
uses: github/codeql-action/analyze@v3

.github/workflows/publish-central.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ jobs:
1010
publish:
1111
runs-on: ubuntu-latest
1212
steps:
13-
- uses: actions/checkout@v3
13+
- uses: actions/checkout@v4
1414
with:
1515
ref: "refs/tags/${{ github.event.inputs.tag }}"
16-
- uses: actions/setup-java@v3
16+
- uses: actions/setup-java@v4
1717
with:
1818
distribution: 'temurin'
1919
java-version: 17

.github/workflows/publish-github.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ jobs:
77
runs-on: ubuntu-latest
88
if: startsWith(github.ref, 'refs/tags/') # only allow publishing tagged versions
99
steps:
10-
- uses: actions/checkout@v3
11-
- uses: actions/setup-java@v3
10+
- uses: actions/checkout@v4
11+
- uses: actions/setup-java@v4
1212
with:
1313
distribution: 'temurin'
1414
java-version: 17

pom.xml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<modelVersion>4.0.0</modelVersion>
66
<groupId>org.cryptomator</groupId>
77
<artifactId>integrations-api</artifactId>
8-
<version>1.3.0</version>
8+
<version>1.3.1</version>
99

1010
<name>Cryptomator Integrations API</name>
1111
<description>Defines optional service interfaces that may be used by Cryptomator</description>
@@ -41,31 +41,31 @@
4141
<dependency>
4242
<groupId>org.slf4j</groupId>
4343
<artifactId>slf4j-api</artifactId>
44-
<version>1.7.36</version>
44+
<version>2.0.12</version>
4545
</dependency>
4646

4747
<dependency>
4848
<groupId>org.jetbrains</groupId>
4949
<artifactId>annotations</artifactId>
50-
<version>23.0.0</version>
50+
<version>24.1.0</version>
5151
<scope>provided</scope>
5252
</dependency>
5353
<dependency>
5454
<groupId>org.slf4j</groupId>
5555
<artifactId>slf4j-simple</artifactId>
56-
<version>1.7.36</version>
56+
<version>2.0.12</version>
5757
<scope>test</scope>
5858
</dependency>
5959
<dependency>
6060
<groupId>org.junit.jupiter</groupId>
6161
<artifactId>junit-jupiter</artifactId>
62-
<version>5.9.0</version>
62+
<version>5.10.2</version>
6363
<scope>test</scope>
6464
</dependency>
6565
<dependency>
6666
<groupId>org.mockito</groupId>
6767
<artifactId>mockito-core</artifactId>
68-
<version>4.8.0</version>
68+
<version>5.10.0</version>
6969
<scope>test</scope>
7070
</dependency>
7171
</dependencies>
@@ -75,14 +75,14 @@
7575
<plugin>
7676
<groupId>org.apache.maven.plugins</groupId>
7777
<artifactId>maven-compiler-plugin</artifactId>
78-
<version>3.9.0</version>
78+
<version>3.12.1</version>
7979
<configuration>
8080
<release>17</release>
8181
</configuration>
8282
</plugin>
8383
<plugin>
8484
<artifactId>maven-source-plugin</artifactId>
85-
<version>3.2.0</version>
85+
<version>3.3.0</version>
8686
<executions>
8787
<execution>
8888
<id>attach-sources</id>
@@ -95,11 +95,11 @@
9595
<plugin>
9696
<groupId>org.apache.maven.plugins</groupId>
9797
<artifactId>maven-surefire-plugin</artifactId>
98-
<version>3.0.0-M7</version>
98+
<version>3.2.5</version>
9999
</plugin>
100100
<plugin>
101101
<artifactId>maven-javadoc-plugin</artifactId>
102-
<version>3.2.0</version>
102+
<version>3.6.3</version>
103103
<executions>
104104
<execution>
105105
<id>attach-javadocs</id>
@@ -148,7 +148,7 @@
148148
<plugins>
149149
<plugin>
150150
<artifactId>maven-gpg-plugin</artifactId>
151-
<version>3.0.1</version>
151+
<version>3.1.0</version>
152152
<executions>
153153
<execution>
154154
<id>sign-artifacts</id>
@@ -183,7 +183,7 @@
183183
<plugin>
184184
<groupId>org.sonatype.plugins</groupId>
185185
<artifactId>nexus-staging-maven-plugin</artifactId>
186-
<version>1.6.8</version>
186+
<version>1.6.13</version>
187187
<extensions>true</extensions>
188188
<configuration>
189189
<serverId>ossrh</serverId>

src/main/java/org/cryptomator/integrations/common/IntegrationsLoader.java

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.Arrays;
1111
import java.util.Comparator;
1212
import java.util.Optional;
13+
import java.util.ServiceConfigurationError;
1314
import java.util.ServiceLoader;
1415
import java.util.stream.Stream;
1516

@@ -21,38 +22,38 @@ private IntegrationsLoader() {
2122
}
2223

2324
/**
24-
* Loads the best suited service, i.e. the one with the highest priority that is supported.
25+
* Loads the best suited service provider, i.e. the one with the highest priority that is supported.
2526
* <p>
2627
* If two services are available with the same priority, it is unspecified which one will be returned.
2728
*
2829
* @param clazz Service class
2930
* @param <T> Type of the service
30-
* @return Highest priority service or empty if no supported service was found
31+
* @return Highest priority service provider or empty if no supported service provider was found
3132
*/
3233
public static <T> Optional<T> load(Class<T> clazz) {
3334
return loadAll(clazz).findFirst();
3435
}
3536

3637
/**
37-
* Loads all suited services ordered by priority in descending order.
38+
* Loads all suited service providers ordered by priority in descending order.
3839
*
3940
* @param clazz Service class
4041
* @param <T> Type of the service
41-
* @return An ordered stream of all suited service candidates
42+
* @return An ordered stream of all suited service providers
4243
*/
4344
public static <T> Stream<T> loadAll(Class<T> clazz) {
4445
return ServiceLoader.load(clazz, ClassLoaderFactory.forPluginDir())
4546
.stream()
46-
.peek(service -> logFoundService(clazz, service.type()))
47+
.peek(serviceProvider -> logFoundServiceProvider(clazz, serviceProvider.type()))
4748
.filter(IntegrationsLoader::isSupportedOperatingSystem)
4849
.filter(IntegrationsLoader::passesStaticAvailabilityCheck)
4950
.sorted(Comparator.comparingInt(IntegrationsLoader::getPriority).reversed())
50-
.map(ServiceLoader.Provider::get)
51+
.flatMap(IntegrationsLoader::instantiateServiceProvider)
5152
.filter(IntegrationsLoader::passesInstanceAvailabilityCheck)
5253
.peek(impl -> logServiceIsAvailable(clazz, impl.getClass()));
5354
}
5455

55-
private static void logFoundService(Class<?> apiType, Class<?> implType) {
56+
private static void logFoundServiceProvider(Class<?> apiType, Class<?> implType) {
5657
if (LOG.isDebugEnabled()) {
5758
LOG.debug("{}: Found implementation: {} in jar {}", apiType.getSimpleName(), implType.getName(), implType.getProtectionDomain().getCodeSource().getLocation().getPath());
5859
}
@@ -68,18 +69,30 @@ private static boolean isSupportedOperatingSystem(ServiceLoader.Provider<?> prov
6869
return annotations.length == 0 || Arrays.stream(annotations).anyMatch(OperatingSystem.Value::isCurrent);
6970
}
7071

72+
private static <T> Stream<T> instantiateServiceProvider(ServiceLoader.Provider<T> provider) {
73+
try {
74+
return Stream.of(provider.get());
75+
} catch (ServiceConfigurationError err) {
76+
//ServiceLoader.Provider::get throws this error if (from javadoc)
77+
// * the public static "provider()" method of a provider factory returns null
78+
// * the service provider cannot be instantiated due to an error/throw
79+
LOG.warn("Unable to load service provider {}.", provider.type().getName(), err);
80+
return Stream.empty();
81+
}
82+
}
83+
7184
private static boolean passesStaticAvailabilityCheck(ServiceLoader.Provider<?> provider) {
7285
return passesStaticAvailabilityCheck(provider.type());
7386
}
7487

7588
@VisibleForTesting
7689
static boolean passesStaticAvailabilityCheck(Class<?> type) {
77-
return passesAvailabilityCheck(type, null);
90+
return silentlyPassesAvailabilityCheck(type, null);
7891
}
7992

8093
@VisibleForTesting
8194
static boolean passesInstanceAvailabilityCheck(Object instance) {
82-
return passesAvailabilityCheck(instance.getClass(), instance);
95+
return silentlyPassesAvailabilityCheck(instance.getClass(), instance);
8396
}
8497

8598
private static void logServiceIsAvailable(Class<?> apiType, Class<?> implType) {
@@ -88,6 +101,15 @@ private static void logServiceIsAvailable(Class<?> apiType, Class<?> implType) {
88101
}
89102
}
90103

104+
private static <T> boolean silentlyPassesAvailabilityCheck(Class<? extends T> type, @Nullable T instance) {
105+
try {
106+
return passesAvailabilityCheck(type, instance);
107+
} catch (ExceptionInInitializerError | NoClassDefFoundError | RuntimeException e) {
108+
LOG.warn("Unable to load service provider {}.", type.getName(), e);
109+
return false;
110+
}
111+
}
112+
91113
private static <T> boolean passesAvailabilityCheck(Class<? extends T> type, @Nullable T instance) {
92114
if (!type.isAnnotationPresent(CheckAvailability.class)) {
93115
return true; // if type is not annotated, skip tests
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.cryptomator.integrations.common;
2+
3+
@CheckAvailability
4+
public class InitExceptionTestClass {
5+
6+
private static final String TEST;
7+
8+
static {
9+
TEST = throwSomething();
10+
}
11+
12+
public InitExceptionTestClass() {
13+
14+
}
15+
16+
static String throwSomething() {
17+
throw new RuntimeException("STATIC FAIL");
18+
}
19+
20+
@CheckAvailability
21+
public static boolean test() {
22+
return true;
23+
}
24+
25+
}

src/test/java/org/cryptomator/integrations/common/IntegrationsLoaderTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@ class C2 extends StaticFalse {
9797
Assertions.assertFalse(IntegrationsLoader.passesStaticAvailabilityCheck(C3.class));
9898
}
9999

100+
@Test
101+
@DisplayName("throwing @CheckAvailability methods are treated as false")
102+
public void testPassesAvailabilityCheckThrowing() {
103+
104+
@CheckAvailability class C1 {
105+
@CheckAvailability public static boolean test() { throw new RuntimeException("FAIL"); }
106+
}
107+
108+
Assertions.assertFalse(IntegrationsLoader.passesStaticAvailabilityCheck(C1.class));
109+
Assertions.assertFalse(IntegrationsLoader.passesStaticAvailabilityCheck(InitExceptionTestClass.class));
110+
Assertions.assertFalse(IntegrationsLoader.passesStaticAvailabilityCheck(InitExceptionTestClass.class)); //NoClassDefFoundError due to repated call
111+
}
100112

101113
}
102114

@@ -190,6 +202,26 @@ class C2 extends InstanceFalse {
190202
Assertions.assertFalse(IntegrationsLoader.passesInstanceAvailabilityCheck(new C3()));
191203
}
192204

205+
206+
@Test
207+
@DisplayName("throwing @CheckAvailability methods are treated as false")
208+
public void testPassesAvailabilityCheckThrowing() {
209+
210+
@CheckAvailability
211+
class C1 {
212+
@CheckAvailability public boolean test1() { throw new RuntimeException("FAIL"); }
213+
}
214+
215+
@CheckAvailability
216+
class C2 {
217+
@CheckAvailability public boolean test1() { return true; }
218+
@CheckAvailability public boolean test2() { throw new RuntimeException("FAIL"); }
219+
}
220+
221+
Assertions.assertFalse(IntegrationsLoader.passesInstanceAvailabilityCheck(new C1()));
222+
Assertions.assertFalse(IntegrationsLoader.passesInstanceAvailabilityCheck(new C2()));
223+
}
224+
193225
}
194226

195227
}

0 commit comments

Comments
 (0)