From 89bdc84d7aca743992f5554053aca564aa348e61 Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Thu, 15 Feb 2024 10:50:04 -0600 Subject: [PATCH] Handle change in installDir between dev mode runs --- .../gradle/tasks/AbstractLibertyTask.groovy | 15 +++ .../gradle/tasks/AbstractServerTask.groovy | 2 + .../tools/gradle/tasks/CreateTask.groovy | 25 ++++- .../tools/gradle/tasks/DevTask.groovy | 29 ++++- .../gradle/tasks/InstallLibertyTask.groovy | 102 +++++++++++++++--- .../gradle/TestCreateConfigDirUpToDate.groovy | 6 +- 6 files changed, 158 insertions(+), 21 deletions(-) diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractLibertyTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractLibertyTask.groovy index d43ec2a3..66126577 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractLibertyTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractLibertyTask.groovy @@ -32,6 +32,21 @@ abstract class AbstractLibertyTask extends DefaultTask { protected String springBootVersion protected Task springBootTask + protected boolean isInstallDirChanged(Project project) { + + XmlParser pluginXmlParser = new XmlParser() + Node libertyPluginConfig = pluginXmlParser.parse(new File(project.buildDir, 'liberty-plugin-config.xml')) + if (!libertyPluginConfig.getAt('installDirectory').isEmpty()) { + Node installDirNode = libertyPluginConfig.getAt('installDirectory').get(0) + File previousInstallDir = new File(installDirNode.text()) + File currentInstallDir = getInstallDir(project) + if (previousInstallDir.exists() && previousInstallDir.equals(currentInstallDir)) { + return false + } + } + return true + } + protected getInstallDir = { Project project -> return Liberty.getInstallDir(project); } diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy index 1c5fd5a3..01c41fcb 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy @@ -380,6 +380,8 @@ abstract class AbstractServerTask extends AbstractLibertyTask { if (serverEnvPath != null && !serverEnvPath.isEmpty()) { logger.info("Update server configuration file server.env from " + serverEnvPath) } + + writeServerPropertiesToXml(project) } private void loadLibertyConfigFromProperties() { diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/CreateTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/CreateTask.groovy index 7db22dc4..2b3a51b6 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/CreateTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/CreateTask.groovy @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2014, 2023. + * (C) Copyright IBM Corporation 2014, 2024. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.Optional import org.gradle.api.tasks.TaskAction import org.gradle.api.logging.LogLevel +import org.gradle.api.Project class CreateTask extends AbstractServerTask { @@ -33,7 +34,7 @@ class CreateTask extends AbstractServerTask { group 'Liberty' }) outputs.upToDateWhen { - getServerDir(project).exists() && (new File(getServerDir(project), 'server.xml')).exists() + getServerDir(project).exists() && (new File(getServerDir(project), 'server.xml')).exists() && !isServerDirChanged(project) } } @@ -93,7 +94,25 @@ class CreateTask extends AbstractServerTask { logger.warn("The " + serverXmlFile.getAbsolutePath() + " does not exist. Copying over the defaultServer template server.xml file.") } copyConfigFiles() - writeServerPropertiesToXml(project) + } + + protected boolean isServerDirChanged(Project project) { + if (!project.buildDir.exists() || !(new File(project.buildDir, 'liberty-plugin-config.xml')).exists()) { + return false + } + + XmlParser pluginXmlParser = new XmlParser() + Node libertyPluginConfig = pluginXmlParser.parse(new File(project.buildDir, 'liberty-plugin-config.xml')) + if (!libertyPluginConfig.getAt('serverDirectory').isEmpty()) { + File currentDir = getServerDir(project) + File previousDir = new File(libertyPluginConfig.getAt('serverDirectory')[0].value) + if (previousDir.exists() && previousDir.equals(currentDir)) { + return false + } + return true + } + // if serverDirectory did not exist in the xml file, do not consider this as a change + return false } File getLibertyPropertyFile(File libertyPropertyFile, String fileName) { diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy index b0a8b639..292b7b65 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy @@ -1260,9 +1260,12 @@ class DevTask extends AbstractFeatureTask { } if (!isNewInstallation) { - logger.info("Skipping installLiberty task for existing installation.") - // will this cause an issue when changing the runtime? Customer would be forced to cleanup first? - gradleBuildLauncher.addArguments("--exclude-task", "installLiberty"); // skip installing Liberty at startup since it was already installed + // if the install dir changed or this is the first dev mode run on this project, need to give installLiberty task + // a chance to check validity of installation and update info in liberty plugin config xml file. + if (!isInstallDirChanged(project, serverInstallDir)) { + logger.info("Skipping installLiberty task for existing installation.") + gradleBuildLauncher.addArguments("--exclude-task", "installLiberty"); // skip installing Liberty at startup since it is the same installation as previous dev mode run + } if (skipInstallFeature) { logger.info("Skipping installFeature task due to skipInstallFeature configuration.") gradleBuildLauncher.addArguments("--exclude-task", "installFeature"); // skip installing features at startup since flag was set @@ -1324,6 +1327,26 @@ class DevTask extends AbstractFeatureTask { } } + private boolean isInstallDirChanged(Project project, File currentInstallDir) { + if (project.buildDir.exists() && new File(project.buildDir, 'liberty-plugin-config.xml').exists()) { + XmlParser pluginXmlParser = new XmlParser() + Node libertyPluginConfig = pluginXmlParser.parse(new File(project.buildDir, 'liberty-plugin-config.xml')) + if (!libertyPluginConfig.getAt('installDirectory').isEmpty()) { + Node installDirNode = libertyPluginConfig.getAt('installDirectory').get(0) + String installDirValue = installDirNode.text() + File previousInstallDir = new File(installDirValue) + if (previousInstallDir.exists() && previousInstallDir.equals(currentInstallDir)) { + return false + } else { + logger.info("Detected change in installDir location from "+installDirValue+" to "+currentInstallDir.getAbsolutePath()) + return true + } + } + } + return true + } + + private void addLibertyRuntimeProperties(BuildLauncher gradleBuildLauncher) { Set> entries = project.getProperties().entrySet() for (Entry entry : entries) { diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/InstallLibertyTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/InstallLibertyTask.groovy index 4b98602d..9bf24623 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/InstallLibertyTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/InstallLibertyTask.groovy @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2014, 2023. + * (C) Copyright IBM Corporation 2014, 2024. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package io.openliberty.tools.gradle.tasks import javax.xml.parsers.* +import groovy.xml.StreamingMarkupBuilder import org.gradle.api.Project import org.gradle.api.tasks.TaskAction @@ -52,7 +53,8 @@ class InstallLibertyTask extends AbstractLibertyTask { outputs.upToDateWhen { // ensure a Liberty installation exists at the install directory getInstallDir(project).exists() && new File(getInstallDir(project), 'lib/ws-launch.jar').exists() && - project.buildDir.exists() && new File(project.buildDir, 'liberty-plugin-config.xml').exists() + project.buildDir.exists() && new File(project.buildDir, 'liberty-plugin-config.xml').exists() && + !isInstallDirChanged(project) } } @@ -109,7 +111,9 @@ class InstallLibertyTask extends AbstractLibertyTask { @TaskAction void install() { // If installDir is set, then use the configured wlp or throw error if it is invalid - if(project.liberty.installDir != null && isLibertyInstalledAndValid(project)) { + boolean isExisting = false + if((project.liberty.installDir != null || project.hasProperty('liberty.installDir')) && isLibertyInstalledAndValid(project)) { + isExisting = true logger.info ("Liberty is already installed at: " + getInstallDir(project)) } else { def params = buildInstallLibertyMap(project) @@ -125,25 +129,94 @@ class InstallLibertyTask extends AbstractLibertyTask { process.waitFor() } } + createPluginXmlFile(isExisting) + } + + protected void updatePluginXmlFile() { + XmlParser pluginXmlParser = new XmlParser() + Node libertyPluginConfig = pluginXmlParser.parse(new File(project.buildDir, 'liberty-plugin-config.xml')) + + Node installDirNode = libertyPluginConfig.getAt('installDirectory').isEmpty() ? libertyPluginConfig.appendNode('installDirectory') : libertyPluginConfig.getAt('installDirectory').get(0) + installDirNode.setValue(getInstallDir(project).toString()) + //logger.info ("Updating liberty-plugin-config.xml installDirectory: " + getInstallDir(project).toString()) + + if (project.liberty.installDir != null || project.hasProperty('liberty.installDir')) { + // remove stale nodes + if (!libertyPluginConfig.getAt('assemblyArchive').isEmpty()) { + //logger.info ("Updating liberty-plugin-config.xml to remove assemblyArchive") + libertyPluginConfig.remove(libertyPluginConfig.getAt('assemblyArchive').get(0)) + } + if (!libertyPluginConfig.getAt('assemblyArtifact').isEmpty()) { + //logger.info ("Updating liberty-plugin-config.xml to remove assemblyArtifact") + libertyPluginConfig.remove(libertyPluginConfig.getAt('assemblyArtifact').get(0)) + } + } else if (detachedCoords != null) { + //logger.info ("Updating liberty-plugin-config.xml to update assemblyArtifact and assemblyArchive") + Node assemblyArchive = libertyPluginConfig.getAt('assemblyArchive').isEmpty() ? libertyPluginConfig.appendNode('assemblyArchive') : libertyPluginConfig.getAt('assemblyArchive').get(0) + Node assemblyArtifact = libertyPluginConfig.getAt('assemblyArtifact').isEmpty() ? libertyPluginConfig.appendNode('assemblyArtifact') : libertyPluginConfig.getAt('assemblyArtifact').get(0) + + //removes the child nodes from the assemblyArtifact element + assemblyArtifact.value = "" + + String[] coords = detachedCoords.split(":") + + assemblyArtifact.appendNode('groupId', coords[0]) + assemblyArtifact.appendNode('artifactId', coords[1]) + assemblyArtifact.appendNode('version', coords[2]) + assemblyArtifact.appendNode('type', 'zip') + + assemblyArchive.setValue(detachedConfigFilePath) + + } else if (project.configurations.libertyRuntime != null) { + //logger.info ("Updating liberty-plugin-config.xml to update assemblyArtifact and assemblyArchive") + Node assemblyArchive = libertyPluginConfig.getAt('assemblyArchive').isEmpty() ? libertyPluginConfig.appendNode('assemblyArchive') : libertyPluginConfig.getAt('assemblyArchive').get(0) + Node assemblyArtifact = libertyPluginConfig.getAt('assemblyArtifact').isEmpty() ? libertyPluginConfig.appendNode('assemblyArtifact') : libertyPluginConfig.getAt('assemblyArtifact').get(0) + + //removes the child nodes from the assemblyArtifact element + assemblyArtifact.value = "" + + project.configurations.libertyRuntime.dependencies.each { libertyArtifact -> + + assemblyArtifact.appendNode('groupId', libertyArtifact.group) + assemblyArtifact.appendNode('artifactId',libertyArtifact.name ) + assemblyArtifact.appendNode('version', libertyArtifact.version) + assemblyArtifact.appendNode('type', 'zip') + + assemblyArchive.setValue(project.configurations.libertyRuntime.resolvedConfiguration.resolvedArtifacts.getAt(0).file.toString()) + } + } + + new File( project.buildDir, 'liberty-plugin-config.xml' ).withWriter('UTF-8') { output -> + output << new StreamingMarkupBuilder().bind { mkp.xmlDeclaration(encoding: 'UTF-8', version: '1.0' ) } + XmlNodePrinter printer = new XmlNodePrinter( new PrintWriter(output) ) + printer.preserveWhitespace = true + printer.print( libertyPluginConfig ) + } + + logger.info ("Updating Liberty plugin config info at ${project.buildDir}/liberty-plugin-config.xml.") - createPluginXmlFile() } - protected void createPluginXmlFile() { + protected void createPluginXmlFile(boolean isExisting) { if(!this.state.upToDate) { if (!project.buildDir.exists()) { logger.info ("Creating missing project buildDir at ${project.buildDir}.") project.buildDir.mkdirs() } - new File(project.buildDir, 'liberty-plugin-config.xml').withWriter { writer -> - def xmlDoc = new MarkupBuilder(writer) - xmlDoc.mkp.xmlDeclaration(version: "1.0", encoding: "UTF-8") - xmlDoc.'liberty-plugin-config'('version':'2.0') { - outputLibertyPropertiesToXml(xmlDoc) + // if the file already exists, update it instead of replacing it + if (new File(project.buildDir, 'liberty-plugin-config.xml').exists()) { + updatePluginXmlFile() + } else { + new File(project.buildDir, 'liberty-plugin-config.xml').withWriter { writer -> + def xmlDoc = new MarkupBuilder(writer) + xmlDoc.mkp.xmlDeclaration(version: "1.0", encoding: "UTF-8") + xmlDoc.'liberty-plugin-config'('version':'2.0') { + outputLibertyPropertiesToXml(xmlDoc, isExisting) + } } + logger.info ("Creating Liberty plugin config info to ${project.buildDir}/liberty-plugin-config.xml.") } - logger.info ("Adding Liberty plugin config info to ${project.buildDir}/liberty-plugin-config.xml.") } } @@ -269,9 +342,14 @@ class InstallLibertyTask extends AbstractLibertyTask { return result } - protected void outputLibertyPropertiesToXml(MarkupBuilder xmlDoc) { + protected void outputLibertyPropertiesToXml(MarkupBuilder xmlDoc, boolean isExisting) { xmlDoc.installDirectory (getInstallDir(project).toString()) + // should only include assemblyArtifact and assemblyArchive if using an installation that was installed by our plugin + if (isExisting && ((project.liberty.installDir != null) || project.hasProperty('liberty.installDir'))) { + return + } + if (detachedCoords != null) { String[] coords = detachedCoords.split(":") xmlDoc.assemblyArtifact { diff --git a/src/test/groovy/io/openliberty/tools/gradle/TestCreateConfigDirUpToDate.groovy b/src/test/groovy/io/openliberty/tools/gradle/TestCreateConfigDirUpToDate.groovy index 432f725f..3f9c39cb 100644 --- a/src/test/groovy/io/openliberty/tools/gradle/TestCreateConfigDirUpToDate.groovy +++ b/src/test/groovy/io/openliberty/tools/gradle/TestCreateConfigDirUpToDate.groovy @@ -55,10 +55,10 @@ public class TestCreateConfigDirUpToDate extends AbstractIntegrationTest { testFileMessageString = "\\build\\testBuilds\\test-create-config-dir-up-to-date\\src\\main\\liberty\\config\\test.txt has changed." } - assert result.getOutput().contains(configDirMessageString) - assert result.getOutput().contains(testFileMessageString) + assert result.getOutput().contains(configDirMessageString) : "configDirMessageString not found in output: "+result.getOutput() + assert result.getOutput().contains(testFileMessageString) : "testFileMessageString not found in output: "+result.getOutput() //Check updated file was copied to server directory - assert serverTestTextFile.text.contains('Test Comment 2') + assert serverTestTextFile.text.contains('Test Comment 2') : "Test Comment 2 not found in "+serverTestTextFile.text } } \ No newline at end of file