Skip to content

Commit c765af7

Browse files
committed
Merge branch 'add-jakarta-support' into 'main'
Generate jakarta servlets See merge request weblogic-cloud/weblogic-monitoring-exporter!300
2 parents 0f2deec + 3a5a750 commit c765af7

30 files changed

+724
-159
lines changed

build-helper-mojo/pom.xml

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
3-
Copyright (c) 2019, 2024, Oracle and/or its affiliates.
3+
Copyright (c) 2019, 2025, Oracle and/or its affiliates.
44
Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
55
-->
66
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
@@ -17,13 +17,29 @@
1717

1818
<name>Exporter Build Helper Maven Mojo</name>
1919

20+
<properties>
21+
<maven.compiler.release>17</maven.compiler.release>
22+
</properties>
23+
2024
<dependencies>
2125
<dependency>
2226
<groupId>org.apache.maven</groupId>
2327
<artifactId>maven-plugin-api</artifactId>
2428
<version>3.9.9</version>
2529
<scope>provided</scope>
2630
</dependency>
31+
<dependency>
32+
<groupId>org.apache.maven</groupId>
33+
<artifactId>maven-core</artifactId>
34+
<version>3.9.9</version>
35+
<scope>provided</scope>
36+
</dependency>
37+
<dependency>
38+
<groupId>org.apache.maven</groupId>
39+
<artifactId>maven-artifact</artifactId>
40+
<version>3.9.9</version>
41+
<scope>provided</scope>
42+
</dependency>
2743
<dependency>
2844
<groupId>org.apache.maven</groupId>
2945
<artifactId>maven-model</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright (c) 2025, Oracle and/or its affiliates.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
3+
4+
package com.oracle.wls.buildhelper;
5+
6+
import org.apache.maven.plugin.AbstractMojo;
7+
import org.apache.maven.plugin.MojoExecutionException;
8+
import org.apache.maven.plugin.MojoFailureException;
9+
import org.apache.maven.plugins.annotations.LifecyclePhase;
10+
import org.apache.maven.plugins.annotations.Mojo;
11+
import org.apache.maven.plugins.annotations.Parameter;
12+
import org.apache.maven.project.MavenProject;
13+
14+
import java.io.BufferedWriter;
15+
import java.io.File;
16+
import java.io.IOException;
17+
import java.nio.file.Files;
18+
import java.nio.file.Path;
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
import java.util.function.Function;
22+
import java.util.stream.Stream;
23+
24+
/**
25+
* Supports generation of web applications that work on both javax-dependent and jakarta-dependent WebLogic Server
26+
* instances. It depends on several things:
27+
* 1. The Exporter web application uses annotations rather than an XML file to configure its servlets,
28+
* 2. WebLogic will ignore servlets whose dependencies it cannot load
29+
* 3. Common code in this application does not depend on classes that depend on the EE version.
30+
* <br/>
31+
* The plugin will look for source files that reference javax.servlet; it will report a failure if any such
32+
* files are in packages whose last element is not "javax." It will then generate corresponding source files
33+
* that reference the corresponding jakarta.servlet classes and place them in a package with "jakarta" instead
34+
* of "javax" in a separate directory, and add the directory to the compiler source roots.
35+
*/
36+
@Mojo(name = "transform", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
37+
public class JavaxToJakartaMojo extends AbstractMojo {
38+
/**
39+
* The source directories containing the sources to be processed.
40+
*/
41+
@Parameter(defaultValue = "${project.compileSourceRoots}", required = true)
42+
List<String> compileSourceRoots;
43+
44+
/**
45+
* Specify where to place generated jakarta-based files created by this mojo.
46+
*/
47+
@Parameter(defaultValue = "${project.build.directory}/generated-sources/jakarta")
48+
File generatedSourcesDirectory;
49+
50+
/**
51+
* The project used as an interface to Maven internals.
52+
*/
53+
@Parameter(defaultValue = "${project}", readonly = true)
54+
MavenProject project;
55+
56+
static Function<String, Path> toPath = Path::of;
57+
58+
59+
@Override
60+
public void execute() throws MojoExecutionException, MojoFailureException {
61+
project.addCompileSourceRoot(generatedSourcesDirectory.getPath());
62+
63+
try {
64+
getFilesToTransform().forEach(this::transformFile);
65+
} catch (RuntimeException e) {
66+
throw new MojoExecutionException(e);
67+
}
68+
}
69+
70+
private void transformFile(Path inputFile) {
71+
Path outputFile = getOutputFile(inputFile);
72+
try {
73+
Files.createDirectories(outputFile.getParent());
74+
transformFile(inputFile, outputFile);
75+
} catch (IOException e) {
76+
throw new RuntimeException("Unable to transform files", e);
77+
}
78+
}
79+
80+
private static void transformFile(Path inputFile, Path outputFile) throws IOException {
81+
try (BufferedWriter bufferedWriter = Files.newBufferedWriter(outputFile);
82+
Stream<String> lines = Files.lines(inputFile)) {
83+
lines.forEach(l -> transformLine(l, bufferedWriter));
84+
}
85+
}
86+
87+
private static void transformLine(String line, BufferedWriter bufferedWriter) {
88+
try {
89+
bufferedWriter.write(line.replaceAll("javax", "jakarta"));
90+
bufferedWriter.newLine();
91+
} catch (IOException e) {
92+
throw new RuntimeException(e.getMessage(), e);
93+
}
94+
}
95+
96+
private Path getGeneratedSourceRoot() {
97+
return toPath.apply(generatedSourcesDirectory.getPath());
98+
}
99+
100+
Stream<Path> getFilesToTransform() throws MojoFailureException {
101+
final List<Path> selectedFiles = new ArrayList<>();
102+
103+
try (Stream<Path> files = Files.walk(getCompileSourceRoot())) {
104+
files.filter(Files::isRegularFile).filter(this::containsTransformedJavaxPackage).forEach(selectedFiles::add);
105+
} catch (IOException e) {
106+
throw new RuntimeException(e);
107+
}
108+
109+
verifySelectedFilesHaveJavaxPackage(selectedFiles);
110+
return selectedFiles.stream();
111+
}
112+
113+
private void verifySelectedFilesHaveJavaxPackage(List<Path> selectedFiles) throws MojoFailureException {
114+
List<String> badPaths = selectedFiles.stream().filter(this::lacksJavaxFinalPackage).map(Path::toString).toList();
115+
116+
if (!badPaths.isEmpty())
117+
throw new MojoFailureException("Cannot do transformation. The following classes reference javax.servlet packages " +
118+
"but are not in a package name ending in .javax: " + String.join(", ", badPaths));
119+
}
120+
121+
private boolean lacksJavaxFinalPackage(Path path) {
122+
return !path.getParent().endsWith("javax");
123+
}
124+
125+
private Path toRelativePath(Path p) {
126+
return getCompileSourceRoot().relativize(p);
127+
}
128+
129+
private Path getCompileSourceRoot() {
130+
return toPath.apply(compileSourceRoots.get(0));
131+
}
132+
133+
private boolean containsTransformedJavaxPackage(Path path) {
134+
try {
135+
return Files.readAllLines(path).stream().anyMatch(s -> s.contains("javax.servlet"));
136+
} catch (IOException e) {
137+
return false;
138+
}
139+
}
140+
141+
public Path getOutputFile(Path inputPath) {
142+
final Path fileName = inputPath.getFileName();
143+
final Path relativePath = toRelativePath(inputPath).getParent().getParent().resolve("jakarta");
144+
return getGeneratedSourceRoot().resolve(relativePath).resolve(fileName);
145+
}
146+
}

0 commit comments

Comments
 (0)