diff --git a/src/main/java/io/openliberty/tools/common/plugins/config/ServerConfigDocument.java b/src/main/java/io/openliberty/tools/common/plugins/config/ServerConfigDocument.java index 386c0e3e..bdaaca58 100644 --- a/src/main/java/io/openliberty/tools/common/plugins/config/ServerConfigDocument.java +++ b/src/main/java/io/openliberty/tools/common/plugins/config/ServerConfigDocument.java @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2017, 2024. + * (C) Copyright IBM Corporation 2017, 2025. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -75,7 +75,8 @@ public class ServerConfigDocument { private Properties defaultProps; private Map libertyDirectoryPropertyToFile = null; - Optional springBootAppNodeLocation=Optional.empty(); + Optional springBootAppNodeLocation = Optional.empty(); + Optional springBootAppNodeDocumentURI = Optional.empty(); private static final XPathExpression XPATH_SERVER_APPLICATION; private static final XPathExpression XPATH_SERVER_WEB_APPLICATION; @@ -505,15 +506,13 @@ private void parseApplication(Document doc, XPathExpression expression) throws X NodeList nodeList = (NodeList) expression.evaluate(doc, XPathConstants.NODESET); if(expression.equals(XPATH_SERVER_SPRINGBOOT_APPLICATION) && nodeList.getLength()>1){ - throw new PluginExecutionException("Found multiple springBootApplication elements specified in the server configuration. Only one springBootApplication can be configured per Liberty server."); + throw new PluginExecutionException(String.format("Found multiple springBootApplication elements specified in the server configuration file %s. Only one springBootApplication can be configured per Liberty server.", doc.getDocumentURI())); } for (int i = 0; i < nodeList.getLength(); i++) { String nodeValue = nodeList.item(i).getAttributes().getNamedItem("location").getNodeValue(); // add unique values only if (!nodeValue.isEmpty()) { - if(expression.equals(XPATH_SERVER_SPRINGBOOT_APPLICATION)){ - springBootAppNodeLocation = Optional.of(nodeValue); - } + checkForSpringBootApplicationNode(doc, expression, nodeValue); String resolved = VariableUtility.resolveVariables(log, nodeValue, null, getProperties(), getDefaultProperties(), getLibertyDirPropertyFiles()); if (resolved == null) { // location could not be resolved, log message and add location as is @@ -529,6 +528,20 @@ private void parseApplication(Document doc, XPathExpression expression) throws X } } + private void checkForSpringBootApplicationNode(Document doc, XPathExpression expression, String nodeValue) throws PluginExecutionException { + if(expression.equals(XPATH_SERVER_SPRINGBOOT_APPLICATION)){ + // checking whether any springBootAppNodeLocation already configured from other server configuration files + if(springBootAppNodeLocation.isPresent() && springBootAppNodeDocumentURI.isPresent()){ + throw new PluginExecutionException(String.format("Found multiple springBootApplication elements specified in the server configuration in files [%s, %s]. Only one springBootApplication can be configured per Liberty server.", springBootAppNodeDocumentURI.get(), doc.getDocumentURI())); + } + else { + log.debug("Setting springBootApplication location as "+ nodeValue); + springBootAppNodeLocation = Optional.of(nodeValue); + springBootAppNodeDocumentURI = Optional.of(doc.getDocumentURI()); + } + } + } + private void parseInclude(Document doc) throws XPathExpressionException, IOException, SAXException, PluginExecutionException { // parse include document in source server xml NodeList nodeList = (NodeList) XPATH_SERVER_INCLUDE.evaluate(doc, XPathConstants.NODESET); @@ -550,9 +563,9 @@ private void parseInclude(Document doc) throws XPathExpressionException, IOExcep for (Document inclDoc : inclDocs) { parseApplication(inclDoc, XPATH_SERVER_APPLICATION); parseApplication(inclDoc, XPATH_SERVER_WEB_APPLICATION); - parseApplication(doc, XPATH_SERVER_SPRINGBOOT_APPLICATION); + parseApplication(inclDoc, XPATH_SERVER_SPRINGBOOT_APPLICATION); parseApplication(inclDoc, XPATH_SERVER_ENTERPRISE_APPLICATION); - parseNames(doc, XPATH_ALL_SERVER_APPLICATIONS); + parseNames(inclDoc, XPATH_ALL_SERVER_APPLICATIONS); // handle nested include elements parseInclude(inclDoc); } @@ -707,7 +720,9 @@ private void parseDocumentsInDirectory(File directory, ArrayList docs) */ public Document parseDocument(File file) throws FileNotFoundException, IOException { try (FileInputStream is = new FileInputStream(file)) { - return parseDocument(is); + Document document= parseDocument(is); + document.setDocumentURI(file.getCanonicalPath()); + return document; } catch (SAXException ex) { // If the file was not valid XML, assume it was some other non XML // file in dropins. diff --git a/src/test/java/io/openliberty/tools/common/config/ServerConfigDocumentOverridesTest.java b/src/test/java/io/openliberty/tools/common/config/ServerConfigDocumentOverridesTest.java index d9a3888c..0b455b93 100644 --- a/src/test/java/io/openliberty/tools/common/config/ServerConfigDocumentOverridesTest.java +++ b/src/test/java/io/openliberty/tools/common/config/ServerConfigDocumentOverridesTest.java @@ -38,6 +38,7 @@ public class ServerConfigDocumentOverridesTest { private final static Path SERVER_CONFIG_DIR = WLP_USER_DIR.resolve("servers/defaultServer"); private final static Path SHARED_CONFIG_DIR = WLP_USER_DIR.resolve("shared"); private final static Path SERVERS_RESOURCES_DIR = RESOURCES_DIR.resolve("servers/"); + private final static Path SERVER_CONFIG_INCLUDE_DIR = SERVER_CONFIG_DIR.resolve("includes"); // 1. variable default values in server.xml file // 6. variable values declared in the server.xml file @@ -277,4 +278,28 @@ public void testServerConfigDocumentForLCLS() throws IOException, PluginExecutio assertEquals("ServerConfigDocument http.port variable is not assigned properly ", "1111", configDocument.getProperties().getProperty("http.port")); assertEquals("ServerConfigDocument includeLocation default property is not assigned properly ", "includes", configDocument.getDefaultProperties().getProperty("includeLocation")); } + + @Test + public void testProcessServerXmlWithMultipleSpringBootNodesInMultipleConfigFiles() throws IOException{ + // we have added in valid_server.xml and included_server.xml + File serverConfigDir = SERVER_CONFIG_DIR.toFile(); + Map libertyDirPropMap = new HashMap(); + libertyDirPropMap.put(ServerFeatureUtil.SERVER_CONFIG_DIR, serverConfigDir); + libertyDirPropMap.put(ServerFeatureUtil.WLP_INSTALL_DIR, WLP_DIR.toFile()); + libertyDirPropMap.put(ServerFeatureUtil.WLP_USER_DIR, WLP_USER_DIR.toFile()); + libertyDirPropMap.put(ServerFeatureUtil.SHARED_CONFIG_DIR, SHARED_CONFIG_DIR.toFile()); + File serversResourceDir = SERVERS_RESOURCES_DIR.toFile(); + File springBootServerXmlDir = new File(serversResourceDir, "springBootApplicationTest"); + + File includedServerXml = new File(springBootServerXmlDir, "included_server.xml"); + File newIncludedServerXml = new File(SERVER_CONFIG_INCLUDE_DIR.toFile(), "included_server.xml"); + Files.copy(includedServerXml.toPath(), newIncludedServerXml.toPath(), StandardCopyOption.REPLACE_EXISTING); + File validServerXml = new File(springBootServerXmlDir, "valid_server.xml"); + File newValidServerXml = new File(SERVER_CONFIG_INCLUDE_DIR.toFile(), "valid_server.xml"); + Files.copy(validServerXml.toPath(), newValidServerXml.toPath(), StandardCopyOption.REPLACE_EXISTING); + assertThrows("Expected multiple springBootApplication elements specified in the server configuration. Only one springBootApplication node is found.", + PluginExecutionException.class, () -> new ServerConfigDocument(new TestLogger(), null, libertyDirPropMap)); + Files.delete(newIncludedServerXml.toPath()); + Files.delete(newValidServerXml.toPath()); + } } \ No newline at end of file diff --git a/src/test/resources/serverConfig/liberty/wlp/usr/servers/defaultServer/server.xml b/src/test/resources/serverConfig/liberty/wlp/usr/servers/defaultServer/server.xml index 77dfb53b..03ab3bde 100644 --- a/src/test/resources/serverConfig/liberty/wlp/usr/servers/defaultServer/server.xml +++ b/src/test/resources/serverConfig/liberty/wlp/usr/servers/defaultServer/server.xml @@ -26,4 +26,7 @@ + + + \ No newline at end of file diff --git a/src/test/resources/servers/springBootApplicationTest/included_server.xml b/src/test/resources/servers/springBootApplicationTest/included_server.xml new file mode 100644 index 00000000..9c2cb215 --- /dev/null +++ b/src/test/resources/servers/springBootApplicationTest/included_server.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file