Skip to content

Commit

Permalink
Merge branch 'release/1.3.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
infeo committed Feb 23, 2024
2 parents b58ecc6 + 2b905cd commit 7b4d701
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 32 deletions.
38 changes: 38 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
version: 2
updates:
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "monthly"
day: "monday"
time: "06:00"
timezone: "Etc/UTC"
groups:
java-test-dependencies:
patterns:
- "org.junit.jupiter:*"
- "org.mockito:*"
maven-build-plugins:
patterns:
- "org.apache.maven.plugins:*"
- "org.sonatype.plugins:nexus-staging-maven-plugin"
java-production-dependencies:
patterns:
- "*"
exclude-patterns:
- "org.apache.maven.plugins:*"
- "org.sonatype.plugins:nexus-staging-maven-plugin"
- "org.junit.jupiter:*"
- "org.mockito:*"


- package-ecosystem: "github-actions"
directory: "/" # even for `.github/workflows`
schedule:
interval: "monthly"
groups:
github-actions:
patterns:
- "*"
labels:
- "ci"
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ jobs:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
Expand All @@ -19,7 +19,7 @@ jobs:
- name: Build and Test
id: buildAndTest
run: mvn -B clean install
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: artifacts
path: target/*.jar
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ jobs:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: actions/setup-java@v3
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
cache: 'maven'
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: java
- name: Build
run: mvn -B compile
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
4 changes: 2 additions & 2 deletions .github/workflows/publish-central.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: "refs/tags/${{ github.event.inputs.tag }}"
- uses: actions/setup-java@v3
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish-github.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ jobs:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') # only allow publishing tagged versions
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
Expand Down
24 changes: 12 additions & 12 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>integrations-api</artifactId>
<version>1.3.0</version>
<version>1.3.1</version>

<name>Cryptomator Integrations API</name>
<description>Defines optional service interfaces that may be used by Cryptomator</description>
Expand Down Expand Up @@ -41,31 +41,31 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
<version>2.0.12</version>
</dependency>

<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>23.0.0</version>
<version>24.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.36</version>
<version>2.0.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.0</version>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.8.0</version>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand All @@ -75,14 +75,14 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<version>3.12.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
Expand All @@ -95,11 +95,11 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M7</version>
<version>3.2.5</version>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<version>3.6.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
Expand Down Expand Up @@ -148,7 +148,7 @@
<plugins>
<plugin>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.0.1</version>
<version>3.1.0</version>
<executions>
<execution>
<id>sign-artifacts</id>
Expand Down Expand Up @@ -183,7 +183,7 @@
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<version>1.6.13</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.Optional;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.stream.Stream;

Expand All @@ -21,38 +22,38 @@ private IntegrationsLoader() {
}

/**
* Loads the best suited service, i.e. the one with the highest priority that is supported.
* Loads the best suited service provider, i.e. the one with the highest priority that is supported.
* <p>
* If two services are available with the same priority, it is unspecified which one will be returned.
*
* @param clazz Service class
* @param <T> Type of the service
* @return Highest priority service or empty if no supported service was found
* @return Highest priority service provider or empty if no supported service provider was found
*/
public static <T> Optional<T> load(Class<T> clazz) {
return loadAll(clazz).findFirst();
}

/**
* Loads all suited services ordered by priority in descending order.
* Loads all suited service providers ordered by priority in descending order.
*
* @param clazz Service class
* @param <T> Type of the service
* @return An ordered stream of all suited service candidates
* @return An ordered stream of all suited service providers
*/
public static <T> Stream<T> loadAll(Class<T> clazz) {
return ServiceLoader.load(clazz, ClassLoaderFactory.forPluginDir())
.stream()
.peek(service -> logFoundService(clazz, service.type()))
.peek(serviceProvider -> logFoundServiceProvider(clazz, serviceProvider.type()))
.filter(IntegrationsLoader::isSupportedOperatingSystem)
.filter(IntegrationsLoader::passesStaticAvailabilityCheck)
.sorted(Comparator.comparingInt(IntegrationsLoader::getPriority).reversed())
.map(ServiceLoader.Provider::get)
.flatMap(IntegrationsLoader::instantiateServiceProvider)
.filter(IntegrationsLoader::passesInstanceAvailabilityCheck)
.peek(impl -> logServiceIsAvailable(clazz, impl.getClass()));
}

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

private static <T> Stream<T> instantiateServiceProvider(ServiceLoader.Provider<T> provider) {
try {
return Stream.of(provider.get());
} catch (ServiceConfigurationError err) {
//ServiceLoader.Provider::get throws this error if (from javadoc)
// * the public static "provider()" method of a provider factory returns null
// * the service provider cannot be instantiated due to an error/throw
LOG.warn("Unable to load service provider {}.", provider.type().getName(), err);
return Stream.empty();
}
}

private static boolean passesStaticAvailabilityCheck(ServiceLoader.Provider<?> provider) {
return passesStaticAvailabilityCheck(provider.type());
}

@VisibleForTesting
static boolean passesStaticAvailabilityCheck(Class<?> type) {
return passesAvailabilityCheck(type, null);
return silentlyPassesAvailabilityCheck(type, null);
}

@VisibleForTesting
static boolean passesInstanceAvailabilityCheck(Object instance) {
return passesAvailabilityCheck(instance.getClass(), instance);
return silentlyPassesAvailabilityCheck(instance.getClass(), instance);
}

private static void logServiceIsAvailable(Class<?> apiType, Class<?> implType) {
Expand All @@ -88,6 +101,15 @@ private static void logServiceIsAvailable(Class<?> apiType, Class<?> implType) {
}
}

private static <T> boolean silentlyPassesAvailabilityCheck(Class<? extends T> type, @Nullable T instance) {
try {
return passesAvailabilityCheck(type, instance);
} catch (ExceptionInInitializerError | NoClassDefFoundError | RuntimeException e) {
LOG.warn("Unable to load service provider {}.", type.getName(), e);
return false;
}
}

private static <T> boolean passesAvailabilityCheck(Class<? extends T> type, @Nullable T instance) {
if (!type.isAnnotationPresent(CheckAvailability.class)) {
return true; // if type is not annotated, skip tests
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.cryptomator.integrations.common;

@CheckAvailability
public class InitExceptionTestClass {

private static final String TEST;

static {
TEST = throwSomething();
}

public InitExceptionTestClass() {

}

static String throwSomething() {
throw new RuntimeException("STATIC FAIL");
}

@CheckAvailability
public static boolean test() {
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ class C2 extends StaticFalse {
Assertions.assertFalse(IntegrationsLoader.passesStaticAvailabilityCheck(C3.class));
}

@Test
@DisplayName("throwing @CheckAvailability methods are treated as false")
public void testPassesAvailabilityCheckThrowing() {

@CheckAvailability class C1 {
@CheckAvailability public static boolean test() { throw new RuntimeException("FAIL"); }
}

Assertions.assertFalse(IntegrationsLoader.passesStaticAvailabilityCheck(C1.class));
Assertions.assertFalse(IntegrationsLoader.passesStaticAvailabilityCheck(InitExceptionTestClass.class));
Assertions.assertFalse(IntegrationsLoader.passesStaticAvailabilityCheck(InitExceptionTestClass.class)); //NoClassDefFoundError due to repated call
}

}

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


@Test
@DisplayName("throwing @CheckAvailability methods are treated as false")
public void testPassesAvailabilityCheckThrowing() {

@CheckAvailability
class C1 {
@CheckAvailability public boolean test1() { throw new RuntimeException("FAIL"); }
}

@CheckAvailability
class C2 {
@CheckAvailability public boolean test1() { return true; }
@CheckAvailability public boolean test2() { throw new RuntimeException("FAIL"); }
}

Assertions.assertFalse(IntegrationsLoader.passesInstanceAvailabilityCheck(new C1()));
Assertions.assertFalse(IntegrationsLoader.passesInstanceAvailabilityCheck(new C2()));
}

}

}

0 comments on commit 7b4d701

Please sign in to comment.