Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion liberty-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
<dependency>
<groupId>io.openliberty.tools</groupId>
<artifactId>ci.common</artifactId>
<version>1.8.40-SNAPSHOT</version>
<version>1.8.40</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
<testServerHttpsPort>9443</testServerHttpsPort>
<!-- end::ports[] -->
<packaging.type>usr</packaging.type>

<!-- Variables for test dependencies -->
<pg.group.id>org.postgresql</pg.group.id>
<pg.artifact.id>postgresql</pg.artifact.id>
<pg.version>42.1.1</pg.version>
<pg.scope>test</pg.scope>
<custom.dir.location>customDirLocation</custom.dir.location>
</properties>

<dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;

import org.apache.commons.io.input.ReversedLinesFileReader;
import org.apache.commons.io.FileUtils;
Expand Down Expand Up @@ -421,14 +422,41 @@ private static void replaceVersion() throws IOException {
replaceString("RUNTIME_VERSION", runtimeVersion, pom);
}

protected static void replaceString(String str, String replacement, File file) throws IOException {
Path path = file.toPath();
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);

content = content.replaceAll(str, replacement);
Files.write(path, content.getBytes(charset));
}
/**
* Replaces all occurrences of a regex pattern in a file.
*
* @param str the regex pattern to search for
* @param replacement the replacement string (supports regex syntax like $1 for backreferences)
* @param file the file to modify
* @throws IOException if the file cannot be read or written
*/
protected static void replaceString(String str, String replacement, File file) throws IOException {
Path path = file.toPath();
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);

content = content.replaceAll(str, replacement);
Files.write(path, content.getBytes(charset));
}

/**
* Replaces all occurrences of a regex pattern in a file with a literal string.
* The replacement string is treated literally - special characters like $ and \ are escaped
* and not interpreted as regex syntax.
*
* @param str the regex pattern to search for
* @param replacement the literal replacement string (special characters are treated as plain text)
* @param file the file to modify
* @throws IOException if the file cannot be read or written
*/
protected static void replaceStringLiteral(String str, String replacement, File file) throws IOException {
Path path = file.toPath();
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);

content = content.replaceAll(str, Matcher.quoteReplacement(replacement));
Files.write(path, content.getBytes(charset));
}

protected static boolean verifyLogMessageExists(String message, int timeout)
throws InterruptedException, FileNotFoundException, IOException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*******************************************************************************
* (c) Copyright IBM Corporation 2025.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package net.wasdev.wlp.test.dev.it;

import static org.junit.Assert.*;

import java.io.File;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
* Test property resolution in copyDependencies location paths.
* This test verifies that Maven properties used in the location attribute
* of dependencyGroups are correctly resolved.
*/
public class DevCopyDependenciesLocationPropertyTest extends BaseDevTest {

@BeforeClass
public static void setUpBeforeClass() throws Exception {
setUpBeforeClass(null, "../resources/basic-dev-project", true, false, null, null);

// Add a provided-scoped dependency with property references
String additionalDependencies = "<dependency> <groupId>${pg.group.id}</groupId> <artifactId>${pg.artifact.id}</artifactId> <version>${pg.version}</version> <scope>provided</scope> </dependency>";
replaceStringLiteral("<!-- ADDITIONAL_DEPENDENCIES -->", additionalDependencies, pom);

// Configure copyDependencies with property reference in location
String additionalConfiguration = "<copyDependencies> <dependencyGroup> <location>${custom.dir.location}</location> <dependency> <groupId>${pg.group.id}</groupId> <artifactId>${pg.artifact.id}</artifactId> </dependency> </dependencyGroup> </copyDependencies>";
replaceStringLiteral("<!-- ADDITIONAL_CONFIGURATION -->", additionalConfiguration, pom);

startProcess(null, true);
}

@AfterClass
public static void cleanUpAfterClass() throws Exception {
BaseDevTest.cleanUpAfterClass();
}

@Test
public void propertyResolutionTest() throws Exception {
// This test verifies that Maven properties are resolved correctly in:
// 1. Dependency variables (${pg.group.id}, ${pg.artifact.id}, etc)
// 2. Location path (${custom.dir.location})

// Verify the dependency was copied successfully with resolved filename
assertTrue("Dependency copy log message not found: " + getLogTail(),
verifyLogMessageExists("copyDependencies copied file postgresql-42.1.1.jar", 2000));

// Verify that the location property was resolved (customDirLocation instead of ${custom.dir.location})
assertTrue("Location property resolution failed - expected 'customDirLocation' in log: "+getLogTail(),
verifyLogMessageExists("customDirLocation", 2000));

// Verify the file exists at the resolved location
File f = new File(targetDir, "liberty/wlp/usr/servers/defaultServer/customDirLocation/postgresql-42.1.1.jar");
assertTrue("Dependency was not copied to the resolved location: " + f.getAbsolutePath(), f.exists());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public class DevCopyTestDependenciesTest extends BaseDevTest {
public static void setUpBeforeClass() throws Exception {
setUpBeforeClass(null, "../resources/basic-dev-project", true, false, null, null);

String additionalDependencies = "<dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.1.1</version> <scope>test</scope> </dependency>";
replaceString("<!-- ADDITIONAL_DEPENDENCIES -->", additionalDependencies, pom);
String additionalDependencies = "<dependency> <groupId>${pg.group.id}</groupId> <artifactId>${pg.artifact.id}</artifactId> <version>${pg.version}</version> <scope>${pg.scope}</scope> </dependency>";
replaceStringLiteral("<!-- ADDITIONAL_DEPENDENCIES -->", additionalDependencies, pom);

String additionalConfiguration = "<copyDependencies> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> </copyDependencies>";
replaceString("<!-- ADDITIONAL_CONFIGURATION -->", additionalConfiguration, pom);
String additionalConfiguration = "<copyDependencies> <dependency> <groupId>${pg.group.id}</groupId> <artifactId>${pg.artifact.id}</artifactId> </dependency> </copyDependencies>";
replaceStringLiteral("<!-- ADDITIONAL_CONFIGURATION -->", additionalConfiguration, pom);

// add new parameter in first argument to skip install features on restart
// in this case, it should not skip install feature because Liberty was not previously installed
Expand Down Expand Up @@ -84,5 +84,5 @@ public void duplicatJvmOptionsTest() throws Exception {
assertTrue("-Xms512m not found on last line", nextLine.equals("-Xms512m"));
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@
package io.openliberty.tools.maven;

import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.HashSet;

import io.openliberty.tools.common.plugins.util.VariableUtility;
import io.openliberty.tools.maven.utils.CommonLogger;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
Expand Down Expand Up @@ -139,25 +143,10 @@ public boolean include(Artifact artifact) {

// Search the value parameter for any properties referenced with ${xxx} syntax and replace those with their property value if defined.
protected String resolvePropertyReferences(String value) {
String returnValue = value;

if (value != null) {
Matcher m = PROP_PATTERN.matcher(value);
while (m.find()) {
String varName = m.group(1);
if (project.getProperties().containsKey(varName)) {
String replacementValue = project.getProperties().getProperty(varName);
if (replacementValue != null) {
returnValue = returnValue.replace("${"+varName+"}", replacementValue);
getLog().info("Replaced Liberty configuration property reference ${"+varName+"} with value "+replacementValue);
}
} else {
getLog().debug("Could not replace property reference: "+varName+" in value: "+value);
}
}
}

return returnValue;
Properties projectProps = new Properties();
CommonLogger logger = new CommonLogger(getLog());
projectProps.putAll(project.getProperties());
return VariableUtility.resolveVariables(logger, value, Collections.emptyList(), projectProps, new Properties(), Collections.emptyMap());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,10 @@ private void copyDependencies() throws MojoExecutionException, IOException {
if (copyDependencies != null) {
List<Dependency> deps = copyDependencies.getDependencies();
boolean defaultStripVersion = copyDependencies.isStripVersion();

String defaultLocation = copyDependencies.getLocation();
defaultLocation = resolvePropertyReferences(defaultLocation);

File dftLocationFile = new File(defaultLocation);

if (!dftLocationFile.isAbsolute()) {
Expand All @@ -335,6 +338,9 @@ private void copyDependencies() throws MojoExecutionException, IOException {
}

for (Dependency dep : deps) {
// Resolve property references in dependency coordinates
resolveDependencyPropertyReferences(dep);

copyDependencies(dep, null, dftLocationPath, defaultStripVersion);
}

Expand All @@ -343,6 +349,7 @@ private void copyDependencies() throws MojoExecutionException, IOException {
for (DependencyGroup depGroup : depGroups) {
String overrideLocation = depGroup.getLocation();
if (overrideLocation != null) {
overrideLocation = resolvePropertyReferences(overrideLocation);
getLog().debug("copyDependencies to location: "+ overrideLocation);
} else {
getLog().debug("copyDependencies to location: "+dftLocationPath);
Expand All @@ -354,6 +361,9 @@ private void copyDependencies() throws MojoExecutionException, IOException {
}
List<Dependency> groupDeps = depGroup.getDependencies();
for (Dependency dep : groupDeps) {
// Resolve property references in dependency coordinates
resolveDependencyPropertyReferences(dep);

copyDependencies(dep, overrideLocation, dftLocationPath, stripVersion);
}
}
Expand Down Expand Up @@ -421,6 +431,24 @@ private void copyDependencies(Dependency dep, String overrideLocation, String de
}
}

private void resolveDependencyPropertyReferences(Dependency dep) {
if (dep.getGroupId() != null) {
dep.setGroupId(resolvePropertyReferences(dep.getGroupId()));
}
if (dep.getArtifactId() != null) {
dep.setArtifactId(resolvePropertyReferences(dep.getArtifactId()));
}
if (dep.getVersion() != null) {
dep.setVersion(resolvePropertyReferences(dep.getVersion()));
}
if (dep.getType() != null) {
dep.setType(resolvePropertyReferences(dep.getType()));
}
if (dep.getClassifier() != null) {
dep.setClassifier(resolvePropertyReferences(dep.getClassifier()));
}
}

/**
* @throws IOException
* @throws MojoExecutionException
Expand Down