Skip to content

Commit a206217

Browse files
committed
Improve and expand the DesktopFile API
1 parent a14a43d commit a206217

File tree

2 files changed

+194
-19
lines changed

2 files changed

+194
-19
lines changed

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

Lines changed: 192 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,33 +41,77 @@
4141
import java.util.Map;
4242

4343
/**
44-
* Simple parser and writer for Linux .desktop files.
44+
* Parser and writer for Linux .desktop files.
4545
* <p>
46-
* Supports reading and writing key-value pairs within the [Desktop Entry] section.
47-
* This implementation is minimal and focused on URI scheme registration needs.
46+
* Instance-based API for reading and writing .desktop files. Supports all
47+
* standard [Desktop Entry] section fields plus custom keys. This class
48+
* provides a convenient way to manage desktop files for both application
49+
* launching and URI scheme registration.
50+
* </p>
51+
* <p>
52+
* Note: This class will eventually move to {@code org.scijava.util.DesktopFile}
53+
* in scijava-common once the design is finalized.
4854
* </p>
4955
*
5056
* @author Curtis Rueden
5157
*/
5258
public class DesktopFile {
5359

60+
private final Path path;
5461
private final Map<String, String> entries;
5562
private final List<String> comments;
5663

57-
public DesktopFile() {
64+
/**
65+
* Creates a DesktopFile instance for the given path.
66+
* <p>
67+
* If the file exists, it will be loaded when {@link #load()} is called.
68+
* If it doesn't exist, the entries map will be empty until populated
69+
* programmatically or {@link #load()} is called.
70+
* </p>
71+
*
72+
* @param path the path to the .desktop file
73+
*/
74+
public DesktopFile(final Path path) {
75+
this.path = path;
5876
this.entries = new LinkedHashMap<>();
5977
this.comments = new ArrayList<>();
6078
}
6179

6280
/**
63-
* Parses a .desktop file from disk.
81+
* Gets the file path for this desktop file.
82+
*
83+
* @return the path
84+
*/
85+
public Path path() {
86+
return path;
87+
}
88+
89+
/**
90+
* Checks if the file exists on disk.
91+
*
92+
* @return true if the file exists
93+
*/
94+
public boolean exists() {
95+
return Files.exists(path);
96+
}
97+
98+
/**
99+
* Loads the .desktop file from disk.
100+
* <p>
101+
* Clears any existing entries and comments, then reads from the file.
102+
* If the file doesn't exist, entries will be empty after this call.
103+
* </p>
64104
*
65-
* @param path Path to the .desktop file
66-
* @return Parsed DesktopFile
67105
* @throws IOException if reading fails
68106
*/
69-
public static DesktopFile parse(final Path path) throws IOException {
70-
final DesktopFile df = new DesktopFile();
107+
public void load() throws IOException {
108+
entries.clear();
109+
comments.clear();
110+
111+
if (!exists()) {
112+
return;
113+
}
114+
71115
boolean inDesktopEntry = false;
72116

73117
try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
@@ -90,7 +134,7 @@ public static DesktopFile parse(final Path path) throws IOException {
90134

91135
// Skip empty lines and comments
92136
if (trimmed.isEmpty() || trimmed.startsWith("#")) {
93-
df.comments.add(line);
137+
comments.add(line);
94138
continue;
95139
}
96140

@@ -99,21 +143,21 @@ public static DesktopFile parse(final Path path) throws IOException {
99143
if (equals > 0) {
100144
final String key = line.substring(0, equals).trim();
101145
final String value = line.substring(equals + 1);
102-
df.entries.put(key, value);
146+
entries.put(key, value);
103147
}
104148
}
105149
}
106-
107-
return df;
108150
}
109151

110152
/**
111-
* Writes the .desktop file to disk.
153+
* Saves the .desktop file to disk.
154+
* <p>
155+
* Creates parent directories if needed. Overwrites any existing file.
156+
* </p>
112157
*
113-
* @param path Path to write to
114158
* @throws IOException if writing fails
115159
*/
116-
public void writeTo(final Path path) throws IOException {
160+
public void save() throws IOException {
117161
// Ensure parent directory exists
118162
final Path parent = path.getParent();
119163
if (parent != null && !Files.exists(parent)) {
@@ -140,6 +184,48 @@ public void writeTo(final Path path) throws IOException {
140184
}
141185
}
142186

187+
/**
188+
* Deletes the file from disk.
189+
*
190+
* @throws IOException if deletion fails
191+
*/
192+
public void delete() throws IOException {
193+
Files.deleteIfExists(path);
194+
}
195+
196+
/**
197+
* Parses a .desktop file from disk (static convenience method).
198+
*
199+
* @param path Path to the .desktop file
200+
* @return Parsed DesktopFile
201+
* @throws IOException if reading fails
202+
*/
203+
public static DesktopFile parse(final Path path) throws IOException {
204+
final DesktopFile df = new DesktopFile(path);
205+
df.load();
206+
return df;
207+
}
208+
209+
/**
210+
* Writes the .desktop file to disk (for backward compatibility).
211+
*
212+
* @param path Path to write to
213+
* @throws IOException if writing fails
214+
*/
215+
public void writeTo(final Path path) throws IOException {
216+
final Path oldPath = this.path;
217+
// Temporarily change path, save, then restore
218+
try {
219+
// Create a temporary instance with the new path
220+
final DesktopFile temp = new DesktopFile(path);
221+
temp.entries.putAll(this.entries);
222+
temp.comments.addAll(this.comments);
223+
temp.save();
224+
} catch (final Exception e) {
225+
throw new IOException("Failed to write to " + path, e);
226+
}
227+
}
228+
143229
/**
144230
* Gets the value for a key.
145231
*
@@ -157,9 +243,98 @@ public String get(final String key) {
157243
* @param value The value
158244
*/
159245
public void set(final String key, final String value) {
160-
entries.put(key, value);
246+
if (value == null) {
247+
entries.remove(key);
248+
} else {
249+
entries.put(key, value);
250+
}
161251
}
162252

253+
// -- Standard field accessors --
254+
255+
public String getType() {
256+
return get("Type");
257+
}
258+
259+
public void setType(final String type) {
260+
set("Type", type);
261+
}
262+
263+
public String getVersion() {
264+
return get("Version");
265+
}
266+
267+
public void setVersion(final String version) {
268+
set("Version", version);
269+
}
270+
271+
public String getName() {
272+
return get("Name");
273+
}
274+
275+
public void setName(final String name) {
276+
set("Name", name);
277+
}
278+
279+
public String getGenericName() {
280+
return get("GenericName");
281+
}
282+
283+
public void setGenericName(final String genericName) {
284+
set("GenericName", genericName);
285+
}
286+
287+
public String getComment() {
288+
return get("Comment");
289+
}
290+
291+
public void setComment(final String comment) {
292+
set("Comment", comment);
293+
}
294+
295+
public String getExec() {
296+
return get("Exec");
297+
}
298+
299+
public void setExec(final String exec) {
300+
set("Exec", exec);
301+
}
302+
303+
public String getIcon() {
304+
return get("Icon");
305+
}
306+
307+
public void setIcon(final String icon) {
308+
set("Icon", icon);
309+
}
310+
311+
public String getPath() {
312+
return get("Path");
313+
}
314+
315+
public void setPath(final String path) {
316+
set("Path", path);
317+
}
318+
319+
public boolean getTerminal() {
320+
final String value = get("Terminal");
321+
return "true".equalsIgnoreCase(value);
322+
}
323+
324+
public void setTerminal(final boolean terminal) {
325+
set("Terminal", terminal ? "true" : "false");
326+
}
327+
328+
public String getCategories() {
329+
return get("Categories");
330+
}
331+
332+
public void setCategories(final String categories) {
333+
set("Categories", categories);
334+
}
335+
336+
// -- MimeType handling --
337+
163338
/**
164339
* Checks if a MimeType entry contains a specific MIME type.
165340
*

src/test/java/org/scijava/desktop/platform/linux/LinuxSchemeInstallerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ public void setUp() throws IOException {
6262
tempDesktopFile = Files.createTempFile("test-app", ".desktop");
6363

6464
// Write basic desktop file content
65-
final DesktopFile df = new DesktopFile();
65+
final DesktopFile df = new DesktopFile(tempDesktopFile);
6666
df.set("Type", "Application");
6767
df.set("Name", "Test App");
6868
df.set("Exec", "/usr/bin/test-app %U");
69-
df.writeTo(tempDesktopFile);
69+
df.save();
7070

7171
// Set system property
7272
originalProperty = System.getProperty("scijava.app.desktop-file");

0 commit comments

Comments
 (0)