Skip to content

Commit 401387a

Browse files
authored
Merge branch 'main' into bug/roller-maven-pom
2 parents 74e5e66 + 42914df commit 401387a

File tree

6 files changed

+291
-26
lines changed

6 files changed

+291
-26
lines changed

plugins/codemodder-plugin-maven/src/main/java/io/codemodder/plugins/maven/operator/CommandChain.java

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,7 @@ class CommandChain {
1616
private static final Logger LOGGER = LoggerFactory.getLogger(CommandChain.class);
1717

1818
/** Internal ArrayList of the Commands */
19-
private List<Command> commandList;
20-
21-
private static List<Command> COMMON_COMMANDS =
22-
List.of(
23-
// Validation commands
24-
CheckDependencyPresent.getInstance(),
25-
CheckParentPackaging.getInstance(),
26-
// Format commands
27-
new FormatCommand(),
28-
new DiscardFormatCommand(),
29-
// Multipom command
30-
new CompositeDependencyManagement());
19+
private final List<Command> commandList;
3120

3221
private CommandChain(List<Command> commands) {
3322
this.commandList = commands;
@@ -93,7 +82,17 @@ public boolean execute(ProjectModel c)
9382
* @return A pre-configured Chain for modifying a POM.
9483
*/
9584
public static CommandChain modifyDependency() {
96-
final List<Command> modifyCommands = new ArrayList<>(COMMON_COMMANDS);
85+
final List<Command> modifyCommands =
86+
new ArrayList<>(
87+
List.of(
88+
// Validation commands
89+
CheckDependencyPresent.getInstance(),
90+
CheckParentPackaging.getInstance(),
91+
// Format commands
92+
new FormatCommand(),
93+
new DiscardFormatCommand(),
94+
// Multipom command
95+
new CompositeDependencyManagement()));
9796
modifyCommands.addAll(
9897
List.of(
9998
SimpleUpgrade.getInstance(),
@@ -109,7 +108,17 @@ public static CommandChain modifyDependency() {
109108
* @return A pre-configured Chain.
110109
*/
111110
public static CommandChain insertDependency() {
112-
final List<Command> insertCommands = new ArrayList<>(COMMON_COMMANDS);
111+
final List<Command> insertCommands =
112+
new ArrayList<>(
113+
List.of(
114+
// Validation commands
115+
CheckDependencyPresent.getInstance(),
116+
CheckParentPackaging.getInstance(),
117+
// Format commands
118+
new FormatCommand(),
119+
new DiscardFormatCommand(),
120+
// Multipom command
121+
new CompositeDependencyManagement()));
113122
insertCommands.add(new SimpleInsert(true));
114123
return new CommandChain(insertCommands);
115124
}
@@ -120,7 +129,17 @@ public static CommandChain insertDependency() {
120129
* @return A pre-configured Chain.
121130
*/
122131
public static CommandChain updateDependency() {
123-
final List<Command> insertCommands = new ArrayList<>(COMMON_COMMANDS);
132+
final List<Command> insertCommands =
133+
new ArrayList<>(
134+
List.of(
135+
// Validation commands
136+
CheckDependencyPresent.getInstance(),
137+
CheckParentPackaging.getInstance(),
138+
// Format commands
139+
new FormatCommand(),
140+
new DiscardFormatCommand(),
141+
// Multipom command
142+
new CompositeDependencyManagement()));
124143
insertCommands.addAll(
125144
List.of(SimpleUpgrade.getInstance(), SimpleDependencyManagement.getInstance()));
126145

@@ -169,7 +188,8 @@ public static CommandChain createForDependencyQuery(QueryType queryType) {
169188
return filterByQueryType(
170189
AVAILABLE_DEPENDENCY_QUERY_COMMANDS,
171190
queryType,
172-
Arrays.asList(CheckLocalRepositoryDirCommand.CheckParentDirCommand.getInstance()),
191+
Collections.singletonList(
192+
CheckLocalRepositoryDirCommand.CheckParentDirCommand.getInstance()),
173193
it -> it == queryType);
174194
}
175195

@@ -196,7 +216,7 @@ public static CommandChain createForVersionQuery(QueryType queryType) {
196216
* and report issues creating
197217
*/
198218
static final List<Pair<QueryType, String>> AVAILABLE_DEPENDENCY_QUERY_COMMANDS =
199-
new ArrayList<>(Arrays.asList(new Pair<>(QueryType.SAFE, "QueryByParsing")));
219+
new ArrayList<>(List.of(new Pair<>(QueryType.SAFE, "QueryByParsing")));
200220

201221
/** List of Commands for Version Query */
202222
private static final List<Pair<QueryType, String>> AVAILABLE_QUERY_VERSION_COMMANDS =

plugins/codemodder-plugin-maven/src/main/java/io/codemodder/plugins/maven/operator/FormatCommand.java

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.net.URISyntaxException;
1010
import java.nio.charset.Charset;
1111
import java.util.*;
12+
import java.util.function.UnaryOperator;
1213
import java.util.regex.Pattern;
1314
import java.util.stream.Collectors;
1415
import java.util.stream.Stream;
@@ -137,22 +138,22 @@ private BitSet elementBitSet(byte[] doc) throws XMLStreamException {
137138
* A Slight variation on writeAsUnicode from stax which writes as a regex string so we could
138139
* rewrite its output
139140
*/
140-
private String writeAsRegex(StartElement element) {
141+
private String writeAsRegex(final StartElement element, final List<Attribute> orderedAttributes) {
141142
StringWriter writer = new StringWriter();
142143

143144
writer.write("<");
144145
writer.write(Pattern.quote(element.getName().getLocalPart()));
145146

146-
Iterator<?> attrIter = element.getAttributes();
147-
while (attrIter.hasNext()) {
148-
Attribute attr = (Attribute) attrIter.next();
149-
147+
for (var attr : orderedAttributes) {
150148
writer.write("\\s+");
151149

152150
writer.write(Pattern.quote(attr.getName().getLocalPart()));
153-
writer.write("=[\\\"\']");
151+
writer.write("\\s*");
152+
writer.write("=");
153+
writer.write("\\s*");
154+
writer.write("[\\\"']");
154155
writer.write(Pattern.quote(attr.getValue()));
155-
writer.write("[\\\"\']");
156+
writer.write("[\\\"']");
156157
}
157158
writer.write("\\s*\\/>");
158159

@@ -335,7 +336,25 @@ private void parseXmlAndCharset(POMDocument pomFile) throws XMLStreamException,
335336
new IntRange(
336337
realElementStart, realElementStart + 1 + trimmedOriginalContent.length());
337338

338-
String contentRe = writeAsRegex(getLastStartElement(prevEvents));
339+
var element = getLastStartElement(prevEvents);
340+
341+
// order the attributes by the original ordering
342+
// attributes names are unique, we can just order them by the index of the name
343+
344+
// Remove attribute contents, just in case some they contain the name of an attribute
345+
// TODO should we trim the element name beforehand?
346+
String contentRemoved = untrimmedOriginalContent.replaceAll("[\\\"'].*[\\\"']", "");
347+
348+
var it = element.getAttributes();
349+
var orderedAttributes =
350+
Stream.iterate(it, Iterator::hasNext, UnaryOperator.identity())
351+
.map(Iterator::next)
352+
.map(a -> new Pair<>(a, contentRemoved.indexOf(a.getName().getLocalPart())))
353+
.sorted(Comparator.comparing(p -> p.getSecond()))
354+
.map(p -> p.getFirst())
355+
.collect(Collectors.toList());
356+
357+
String contentRe = writeAsRegex(element, orderedAttributes);
339358

340359
Regex modifiedContentRE = new Regex(contentRe);
341360

@@ -494,6 +513,8 @@ private byte[] serializePomFile(POMDocument pom) throws XMLStreamException {
494513
// Let's find out the original empty elements from the original pom and store into a stack
495514
List<MatchData> elementsToReplace = getElementsToReplace(originalElementMap, pom);
496515

516+
// DOM parsers don't guarantee attribute ordering, extract the original ordering for the regex
517+
497518
// Lets to the replacements backwards on the existing, current pom
498519
Map<Integer, MatchData> emptyElements = getEmptyElements(targetElementMap, xmlRepresentation);
499520

plugins/codemodder-plugin-maven/src/test/java/io/codemodder/plugins/maven/operator/AbstractTestBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ protected ProjectModel performAndAssertPomOperation(
5959
String testName, ProjectModel context, final OperationType operationType) throws Exception {
6060

6161
String resultFile = "pom-" + testName + "-result.xml";
62-
URL resource = AbstractTestBase.class.getClass().getResource(resultFile);
62+
URL resource = AbstractTestBase.class.getResource(resultFile);
6363

6464
if (resource != null) {
6565
Document outcome = new SAXReader().read(resource);

plugins/codemodder-plugin-maven/src/test/java/io/codemodder/plugins/maven/operator/POMOperatorTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,19 @@ void modify_adds_dependency_to_file_with_tabs()
581581
"\n\t\t<dependency>\n\t\t\t<groupId>org.dom4j</groupId>\n\t\t\t<artifactId>dom4j</artifactId>\n\t\t</dependency>\n");
582582
}
583583

584+
@Test
585+
void modify_adds_dependency_to_pom_with_empty_elements_with_multiple_attributes()
586+
throws Exception {
587+
Dependency dependencyToUpgrade =
588+
new Dependency("io.github.pixee", "java-security-toolkit", "1.0.2", null, null, null);
589+
590+
performAndAssertModifyPomOperation(
591+
"trimmed-roller",
592+
ProjectModelFactory.load(POMOperatorTest.class.getResource("pom-trimmed-roller.xml"))
593+
.withDependency(dependencyToUpgrade)
594+
.withUseProperties(true));
595+
}
596+
584597
/**
585598
* Tests a scenario with an empty element from a customer's POM file and validates the resultant
586599
* POM.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Licensed to the Apache Software Foundation (ASF) under one or more
4+
contributor license agreements. See the NOTICE file distributed with
5+
this work for additional information regarding copyright ownership.
6+
The ASF licenses this file to You under the Apache License, Version 2.0
7+
(the "License"); you may not use this file except in compliance with
8+
the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
-->
18+
<project xmlns="http://maven.apache.org/POM/4.0.0"
19+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
22+
<dependencies>
23+
<dependency>
24+
<groupId>org.instancio</groupId>
25+
<artifactId>instancio-junit</artifactId>
26+
<version>5.0.1</version>
27+
<scope>test</scope>
28+
</dependency>
29+
<dependency>
30+
<groupId>io.github.pixee</groupId>
31+
<artifactId>java-security-toolkit</artifactId>
32+
</dependency>
33+
</dependencies>
34+
35+
<build>
36+
37+
<finalName>roller</finalName>
38+
39+
<plugins>
40+
41+
<plugin>
42+
<artifactId>maven-antrun-plugin</artifactId>
43+
<version>3.1.0</version>
44+
<dependencies>
45+
<dependency>
46+
<groupId>ant-contrib</groupId>
47+
<artifactId>ant-contrib</artifactId>
48+
<version>${maven-antrun.version}</version>
49+
<exclusions>
50+
<exclusion>
51+
<groupId>ant</groupId>
52+
<artifactId>ant</artifactId>
53+
</exclusion>
54+
</exclusions>
55+
</dependency>
56+
<!-- last velocity version which had the Ant TexenTask -->
57+
<dependency>
58+
<groupId>org.apache.velocity</groupId>
59+
<artifactId>velocity</artifactId>
60+
<version>1.7</version>
61+
</dependency>
62+
</dependencies>
63+
64+
<executions>
65+
<execution>
66+
<id>gen-db-scripts</id>
67+
<phase>generate-resources</phase>
68+
<goals>
69+
<goal>run</goal>
70+
</goals>
71+
<configuration>
72+
<target>
73+
<!-- Workaround for git distribution that doesn't keep empty directories.
74+
For detail check [ROL-2086] -->
75+
<taskdef resource="net/sf/antcontrib/antlib.xml" />
76+
<property file="${basedir}/src/main/resources/sql/dbscripts.properties" />
77+
<for list="${databases}" param="database" delimiter=" ">
78+
<sequential>
79+
<mkdir dir="${basedir}/target/classes/dbscripts/@{database}" />
80+
</sequential>
81+
</for>
82+
83+
<taskdef name="texen"
84+
classname="org.apache.velocity.texen.ant.TexenTask"
85+
classpathref="maven.plugin.classpath"/>
86+
<texen
87+
controlTemplate ="control.vm"
88+
contextProperties="${basedir}/src/main/resources/sql/dbscripts.properties"
89+
templatePath ="${basedir}/src/main/resources/sql"
90+
outputDirectory ="${basedir}/target/classes/dbscripts"
91+
outputFile ="README.txt"/>
92+
</target>
93+
</configuration>
94+
</execution>
95+
</executions>
96+
</plugin>
97+
98+
</plugins>
99+
100+
</build>
101+
<dependencyManagement>
102+
<dependencies>
103+
<dependency>
104+
<groupId>io.github.pixee</groupId>
105+
<artifactId>java-security-toolkit</artifactId>
106+
<version>${versions.java-security-toolkit}</version>
107+
</dependency>
108+
</dependencies>
109+
</dependencyManagement>
110+
<properties>
111+
<versions.java-security-toolkit>1.0.2</versions.java-security-toolkit>
112+
</properties>
113+
</project>

0 commit comments

Comments
 (0)