feat(fls): topology of a .fls file as Java loads it
readTopology maps the decoded JavaBeans graph to devices, cables and documentation items the way SzenarioVerwaltung.netzwerkLaden does: the kind from the Java class (the palette label is not file data), devices without bounds at 0,0, interface values through Java's setters. All 23 corpus files match Java field by field. Found on the way: - listItems mixed a constructor's elements with added ones; a router's second interface was lost. Lists now replay add/set in order after the elements the constructor made. - The first 0 of a file may be SwingConstants.CENTER; measured like the getter defaults. - IP.ipCheck (javaIp.ts) measured on 46 cases: empty tokens skipped, signs, leading zeros and BMP digits of any script accepted. - The Java oracle took lower-case MACs in a file for random ones (8 interfaces); it now compares case-insensitively and reports the host name flags. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,8 +19,12 @@ virtuellen Bildschirm statt „headless".
|
||||
Lauf nach `.upstream/` geholt und gebaut.
|
||||
* **MAC-Adressen**, die nicht in der Datei stehen, würfelt Filius beim Anlegen
|
||||
der Netzwerkkarte. Sie erscheinen als `null`; zwei Läufe sind byte-gleich.
|
||||
* Ob eine MAC in der Datei steht, wird **ohne Rücksicht auf Groß-/Kleinschreibung**
|
||||
geprüft: `getMac()` schreibt groß, acht Korpus-Dateien speichern klein (bis
|
||||
29.09.2026 erschienen sie fälschlich als `null`).
|
||||
* Bisher ausgelesen: Geräte (Klasse, Name, Beschriftung, Position,
|
||||
Schnittstellen), Kabel (Enden als Gerät/Schnittstelle), Doku-Elemente.
|
||||
Schnittstellen, bei Rechner/Notebook `useIPAsName`/`useMACAsName`), Kabel
|
||||
(Enden als Gerät/Schnittstelle), Doku-Elemente.
|
||||
Systemsoftware, Dateisysteme und Anwendungen folgen schrittweise.
|
||||
|
||||
## Getter-Standardwerte
|
||||
@@ -34,3 +38,19 @@ x-Koordinate eines Geräts. Daran scheitert der Swift-Leser (Plan §13, M2).
|
||||
Argumente) und ruft den Getter auf; das Ergebnis steht in
|
||||
`packages/fls/src/javaDefaults.json`. Gemessen, nicht geraten: Filius' Knopf
|
||||
setzt `verticalTextPosition` auf 3 (BOTTOM), nicht auf Swings 0 (CENTER).
|
||||
|
||||
Dasselbe gilt für **statische Konstanten**: Die erste `0` einer Datei kann als
|
||||
`<object class="javax.swing.SwingConstants" field="CENTER"/>` stehen, und jede
|
||||
spätere `0` — etwa die Rot-, Grün- und Blauwerte einer schwarzen Doku-Farbe —
|
||||
verweist darauf. Schreibweise im Aufruf: `klasse::FELD`, Ergebnis
|
||||
`"SwingConstants.CENTER": 0`.
|
||||
|
||||
## `IP.ipCheck`
|
||||
|
||||
Java-Filius schickt jede IP-Adresse und Maske beim Laden durch
|
||||
`IP.ipCheck`. `IpCheckCases` ruft es für jede Zeile von
|
||||
`packages/fls/test/ip-check.cases.txt` auf (ASCII, Nicht-ASCII als
|
||||
`\uXXXX`) und schreibt `ip-check.java.json`. Gemessen: leere Abschnitte
|
||||
zählen nicht (`10..0.0.1`), Vorzeichen und führende Nullen gehen, ebenso
|
||||
Ziffern jeder Schrift in der BMP (Thai, Devanagari, Vollbreite) — aber kein
|
||||
Leerzeichen und kein 𝟏 (Ersatzpaar).
|
||||
|
||||
@@ -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"
|
||||
javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.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.
|
||||
@@ -30,7 +30,7 @@ HOME="$here/.build/home" xvfb-run -a java -cp "$classpath:$here/.build" FlsOracl
|
||||
"$root/corpus" "$root/corpus/corpus.java.json" 2>&1 | grep -v 'logback\|^$' || true
|
||||
test -s "$root/corpus/corpus.java.json"
|
||||
|
||||
# Getter defaults for the XMLEncoder references (packages/fls/src/javaDefaults.json).
|
||||
# Getter defaults and static constants for the XMLEncoder references (packages/fls/src/javaDefaults.json).
|
||||
defaults="$root/packages/fls/src/javaDefaults.json"
|
||||
rm -f "$defaults"
|
||||
HOME="$here/.build/home" xvfb-run -a java -cp "$classpath:$here/.build" GetterDefaults "$defaults" \
|
||||
@@ -49,5 +49,13 @@ HOME="$here/.build/home" xvfb-run -a java -cp "$classpath:$here/.build" GetterDe
|
||||
filius.software.dns.DNSServer#port \
|
||||
filius.software.rip.RIPServer#port \
|
||||
filius.software.www.WebServer#port \
|
||||
javax.swing.SwingConstants::CENTER \
|
||||
2>&1 | grep -v 'logback\|^$' || true
|
||||
test -s "$defaults"
|
||||
|
||||
# IP.ipCheck on hand-picked cases (packages/fls/src/javaIp.ts).
|
||||
cases="$root/packages/fls/test/ip-check.cases.txt"
|
||||
ipcheck="$root/packages/fls/test/ip-check.java.json"
|
||||
rm -f "$ipcheck"
|
||||
HOME="$here/.build/home" java -cp "$classpath:$here/.build" IpCheckCases "$cases" "$ipcheck" 2>&1 | grep -v 'logback\|^$' || true
|
||||
test -s "$ipcheck"
|
||||
|
||||
@@ -10,6 +10,7 @@ import filius.gui.netzwerksicht.GUIKnotenItem;
|
||||
import filius.hardware.Kabel;
|
||||
import filius.hardware.NetzwerkInterface;
|
||||
import filius.hardware.Port;
|
||||
import filius.hardware.knoten.Host;
|
||||
import filius.hardware.knoten.InternetKnoten;
|
||||
import filius.hardware.knoten.Knoten;
|
||||
import filius.hardware.knoten.LokalerKnoten;
|
||||
@@ -31,6 +32,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
@@ -114,6 +116,10 @@ public class FlsOracle {
|
||||
json.put("label", item.getImageLabel() == null ? null : item.getImageLabel().getTyp());
|
||||
Rectangle bounds = item.getImageLabel() == null ? null : item.getImageLabel().getBounds();
|
||||
json.put("bounds", bounds == null ? null : List.of(bounds.x, bounds.y, bounds.width, bounds.height));
|
||||
if (node instanceof Host host) {
|
||||
json.put("useIpAsName", host.isUseIPAsName());
|
||||
json.put("useMacAsName", host.isUseMACAsName());
|
||||
}
|
||||
List<Object> ports = new ArrayList<>();
|
||||
if (node instanceof InternetKnoten internet) {
|
||||
List<NetzwerkInterface> nics = internet.getNetzwerkInterfaces();
|
||||
@@ -125,7 +131,10 @@ public class FlsOracle {
|
||||
// Without a MAC address in the file, FILIUS rolls a random one when it
|
||||
// creates the interface; only a MAC that stands in the file is stable.
|
||||
String mac = nic.getMac();
|
||||
port.put("mac", mac != null && xmlText.contains(">" + mac + "<") ? mac : null);
|
||||
// getMac() upper-cases; the file may not.
|
||||
boolean macInFile = mac != null && Pattern
|
||||
.compile(">" + Pattern.quote(mac) + "<", Pattern.CASE_INSENSITIVE).matcher(xmlText).find();
|
||||
port.put("mac", macInFile ? mac : null);
|
||||
port.put("gateway", nic.getGateway());
|
||||
port.put("dns", nic.getDns());
|
||||
ports.add(port);
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
// later referenced by id — e.g. as a node's x coordinate. Decoding such a file
|
||||
// needs these defaults; they are measured here, not guessed.
|
||||
//
|
||||
// Usage: java -cp filius.jar:lib/*:classes GetterDefaults <output json> <fqcn#property>...
|
||||
// The same holds for static constants: the first Integer 0 in a file may be
|
||||
// written as `SwingConstants.CENTER`, and every later 0 refers to it.
|
||||
//
|
||||
// Usage: java -cp filius.jar:lib/*:classes GetterDefaults <output json> <fqcn#property | fqcn::FIELD>...
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
@@ -20,6 +23,13 @@ public class GetterDefaults {
|
||||
Map<String, Object> result = new TreeMap<>();
|
||||
for (int index = 1; index < args.length; index++) {
|
||||
String key = args[index];
|
||||
if (key.contains("::")) {
|
||||
String className = key.substring(0, key.indexOf("::"));
|
||||
String field = key.substring(key.indexOf("::") + 2);
|
||||
String simpleName = className.substring(className.lastIndexOf('.') + 1);
|
||||
result.put(simpleName + "." + field, Class.forName(className).getField(field).get(null));
|
||||
continue;
|
||||
}
|
||||
String className = key.substring(0, key.indexOf('#'));
|
||||
String property = key.substring(key.indexOf('#') + 1);
|
||||
String simpleName = className.substring(className.lastIndexOf('.') + 1);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Runs FILIUS's own IP.ipCheck on every case of a list and writes what Java
|
||||
// returns — the reference for packages/fls/src/javaIp.ts. The cases file is
|
||||
// ASCII, one case per line, with Java-style unicode escapes (backslash, u,
|
||||
// four hex digits) for anything else (so no editor or
|
||||
// hook can change a case by trimming or normalising it).
|
||||
//
|
||||
// Usage: java -cp filius.jar:lib/*:classes IpCheckCases <cases txt> <output json>
|
||||
|
||||
import filius.software.vermittlungsschicht.IP;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class IpCheckCases {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
List<Object> result = new ArrayList<>();
|
||||
for (String line : Files.readAllLines(Path.of(args[0]), StandardCharsets.US_ASCII)) {
|
||||
String input = unescape(line);
|
||||
String output;
|
||||
try {
|
||||
output = IP.ipCheck(input);
|
||||
} catch (RuntimeException error) {
|
||||
output = "!" + error.getClass().getSimpleName();
|
||||
}
|
||||
result.add(Arrays.asList(line, output));
|
||||
}
|
||||
try (FileOutputStream out = new FileOutputStream(args[1])) {
|
||||
out.write((FlsOracle.Json.write(result, "") + "\n").getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
System.out.println("ip check cases: " + result.size());
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
static String unescape(String line) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
for (int index = 0; index < line.length(); index++) {
|
||||
if (line.startsWith("\\u", index) && index + 6 <= line.length()) {
|
||||
out.append((char) Integer.parseInt(line.substring(index + 2, index + 6), 16));
|
||||
index += 5;
|
||||
} else {
|
||||
out.append(line.charAt(index));
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user