add compatibility check - resolves #477

Sat, 02 Nov 2024 14:22:05 +0100

author
Mike Becker <universe@uap-core.de>
date
Sat, 02 Nov 2024 14:22:05 +0100
changeset 120
0e3827ebc6e4
parent 119
4152d98baed3
child 121
155cd224b51d

add compatibility check - resolves #477

src/main/java/de/unixwork/uwproj/CompatibilityCheck.java file | annotate | diff | comparison | revisions
src/main/java/de/unixwork/uwproj/Main.java file | annotate | diff | comparison | revisions
src/main/resources/make/project.xml file | annotate | diff | comparison | revisions
src/main/resources/make/uwproj.xsd file | annotate | diff | comparison | revisions
test/make/project.xml file | annotate | diff | comparison | revisions
test/make/project2.xml file | annotate | diff | comparison | revisions
test/make/uwproj.xsd file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/unixwork/uwproj/CompatibilityCheck.java	Sat Nov 02 14:22:05 2024 +0100
@@ -0,0 +1,35 @@
+package de.unixwork.uwproj;
+
+public class CompatibilityCheck {
+
+    private CompatibilityCheck() {}
+
+    private static int[] versionParts(String ver) {
+        if (ver.isBlank()) return new int[]{0,0,0};
+        final var partStrings = ver.split("\\.");
+        try {
+            return new int[]{
+                    partStrings.length > 0 ? Integer.parseInt(partStrings[0]) : 0,
+                    partStrings.length > 1 ? Integer.parseInt(partStrings[1]) : 0,
+                    partStrings.length > 2 ? Integer.parseInt(partStrings[2]) : 0
+            };
+        } catch (NumberFormatException e) {
+            return new int[]{0,0,0};
+        }
+    }
+
+    public static void check(String expected, String actual) throws CompatibilityException {
+        final var expectedVer = versionParts(expected);
+        final var actualVer = versionParts(actual);
+        if (expectedVer[0] > actualVer[0] || expectedVer[1] > actualVer[1]) {
+            if (actual.isBlank()) actual = "unspecified";
+            throw new CompatibilityException("Expected project file version '" + expected + "' but got '" + actual + "'.");
+        }
+    }
+
+    public static class CompatibilityException extends Exception {
+        public CompatibilityException(String message) {
+            super(message);
+        }
+    }
+}
--- a/src/main/java/de/unixwork/uwproj/Main.java	Sun Oct 06 14:02:50 2024 +0200
+++ b/src/main/java/de/unixwork/uwproj/Main.java	Sat Nov 02 14:22:05 2024 +0100
@@ -18,13 +18,27 @@
 import java.util.Objects;
 
 public class Main {
+    public static final String PROGRAM_VERSION = "0.3";
 
     public final static String IN_FILE_DEFAULT = "make/project.xml";
     public final static String TPL_FILE_DEFAULT = "make/configure.vm";
     public final static String OUT_FILE_DEFAULT = "configure";
 
-    static Project loadProjectFile(String fileName) {
+    static Project loadProjectFile(String fileName) throws CompatibilityCheck.CompatibilityException {
         try (final var xsdResource = Objects.requireNonNull(Main.class.getClassLoader().getResourceAsStream("make/uwproj.xsd"))) {
+            // Load the DOM from the input file
+            final var dom = DocumentBuilderFactory.
+                    newDefaultNSInstance().
+                    newDocumentBuilder().
+                    parse(fileName).
+                    getDocumentElement();
+
+            // Check the version, first
+            CompatibilityCheck.check(PROGRAM_VERSION, dom.getAttribute("version"));
+
+            // Parse the XML
+            final var proj = new Project(dom);
+
             // Create the XSD validator
             final var factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
             final var schema = factory.newSchema(new StreamSource(xsdResource));
@@ -33,21 +47,15 @@
             // Validate the XML as stream (DOM validation cannot output line numbers in error message)
             validator.validate(new StreamSource(new File(fileName)));
 
-            // Load the DOM from the input file
-            final var dom = DocumentBuilderFactory.
-                    newDefaultNSInstance().
-                    newDocumentBuilder().
-                    parse(fileName).
-                    getDocumentElement();
-
-            // Parse the XML
-            return new Project(dom);
+            return proj;
         } catch (SAXParseException saxerror) {
             System.err.printf("Parse error in line %d, column %d: %s",
                     saxerror.getLineNumber(),
                     saxerror.getColumnNumber(),
                     saxerror.getMessage());
             throw new RuntimeException("XML validation failed.");
+        } catch (CompatibilityCheck.CompatibilityException e) {
+            throw e;
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
@@ -207,8 +215,11 @@
                 writeConfigureScript(out, tplFileName, loadProjectFile(inFileName));
             }
             Files.copy(tmp.toPath(), outFilePath, StandardCopyOption.REPLACE_EXISTING);
+        } catch (CompatibilityCheck.CompatibilityException e) {
+            System.err.println("Compatibility problem: " + e.getMessage());
+            abort();
         } catch (Throwable t) {
-            System.err.printf("Unexpected error: %s\n", t.getMessage());
+            System.err.println("Unexpected error: " + t.getMessage());
             abort();
         }
 
@@ -216,7 +227,7 @@
         try {
             Files.setPosixFilePermissions(outFilePath, PosixFilePermissions.fromString("rwxr-xr-x"));
         } catch (Throwable t) {
-            System.err.printf("WARN: Setting file permissions failed: %s\n", t.getMessage());
+            System.err.println("WARN: Setting file permissions failed: " + t.getMessage());
         }
     }
 }
--- a/src/main/resources/make/project.xml	Sun Oct 06 14:02:50 2024 +0200
+++ b/src/main/resources/make/project.xml	Sat Nov 02 14:22:05 2024 +0100
@@ -1,4 +1,3 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://unixwork.de/uwproj">
+<project version="0.3" xmlns="http://unixwork.de/uwproj">
 </project>
-
--- a/src/main/resources/make/uwproj.xsd	Sun Oct 06 14:02:50 2024 +0200
+++ b/src/main/resources/make/uwproj.xsd	Sat Nov 02 14:22:05 2024 +0100
@@ -3,7 +3,7 @@
            xmlns="http://unixwork.de/uwproj"
            targetNamespace="http://unixwork.de/uwproj"
            elementFormDefault="qualified"
-           version="0.2"
+           version="0.3"
 >
     <xs:element name="project" type="ProjectType"/>
 
@@ -21,6 +21,7 @@
             <xs:element name="dependency" type="DependencyType" minOccurs="0" maxOccurs="unbounded"/>
             <xs:element name="target" type="TargetType" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
+        <xs:attribute name="version" type="xs:string" use="required" />
     </xs:complexType>
 
     <xs:complexType name="ConfigType">
--- a/test/make/project.xml	Sun Oct 06 14:02:50 2024 +0200
+++ b/test/make/project.xml	Sat Nov 02 14:22:05 2024 +0100
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://unixwork.de/uwproj">
+<project version="0.3" xmlns="http://unixwork.de/uwproj">
 	<!-- makefile config -->
 	<config not="mingw">
 		<var name="prefix">`pwd`/work</var>
--- a/test/make/project2.xml	Sun Oct 06 14:02:50 2024 +0200
+++ b/test/make/project2.xml	Sat Nov 02 14:22:05 2024 +0100
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://unixwork.de/uwproj">
+<project version="0.3" xmlns="http://unixwork.de/uwproj">
 	<dependency name="curl" platform="windows">
 		<cflags>-I/mingw/include</cflags>
 		<ldflags>-lcurl</ldflags>
--- a/test/make/uwproj.xsd	Sun Oct 06 14:02:50 2024 +0200
+++ b/test/make/uwproj.xsd	Sat Nov 02 14:22:05 2024 +0100
@@ -3,7 +3,7 @@
            xmlns="http://unixwork.de/uwproj"
            targetNamespace="http://unixwork.de/uwproj"
            elementFormDefault="qualified"
-           version="0.2"
+           version="0.3"
 >
     <xs:element name="project" type="ProjectType"/>
 
@@ -21,6 +21,7 @@
             <xs:element name="dependency" type="DependencyType" minOccurs="0" maxOccurs="unbounded"/>
             <xs:element name="target" type="TargetType" minOccurs="0" maxOccurs="unbounded"/>
         </xs:sequence>
+        <xs:attribute name="version" type="xs:string" use="required" />
     </xs:complexType>
 
     <xs:complexType name="ConfigType">

mercurial