173 lines
No EOL
6.8 KiB
Java
173 lines
No EOL
6.8 KiB
Java
/**
|
|
** Simple application to update cs/labs.jar to the most recent version.
|
|
**
|
|
** The labs.jar file is fetched from the gitlab.com repository.
|
|
**/
|
|
|
|
import java.awt.BorderLayout;
|
|
import java.awt.Dimension;
|
|
import java.awt.FlowLayout;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.URI;
|
|
import java.net.http.HttpClient;
|
|
import java.net.http.HttpRequest;
|
|
import java.net.http.HttpResponse.BodyHandlers;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.StandardCopyOption;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.jar.Attributes;
|
|
import java.util.jar.JarFile;
|
|
import java.util.stream.Collectors;
|
|
|
|
import javax.swing.JButton;
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.SwingConstants;
|
|
import javax.swing.SwingUtilities;
|
|
import javax.swing.UIManager;
|
|
|
|
public class UpdateLabCode extends JFrame {
|
|
|
|
private static final URI DOWNLOAD_URI = URI.create("https://gitlab.com/api/v4/projects/edaf85%2Fedaf85-labs/repository/files/cs%2Flabs.jar/raw?ref=main");
|
|
|
|
private final JLabel messageArea = new JLabel("", SwingConstants.CENTER);
|
|
private final JPanel buttonArea = new JPanel(new FlowLayout(FlowLayout.RIGHT, 20, 20));
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
public UpdateLabCode() {
|
|
super("Update lab code (EDAF85, fall 2024)");
|
|
|
|
add(messageArea, BorderLayout.CENTER);
|
|
add(buttonArea, BorderLayout.SOUTH);
|
|
|
|
try {
|
|
List<Path> candidates = Files.walk(Path.of(System.getProperty("user.dir")).getParent())
|
|
.filter(Files::isRegularFile)
|
|
.filter(f -> f.endsWith(Path.of("cs", "labs.jar")))
|
|
.collect(Collectors.toList());
|
|
if (candidates.size() == 1) {
|
|
showDialog("Currently using version: " + getJarVersion(candidates.get(0)),
|
|
"Check for update", () -> check(candidates.get(0)));
|
|
} else {
|
|
if (candidates.size() != 0) {
|
|
System.err.println("*** ERROR: found multiple 'cs/labs.jar', cannot decide which one to use:");
|
|
candidates.forEach(System.err::println);
|
|
}
|
|
throw new FileNotFoundException("cannot locate 'cs/labs.jar'");
|
|
}
|
|
} catch (IOException e) {
|
|
fail(e);
|
|
}
|
|
|
|
setPreferredSize(new Dimension(600, 150));
|
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
setResizable(false);
|
|
pack();
|
|
|
|
setLocationRelativeTo(null);
|
|
|
|
setVisible(true);
|
|
}
|
|
|
|
private void showDialog(String message, String buttonLabel, Runnable onClick) {
|
|
SwingUtilities.invokeLater(() -> {
|
|
messageArea.setText(message);
|
|
buttonArea.removeAll();
|
|
buttonArea.repaint();
|
|
JButton b = new JButton(buttonLabel);
|
|
b.addActionListener(e -> {
|
|
b.setEnabled(false);
|
|
onClick.run();
|
|
});
|
|
buttonArea.add(b);
|
|
getRootPane().setDefaultButton(b);
|
|
});
|
|
}
|
|
|
|
private void fail(Throwable t) {
|
|
t.printStackTrace(System.err);
|
|
showDialog("Error: " + t.getClass().getSimpleName() + " (see console)",
|
|
"Quit", () -> System.exit(1));
|
|
}
|
|
|
|
private void check(Path labsJar) {
|
|
try {
|
|
messageArea.setText("Checking...");
|
|
|
|
Path tempDir = labsJar.getParent().resolve("archive");
|
|
Files.createDirectories(tempDir);
|
|
|
|
Path downloadJar = Files.createTempFile(tempDir, ".download-", ".jar");
|
|
downloadJar.toFile().deleteOnExit();
|
|
|
|
HttpRequest req = HttpRequest.newBuilder(DOWNLOAD_URI).build();
|
|
HttpClient.newHttpClient()
|
|
.sendAsync(req, BodyHandlers.ofFile(downloadJar))
|
|
.thenAccept(response -> {
|
|
try {
|
|
int status = response.statusCode();
|
|
if (status != HttpURLConnection.HTTP_OK) {
|
|
showDialog("Unexpected status code: " + status,
|
|
"Quit", () -> System.exit(1));
|
|
} else if (Arrays.equals(Files.readAllBytes(labsJar), Files.readAllBytes(downloadJar))) { // same content
|
|
showDialog("No update available: you are using the latest version (" + getJarVersion(labsJar) + ")",
|
|
"OK", () -> System.exit(0));
|
|
} else if (!getCourseVersion(downloadJar).equals("fall 2024")) {
|
|
showDialog("Cannot update: latest update requires repo from " + getCourseVersion(downloadJar),
|
|
"OK", () -> System.exit(0));
|
|
} else {
|
|
showDialog("Update available: " + getJarVersion(downloadJar),
|
|
"Update now", () -> updateLabsJar(labsJar, downloadJar, tempDir));
|
|
}
|
|
} catch (IOException e) {
|
|
fail(e);
|
|
}
|
|
});
|
|
} catch (IOException e) {
|
|
fail(e);
|
|
}
|
|
}
|
|
|
|
private void updateLabsJar(Path labsJar, Path downloadJar, Path tempDir) {
|
|
try {
|
|
Path tempFile = Files.createTempFile(tempDir, "labs_jar_", ".old");
|
|
Files.move(labsJar, tempFile, StandardCopyOption.REPLACE_EXISTING);
|
|
Files.move(downloadJar, labsJar, StandardCopyOption.REPLACE_EXISTING);
|
|
showDialog("Success: you are now using the latest version!",
|
|
"OK", () -> System.exit(0));
|
|
} catch (IOException e) {
|
|
fail(e);
|
|
}
|
|
}
|
|
|
|
private static String getCourseVersion(Path jar) {
|
|
try (JarFile f = new JarFile(jar.toFile())) {
|
|
Attributes a = f.getManifest().getAttributes("common");
|
|
return (a != null) ? a.getValue(Attributes.Name.SPECIFICATION_VERSION) : "unknown";
|
|
} catch (IOException e) {
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
private static String getJarVersion(Path jar) {
|
|
try (JarFile f = new JarFile(jar.toFile())) {
|
|
Attributes a = f.getManifest().getAttributes("common");
|
|
return (a != null) ? a.getValue(Attributes.Name.IMPLEMENTATION_VERSION) : "unknown";
|
|
} catch (IOException e) {
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
|
|
SwingUtilities.invokeLater(UpdateLabCode::new);
|
|
}
|
|
} |