Skip to content

Commit e3920c6

Browse files
committed
Move file-type-related logic to separate service
This commit introduces a new DesktopService, more general than LinkService. While the LinkService is focused on handling URI schemes in an extensible way, the DesktopService provides a way to manage the application's supported file extensions and associated MIME types.
1 parent d40d297 commit e3920c6

File tree

6 files changed

+170
-38
lines changed

6 files changed

+170
-38
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*-
2+
* #%L
3+
* Desktop integration for SciJava.
4+
* %%
5+
* Copyright (C) 2010 - 2026 SciJava developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
package org.scijava.desktop;
30+
31+
import org.scijava.plugin.Plugin;
32+
import org.scijava.service.AbstractService;
33+
import org.scijava.service.SciJavaService;
34+
import org.scijava.service.Service;
35+
36+
import java.util.Collections;
37+
import java.util.HashMap;
38+
import java.util.Map;
39+
40+
/**
41+
* Service interface for an application's desktop-related concerns.
42+
*
43+
* @author Curtis Rueden
44+
*/
45+
@Plugin(type = Service.class)
46+
public class DefaultDesktopService extends AbstractService implements DesktopService {
47+
48+
private final Map<String, String> fileTypes = new HashMap<>();
49+
50+
@Override
51+
public void addFileType(String ext, String mimeType) {
52+
fileTypes.put(ext, mimeType);
53+
}
54+
55+
@Override
56+
public void addFileTypes(String mimePrefix, String... extensions) {
57+
throw new UnsupportedOperationException("Not yet implemented");
58+
}
59+
60+
@Override
61+
public void addFileTypes(final Map<String, String> extToMimeType) {
62+
fileTypes.putAll(extToMimeType);
63+
}
64+
65+
/**
66+
* Gets the map of supported file types.
67+
*/
68+
public Map<String, String> getFileTypes() {
69+
return Collections.unmodifiableMap(fileTypes);
70+
}
71+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*-
2+
* #%L
3+
* Desktop integration for SciJava.
4+
* %%
5+
* Copyright (C) 2010 - 2026 SciJava developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
package org.scijava.desktop;
30+
31+
import org.scijava.desktop.links.LinkHandler;
32+
import org.scijava.service.SciJavaService;
33+
34+
import java.util.Map;
35+
36+
/**
37+
* Service interface for an application's desktop-related concerns.
38+
*
39+
* @author Curtis Rueden
40+
*/
41+
public interface DesktopService extends SciJavaService {
42+
43+
/**
44+
* Adds to the set of supported file types, looking up each extension's MIME
45+
* type from the built-in database. If an extension is not found in the
46+
* database, it falls back to {@code mimePrefix/x-ext} (e.g. passing prefix
47+
* {@code "image"} for unknown extension {@code "foo"} yields
48+
* {@code "image/x-foo"}).
49+
*
50+
* @param mimePrefix The MIME type prefix (e.g. {@code "image"},
51+
* {@code "application"}) used when an extension is absent
52+
* from the database.
53+
* @param extensions One or more file extensions to register (without leading
54+
* dot, e.g. {@code "tiff"}, {@code "png"}).
55+
*/
56+
void addFileTypes(String mimePrefix, String... extensions);
57+
58+
/**
59+
* Adds to the set of supported file types using an explicit mapping.
60+
*
61+
* @param extToMimeType Map from file extension (without leading dot,
62+
* e.g. {@code "png"}) to MIME type
63+
* (e.g. {@code "image/png"}).
64+
*/
65+
void addFileTypes(Map<String, String> extToMimeType);
66+
67+
/**
68+
* Adds a single file type with an explicit MIME type.
69+
*
70+
* @param ext File extension without leading dot (e.g. {@code "png"}).
71+
* @param mimeType MIME type (e.g. {@code "image/png"}).
72+
*/
73+
void addFileType(String ext, String mimeType);
74+
75+
/**
76+
* Gets the map of supported file types.
77+
*/
78+
Map<String, String> getFileTypes();
79+
}

src/main/java/org/scijava/desktop/links/DefaultLinkService.java

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.Set;
3737

3838
import org.scijava.desktop.DesktopIntegrationProvider;
39+
import org.scijava.desktop.DesktopService;
3940
import org.scijava.event.ContextCreatedEvent;
4041
import org.scijava.event.EventHandler;
4142
import org.scijava.log.LogService;
@@ -60,25 +61,6 @@ public class DefaultLinkService extends AbstractHandlerService<URI, LinkHandler>
6061
@Parameter(required = false)
6162
private PlatformService platformService;
6263

63-
private final Set<String> extensions = new HashSet<>();
64-
65-
/**
66-
* Gets supported file extensions.
67-
*/
68-
@Override
69-
public Set<String> getFileExtensions() {
70-
return Collections.unmodifiableSet(extensions);
71-
}
72-
73-
/**
74-
* Gets supported file extensions.
75-
*/
76-
@Override
77-
public void addFileExtensions(final String... extensions) {
78-
this.extensions.addAll(Arrays.asList(extensions));
79-
}
80-
81-
8264
@EventHandler
8365
private void onEvent(final ContextCreatedEvent evt) {
8466
// Register URI handler with the desktop system, if possible.

src/main/java/org/scijava/desktop/links/LinkService.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,12 @@ public interface LinkService extends HandlerService<URI, LinkHandler>,
4747
SciJavaService
4848
{
4949

50-
/**
51-
* Gets the set of supported file extensions.
52-
*/
53-
public Set<String> getFileExtensions();
54-
55-
/**
56-
* Adds to the set of supported file extensions.
57-
*/
58-
public void addFileExtensions(final String... extension);
59-
6050
default void handle(final URI uri) {
6151
// Find the highest-priority link handler plugin which matches, if any.
6252
final Optional<LinkHandler> match = getInstances().stream() //
6353
.filter(handler -> handler.supports(uri)) //
6454
.findFirst();
65-
if (!match.isPresent()) {
55+
if (match.isEmpty()) {
6656
// No appropriate link handler plugin was found.
6757
final Logger log = log();
6858
if (log != null) log.debug("No handler for URI: " + uri);

src/main/java/org/scijava/desktop/platform/linux/LinuxPlatform.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.scijava.Context;
3333
import org.scijava.app.AppService;
3434
import org.scijava.desktop.DesktopIntegrationProvider;
35+
import org.scijava.desktop.DesktopService;
3536
import org.scijava.desktop.links.LinkService;
3637
import org.scijava.desktop.links.SchemeInstaller;
3738
import org.scijava.log.LogService;
@@ -400,10 +401,14 @@ private Set<String> schemes() {
400401
Collections.emptySet() : linkService.getSchemes();
401402
}
402403

403-
private Set<String> extensions() {
404-
final LinkService linkService = linkService();
405-
return linkService == null ?
406-
Collections.emptySet() : linkService.getFileExtensions();
404+
private DesktopService desktopService() {
405+
return context.getService(DesktopService.class);
406+
}
407+
408+
private Map<String, String> fileTypes() {
409+
final DesktopService desktopService = desktopService();
410+
return desktopService == null ?
411+
Collections.emptyMap() : desktopService.getFileTypes();
407412
}
408413

409414
/**
@@ -414,7 +419,7 @@ private synchronized Map<String, String> loadMimeTypeMapping() throws IOExceptio
414419

415420
extensionToMime = new LinkedHashMap<>();
416421

417-
final Set<String> extensions = extensions();
422+
final Map<String, String> fileTypes = fileTypes();
418423
// TODO: How do we know the MIME type of each extension?
419424

420425
return extensionToMime;

src/main/java/org/scijava/desktop/platform/windows/WindowsPlatform.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
import org.scijava.Context;
3838
import org.scijava.desktop.DesktopIntegrationProvider;
39+
import org.scijava.desktop.DesktopService;
3940
import org.scijava.desktop.links.LinkService;
4041
import org.scijava.desktop.links.SchemeInstaller;
4142
import org.scijava.log.LogService;
@@ -267,10 +268,14 @@ private Set<String> schemes() {
267268
Collections.emptySet() : linkService.getSchemes();
268269
}
269270

271+
private DesktopService desktopService() {
272+
return context.getService(DesktopService.class);
273+
}
274+
270275
private Set<String> extensions() {
271-
final LinkService linkService = linkService();
272-
return linkService == null ?
273-
Collections.emptySet() : linkService.getFileExtensions();
276+
final DesktopService desktopService = desktopService();
277+
return desktopService == null ?
278+
Collections.emptySet() : desktopService.getFileTypes().keySet();
274279
}
275280

276281
/**

0 commit comments

Comments
 (0)