feat(fls): write the installed applications of a .fls, loaded by Java as the original
topologyWriter.ts puts each installed application of a PC or notebook under its key and gives it the system software, as installApp does, with its settings: a server's switch and port, a client's target, DNS recursion, virtual hosts, the peer count, the personal firewall. The applications follow the files, as in Java's own files: the web server, the peer-to-peer application and the e-mail server make their directories only where the files lack them, and the DNS server reads /dns/hosts when it is installed. E-mail accounts, messages and address books are the next step. The Java oracle now reports a personal firewall's rules in full, not their number (the corpus has none; its result is byte-equal). Checked by Java against Java: every corpus file, read and written again, loads with the same applications as the original. The synthetic topology adds every FILIUS application with settings away from its defaults, a personal firewall with a rule, an own index.html (Java makes no second) and a missing /peer2peer directory, which Java makes at the end. 12 mutation probes, among them files and applications in reverse order, each loaded by Java, were all caught. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,13 @@
|
||||
// which holds the same object (its key among the installed applications
|
||||
// differs: Firewall on a router, NatGateway on a home router). Files are
|
||||
// added to the constructor's root, as XMLEncoder adds them — on a router
|
||||
// after the files its constructor makes. Applications are a later layer.
|
||||
// after the files its constructor makes. The installed applications of a PC
|
||||
// or notebook follow the files, as in Java's own files: the constructors of
|
||||
// the web server, the peer-to-peer application and the e-mail server make
|
||||
// their directories only where the files lack them, and the DNS server reads
|
||||
// /dns/hosts when it is installed. Each is put under its key and given the
|
||||
// system software, as installApp does. E-mail accounts, messages and address
|
||||
// books are a later layer.
|
||||
//
|
||||
// Checked by Java: every corpus file, read and written again, loads in Java
|
||||
// FILIUS to the same topology and system software (topologyWriter.test.ts,
|
||||
@@ -32,14 +38,19 @@ import {
|
||||
type BeanValue,
|
||||
short,
|
||||
} from './javaBeansWriter.js';
|
||||
import type { FlsFileTree, FlsFirewall, FlsSystemSoftware } from './systemSoftware.js';
|
||||
import type { FlsApplication, FlsFileTree, FlsFirewall, FlsSystemSoftware } from './systemSoftware.js';
|
||||
import type { FlsDocumentationItem, FlsInterface, FlsLink, FlsNode, FlsNodeClass } from './topology.js';
|
||||
|
||||
/** The version line of the files this writer makes: the format of FILIUS 2.14. */
|
||||
export const WRITTEN_VERSION_LINE = 'Filius version: 2.14.0 (mdg-filius)';
|
||||
|
||||
/** The system software's settings and files; its applications are a later layer. */
|
||||
export type SystemToWrite = Omit<FlsSystemSoftware, 'applications'>;
|
||||
/** An installed application; e-mail accounts, messages and address books are a later layer. */
|
||||
export type ApplicationToWrite = Omit<FlsApplication, 'source'>;
|
||||
|
||||
/** The system software's settings, files and applications. */
|
||||
export type SystemToWrite = Omit<FlsSystemSoftware, 'applications'> & {
|
||||
readonly applications?: readonly ApplicationToWrite[];
|
||||
};
|
||||
|
||||
export type NodeToWrite = Pick<
|
||||
FlsNode,
|
||||
@@ -140,7 +151,14 @@ function device(node: NodeToWrite, ports: BeanValue[]): BeanObject {
|
||||
),
|
||||
);
|
||||
}
|
||||
statements.push({ get: 'systemSoftware', statements: systemStatements(node.system, node.javaClass) });
|
||||
// Named for the applications, which are given it.
|
||||
const system = (node.system.applications?.length ?? 0) > 0 ? reference('SystemSoftware') : undefined;
|
||||
const systemStatementList = systemStatements(node.system, node.javaClass, system);
|
||||
statements.push(
|
||||
system === undefined
|
||||
? { get: 'systemSoftware', statements: systemStatementList }
|
||||
: { get: 'systemSoftware', statements: systemStatementList, as: system },
|
||||
);
|
||||
return object(`filius.hardware.knoten.${node.javaClass}`, statements);
|
||||
}
|
||||
|
||||
@@ -150,7 +168,7 @@ const WEB_SERVER_CLASS = 'filius.software.www.WebServer';
|
||||
* The settings the file has, each set on the constructor's system software.
|
||||
* A switch's SSID the file lacked stays unwritten, so Java rolls one as it did.
|
||||
*/
|
||||
function systemStatements(system: SystemToWrite, javaClass: FlsNodeClass): BeanStatement[] {
|
||||
function systemStatements(system: SystemToWrite, javaClass: FlsNodeClass, self: BeanReference | undefined): BeanStatement[] {
|
||||
const statements: BeanStatement[] = [];
|
||||
if (system.firewall !== undefined) {
|
||||
statements.push({
|
||||
@@ -167,6 +185,15 @@ function systemStatements(system: SystemToWrite, javaClass: FlsNodeClass): BeanS
|
||||
});
|
||||
}
|
||||
if (system.fileSystem !== undefined) statements.push(fileSystemStatement(system.fileSystem, system.templateFiles !== false));
|
||||
if (self !== undefined && system.applications !== undefined) {
|
||||
statements.push({
|
||||
get: 'installierteAnwendungen',
|
||||
statements: system.applications.map((application) => ({
|
||||
call: 'put',
|
||||
args: [application.key, object(application.javaClass, applicationStatements(application, self))],
|
||||
})),
|
||||
});
|
||||
}
|
||||
if (system.dhcpServer !== undefined) {
|
||||
const server = system.dhcpServer;
|
||||
statements.push({
|
||||
@@ -236,6 +263,28 @@ function userObject(tree: FlsFileTree): BeanValue {
|
||||
return tree.kind === 'directory' ? tree.name : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* An application's settings, after the system software it runs on. A
|
||||
* peer-to-peer application's peer count the file lacked stays unwritten, so
|
||||
* Java rolls one as it did.
|
||||
*/
|
||||
function applicationStatements(application: ApplicationToWrite, system: BeanReference): BeanStatement[] {
|
||||
const statements: BeanStatement[] = [{ set: 'systemSoftware', value: system }];
|
||||
if (application.isActive !== undefined) statements.push({ set: 'aktiv', value: application.isActive });
|
||||
if (application.port !== undefined) statements.push({ set: 'port', value: int(application.port) });
|
||||
if (application.targetAddress !== undefined) statements.push({ set: 'zielIPAdresse', value: application.targetAddress });
|
||||
if (application.targetPort !== undefined) statements.push({ set: 'zielPort', value: int(application.targetPort) });
|
||||
if (application.recursiveResolutionEnabled !== undefined) {
|
||||
statements.push({ set: 'recursiveResolutionEnabled', value: application.recursiveResolutionEnabled });
|
||||
}
|
||||
if (application.useVirtualHosts !== undefined) statements.push({ set: 'useVHost', value: application.useVirtualHosts });
|
||||
if (application.maxPeers !== undefined && application.maxPeers !== null) {
|
||||
statements.push({ set: 'maxTeilnehmerZahl', value: int(application.maxPeers) });
|
||||
}
|
||||
if (application.firewall !== undefined) statements.push(...firewallStatements(application.firewall));
|
||||
return statements;
|
||||
}
|
||||
|
||||
/** A LinkedList of String arrays: routes, static NAT. */
|
||||
function rows(table: readonly (readonly (string | null)[])[]): BeanObject {
|
||||
return listOf(table.map((row) => ({ kind: 'array', componentClass: 'java.lang.String', items: [...row] })));
|
||||
|
||||
Reference in New Issue
Block a user