Skip to content

Commit 0f9c99a

Browse files
Merge branch 'develop' into release/1.1.0
2 parents 6fd93ef + 70fb01c commit 0f9c99a

18 files changed

+304
-38
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,11 @@ jobs:
88
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
99
steps:
1010
- uses: actions/checkout@v2
11-
- uses: actions/setup-java@v1
11+
- uses: actions/setup-java@v2
1212
with:
13-
java-version: 11
14-
- uses: actions/cache@v2
15-
with:
16-
path: ~/.m2/repository
17-
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
18-
restore-keys: |
19-
${{ runner.os }}-maven-
13+
distribution: 'temurin'
14+
java-version: 17
15+
cache: 'maven'
2016
- name: Ensure to use tagged version
2117
if: startsWith(github.ref, 'refs/tags/')
2218
run: mvn versions:set --file ./pom.xml -DnewVersion=${GITHUB_REF##*/}

.github/workflows/codeql-analysis.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,11 @@ jobs:
1818
- uses: actions/checkout@v2
1919
with:
2020
fetch-depth: 2
21-
- uses: actions/setup-java@v1
21+
- uses: actions/setup-java@v2
2222
with:
23-
java-version: 11
24-
- uses: actions/cache@v2
25-
with:
26-
path: ~/.m2/repository
27-
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
28-
restore-keys: |
29-
${{ runner.os }}-maven-
23+
distribution: 'temurin'
24+
java-version: 17
25+
cache: 'maven'
3026
- name: Initialize CodeQL
3127
uses: github/codeql-action/init@v1
3228
with:

.github/workflows/publish-central.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,16 @@ jobs:
1313
- uses: actions/checkout@v2
1414
with:
1515
ref: "refs/tags/${{ github.event.inputs.tag }}"
16-
- uses: actions/setup-java@v1
16+
- uses: actions/setup-java@v2
1717
with:
18-
java-version: 11
18+
distribution: 'temurin'
19+
java-version: 17
20+
cache: 'maven'
1921
server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
2022
server-username: MAVEN_USERNAME # env variable for username in deploy
2123
server-password: MAVEN_PASSWORD # env variable for token in deploy
2224
gpg-private-key: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
2325
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
24-
- uses: actions/cache@v2
25-
with:
26-
path: ~/.m2/repository
27-
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
28-
restore-keys: |
29-
${{ runner.os }}-maven-
3026
- name: Enforce project version ${{ github.event.inputs.tag }}
3127
run: mvn versions:set -B -DnewVersion=${{ github.event.inputs.tag }}
3228
- name: Deploy

.github/workflows/publish-github.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,13 @@ jobs:
88
if: startsWith(github.ref, 'refs/tags/') # only allow publishing tagged versions
99
steps:
1010
- uses: actions/checkout@v2
11-
- uses: actions/setup-java@v1
11+
- uses: actions/setup-java@v2
1212
with:
13-
java-version: 11
13+
distribution: 'temurin'
14+
java-version: 17
15+
cache: 'maven'
1416
gpg-private-key: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
1517
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
16-
- uses: actions/cache@v2
17-
with:
18-
path: ~/.m2/repository
19-
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
20-
restore-keys: |
21-
${{ runner.os }}-maven-
2218
- name: Enforce project version ${{ github.event.release.tag_name }}
2319
run: mvn versions:set -B -DnewVersion=${{ github.event.release.tag_name }}
2420
- name: Deploy

pom.xml

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,23 @@
3737
</license>
3838
</licenses>
3939

40+
<dependencies>
41+
<dependency>
42+
<groupId>org.jetbrains</groupId>
43+
<artifactId>annotations</artifactId>
44+
<version>23.0.0</version>
45+
<scope>provided</scope>
46+
</dependency>
47+
</dependencies>
48+
4049
<build>
4150
<plugins>
4251
<plugin>
4352
<groupId>org.apache.maven.plugins</groupId>
4453
<artifactId>maven-compiler-plugin</artifactId>
45-
<version>3.8.1</version>
54+
<version>3.9.0</version>
4655
<configuration>
47-
<release>11</release>
56+
<release>17</release>
4857
</configuration>
4958
</plugin>
5059
<plugin>
@@ -72,7 +81,7 @@
7281
</executions>
7382
<configuration>
7483
<quiet>true</quiet>
75-
<release>11</release>
84+
<release>17</release>
7685
<tags>
7786
<!-- workaround for "unknown tag: implNote", see https://blog.codefx.org/java/new-javadoc-tags/#Maven -->
7887
<tag>
@@ -110,7 +119,7 @@
110119
<plugins>
111120
<plugin>
112121
<artifactId>maven-gpg-plugin</artifactId>
113-
<version>1.6</version>
122+
<version>3.0.1</version>
114123
<executions>
115124
<execution>
116125
<id>sign-artifacts</id>
@@ -137,7 +146,7 @@
137146
<repository>
138147
<id>ossrh</id>
139148
<name>Maven Central</name>
140-
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
149+
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
141150
</repository>
142151
</distributionManagement>
143152
<build>
@@ -149,7 +158,7 @@
149158
<extensions>true</extensions>
150159
<configuration>
151160
<serverId>ossrh</serverId>
152-
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
161+
<nexusUrl>https://s01.oss.sonatype.org/</nexusUrl>
153162
<autoReleaseAfterClose>true</autoReleaseAfterClose>
154163
</configuration>
155164
</plugin>

src/main/java/module-info.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
1+
import org.cryptomator.integrations.tray.TrayMenuController;
2+
import org.cryptomator.integrations.autostart.AutoStartProvider;
3+
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
4+
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
5+
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
6+
7+
18
module org.cryptomator.integrations.api {
9+
requires static org.jetbrains.annotations;
10+
211
exports org.cryptomator.integrations.autostart;
312
exports org.cryptomator.integrations.keychain;
413
exports org.cryptomator.integrations.tray;
514
exports org.cryptomator.integrations.uiappearance;
15+
16+
uses AutoStartProvider;
17+
uses KeychainAccessProvider;
18+
uses TrayIntegrationProvider;
19+
uses TrayMenuController;
20+
uses UiAppearanceProvider;
621
}

src/main/java/org/cryptomator/integrations/autostart/AutoStartProvider.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,26 @@
11
package org.cryptomator.integrations.autostart;
22

3+
import org.cryptomator.integrations.common.IntegrationsLoader;
4+
import org.jetbrains.annotations.Blocking;
5+
6+
import java.util.Optional;
7+
38
public interface AutoStartProvider {
49

10+
/**
11+
* Loads the best-suited AutoStartProvider.
12+
*
13+
* @return preferred AutoStartProvider (if any)
14+
* @since 1.1.0
15+
*/
16+
static Optional<AutoStartProvider> get() {
17+
return IntegrationsLoader.load(AutoStartProvider.class);
18+
}
19+
20+
@Blocking
521
void enable() throws ToggleAutoStartFailedException;
622

23+
@Blocking
724
void disable() throws ToggleAutoStartFailedException;
825

926
boolean isEnabled();
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.cryptomator.integrations.common;
2+
3+
import java.util.Arrays;
4+
import java.util.Comparator;
5+
import java.util.Optional;
6+
import java.util.ServiceLoader;
7+
import java.util.stream.Stream;
8+
9+
public class IntegrationsLoader {
10+
11+
/**
12+
* Loads the best suited service, i.e. the one with the highest priority that is supported.
13+
* <p>
14+
* If two services are available with the same priority, it is unspecified which one will be returned.
15+
*
16+
* @param clazz Service class
17+
* @param <T> Type of the service
18+
* @return Highest priority service or empty if no supported service was found
19+
*/
20+
public static <T> Optional<T> load(Class<T> clazz) {
21+
return loadAll(clazz).findFirst();
22+
}
23+
24+
/**
25+
* Loads all suited services ordered by priority in descending order.
26+
*
27+
* @param clazz Service class
28+
* @param <T> Type of the service
29+
* @return An ordered stream of all suited service candidates
30+
*/
31+
public static <T> Stream<T> loadAll(Class<T> clazz) {
32+
return ServiceLoader.load(clazz)
33+
.stream()
34+
.filter(IntegrationsLoader::isSupportedOperatingSystem)
35+
.sorted(Comparator.comparingInt(IntegrationsLoader::getPriority).reversed())
36+
.map(ServiceLoader.Provider::get);
37+
}
38+
39+
private static int getPriority(ServiceLoader.Provider<?> provider) {
40+
var prio = provider.type().getAnnotation(Priority.class);
41+
return prio == null ? Priority.DEFAULT : prio.value();
42+
}
43+
44+
private static boolean isSupportedOperatingSystem(ServiceLoader.Provider<?> provider) {
45+
var annotations = provider.type().getAnnotationsByType(OperatingSystem.class);
46+
return annotations.length == 0 || Arrays.stream(annotations).anyMatch(OperatingSystem.Value::isCurrent);
47+
}
48+
49+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.cryptomator.integrations.common;
2+
3+
import java.lang.annotation.Documented;
4+
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Repeatable;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
/**
11+
* Restricts the annotated integration provider to one or more operating system(s).
12+
*
13+
* @since 1.1.0
14+
*/
15+
@Documented
16+
@Retention(RetentionPolicy.RUNTIME)
17+
@Target({ElementType.TYPE})
18+
@Repeatable(OperatingSystem.OperatingSystems.class)
19+
public @interface OperatingSystem {
20+
Value value() default Value.UNKNOWN;
21+
22+
@Documented
23+
@Retention(RetentionPolicy.RUNTIME)
24+
@Target({ElementType.TYPE})
25+
@interface OperatingSystems {
26+
OperatingSystem[] value();
27+
}
28+
29+
enum Value {
30+
LINUX,
31+
MAC,
32+
WINDOWS,
33+
UNKNOWN;
34+
35+
private static final String OS_NAME = System.getProperty("os.name", "").toLowerCase();
36+
37+
public static Value current() {
38+
if (OS_NAME.contains("linux")) {
39+
return LINUX;
40+
} else if (OS_NAME.contains("mac")) {
41+
return MAC;
42+
} else if (OS_NAME.contains("windows")) {
43+
return WINDOWS;
44+
} else {
45+
return UNKNOWN;
46+
}
47+
}
48+
49+
public static boolean isCurrent(OperatingSystem os) {
50+
return current().equals(os.value());
51+
}
52+
}
53+
}
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+
import java.lang.annotation.Documented;
4+
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Repeatable;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
/**
11+
* Integration Priority.
12+
* <p>
13+
* If multiple implementations for an integration can be provided, the provider with the highest priority will be used.
14+
*
15+
* @since 1.1.0
16+
*/
17+
@Documented
18+
@Retention(RetentionPolicy.RUNTIME)
19+
@Target({ElementType.TYPE})
20+
public @interface Priority {
21+
int DEFAULT = 0;
22+
int FALLBACK = Integer.MIN_VALUE;
23+
24+
int value() default DEFAULT;
25+
}

0 commit comments

Comments
 (0)