From 08ede30460a5d0c6eff7eae479cfd38d9747d0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20B=C3=A4ck?= Date: Fri, 26 Feb 2021 11:30:26 +0100 Subject: [PATCH 1/2] Make file paths separator-agnostic to fix non-Windows executions Rework various constants in EiffelConstants to be java.nio.file.Path objects instead of strings. That makes the intention of the constants clear and we can easily work with Path objects to generate correct paths on any platform. --- .../clone/PrepareLocalEiffelSchemas.java | 27 +++++++-------- .../semantics/schemas/EiffelConstants.java | 11 ++++--- .../remrem/semantics/schemas/LocalRepo.java | 33 ++++++++++--------- .../remrem/semantics/schemas/SchemaFile.java | 8 ++--- 4 files changed, 43 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/ericsson/eiffel/remrem/semantics/clone/PrepareLocalEiffelSchemas.java b/src/main/java/com/ericsson/eiffel/remrem/semantics/clone/PrepareLocalEiffelSchemas.java index b3660f3a..06fcb0b6 100644 --- a/src/main/java/com/ericsson/eiffel/remrem/semantics/clone/PrepareLocalEiffelSchemas.java +++ b/src/main/java/com/ericsson/eiffel/remrem/semantics/clone/PrepareLocalEiffelSchemas.java @@ -23,6 +23,8 @@ import java.net.ProxySelector; import java.net.SocketAddress; import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -64,17 +66,17 @@ public class PrepareLocalEiffelSchemas { * @param localEiffelRepoPath * destination path to clone the repo. */ - private void cloneEiffelRepo(final String repoURL, final String branch, final File localEiffelRepoPath) { + private void cloneEiffelRepo(final String repoURL, final String branch, final Path localEiffelRepoPath) { Git localGitRepo = null; // checking for repository exists or not in the localEiffelRepoPath try { - if (!localEiffelRepoPath.exists()) { + if (Files.notExists(localEiffelRepoPath)) { // cloning github repository by using URL and branch name into local - localGitRepo = Git.cloneRepository().setURI(repoURL).setBranch("master").setDirectory(localEiffelRepoPath).call(); + localGitRepo = Git.cloneRepository().setURI(repoURL).setBranch("master").setDirectory(localEiffelRepoPath.toFile()).call(); } else { // If required repository already exists - localGitRepo = Git.open(localEiffelRepoPath); + localGitRepo = Git.open(localEiffelRepoPath.toFile()); // Reset to normal if uncommitted changes are present localGitRepo.reset().call(); @@ -152,12 +154,12 @@ public PasswordAuthentication getPasswordAuthentication() { * @param eiffelRepoPath * local eiffel repository url */ - private void copyOperationSchemas(final String operationsRepoPath, final String eiffelRepoPath) { - final File operationSchemas = new File(operationsRepoPath + File.separator + EiffelConstants.SCHEMA_LOCATION); - final File eiffelSchemas = new File(eiffelRepoPath + File.separator + EiffelConstants.SCHEMA_LOCATION); - if (operationSchemas.isDirectory()) { + private void copyOperationSchemas(final Path operationsRepoPath, final Path eiffelRepoPath) { + final Path operationSchemas = operationsRepoPath.resolve(EiffelConstants.SCHEMA_LOCATION); + final Path eiffelSchemas = eiffelRepoPath.resolve(EiffelConstants.SCHEMA_LOCATION); + if (Files.isDirectory(operationSchemas)) { try { - FileUtils.copyDirectory(operationSchemas, eiffelSchemas); + FileUtils.copyDirectory(operationSchemas.toFile(), eiffelSchemas.toFile()); } catch (IOException e) { System.out.println("Exception occurred while copying schemas from operations repository to eiffel repository"); e.printStackTrace(); @@ -176,9 +178,8 @@ public static void main(String[] args) throws IOException { final String operationRepoUrl = args[2]; final String operationRepoBranch = args[3]; - final File localEiffelRepoPath = new File(System.getProperty(EiffelConstants.USER_HOME) + File.separator + EiffelConstants.EIFFEL); - final File localOperationsRepoPath = new File( - System.getProperty(EiffelConstants.USER_HOME) + File.separator + EiffelConstants.OPERATIONS_REPO_NAME); + final Path localEiffelRepoPath = EiffelConstants.USER_HOME.resolve(EiffelConstants.EIFFEL); + final Path localOperationsRepoPath = EiffelConstants.USER_HOME.resolve(EiffelConstants.OPERATIONS_REPO_NAME); // Clone Eiffel Repo from GitHub prepareLocalSchema.cloneEiffelRepo(eiffelRepoUrl, eiffelRepoBranch, localEiffelRepoPath); @@ -187,7 +188,7 @@ public static void main(String[] args) throws IOException { prepareLocalSchema.cloneEiffelRepo(operationRepoUrl, operationRepoBranch, localOperationsRepoPath); //Copy operations repo Schemas to location where Eiffel repo schemas available - prepareLocalSchema.copyOperationSchemas(localOperationsRepoPath.getAbsolutePath(), localEiffelRepoPath.getAbsolutePath()); + prepareLocalSchema.copyOperationSchemas(localOperationsRepoPath.toAbsolutePath(), localEiffelRepoPath.toAbsolutePath()); // Read and Load JsonSchemas from Cloned Directory final LocalRepo localRepo = new LocalRepo(localEiffelRepoPath); diff --git a/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/EiffelConstants.java b/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/EiffelConstants.java index 157bab0c..8230a58e 100644 --- a/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/EiffelConstants.java +++ b/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/EiffelConstants.java @@ -14,6 +14,9 @@ */ package com.ericsson.eiffel.remrem.semantics.schemas; +import java.nio.file.Path; +import java.nio.file.Paths; + /** * This is a constants class used in other classes * @@ -41,13 +44,13 @@ public final class EiffelConstants { public static String COM_ERICSSON_EIFFEL_SEMANTICS_EVENTS = "com.ericsson.eiffel.semantics.events."; public static String TYPE = "type"; public static String OBJECTTYPE = "object"; - public static String INPUT_EIFFEL_SCHEMAS = "src\\main\\resources\\schemas\\input"; + public static Path INPUT_EIFFEL_SCHEMAS = Paths.get("src", "main", "resources", "schemas", "input"); public static String EIFFEL = "eiffel"; public static String OPERATIONS_REPO_NAME = "eiffel-operations-extension"; - public static String USER_DIR = System.getProperty("user.dir"); - public static String SCHEMA_LOCATION = "\\schemas"; + public static Path USER_DIR = Paths.get(System.getProperty("user.dir")); + public static Path SCHEMA_LOCATION = Paths.get("schemas"); public static String JSON_MIME_TYPE = ".json"; - public static String USER_HOME = "user.home"; + public static Path USER_HOME = Paths.get(System.getProperty("user.home")); public static String ACTIVITY = "activity"; public static String ARTIFACT = "artifact"; public static String SERVICE = "service"; diff --git a/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/LocalRepo.java b/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/LocalRepo.java index 0198afeb..90b68a89 100644 --- a/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/LocalRepo.java +++ b/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/LocalRepo.java @@ -16,6 +16,10 @@ import java.io.File; import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import org.apache.commons.io.FileUtils; @@ -29,10 +33,10 @@ */ public class LocalRepo { private ArrayList jsonEventSchemas; - private File localSchemasPath; + private Path localSchemasPath; private ArrayList jsonEventNames; - public LocalRepo(File localSchemasPath) { + public LocalRepo(Path localSchemasPath) { this.localSchemasPath = localSchemasPath; } @@ -41,16 +45,15 @@ public LocalRepo(File localSchemasPath) { * Repo */ - public void readSchemas() { + public void readSchemas() throws IOException { try { - FileUtils.cleanDirectory(new File(EiffelConstants.USER_DIR + File.separator + EiffelConstants.INPUT_EIFFEL_SCHEMAS)); + FileUtils.cleanDirectory(EiffelConstants.USER_DIR.resolve(EiffelConstants.INPUT_EIFFEL_SCHEMAS).toFile()); } catch (IOException e) { e.printStackTrace(); } jsonEventNames = new ArrayList(); jsonEventSchemas = new ArrayList(); - String filePath = localSchemasPath + EiffelConstants.SCHEMA_LOCATION; - loadEiffelSchemas(filePath, ""); + loadEiffelSchemas(localSchemasPath.resolve(EiffelConstants.SCHEMA_LOCATION), Paths.get("")); } /** @@ -65,15 +68,15 @@ public void readSchemas() { * event name. * */ - private void loadEiffelSchemas(String jsonFilePath, String directoryName) { - File file = new File(jsonFilePath); - File[] files = file.listFiles(); - for (File jsonFile : files) { - if (jsonFile.isDirectory()) { - loadEiffelSchemas(jsonFile.getAbsolutePath(), jsonFile.getName()); - } else { - jsonEventNames.add(directoryName); - jsonEventSchemas.add(jsonFile); + private void loadEiffelSchemas(Path jsonFilePath, Path directoryName) throws IOException { + try (DirectoryStream dirStream = Files.newDirectoryStream(jsonFilePath)) { + for (Path jsonFile : dirStream) { + if (Files.isDirectory(jsonFile)) { + loadEiffelSchemas(jsonFile.toAbsolutePath(), jsonFile.getFileName()); + } else { + jsonEventNames.add(directoryName.toString()); + jsonEventSchemas.add(jsonFile.toFile()); + } } } } diff --git a/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/SchemaFile.java b/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/SchemaFile.java index 4f0edeaf..113aa9a5 100644 --- a/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/SchemaFile.java +++ b/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/SchemaFile.java @@ -17,6 +17,7 @@ import java.io.File; import java.io.FileWriter; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Iterator; import java.util.Map.Entry; @@ -236,16 +237,15 @@ private void addingItemsProperties(String elementName, JsonElement jsonValue, Js * an input parameter to this method */ public void createNewInputJsonSchema(String jsonFileName, JsonObject jsonObject) { - String currentWorkingDir = EiffelConstants.USER_DIR; FileWriter writer = null; - String copyFilePath = currentWorkingDir + File.separator + EiffelConstants.INPUT_EIFFEL_SCHEMAS; - String newFileName = copyFilePath + File.separator + jsonFileName + EiffelConstants.JSON_MIME_TYPE; + Path newFileName = EiffelConstants.USER_DIR.resolve(EiffelConstants.INPUT_EIFFEL_SCHEMAS) + .resolve(jsonFileName + EiffelConstants.JSON_MIME_TYPE); Gson gson = new GsonBuilder().setPrettyPrinting().create(); JsonParser jp = new JsonParser(); JsonElement je = jp.parse(jsonObject.toString()); String prettyJsonString = gson.toJson(je); try { - writer = new FileWriter(newFileName); + writer = new FileWriter(newFileName.toFile()); writer.write(prettyJsonString); } catch (Exception e) { e.printStackTrace(); From b9e98523fdd45a2cc951c1f028a85bbd8388d02e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20B=C3=A4ck?= Date: Fri, 26 Feb 2021 11:30:29 +0100 Subject: [PATCH 2/2] Make schema generation independent of order of files returned from OS Previously all versions of the events were returned and they were all converted and written to the same destination file. This happened to work fine when the list of files returned from File.listFiles() was in the correct order so that the latest version was the last file to be processed. If that wasn't the case one or more schema files didn't get the most recent version of the event. We address this by using a version string parser to sort the filenames in version order before picking the greatest version and generating a schema from that file only. --- pom.xml | 5 ++ .../clone/PrepareLocalEiffelSchemas.java | 19 +++---- .../remrem/semantics/schemas/LocalRepo.java | 50 ++++++++----------- 3 files changed, 32 insertions(+), 42 deletions(-) diff --git a/pom.xml b/pom.xml index 40fb034d..deb32501 100644 --- a/pom.xml +++ b/pom.xml @@ -42,6 +42,11 @@ jackson-databind compile + + com.vdurmont + semver4j + 3.1.0 + org.glassfish.hk2.external javax.inject diff --git a/src/main/java/com/ericsson/eiffel/remrem/semantics/clone/PrepareLocalEiffelSchemas.java b/src/main/java/com/ericsson/eiffel/remrem/semantics/clone/PrepareLocalEiffelSchemas.java index 06fcb0b6..3e6b2086 100644 --- a/src/main/java/com/ericsson/eiffel/remrem/semantics/clone/PrepareLocalEiffelSchemas.java +++ b/src/main/java/com/ericsson/eiffel/remrem/semantics/clone/PrepareLocalEiffelSchemas.java @@ -14,7 +14,6 @@ */ package com.ericsson.eiffel.remrem.semantics.clone; -import java.io.File; import java.io.IOException; import java.net.Authenticator; import java.net.InetSocketAddress; @@ -25,10 +24,10 @@ import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.ResourceBundle; import org.apache.commons.io.FileUtils; @@ -194,18 +193,12 @@ public static void main(String[] args) throws IOException { final LocalRepo localRepo = new LocalRepo(localEiffelRepoPath); localRepo.readSchemas(); - final ArrayList jsonEventNames = localRepo.getJsonEventNames(); - final ArrayList jsonEventSchemas = localRepo.getJsonEventSchemas(); - - // Schema changes + // Schema changes final SchemaFile schemaFile = new SchemaFile(); - // Iterate the Each jsonSchema file to Add and Modify the necessary properties - if (jsonEventNames != null && jsonEventSchemas != null) { - for (int i = 0; i < jsonEventNames.size(); i++) { - schemaFile.modify(jsonEventSchemas.get(i), jsonEventNames.get(i)); - } + // Iterate over available input schemas and create new and patched files + for (Map.Entry event : localRepo.getJsonEventSchemas().entrySet()) { + schemaFile.modify(event.getValue().toFile(), event.getKey()); } - } -} \ No newline at end of file +} diff --git a/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/LocalRepo.java b/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/LocalRepo.java index 90b68a89..0f77a556 100644 --- a/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/LocalRepo.java +++ b/src/main/java/com/ericsson/eiffel/remrem/semantics/schemas/LocalRepo.java @@ -14,15 +14,16 @@ */ package com.ericsson.eiffel.remrem.semantics.schemas; -import java.io.File; +import com.vdurmont.semver4j.Semver; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; - +import java.util.HashMap; +import java.util.Map; +import java.util.stream.StreamSupport; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; /** * This class is used to Iterate over the Eiffel schemas that are cloned from @@ -32,9 +33,8 @@ * */ public class LocalRepo { - private ArrayList jsonEventSchemas; + private final Map jsonEventSchemas = new HashMap<>(); private Path localSchemasPath; - private ArrayList jsonEventNames; public LocalRepo(Path localSchemasPath) { this.localSchemasPath = localSchemasPath; @@ -51,9 +51,7 @@ public void readSchemas() throws IOException { } catch (IOException e) { e.printStackTrace(); } - jsonEventNames = new ArrayList(); - jsonEventSchemas = new ArrayList(); - loadEiffelSchemas(localSchemasPath.resolve(EiffelConstants.SCHEMA_LOCATION), Paths.get("")); + loadEiffelSchemas(localSchemasPath.resolve(EiffelConstants.SCHEMA_LOCATION)); } /** @@ -63,32 +61,26 @@ public void readSchemas() throws IOException { * @param jsonFilePath * - This parameter is used to pass Location of the Schemas * Directory - * @param directoryName - * - This parameter is used to rename the File with corresponding - * event name. - * */ - private void loadEiffelSchemas(Path jsonFilePath, Path directoryName) throws IOException { - try (DirectoryStream dirStream = Files.newDirectoryStream(jsonFilePath)) { - for (Path jsonFile : dirStream) { - if (Files.isDirectory(jsonFile)) { - loadEiffelSchemas(jsonFile.toAbsolutePath(), jsonFile.getFileName()); - } else { - jsonEventNames.add(directoryName.toString()); - jsonEventSchemas.add(jsonFile.toFile()); + private void loadEiffelSchemas(final Path jsonFilePath) throws IOException { + try (DirectoryStream schemaDirStream = + Files.newDirectoryStream(jsonFilePath, Files::isDirectory)) { + for (Path eventDir : schemaDirStream) { + try (DirectoryStream eventDirStream = + Files.newDirectoryStream(eventDir, file -> file.toString().endsWith(".json"))) { + // Turn the filenames into versions and find the greatest version + Semver latestSchemaVersion = StreamSupport.stream(eventDirStream.spliterator(), false) + .map(path -> new Semver(FilenameUtils.removeExtension(path.getFileName().toString()))) + .max(Semver::compareTo) + .get(); + jsonEventSchemas.put(eventDir.getFileName().toString(), + eventDir.resolve(latestSchemaVersion.toString() + ".json")); } } } } - public ArrayList getJsonEventSchemas() { + public Map getJsonEventSchemas() { return jsonEventSchemas; } - - public ArrayList getJsonEventNames() { - return jsonEventNames; - } - - - }