Skip to content

Commit

Permalink
Additional support for multi-module loose ear applications
Browse files Browse the repository at this point in the history
  • Loading branch information
mattbsox committed Apr 12, 2023
1 parent 90de9bf commit 70c8acc
Show file tree
Hide file tree
Showing 12 changed files with 379 additions and 25 deletions.
60 changes: 44 additions & 16 deletions src/main/groovy/io/openliberty/tools/gradle/tasks/DeployTask.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import io.openliberty.tools.common.plugins.config.ApplicationXmlDocument
import io.openliberty.tools.common.plugins.config.LooseApplication
import io.openliberty.tools.common.plugins.config.LooseConfigData
import io.openliberty.tools.common.plugins.config.ServerConfigDocument
import io.openliberty.tools.common.plugins.util.DevUtil;
import io.openliberty.tools.common.plugins.util.DevUtil
import io.openliberty.tools.common.plugins.util.OSUtil

import org.apache.commons.io.FilenameUtils
import org.gradle.api.artifacts.UnknownConfigurationException
Expand All @@ -42,6 +43,7 @@ import java.lang.NumberFormatException
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.text.MessageFormat
import java.util.HashSet
import java.util.regex.Matcher
import java.util.regex.Pattern
import java.io.File
Expand Down Expand Up @@ -345,7 +347,7 @@ class DeployTask extends AbstractServerTask {
return false;
}

private void addWarEmbeddedLib(Element parent, LooseWarApplication looseApp, Task task) throws Exception {
private void addWarEmbeddedLib(Element parent, LooseApplication looseApp, Task task) throws Exception {
ArrayList<File> deps = new ArrayList<File>();
task.classpath.each {
deps.add(it)
Expand All @@ -357,8 +359,12 @@ class DeployTask extends AbstractServerTask {
File parentProjectDir = new File(task.getProject().getRootProject().rootDir.getAbsolutePath())
for (File dep: deps) {
String dependencyProjectName = getProjectPath(parentProjectDir, dep)
String projectDependencyString = "project ':" + dependencyProjectName + "'"
Project siblingProject = project.getRootProject().findProject(dependencyProjectName)
String projectDependencyString
Project siblingProject
if (dependencyProjectName != null && !dependencyProjectName.isEmpty()) {
projectDependencyString = "project ':" + dependencyProjectName + "'"
siblingProject = project.getRootProject().findProject(dependencyProjectName)
}
boolean isCurrentProject = ((task.getProject().toString()).equals(projectDependencyString))
if (!isCurrentProject && siblingProject != null) {
Element archive = looseApp.addArchive(parent, "/WEB-INF/lib/" + dep.getName());
Expand Down Expand Up @@ -428,7 +434,12 @@ class DeployTask extends AbstractServerTask {
break;
case "war":
Element warElement = looseEar.addWarModule(dependencyProject)
addEmbeddedLib(warElement, dependencyProject, looseEar, "/WEB-INF/lib/")
Task warTask = dependencyProject.getTasks().findByName('war')
if (warTask != null) {
addWarEmbeddedLib(warElement, looseEar, warTask)
} else {
addEmbeddedLib(warElement, dependencyProject, looseEar, "/WEB-INF/lib/")
}
break;
default:
logger.warn('Application ' + dependencyProject.getName() + ' is expressed as ' + projectType + ' which is not a supported input type. Define applications using Task or File objects of type war, ear, or jar.')
Expand Down Expand Up @@ -522,14 +533,20 @@ class DeployTask extends AbstractServerTask {

private void addEmbeddedLib(Element parent, Project project, LooseApplication looseApp, String dir) throws Exception {
try {
if (project.configurations.getByName('compile') != null) {
//Get only the compile dependencies that are included in the war
File[] filesAsDeps = project.configurations.compile.minus(project.configurations.providedCompile).getFiles().toArray()
for (File f : filesAsDeps){
String extension = FilenameUtils.getExtension(f.getAbsolutePath())
if(extension.equals("jar")){
addLibrary(parent, looseApp, dir, f);
}
Set<File> filesAsDeps = new HashSet<File>()
//Get the compile and implementation dependencies that are included in the war
if (project.configurations.findByName('compile') != null) {
Set<File> compileDepFiles = project.configurations.compile.minus(project.configurations.providedCompile).getFiles()
filesAsDeps.addAll(compileDepFiles)
}
if (project.configurations.findByName('impementation') != null) {
Set<File> implementationDepFiles = project.configurations.implementation.minus(project.configurations.providedCompile).getFiles()
filesAsDeps.addAll(implementationDepFiles)
}
for (File f : filesAsDeps){
String extension = FilenameUtils.getExtension(f.getAbsolutePath())
if(extension.equals("jar")){
addLibrary(parent, looseApp, dir, f);
}
}
} catch (UnknownConfigurationException uce) {
Expand All @@ -553,12 +570,23 @@ class DeployTask extends AbstractServerTask {
}

private String getProjectPath(File parentProjectDir, File dep) {
String dependencyPathPortion = dep.getAbsolutePath().replace(parentProjectDir.getAbsolutePath()+"/","")
String dependencyPathPortion = dep.getAbsolutePath().replace(parentProjectDir.getAbsolutePath(),"")
String projectPath = dep.getAbsolutePath().replace(dependencyPathPortion,"")
Pattern pattern = Pattern.compile("/build/.*")
Pattern pattern
if (OSUtil.isWindows()) {
pattern = Pattern.compile("\\\\build\\\\.*")
} else {
pattern = Pattern.compile("/build/.*")
}
Matcher matcher = pattern.matcher(dependencyPathPortion)
projectPath = matcher.replaceAll("")
return projectPath;

//Remove leading slash character from trimmed path
if (projectPath.length() > 1) {
projectPath = projectPath.substring(1, projectPath.length())
}

return projectPath
}

private boolean isSupportedType(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ public class LooseEarApplication extends LooseApplication {
config.addFile(moduleArchive, f, "/WEB-INF/lib/" + f.getName());
break
case "MF":
addManifestFileWithParent(moduleArchive, f)
//This checks the manifest file and resource directory of the project's jar source set.
//The location of the resource directory should be the same as proj.getProjectDir()/build/resources.
//If the manifest file exists, it is copied to proj.getProjectDir()/build/resources/tmp/META-INF. If it does not exist, one is created there.
addManifestFileWithParent(moduleArchive, f, proj.sourceSets.main.getOutput().getResourcesDir().getParentFile().getCanonicalPath())
break
default:
break
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import io.openliberty.tools.common.plugins.util.OSUtil

public class TestLooseWarWithLooseJar extends AbstractIntegrationTest{
static File resourceDir = new File("build/resources/test/loose-war-with-loose-jar")
static File buildDir = new File(integTestDir, "/loose-war-with-loose-jar")
Expand Down Expand Up @@ -93,8 +95,13 @@ public class TestLooseWarWithLooseJar extends AbstractIntegrationTest{

//Check loose jar classes dir location
String nodeValue = nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
Assert.assertEquals("sibling archive targetInArchive attribute value", buildDir.getCanonicalPath() + "/ejb-ejb/build/classes/java/main",
nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue());
if (OSUtil.isWindows()) {
Assert.assertEquals("sibling archive targetInArchive attribute value", buildDir.getCanonicalPath() + "\\ejb-ejb\\build\\classes\\java\\main",
nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue());
} else {
Assert.assertEquals("sibling archive targetInArchive attribute value", buildDir.getCanonicalPath() + "/ejb-ejb/build/classes/java/main",
nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue());
}

//Check loose jar contains correct amount of file elements
expression = "/archive/archive/file";
Expand All @@ -103,33 +110,51 @@ public class TestLooseWarWithLooseJar extends AbstractIntegrationTest{

//Check loose jar manifest file location
nodeValue = nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
Assert.assertEquals("sibling archive targetInArchive attribute value", buildDir.getCanonicalPath() + "/ejb-ejb/build/resources/tmp/META-INF/MANIFEST.MF",
nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue());
if (OSUtil.isWindows()) {
Assert.assertEquals("sibling archive targetInArchive attribute value", buildDir.getCanonicalPath() + "\\ejb-ejb\\build\\resources\\tmp\\META-INF\\MANIFEST.MF",
nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue());
} else {
Assert.assertEquals("sibling archive targetInArchive attribute value", buildDir.getCanonicalPath() + "/ejb-ejb/build/resources/tmp/META-INF/MANIFEST.MF",
nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue());
}


//Check correct number of additional file elements are present
expression = "/archive/file";
nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
Assert.assertEquals("Number of <file/> element ==>", 4, nodes.getLength());

Assert.assertEquals("archive targetInArchive attribute value", "/WEB-INF/lib/javaee-api-7.0.jar",
nodes.item(0).getAttributes().getNamedItem("targetInArchive").getNodeValue());
nodes.item(0).getAttributes().getNamedItem("targetInArchive").getNodeValue());

// Check that dependencies are not located in the test build dir since copyLibsDirectory not set. They will be located in the gradle cache somewhere.
nodeValue = nodes.item(0).getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
assert nodeValue.endsWith("/javaee-api-7.0.jar") && !nodeValue.contains("/loose-war-with-loose-jar/") : 'archive sourceOnDisk attribute value not correct'
if (OSUtil.isWindows()) {
assert nodeValue.endsWith("\\javaee-api-7.0.jar") && !nodeValue.contains("\\loose-war-with-loose-jar\\") : 'archive sourceOnDisk attribute value not correct'
} else {
assert nodeValue.endsWith("/javaee-api-7.0.jar") && !nodeValue.contains("/loose-war-with-loose-jar/") : 'archive sourceOnDisk attribute value not correct'
}

Assert.assertEquals("archive targetInArchive attribute value", "/WEB-INF/lib/javax.mail-1.5.0.jar",
nodes.item(1).getAttributes().getNamedItem("targetInArchive").getNodeValue());

// Check that dependencies are not located in the test build dir since copyLibsDirectory not set. They will be located in the gradle cache somewhere.
nodeValue = nodes.item(1).getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
assert nodeValue.endsWith("/javax.mail-1.5.0.jar") && !nodeValue.contains("/loose-war-with-loose-jar/") : 'archive sourceOnDisk attribute value not correct'
if (OSUtil.isWindows()) {
assert nodeValue.endsWith("\\javax.mail-1.5.0.jar") && !nodeValue.contains("\\loose-war-with-loose-jar/") : 'archive sourceOnDisk attribute value not correct'
} else {
assert nodeValue.endsWith("/javax.mail-1.5.0.jar") && !nodeValue.contains("/loose-war-with-loose-jar/") : 'archive sourceOnDisk attribute value not correct'
}

Assert.assertEquals("archive targetInArchive attribute value", "/WEB-INF/lib/activation-1.1.jar",
nodes.item(2).getAttributes().getNamedItem("targetInArchive").getNodeValue());

// Check that dependencies are not located in the test build dir since copyLibsDirectory not set. They will be located in the gradle cache somewhere.
nodeValue = nodes.item(2).getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
assert nodeValue.endsWith("/activation-1.1.jar") && !nodeValue.contains("/loose-war-with-loose-jar/") : 'archive sourceOnDisk attribute value not correct'
if (OSUtil.isWindows()) {
assert nodeValue.endsWith("\\activation-1.1.jar") && !nodeValue.contains("\\loose-war-with-loose-jar\\") : 'archive sourceOnDisk attribute value not correct'
} else {
assert nodeValue.endsWith("/activation-1.1.jar") && !nodeValue.contains("/loose-war-with-loose-jar/") : 'archive sourceOnDisk attribute value not correct'
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package io.openliberty.tools.gradle;

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

import java.io.File;
import java.io.FileInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.junit.Assert;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

import java.net.HttpURLConnection;
import java.net.URL;

import io.openliberty.tools.common.plugins.util.OSUtil

public class TestMultiModuleLooseEar extends AbstractIntegrationTest{
static File resourceDir = new File("build/resources/test/multi-module-loose-ear-test")
static File buildDir = new File(integTestDir, "/multi-module-loose-ear-test")
static String buildFilename = "build.gradle"

@BeforeClass
public static void setup() {
createDir(buildDir)
createTestProject(buildDir, resourceDir, buildFilename)
}

@AfterClass
public static void tearDown() throws Exception {
runTasks(buildDir, 'libertyStop')
}

@Test
public void test_loose_config_file_exists() {
try {
runTasks(buildDir, 'deploy')
} catch (Exception e) {
throw new AssertionError ("Fail on task deploy. " + e)
}
assert new File('build/testBuilds/multi-module-loose-ear-test/ejb-ear/build/wlp/usr/servers/ejbServer/apps/ejb-ear.ear.xml').exists() : 'looseApplication config file was not copied over to the liberty runtime'
}
/*
Expected output to the XML
<?xml version="1.0" encoding="UTF-8"?>
<archive>
<file sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/multi-module-loose-ear-test/ejb-ear/build/tmp/ear/application.xml" targetInArchive="/META-INF/application.xml"/>
<file sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/multi-module-loose-ear-test/ejb-ear/build/libs/1557427330063525/commons-text-1.1.jar" targetInArchive="/WEB-INF/lib/commons-text-1.1.jar"/>
<archive targetInArchive="/ejb-war.war">
<dir sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/multi-module-loose-ear-test/ejb-war/build/classes/java/main" targetInArchive="/WEB-INF/classes"/>
<file sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/multi-module-loose-ear-test/ejb-war/build/resources/tmp/META-INF/MANIFEST.MF" targetInArchive="/META-INF/MANIFEST.MF"/>
<archive targetInArchive="/WEB-INF/lib/ejb-ejb.jar">
<dir sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/multi-module-loose-ear-test/ejb-ejb/build/classes/java/main" targetInArchive="/"/>
<file sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/multi-module-loose-ear-test/ejb-ejb/build/resources/tmp/META-INF/MANIFEST.MF" targetInArchive="/META-INF/MANIFEST.MF"/>
</archive>
</archive>
<file sourceOnDisk="/Users/../../ci.gradle/build/testBuilds/multi-module-loose-ear-test/loose-ear-test/ejb-ear/build/tmp/META-INF/MANIFEST.MF" targetInArchive="/META-INF/MANIFEST.MF"/>
</archive>
*/
@Test
public void test_loose_config_file_contents_are_correct(){
File on = new File("build/testBuilds/multi-module-loose-ear-test/ejb-ear/build/wlp/usr/servers/ejbServer/apps/ejb-ear.ear.xml");
FileInputStream input = new FileInputStream(on);

// get input XML Document
DocumentBuilderFactory inputBuilderFactory = DocumentBuilderFactory.newInstance();
inputBuilderFactory.setIgnoringComments(true);
inputBuilderFactory.setCoalescing(true);
inputBuilderFactory.setIgnoringElementContentWhitespace(true);
inputBuilderFactory.setValidating(false);
DocumentBuilder inputBuilder = inputBuilderFactory.newDocumentBuilder();
Document inputDoc=inputBuilder.parse(input);

// parse input XML Document
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/archive/dir";
NodeList nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
Assert.assertEquals("Number of <dir/> element ==>", 0, nodes.getLength());

expression = "/archive/archive";
nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
Assert.assertEquals("Number of <archive/> element ==>", 1, nodes.getLength());

String ejbWar = "/ejb-war.war"

Assert.assertTrue(ejbWar.equals(nodes.item(0).getAttributes().getNamedItem("targetInArchive").getNodeValue()))

expression = "/archive/archive/archive";
nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
Assert.assertEquals("Number of <archive/> element ==>", 1, nodes.getLength());

String ejbJar = "/WEB-INF/lib/ejb-ejb.jar"

Assert.assertTrue(ejbJar.equals(nodes.item(0).getAttributes().getNamedItem("targetInArchive").getNodeValue()))

expression = "/archive/file";
nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
Assert.assertEquals("Number of <file/> element ==>", 3, nodes.getLength());

// check that lib dependency is referenced in copyLibsDirectory location
for (Node node : nodes) {
if (node.getAttributes().getNamedItem("targetInArchive").getNodeValue().equals("/WEB-INF/lib/commons-text-1.1.jar")) {
// Check that dependencies are located in the test build dir specified by copyLibsDirectory. Otherwise they would be located in the gradle cache somewhere.
String nodeValue = node.getAttributes().getNamedItem("sourceOnDisk").getNodeValue();

if (OSUtil.isWindows()) {
Assert.assertTrue(nodeValue.endsWith("\\commons-text-1.1.jar") && nodeValue.contains("\\multi-module-loose-ear-test\\ejb-ear\\build\\libs\\"))
} else {
Assert.assertTrue(nodeValue.endsWith("/commons-text-1.1.jar") && nodeValue.contains("/multi-module-loose-ear-test/ejb-ear/build/libs/"))
}
}
}
}
}
19 changes: 19 additions & 0 deletions src/test/resources/multi-module-loose-ear-test/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
allprojects {
group = 'sample'
version = '1.0'
}

subprojects {
apply plugin: 'java'

sourceCompatibility = 1.8
targetCompatibility = 1.8
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}

repositories {
mavenLocal()
mavenCentral()
}
}
Loading

0 comments on commit 70c8acc

Please sign in to comment.