Skip to content

Commit 80913cb

Browse files
committed
Merge branch 'release/1.4.0'
2 parents 7b4d701 + e27d7bb commit 80913cb

File tree

10 files changed

+213
-17
lines changed

10 files changed

+213
-17
lines changed

.github/workflows/build.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
name: Build
22
on:
3-
[push]
3+
push:
4+
pull_request_target:
5+
types: [labeled]
46
jobs:
57
build:
68
name: Build and Test
@@ -24,9 +26,9 @@ jobs:
2426
name: artifacts
2527
path: target/*.jar
2628
- name: Create Release
27-
uses: softprops/action-gh-release@v1
29+
uses: softprops/action-gh-release@v2
2830
if: startsWith(github.ref, 'refs/tags/')
2931
with:
3032
prerelease: true
3133
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
32-
generate_release_notes: true
34+
generate_release_notes: true

.github/workflows/codeql-analysis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ jobs:
1313
analyse:
1414
name: Analyse
1515
runs-on: ubuntu-latest
16-
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
16+
# dependeabot has on push events only read-only access, but codeql requires write access
17+
if: ${{ !(github.actor == 'dependabot[bot]' && contains(fromJSON('["push"]'), github.event_name)) }}
1718
steps:
1819
- uses: actions/checkout@v4
1920
with:
@@ -30,4 +31,4 @@ jobs:
3031
- name: Build
3132
run: mvn -B compile
3233
- name: Perform CodeQL Analysis
33-
uses: github/codeql-action/analyze@v3
34+
uses: github/codeql-action/analyze@v3

pom.xml

Lines changed: 11 additions & 11 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.1</version>
8+
<version>1.4.0</version>
99

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

4747
<dependency>
@@ -53,19 +53,19 @@
5353
<dependency>
5454
<groupId>org.slf4j</groupId>
5555
<artifactId>slf4j-simple</artifactId>
56-
<version>2.0.12</version>
56+
<version>2.0.13</version>
5757
<scope>test</scope>
5858
</dependency>
5959
<dependency>
6060
<groupId>org.junit.jupiter</groupId>
6161
<artifactId>junit-jupiter</artifactId>
62-
<version>5.10.2</version>
62+
<version>5.10.3</version>
6363
<scope>test</scope>
6464
</dependency>
6565
<dependency>
6666
<groupId>org.mockito</groupId>
6767
<artifactId>mockito-core</artifactId>
68-
<version>5.10.0</version>
68+
<version>5.12.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.12.1</version>
78+
<version>3.13.0</version>
7979
<configuration>
8080
<release>17</release>
8181
</configuration>
8282
</plugin>
8383
<plugin>
8484
<artifactId>maven-source-plugin</artifactId>
85-
<version>3.3.0</version>
85+
<version>3.3.1</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.2.5</version>
98+
<version>3.3.1</version>
9999
</plugin>
100100
<plugin>
101101
<artifactId>maven-javadoc-plugin</artifactId>
102-
<version>3.6.3</version>
102+
<version>3.8.0</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.1.0</version>
151+
<version>3.2.4</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.13</version>
186+
<version>1.7.0</version>
187187
<extensions>true</extensions>
188188
<configuration>
189189
<serverId>ossrh</serverId>

src/main/java/module-info.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import org.cryptomator.integrations.quickaccess.QuickAccessService;
12
import org.cryptomator.integrations.mount.MountService;
23
import org.cryptomator.integrations.revealpath.RevealPathService;
34
import org.cryptomator.integrations.tray.TrayMenuController;
@@ -18,6 +19,7 @@
1819
exports org.cryptomator.integrations.revealpath;
1920
exports org.cryptomator.integrations.tray;
2021
exports org.cryptomator.integrations.uiappearance;
22+
exports org.cryptomator.integrations.quickaccess;
2123

2224
uses AutoStartProvider;
2325
uses KeychainAccessProvider;
@@ -26,4 +28,5 @@
2628
uses TrayIntegrationProvider;
2729
uses TrayMenuController;
2830
uses UiAppearanceProvider;
31+
uses QuickAccessService;
2932
}
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 org.jetbrains.annotations.ApiStatus;
4+
5+
import java.lang.annotation.Documented;
6+
import java.lang.annotation.ElementType;
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.RetentionPolicy;
9+
import java.lang.annotation.Target;
10+
11+
/**
12+
* A humanreadable name of the annotated class.
13+
* <p>
14+
* Checked in the default implementation of the {@link NamedServiceProvider#getName()} with lower priority.
15+
*
16+
* @see NamedServiceProvider
17+
* @see LocalizedDisplayName
18+
*/
19+
@Documented
20+
@Retention(RetentionPolicy.RUNTIME)
21+
@Target(ElementType.TYPE)
22+
@ApiStatus.Experimental
23+
public @interface DisplayName {
24+
String value();
25+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.cryptomator.integrations.common;
2+
3+
import org.jetbrains.annotations.ApiStatus;
4+
5+
import java.lang.annotation.Documented;
6+
import java.lang.annotation.ElementType;
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.RetentionPolicy;
9+
import java.lang.annotation.Target;
10+
11+
/**
12+
* A humanreadable, localized name of the annotated class.
13+
* <p>
14+
* Checked in the default implementation of the {@link NamedServiceProvider#getName()} with highest priority.
15+
*
16+
* @see NamedServiceProvider
17+
* @see DisplayName
18+
*/
19+
@Documented
20+
@Retention(RetentionPolicy.RUNTIME)
21+
@Target(ElementType.TYPE)
22+
@ApiStatus.Experimental
23+
public @interface LocalizedDisplayName {
24+
25+
/**
26+
* Name of the localization bundle, where the display name is loaded from.
27+
*
28+
* @return Name of the localization bundle
29+
*/
30+
String bundle();
31+
32+
/**
33+
* The localization key containing the display name.
34+
*
35+
* @return Localization key to use
36+
*/
37+
String key();
38+
39+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.cryptomator.integrations.common;
2+
3+
import org.slf4j.LoggerFactory;
4+
5+
import java.util.MissingResourceException;
6+
import java.util.ResourceBundle;
7+
8+
/**
9+
* A service provider with a human-readable, possibly localized name.
10+
*/
11+
public interface NamedServiceProvider {
12+
13+
/**
14+
* Get the name of this service provider.
15+
*
16+
* @return The name of the service provider
17+
* @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.
18+
* @see DisplayName
19+
* @see LocalizedDisplayName
20+
*/
21+
default String getName() {
22+
var localizedDisplayName = this.getClass().getAnnotation(LocalizedDisplayName.class);
23+
if (localizedDisplayName != null) {
24+
try {
25+
return ResourceBundle.getBundle(localizedDisplayName.bundle()) //
26+
.getString(localizedDisplayName.key());
27+
} catch (MissingResourceException e) {
28+
var clazz = this.getClass();
29+
var logger = LoggerFactory.getLogger(clazz);
30+
logger.warn("Failed to load localized display name for {}. Falling back to not-localized display name/class name.", clazz.getName(), e);
31+
}
32+
}
33+
34+
var displayName = this.getClass().getAnnotation(DisplayName.class);
35+
if (displayName != null) {
36+
return displayName.value();
37+
} else {
38+
return this.getClass().getName();
39+
}
40+
}
41+
}

src/main/java/org/cryptomator/integrations/keychain/KeychainAccessProvider.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,24 @@ default void storePassphrase(String key, CharSequence passphrase) throws Keychai
5656
* @throws KeychainAccessException If storing the password failed
5757
*/
5858
@Blocking
59-
void storePassphrase(String key, @Nullable String displayName, CharSequence passphrase) throws KeychainAccessException;
59+
default void storePassphrase(String key, @Nullable String displayName, CharSequence passphrase) throws KeychainAccessException {
60+
storePassphrase(key, displayName, passphrase, false);
61+
}
62+
63+
/**
64+
* Associates a passphrase with a given key and a name for that key.
65+
*
66+
* @param key Key used to retrieve the passphrase via {@link #loadPassphrase(String)}.
67+
* @param displayName The according name to the key. That's the name of the vault displayed in the UI.
68+
* It's passed to the keychain as an additional information about the vault besides the key.
69+
* The parameter does not need to be unique or be checked by the keychain.
70+
* @param passphrase The secret to store in this keychain.
71+
* @param requireOsAuthentication Defines, whether the user needs to authenticate to store a passphrase.
72+
* The authentication mechanism is provided by the operating system dependent
73+
* implementations of this API.
74+
* @throws KeychainAccessException If storing the password failed
75+
*/
76+
void storePassphrase(String key, @Nullable String displayName, CharSequence passphrase, boolean requireOsAuthentication) throws KeychainAccessException;
6077

6178
/**
6279
* @param key Unique key previously used while {@link #storePassphrase(String, String, CharSequence)} storing a passphrase}.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.cryptomator.integrations.quickaccess;
2+
3+
import org.cryptomator.integrations.common.IntegrationsLoader;
4+
import org.cryptomator.integrations.common.NamedServiceProvider;
5+
import org.jetbrains.annotations.Blocking;
6+
import org.jetbrains.annotations.NotNull;
7+
8+
import java.nio.file.Path;
9+
import java.util.stream.Stream;
10+
11+
/**
12+
* Service adding a system path link to a quick access area of the OS or an application (e.g. file manager).
13+
*
14+
* @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.
15+
*/
16+
@FunctionalInterface
17+
public interface QuickAccessService extends NamedServiceProvider {
18+
19+
/**
20+
* Creates an entry in the quick access area.
21+
*
22+
* @param target The filesystem path the quick access entry points to
23+
* @param displayName The display name of the quick access entry
24+
* @return a {@link QuickAccessEntry }, used to remove the entry again
25+
* @throws QuickAccessServiceException if adding an entry to the quick access area fails
26+
* @apiNote It depends on the service implementation wether the display name is used or not.
27+
*/
28+
@Blocking
29+
QuickAccessEntry add(@NotNull Path target, @NotNull String displayName) throws QuickAccessServiceException;
30+
31+
/**
32+
* An entry of the quick access area, created by a service implementation.
33+
*/
34+
@FunctionalInterface
35+
interface QuickAccessEntry {
36+
37+
/**
38+
* Removes this entry from the quick access area.
39+
*
40+
* @throws QuickAccessServiceException if removal fails.
41+
* @implSpec Service implementations should make this function <em>idempotent</em>, i.e. after the method is called once and succeeded, consecutive calls should not change anything or throw an error.
42+
*/
43+
@Blocking
44+
void remove() throws QuickAccessServiceException;
45+
46+
}
47+
48+
/**
49+
* Loads all supported service providers.
50+
*
51+
* @return Stream of supported {@link QuickAccessService} implementations (may be empty)
52+
*/
53+
static Stream<QuickAccessService> get() {
54+
return IntegrationsLoader.loadAll(QuickAccessService.class);
55+
}
56+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.cryptomator.integrations.quickaccess;
2+
3+
public class QuickAccessServiceException extends Exception {
4+
5+
public QuickAccessServiceException(String message) {
6+
super(message);
7+
}
8+
9+
public QuickAccessServiceException(String message, Throwable t) {
10+
super(message, t);
11+
}
12+
}

0 commit comments

Comments
 (0)