Skip to content

Commit 63476c9

Browse files
authored
Refactor POM Operator (#226)
Stop using static methods and move POM Operator related logic from MavenProvider to reduce public visibility of types
1 parent 3425168 commit 63476c9

File tree

12 files changed

+231
-160
lines changed

12 files changed

+231
-160
lines changed

plugins/codemodder-plugin-maven/src/main/java/io/codemodder/plugins/maven/MavenProvider.java

Lines changed: 75 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@
77
import io.codemodder.*;
88
import io.codemodder.codetf.CodeTFChange;
99
import io.codemodder.codetf.CodeTFChangesetEntry;
10-
import io.codemodder.plugins.maven.operator.Dependency;
1110
import io.codemodder.plugins.maven.operator.POMDocument;
1211
import io.codemodder.plugins.maven.operator.POMOperator;
13-
import io.codemodder.plugins.maven.operator.POMScanner;
1412
import io.codemodder.plugins.maven.operator.ProjectModel;
15-
import io.codemodder.plugins.maven.operator.ProjectModelFactory;
1613
import java.io.File;
1714
import java.io.IOException;
1815
import java.io.UncheckedIOException;
@@ -163,128 +160,103 @@ private DependencyUpdateResult updateDependenciesInternal(
163160
return DependencyUpdateResult.EMPTY_UPDATE;
164161
}
165162

166-
Path pomFile = maybePomFile.get();
167-
List<CodeTFChangesetEntry> changesets = new ArrayList<>();
163+
final Path pomFile = maybePomFile.get();
164+
final List<CodeTFChangesetEntry> changesets = new ArrayList<>();
168165

169166
final List<DependencyGAV> skippedDependencies = new ArrayList<>();
170167
final List<DependencyGAV> injectedDependencies = new ArrayList<>();
171168
final Set<Path> erroredFiles = new LinkedHashSet<>();
169+
final POMOperator pomOperator = new POMOperator(pomFile, projectDir);
172170

173-
AtomicReference<Collection<DependencyGAV>> foundDependenciesMapped =
174-
new AtomicReference<>(getDependenciesFrom(pomFile, projectDir));
171+
final AtomicReference<Collection<DependencyGAV>> foundDependenciesMapped =
172+
new AtomicReference<>(pomOperator.getAllFoundDependencies());
175173
LOG.trace("Beginning dependency set size: {}", foundDependenciesMapped.get().size());
176174

177175
dependencies.forEach(
178176
newDependencyGAV -> {
179-
LOG.trace("Looking at injecting new dependency: {}", newDependencyGAV);
180-
boolean foundIt =
181-
foundDependenciesMapped.get().stream().anyMatch(newDependencyGAV::equals);
182-
183-
if (foundIt) {
184-
LOG.trace("Found it -- skipping");
185-
skippedDependencies.add(newDependencyGAV);
186-
return;
187-
}
188-
189-
LOG.trace("Need to inject it...");
190-
Dependency newDependency =
191-
new Dependency(
192-
newDependencyGAV.group(),
193-
newDependencyGAV.artifact(),
194-
newDependencyGAV.version(),
195-
null,
196-
null,
197-
null);
198-
ProjectModelFactory projectModelFactory = null;
199-
try {
200-
projectModelFactory =
201-
POMScanner.legacyScanFrom(pomFile.toFile(), projectDir.toFile())
202-
.withDependency(newDependency)
203-
.withSkipIfNewer(true)
204-
.withUseProperties(true);
205-
} catch (DocumentException e) {
206-
throw new RuntimeException(e);
207-
} catch (IOException e) {
208-
throw new RuntimeException(e);
209-
} catch (URISyntaxException e) {
210-
throw new RuntimeException(e);
211-
}
212-
213-
try {
214-
projectModelFactory =
215-
projectModelFactory.withRepositoryPath(Files.createTempDirectory(null).toFile());
216-
} catch (IOException e) {
217-
throw new RuntimeException(e);
218-
}
219-
220-
ProjectModel projectModel = projectModelFactory.build();
221-
222-
boolean result = false;
223177
try {
224-
result = POMOperator.modify(projectModel);
225-
} catch (URISyntaxException e) {
226-
throw new RuntimeException(e);
227-
} catch (IOException e) {
228-
throw new RuntimeException(e);
229-
} catch (XMLStreamException e) {
230-
throw new RuntimeException(e);
231-
}
232-
233-
if (result) {
234-
LOG.trace("Modified the pom -- writing it back");
235-
Collection<POMDocument> allPomFiles = projectModel.allPomFiles();
236-
LOG.trace("Found " + allPomFiles.size() + " pom files -- " + allPomFiles);
237-
for (POMDocument aPomFile : allPomFiles) {
238-
URI uri;
239-
try {
240-
uri = aPomFile.getPomPath().toURI();
241-
} catch (URISyntaxException ex) {
242-
ex.printStackTrace();
243-
throw new DependencyUpdateException("Failure parsing URL: " + aPomFile, ex);
244-
}
178+
LOG.trace("Looking at injecting new dependency: {}", newDependencyGAV);
179+
final boolean foundIt =
180+
foundDependenciesMapped.get().stream().anyMatch(newDependencyGAV::equals);
181+
182+
if (foundIt) {
183+
LOG.trace("Found it -- skipping");
184+
skippedDependencies.add(newDependencyGAV);
185+
return;
186+
}
245187

246-
Path path = Path.of(uri);
247-
248-
if (aPomFile.getDirty()) {
249-
LOG.trace("POM file {} was dirty", path);
250-
try {
251-
CodeTFChangesetEntry entry = getChanges(projectDir, aPomFile, newDependencyGAV);
252-
pomModifier.modify(path, aPomFile.getResultPomBytes());
253-
LOG.trace("POM written!");
254-
injectedDependencies.add(newDependencyGAV);
255-
changesets.add(entry);
256-
} catch (IOException | UncheckedIOException exc) {
257-
LOG.error("Failed to write pom", exc);
258-
erroredFiles.add(path);
188+
final ProjectModel modifiedProjectModel = pomOperator.addDependency(newDependencyGAV);
189+
190+
if (modifiedProjectModel != null) {
191+
LOG.trace("Modified the pom -- writing it back");
192+
Collection<POMDocument> allPomFiles = modifiedProjectModel.allPomFiles();
193+
LOG.trace("Found " + allPomFiles.size() + " pom files -- " + allPomFiles);
194+
for (POMDocument aPomFile : allPomFiles) {
195+
final URI uri = getPomFileURI(aPomFile);
196+
197+
Path path = Path.of(uri);
198+
199+
if (aPomFile.getDirty()) {
200+
modifyDirtyPomFile(
201+
projectDir,
202+
path,
203+
aPomFile,
204+
newDependencyGAV,
205+
changesets,
206+
injectedDependencies,
207+
erroredFiles);
208+
} else {
209+
LOG.trace("POM file {} wasn't dirty", path);
259210
}
260-
} else {
261-
LOG.trace("POM file {} wasn't dirty", path);
262211
}
263-
}
264212

265-
Collection<DependencyGAV> newDependencySet = null;
266-
try {
267-
newDependencySet = getDependenciesFrom(pomFile, projectDir);
268-
} catch (DocumentException e) {
269-
throw new RuntimeException(e);
270-
} catch (IOException e) {
271-
throw new RuntimeException(e);
272-
} catch (URISyntaxException e) {
273-
throw new RuntimeException(e);
274-
} catch (XMLStreamException e) {
275-
throw new RuntimeException(e);
213+
final Collection<DependencyGAV> newDependencySet =
214+
pomOperator.getAllFoundDependencies();
215+
216+
LOG.trace("New dependency set size: {}", newDependencySet.size());
217+
foundDependenciesMapped.set(newDependencySet);
218+
} else {
219+
LOG.trace("POM file didn't need modification or it failed?");
276220
}
277-
LOG.trace("New dependency set size: {}", newDependencySet.size());
278-
foundDependenciesMapped.set(newDependencySet);
279-
} else {
280-
LOG.trace("POM file didn't need modification or it failed?");
221+
} catch (DocumentException | IOException | URISyntaxException | XMLStreamException e) {
222+
throw new RuntimeException(e);
281223
}
282224
});
283225

284226
return DependencyUpdateResult.create(
285227
injectedDependencies, skippedDependencies, changesets, erroredFiles);
286228
}
287229

230+
private void modifyDirtyPomFile(
231+
final Path projectDir,
232+
final Path path,
233+
final POMDocument aPomFile,
234+
final DependencyGAV newDependencyGAV,
235+
final List<CodeTFChangesetEntry> changesets,
236+
final List<DependencyGAV> injectedDependencies,
237+
final Set<Path> erroredFiles) {
238+
LOG.trace("POM file {} was dirty", path);
239+
try {
240+
CodeTFChangesetEntry entry = getChanges(projectDir, aPomFile, newDependencyGAV);
241+
pomModifier.modify(path, aPomFile.getResultPomBytes());
242+
LOG.trace("POM written!");
243+
injectedDependencies.add(newDependencyGAV);
244+
changesets.add(entry);
245+
} catch (IOException | UncheckedIOException exc) {
246+
LOG.error("Failed to write pom", exc);
247+
erroredFiles.add(path);
248+
}
249+
}
250+
251+
private URI getPomFileURI(final POMDocument aPomFile) {
252+
try {
253+
return aPomFile.getPomPath().toURI();
254+
} catch (URISyntaxException ex) {
255+
LOG.error("Unexpected problem getting pom URI", ex);
256+
throw new MavenProvider.DependencyUpdateException("Failure parsing URL: " + aPomFile, ex);
257+
}
258+
}
259+
288260
private List<String> getLinesFrom(final POMDocument doc, final byte[] byteArray) {
289261
return Arrays.asList(
290262
new String(byteArray, doc.getCharset()).split(Pattern.quote(doc.getEndl())));
@@ -331,30 +303,5 @@ private CodeTFChangesetEntry getChanges(
331303
return new CodeTFChangesetEntry(relativePomPath, diff, List.of(change));
332304
}
333305

334-
@NotNull
335-
private Collection<DependencyGAV> getDependenciesFrom(final Path pomFile, final Path projectDir)
336-
throws DocumentException, IOException, URISyntaxException, XMLStreamException {
337-
ProjectModelFactory projectModelFactory =
338-
POMScanner.legacyScanFrom(pomFile.toFile(), projectDir.toFile()).withSafeQueryType();
339-
340-
try {
341-
projectModelFactory =
342-
projectModelFactory.withRepositoryPath(Files.createTempDirectory(null).toFile());
343-
} catch (IOException e) {
344-
throw new RuntimeException(e);
345-
}
346-
347-
ProjectModel originalProjectModel = projectModelFactory.build();
348-
349-
Collection<Dependency> foundDependencies = POMOperator.queryDependency(originalProjectModel);
350-
351-
return foundDependencies.stream()
352-
.map(
353-
dependency ->
354-
DependencyGAV.createDefault(
355-
dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion()))
356-
.collect(Collectors.toList());
357-
}
358-
359306
private static final Logger LOG = LoggerFactory.getLogger(MavenProvider.class);
360307
}

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package io.codemodder.plugins.maven.operator;
22

3+
import io.codemodder.DependencyGAV;
34
import java.util.Objects;
45

56
/**
67
* Represents a dependency in a Maven POM. A dependency consists of a group ID, artifact ID,
78
* version, classifier, packaging, and scope.
89
*/
9-
public class Dependency {
10+
class Dependency {
1011
private String groupId;
1112
private String artifactId;
1213
private String version;
@@ -24,7 +25,7 @@ public class Dependency {
2425
* @param packaging The packaging type of the dependency (default is "jar" if null).
2526
* @param scope The scope of the dependency (default is "compile" if null).
2627
*/
27-
public Dependency(
28+
Dependency(
2829
String groupId,
2930
String artifactId,
3031
String version,
@@ -39,6 +40,16 @@ public Dependency(
3940
this.scope = scope != null ? scope : "compile";
4041
}
4142

43+
Dependency(final DependencyGAV newDependencyGAV) {
44+
this(
45+
newDependencyGAV.group(),
46+
newDependencyGAV.artifact(),
47+
newDependencyGAV.version(),
48+
null,
49+
null,
50+
null);
51+
}
52+
4253
@Override
4354
public String toString() {
4455
return String.join(":", groupId, artifactId, packaging, version);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.codemodder.plugins.maven.operator;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Files;
5+
import java.nio.file.Path;
6+
import java.nio.file.Paths;
7+
import java.nio.file.attribute.PosixFilePermission;
8+
import java.util.HashSet;
9+
import java.util.Set;
10+
11+
public class FileUtils {
12+
13+
private FileUtils() {}
14+
15+
private static final String TEMP_SUBFOLDER = "mySecureDirectory";
16+
17+
public static Path createTempDirectoryWithPermissions() throws IOException {
18+
// Get the system's temporary directory
19+
Path systemTempDir = Paths.get(System.getProperty("java.io.tmpdir"));
20+
21+
// Create a dedicated sub-folder within the temporary directory
22+
Path tempDirectory = Files.createTempDirectory(systemTempDir, TEMP_SUBFOLDER);
23+
24+
// Set permissions (read, write, execute for owner; no permissions for others)
25+
Set<PosixFilePermission> perms = new HashSet<>();
26+
perms.add(PosixFilePermission.OWNER_READ);
27+
perms.add(PosixFilePermission.OWNER_WRITE);
28+
perms.add(PosixFilePermission.OWNER_EXECUTE);
29+
30+
Files.setPosixFilePermissions(tempDirectory, perms);
31+
32+
return tempDirectory;
33+
}
34+
}

0 commit comments

Comments
 (0)