Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit db4a75f

Browse files
committedJul 13, 2024
Fixed issue where resources did not load when running JAR
1 parent d9e2e28 commit db4a75f

File tree

5 files changed

+127
-57
lines changed

5 files changed

+127
-57
lines changed
 

‎.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2+
src/main/resources/examples/_example_list
3+
14
# Created by https://www.toptal.com/developers/gitignore/api/eclipse,visualstudiocode,intellij,java,gradle,maven,macos,netbeans
25
# Edit at https://www.toptal.com/developers/gitignore?templates=eclipse,visualstudiocode,intellij,java,gradle,maven,macos,netbeans
36

‎build.gradle

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ plugins {
44
id 'application'
55
}
66

7+
// Set project properties
78
group 'dod-c3pu'
8-
version '0.2'
9+
version 'v0.1'
10+
sourceCompatibility = JavaVersion.VERSION_17
11+
targetCompatibility = JavaVersion.VERSION_17
912

1013
repositories {
1114
mavenCentral()
@@ -92,10 +95,36 @@ tasks.withType(Test) {
9295
}
9396
}
9497

98+
task generateExampleList {
99+
doLast {
100+
// Define the directory and output file
101+
def examplesDir = new File('src/main/resources/examples')
102+
def outputFile = new File('src/main/resources/examples/_example_list')
103+
104+
// Ensure the output file exists
105+
outputFile.text = ''
106+
107+
// List files and write their names to the output file
108+
examplesDir.eachFile { File file ->
109+
if (file.isFile() && file.name.endsWith('.txt')) {
110+
outputFile.append(file.name + '\n')
111+
}
112+
}
113+
}
114+
}
115+
116+
// Ensure this task is run before the jar is built
117+
jar.dependsOn(generateExampleList)
118+
119+
95120
// Create a FAT JAR including all dependencies
96121
jar {
122+
archiveBaseName.set('c3pu')
123+
archiveVersion.set(version)
97124
manifest {
98-
attributes 'Main-Class': 'view.Main'
125+
attributes 'Main-Class': 'view.Main',
126+
'Implementation-Title': archiveBaseName.get(),
127+
'Implementation-Version': archiveVersion.get()
99128
}
100129
from {
101130
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
Lines changed: 87 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
package util;
22

33
import java.io.BufferedReader;
4-
import java.io.File;
54
import java.io.FileReader;
5+
import java.io.IOException;
6+
import java.io.InputStreamReader;
7+
import java.net.URI;
68
import java.net.URISyntaxException;
7-
import java.nio.file.Path;
9+
import java.net.URL;
10+
import java.nio.file.Files;
11+
import java.nio.file.Paths;
812
import java.util.Arrays;
913
import java.util.Collections;
14+
import java.util.HashMap;
1015
import java.util.List;
1116
import java.util.Map;
12-
import java.util.Objects;
1317
import java.util.stream.Collectors;
1418

1519
/**
@@ -19,67 +23,104 @@
1923
public class ExamplesHandler {
2024

2125
private static final String EXAMPLES_DIR = "/examples/";
26+
private static final String EXAMPLES_LIST_FILE = EXAMPLES_DIR + "_example_list";
2227

23-
private static Map<String, Path> exampleMap = null;
28+
private static Map<String, String[]> exampleMap = null;
2429

2530
private ExamplesHandler() {}
2631

27-
private static Map<String, Path> getExampleMap() {
32+
private static Map<String, String[]> getExampleMap() {
2833
if (exampleMap == null) {
34+
// Read examples in one of two ways:
35+
// 1. If running from from the source via Gradle, e.g. in your IDE or terminal, list the files
36+
// in the examples dir and load them.
37+
2938
try {
30-
exampleMap =
31-
Arrays.stream(
32-
Objects.requireNonNull(
33-
new File(ExamplesHandler.class.getResource(EXAMPLES_DIR).toURI())
34-
.listFiles()))
35-
.map(File::toPath) // Convert File to Path
36-
.collect(
37-
Collectors.toMap(
38-
path -> {
39-
// Process the file name to create a readable name
40-
String name = path.getFileName().toString();
41-
name = name.substring(0, name.lastIndexOf('.'));
42-
name = name.replace('_', ' ');
43-
name = name.substring(0, 1).toUpperCase() + name.substring(1);
44-
return name;
45-
},
46-
path -> path // Use the Path object itself as the map value
47-
));
48-
} catch (URISyntaxException e) {
49-
e.printStackTrace();
39+
URI uri = ExamplesHandler.class.getResource(EXAMPLES_DIR).toURI();
40+
// Check if uri points to a file (directory), or just a resource in a JAR
41+
if (uri.getScheme().equals("file")) {
42+
exampleMap =
43+
Files.list(Paths.get(uri))
44+
.filter(Files::isRegularFile)
45+
.filter(path -> path.getFileName().toString().endsWith(".txt"))
46+
.collect(
47+
Collectors.toMap(
48+
path -> nameFromPath(path.getFileName().toString()),
49+
path -> {
50+
// Load the file from the file system
51+
try (BufferedReader reader =
52+
new BufferedReader(new FileReader(path.toFile()))) {
53+
return reader.lines().toArray(String[]::new);
54+
} catch (Exception e) {
55+
return new String[0];
56+
}
57+
}));
58+
}
59+
} catch (URISyntaxException | IOException e) {
60+
// Ignore
61+
exampleMap = null;
62+
}
63+
64+
// 2. If running from a JAR, files in examples dir cannot be listed. Instead, first read the
65+
// special file that contains their names, and then load them explicitly.
66+
if (exampleMap == null) {
67+
// Read the list of examples from the _example_list file using getResourceAsStream
68+
try (BufferedReader reader =
69+
new BufferedReader(
70+
new InputStreamReader(
71+
ExamplesHandler.class.getResourceAsStream(EXAMPLES_LIST_FILE)))) {
72+
Map<String, String[]> tmpMap = new HashMap<>();
73+
String line;
74+
while ((line = reader.readLine()) != null) {
75+
URL fileURL = ExamplesHandler.class.getResource(EXAMPLES_DIR + line);
76+
if (fileURL != null) {
77+
try (BufferedReader fileReader =
78+
new BufferedReader(new InputStreamReader(fileURL.openStream()))) {
79+
tmpMap.put(nameFromPath(line), fileReader.lines().toArray(String[]::new));
80+
}
81+
}
82+
}
83+
exampleMap = tmpMap;
84+
} catch (Exception e) {
85+
// Ignore
86+
exampleMap = null;
87+
}
88+
}
89+
90+
if (exampleMap == null) {
5091
exampleMap = Collections.emptyMap();
5192
}
5293
}
5394
return exampleMap;
5495
}
5596

97+
private static String nameFromPath(final String filename) {
98+
// Process the file name to create a readable name
99+
String name = filename;
100+
name = name.substring(0, name.lastIndexOf('.'));
101+
name = name.replace('_', ' ');
102+
name = name.substring(0, 1).toUpperCase() + name.substring(1);
103+
return name;
104+
}
105+
56106
public static List<String> getExampleNames() {
57107
return getExampleMap().keySet().stream().sorted().collect(Collectors.toList());
58108
}
59109

60110
public static String[] getExample(String name) {
61-
Path path = getExampleMap().get(name);
62-
if (path == null) {
63-
return new String[0];
64-
}
65-
try (BufferedReader reader = new BufferedReader(new FileReader(path.toFile()))) {
66-
String[] lines =
67-
reader
68-
.lines()
69-
.map(s -> s.split("(//|#|%)", 2)[0])
70-
.map(s -> s.replace(" ", ""))
71-
.toArray(String[]::new);
72-
// verify that each line contains only 0s and 1s, and is 8 characters long
73-
for (int i = 0; i < lines.length; i++) {
74-
String line = lines[i];
75-
if (line.length() != 8 || !line.matches("[01]+")) {
76-
throw new IllegalArgumentException(
77-
String.format("Invalid file format at line %d: '%s'", (i + 1), line));
78-
}
111+
String[] lines =
112+
Arrays.stream(getExampleMap().get(name))
113+
.map(s -> s.split("(//|#|%)", 2)[0])
114+
.map(s -> s.replace(" ", ""))
115+
.toArray(String[]::new);
116+
// verify that each line contains only 0s and 1s, and is 8 characters long
117+
for (int i = 0; i < lines.length; i++) {
118+
String line = lines[i];
119+
if (line.length() != 8 || !line.matches("[01]+")) {
120+
throw new IllegalArgumentException(
121+
String.format("Invalid file format at line %d: '%s'", (i + 1), line));
79122
}
80-
return lines;
81-
} catch (Exception e) {
82-
return new String[0];
83123
}
124+
return lines;
84125
}
85126
}

‎src/main/java/view/HelpWindow.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,9 @@
44
import static util.LazySwing.inv;
55

66
import java.io.IOException;
7-
import java.net.URISyntaxException;
7+
import java.io.InputStream;
88
import java.net.URL;
99
import java.nio.charset.StandardCharsets;
10-
import java.nio.file.Files;
11-
import java.nio.file.Path;
12-
import java.nio.file.Paths;
1310
import javax.swing.JDialog;
1411
import javax.swing.JEditorPane;
1512
import javax.swing.JFrame;
@@ -52,16 +49,14 @@ public HelpWindow(JFrame parent, Settings settings) {
5249
// Schedule a non-EDT task to load the html content
5350
new Thread(
5451
() -> {
55-
Path path;
56-
try {
57-
path = Paths.get(helpUrl.toURI());
58-
byte[] fileBytes = Files.readAllBytes(path);
52+
try (InputStream inputStream = getClass().getResourceAsStream("/help/help.html")) {
53+
byte[] fileBytes = inputStream.readAllBytes();
5954
inv(
6055
() -> {
6156
helpContent.setText(new String(fileBytes, StandardCharsets.UTF_8));
6257
helpContent.setCaretPosition(0);
6358
});
64-
} catch (URISyntaxException | IOException e) {
59+
} catch (IOException e) {
6560
inv(
6661
() ->
6762
helpContent.setText(

‎todo.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@
102102
[x] Update example programs, after instruction changes (again...)
103103
[] Add config/view option to turn off auto scroll to active cell
104104
[] Think about: Should conditional jump use another dst register, e.g. R2? (Instead of RES)
105+
[x] Resources failed to load when building and running from JAR. Fix!
106+
[] Set up a Logger, that can collect errors in a local file.$
105107
[]
106108
0100 1010
107109
0001 0000

0 commit comments

Comments
 (0)
Please sign in to comment.