feat(editor): F4.6c the software installation on a computer's desktop

A new oracle, InstallRun, installs each of Java's programs on new
computers, all of them on one, each installed and removed again, and a
DNS and an e-mail server installed again after their removal; Java saves
the result as a project. A new program is switched off (a computer's
firewall is on), makes the folders and files it lacks (the web server's
start page in FILIUS' language and its picture, /peer2peer,
/mailserver/konten.txt, /dns/hosts), and removing it takes its settings
and leaves its files; a server installed again reads its records or
accounts from them. Java installs in the order of its list and starts
the program at once.

The document's setSoftware does the same, checked against Java's saved
installation. The core knows what a program makes in the files and
installs or removes a program while the simulation runs; the room
watches the document's programs and hands changes to the engine, so a
new command line works at once. The desktop offers Java's dialog with
two lists, arrows, double click and apply changes.

Also: Java's file may name a number it rolled by the result of any
getter (an idref, here a thread's priority); GetterDefaults now
measures the priority of the saved thread classes, which the import
read as 0 before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 15:03:35 +00:00
co-authored by Claude Opus 5.5
parent ac48e969f4
commit f0e7c73ec7
29 changed files with 1264 additions and 52 deletions
+27
View File
@@ -1265,3 +1265,30 @@ Gemessen (03.10.2026):
Javas Terminal setzt den Ordner nur bei der Installation
(`setSystemSoftware`), und das Fenster ist dasselbe Objekt.
### Software-Installation (F4.6c)
`InstallRun` installiert jedes Programm aus Javas Liste, wie
`GUIInstallationsDialog.aenderungenSpeichern` es tut
(`installAndStartAppIfAvailable`), auf einem eigenen neuen Rechner, alle auf
einem („Alle“), jedes einmal mit anschließendem `entferneSoftware`
(„Entfernt-…“), dazu einen DNS-Server mit Eintrag und einen E-Mail-Server
mit Konto, die entfernt und neu installiert werden („Wieder-…“); Java
speichert das als Projekt (`packages/doc/test/fixtures/installed-programs.fls`).
Gemessen (03.10.2026):
* Ein neues Programm ist aus (kein Server läuft); die Firewall eines
Rechners dagegen ist sofort aktiv (verwerfen, UDP filtern).
* Es legt an, was fehlt: der Webserver `/webserver` mit Javas Startseite in
der Sprache, in der FILIUS läuft, und `splashscreen-mini.png` (nur, wenn
noch keine `index.html` da ist), Gnutella `/peer2peer`, der E-Mail-Server
`/mailserver/konten.txt` (leer), der DNS-Server `/dns/hosts` (leer).
* Entfernt, verschwinden Programm und Einstellungen; die Dateien bleiben.
Neu installiert, liest der DNS-Server seine Einträge aus `/dns/hosts`, der
E-Mail-Server seine Konten aus `konten.txt`.
* Gnutellas Teilnehmerzahl würfelt der Konstruktor (3 bis 5); die Datei
verweist darauf mit `idref` auf irgendeine frühere gleiche Zahl — hier den
Rückgabewert von `iconTextGap` (4) oder einer Thread-Priorität (5).
Darum misst `GetterDefaults` jetzt auch `#priority` der gespeicherten
Thread-Klassen (alle 5), die vorher unaufgelöst als 0 gelesen wurden.
+24 -1
View File
@@ -21,7 +21,7 @@ if [ ! -f "$upstream/target/filius.jar" ]; then
fi
classpath="$upstream/target/filius.jar:$upstream/target/lib/*"
mkdir -p "$here/.build"
javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.java" "$here/src/DnsHostsCases.java" "$here/src/EmailFileCases.java" "$here/src/BeansDump.java" "$here/src/Base64Cases.java" "$here/src/ScenarioNetwork.java" "$here/src/DhcpRun.java" "$here/src/TcpRun.java" "$here/src/DnsRun.java" "$here/src/ArpRun.java" "$here/src/RipRun.java" "$here/src/NatRun.java" "$here/src/WlanRun.java" "$here/src/ExampleRun.java" "$here/src/EchoRun.java" "$here/src/WebRun.java" "$here/src/RouterWebRun.java" "$here/src/KonfigCases.java" "$here/src/EmailRun.java" "$here/src/MailCases.java" "$here/src/EmailClientRun.java" "$here/src/TerminalCases.java" "$here/src/TerminalRun.java" "$here/src/FileCases.java" "$here/src/GnutellaRun.java" "$here/src/NewDeviceRun.java" "$here/src/SheetRun.java" "$here/src/TerminalWindowRun.java"
javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.java" "$here/src/DnsHostsCases.java" "$here/src/EmailFileCases.java" "$here/src/BeansDump.java" "$here/src/Base64Cases.java" "$here/src/ScenarioNetwork.java" "$here/src/DhcpRun.java" "$here/src/TcpRun.java" "$here/src/DnsRun.java" "$here/src/ArpRun.java" "$here/src/RipRun.java" "$here/src/NatRun.java" "$here/src/WlanRun.java" "$here/src/ExampleRun.java" "$here/src/EchoRun.java" "$here/src/WebRun.java" "$here/src/RouterWebRun.java" "$here/src/KonfigCases.java" "$here/src/EmailRun.java" "$here/src/MailCases.java" "$here/src/EmailClientRun.java" "$here/src/TerminalCases.java" "$here/src/TerminalRun.java" "$here/src/FileCases.java" "$here/src/GnutellaRun.java" "$here/src/NewDeviceRun.java" "$here/src/SheetRun.java" "$here/src/TerminalWindowRun.java" "$here/src/InstallRun.java"
# FILIUS writes its settings below $HOME; keep them out of the real one.
mkdir -p "$here/.build/home"
# Removed first: a crashed run must not leave the previous result standing.
@@ -57,6 +57,21 @@ HOME="$here/.build/home" xvfb-run -a java -cp "$classpath:$here/.build" GetterDe
filius.software.www.WebServer#aktiv \
filius.software.www.WebServer#useVHost \
filius.software.dateiaustausch.PeerToPeerAnwendung#maxTeilnehmerZahl \
filius.software.dhcp.DHCPServer#priority \
filius.software.rip.RIPServer#priority \
filius.software.lokal.Terminal#priority \
filius.software.lokal.ImageViewer#priority \
filius.software.lokal.FileExplorer#priority \
filius.software.dns.DNSServer#priority \
filius.software.email.EmailAnwendung#priority \
filius.software.email.EmailServer#priority \
filius.software.clientserver.ServerBaustein#priority \
filius.software.clientserver.ClientBaustein#priority \
filius.software.firewall.Firewall#priority \
filius.software.dateiaustausch.PeerToPeerAnwendung#priority \
filius.software.lokal.TextEditor#priority \
filius.software.www.WebServer#priority \
filius.software.www.WebBrowser#priority \
2>&1 | grep -v 'logback\|^$' || true
test -s "$defaults"
@@ -328,6 +343,14 @@ rm -f "$output"
HOME="$here/.build/home" xvfb-run -a java -cp "$classpath:$here/.build" NewDeviceRun "$output" 2>&1 | grep -v 'logback\|^$' || true
test -s "$output"
# FILIUS' programs as its software installation installs and removes them
# (InstallRun), saved as Java saves a project: the editor's installation
# (packages/doc/test/install.test.ts).
output="$root/packages/doc/test/fixtures/installed-programs.fls"
rm -f "$output"
HOME="$here/.build/home" xvfb-run -a java -Duser.language=de -Duser.country=DE -cp "$classpath:$here/.build" InstallRun "$output" 2>&1 | grep -v 'logback\|^$\|INFO' || true
test -s "$output"
# Text typed into FILIUS' settings panels of a host, a switch and a modem and
# taken as they take it (SheetRun): what the editor's device sheet marks and
# keeps (packages/doc/test/sheet.test.ts).
+81
View File
@@ -0,0 +1,81 @@
// Installs FILIUS' programs as its software installation does
// (GUIInstallationsDialog.aenderungenSpeichern: installAndStartAppIfAvailable,
// entferneSoftware) on new computers and saves them as Java saves a project
// (SzenarioVerwaltung.speichern): what a program brings along when it is
// installed — its settings, its folders and files — and what stays when it
// is removed. The reference for the editor's software installation
// (packages/doc/test/install.test.ts). One computer per program, named after
// its class's simple name; "Alle" has them all; "Entfernt-<name>" had the
// program installed and removed again; "Wieder-<name>" had a DNS server with
// a record or an e-mail server with an account installed, removed and
// installed again.
//
// Usage: java -cp filius.jar:lib/*:classes InstallRun <output fls>
import filius.gui.GUIContainer;
import filius.gui.netzwerksicht.GUIDesignSidebar;
import filius.gui.netzwerksicht.GUIDocuItem;
import filius.gui.netzwerksicht.GUIKabelItem;
import filius.gui.netzwerksicht.GUIKnotenItem;
import filius.hardware.knoten.Rechner;
import filius.rahmenprogramm.Information;
import filius.rahmenprogramm.SzenarioVerwaltung;
import filius.software.system.Betriebssystem;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class InstallRun {
public static void main(String[] args) throws Exception {
try {
run(args);
} catch (Throwable error) {
error.printStackTrace();
System.exit(1);
}
System.exit(0);
}
static Rechner computer(List<GUIKnotenItem> items, String name, int place) {
Rechner host = new Rechner();
host.setName(name);
NewDeviceRun.add(items, host, GUIDesignSidebar.RECHNER, 100 + 150 * (place % 6), 100 + 150 * (place / 6));
return host;
}
static void run(String[] args) throws Exception {
GUIContainer.getGUIContainer();
List<GUIKnotenItem> items = new ArrayList<>();
List<Map<String, String>> programs = Information.getInformation().ladeProgrammListe();
int place = 0;
Rechner all = computer(items, "Alle", place++);
for (Map<String, String> program : programs) {
String className = program.get("Klasse");
String name = className.substring(className.lastIndexOf('.') + 1);
Betriebssystem system = (Betriebssystem) computer(items, name, place++).getSystemSoftware();
if (!system.installAndStartAppIfAvailable(className)) throw new IllegalStateException("not installed: " + className);
((Betriebssystem) all.getSystemSoftware()).installAndStartAppIfAvailable(className);
Betriebssystem removed = (Betriebssystem) computer(items, "Entfernt-" + name, place++).getSystemSoftware();
removed.installAndStartAppIfAvailable(className);
if (!removed.entferneSoftware(className)) throw new IllegalStateException("not removed: " + className);
}
// Installed again where a removed program left its files: a DNS server with a record, an e-mail server with an account.
Betriebssystem dns = (Betriebssystem) computer(items, "Wieder-DNSServer", place++).getSystemSoftware();
dns.installAndStartAppIfAvailable("filius.software.dns.DNSServer");
((filius.software.dns.DNSServer) dns.holeSoftware("filius.software.dns.DNSServer")).hinzuRecord("www.filius.de", "A", "1.2.3.4");
dns.entferneSoftware("filius.software.dns.DNSServer");
dns.installAndStartAppIfAvailable("filius.software.dns.DNSServer");
Betriebssystem mail = (Betriebssystem) computer(items, "Wieder-EmailServer", place++).getSystemSoftware();
mail.installAndStartAppIfAvailable("filius.software.email.EmailServer");
((filius.software.email.EmailServer) mail.holeSoftware("filius.software.email.EmailServer")).benutzerHinzufuegen("anna", "geheim", "Muster", "Anna");
mail.entferneSoftware("filius.software.email.EmailServer");
mail.installAndStartAppIfAvailable("filius.software.email.EmailServer");
// Let the programs' threads come to rest before the files are read.
Thread.sleep(1000);
if (!SzenarioVerwaltung.getInstance().speichern(args[0], items, new ArrayList<GUIKabelItem>(), new ArrayList<GUIDocuItem>())) {
throw new IllegalStateException("FILIUS could not save " + args[0]);
}
System.out.println("computers: " + items.size());
}
}