Skip to content

Commit a5958a8

Browse files
committed
feat: Use MavenPomCache that stores and retrieves pom files from local Maven repo
- Provides an initial (and incomplete) PomSerializer to serialize Pom model instances to a pom test file - Problem: The Pom contains information that can't be kept in a pom file and thus it can't always be de-/serialized which prevents using local Maven repo as cache store
1 parent 4879f07 commit a5958a8

File tree

6 files changed

+941
-0
lines changed

6 files changed

+941
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.maven;
17+
/**
18+
* @author Fabian Krüger
19+
*/
20+
interface Cache<K, V> {
21+
void put(K key, V value);
22+
23+
V getIfPresent(K key);
24+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.maven;
17+
18+
import lombok.Value;
19+
import org.openrewrite.internal.lang.Nullable;
20+
import org.openrewrite.maven.cache.MavenPomCache;
21+
import org.openrewrite.maven.tree.*;
22+
23+
import java.net.URI;
24+
import java.nio.file.Path;
25+
import java.util.Optional;
26+
27+
/**
28+
* A `MavenPomCache` that uses local filesystem, e.g. Maven repository, to store and retrieve pom files.
29+
*
30+
* The cache directory is optionally configurable. If not set local Maven repository is used.
31+
*
32+
* The `FilesystemPomCache` must be provided through `ExecutionContext`.
33+
*
34+
* [source,java]
35+
* ....
36+
* ExecutionContext executionContext = ...
37+
* MavenExecutionContextView.view(executionContext).setPomCache(new LocalMavenPomCache());
38+
* ....
39+
*
40+
* @author Fabian Krüger
41+
*/
42+
public class FilesystemMavenPomCache implements MavenPomCache {
43+
44+
private final Cache<MetadataKey, Optional<MavenMetadata>> mavenMetadataCache;
45+
private Cache<ResolvedGroupArtifactVersion, Optional<Pom>> pomCache;
46+
private final Cache<MavenRepository, Optional<MavenRepository>> repositoryCache;
47+
private final Cache<ResolvedGroupArtifactVersion, ResolvedPom> dependencyCache;
48+
49+
@Value
50+
public static class MetadataKey {
51+
URI repository;
52+
GroupArtifactVersion gav;
53+
}
54+
55+
/**
56+
* Creates `FileSystemPomCache` using local Maven repository `${user.home}/.m2/repository` as cache dir.
57+
*/
58+
public FilesystemMavenPomCache() {
59+
this(Path.of(System.getProperty("user.home")).resolve(".m2").resolve("repository"));
60+
}
61+
62+
63+
/**
64+
* Creates a `FileSystemPomCache` using the provided `cacheDir`.
65+
*
66+
* @throws IllegalArgumentException if cacheDir does not exist.
67+
*/
68+
public FilesystemMavenPomCache(Path cacheDir) {
69+
if(!cacheDir.toFile().exists()) {
70+
throw new IllegalArgumentException("The given cache dir '%s' does not exist, Please provide an existing dir.".formatted(cacheDir));
71+
}
72+
pomCache = new FilesystemPomCache(cacheDir);
73+
mavenMetadataCache = new MavenMetadataCache();
74+
repositoryCache = new RepositoryCache();
75+
dependencyCache = new DependencyCache();
76+
}
77+
78+
@Override
79+
public @Nullable ResolvedPom getResolvedDependencyPom(ResolvedGroupArtifactVersion dependency) {
80+
return dependencyCache.getIfPresent(dependency);
81+
}
82+
83+
@Override
84+
public void putResolvedDependencyPom(ResolvedGroupArtifactVersion dependency, ResolvedPom resolved) {
85+
dependencyCache.put(dependency, resolved.deduplicate());
86+
}
87+
88+
@Override
89+
public @Nullable Optional<MavenMetadata> getMavenMetadata(URI repo, GroupArtifactVersion gav) {
90+
return mavenMetadataCache.getIfPresent(new MetadataKey(repo, gav));
91+
}
92+
93+
@Override
94+
public void putMavenMetadata(URI repo, GroupArtifactVersion gav, @Nullable MavenMetadata metadata) {
95+
mavenMetadataCache.put(new MetadataKey(repo, gav), Optional.ofNullable(metadata));
96+
}
97+
98+
@Override
99+
public @Nullable Optional<Pom> getPom(ResolvedGroupArtifactVersion gav) throws MavenDownloadingException {
100+
return pomCache.getIfPresent(gav);
101+
}
102+
103+
@Override
104+
public void putPom(ResolvedGroupArtifactVersion gav, @Nullable Pom pom) {
105+
pomCache.put(gav, Optional.ofNullable(pom));
106+
}
107+
108+
@Override
109+
public @Nullable Optional<MavenRepository> getNormalizedRepository(MavenRepository repository) {
110+
return repositoryCache.getIfPresent(repository);
111+
}
112+
113+
@Override
114+
public void putNormalizedRepository(MavenRepository repository, MavenRepository normalized) {
115+
repositoryCache.put(repository, Optional.ofNullable(normalized));
116+
}
117+
118+
private class MavenMetadataCache implements Cache<MetadataKey, Optional<MavenMetadata>> {
119+
@Override
120+
public void put(MetadataKey key, Optional<MavenMetadata> value) {
121+
122+
}
123+
124+
@Override
125+
public Optional<MavenMetadata> getIfPresent(MetadataKey key) {
126+
return Optional.empty();
127+
}
128+
}
129+
130+
private class RepositoryCache implements Cache<MavenRepository, Optional<MavenRepository>> {
131+
@Override
132+
public void put(MavenRepository key, Optional<MavenRepository> value) {
133+
134+
}
135+
136+
@Override
137+
public Optional<MavenRepository> getIfPresent(MavenRepository key) {
138+
return Optional.empty();
139+
}
140+
}
141+
142+
private class DependencyCache implements Cache<ResolvedGroupArtifactVersion, ResolvedPom> {
143+
@Override
144+
public void put(ResolvedGroupArtifactVersion key, ResolvedPom value) {
145+
146+
}
147+
148+
@Override
149+
public ResolvedPom getIfPresent(ResolvedGroupArtifactVersion key) {
150+
return null;
151+
}
152+
}
153+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.maven;
17+
18+
import org.jetbrains.annotations.NotNull;
19+
import org.openrewrite.maven.internal.RawPom;
20+
import org.openrewrite.maven.tree.Pom;
21+
import org.openrewrite.maven.tree.ResolvedGroupArtifactVersion;
22+
23+
import java.io.ByteArrayInputStream;
24+
import java.io.IOException;
25+
import java.nio.file.Files;
26+
import java.nio.file.Path;
27+
import java.util.Optional;
28+
29+
/**
30+
* Cache implementation to store {@link Pom} objects as pom files in local Maven repository.
31+
*
32+
* @author Fabian Krüger
33+
*/
34+
class FilesystemPomCache implements Cache<ResolvedGroupArtifactVersion, Optional<Pom>> {
35+
36+
private Path cacheDir;
37+
38+
public FilesystemPomCache(Path cacheDir) {
39+
this.cacheDir = cacheDir;
40+
}
41+
42+
@Override
43+
public void put(ResolvedGroupArtifactVersion key, Optional<Pom> optionalPom) {
44+
if (optionalPom.isPresent()) {
45+
Pom pom = optionalPom.get();
46+
Path path = Path.of(key.getGroupId()).resolve(key.getArtifactId()).resolve(key.getVersion());
47+
Path pomPath = cacheDir.resolve(path).resolve(pom.getSourcePath().getFileName());
48+
49+
String pomXml = new PomSerializer().serialize(pom);
50+
51+
Path pomDir = buildPomPath(key);
52+
String pomFile = buildPomFilename(key);
53+
54+
if(!pomDir.toFile().exists()) {
55+
if(!pomDir.toFile().exists()) {
56+
boolean dirCreated = pomDir.toFile().mkdirs();
57+
if(!dirCreated) {
58+
throw new RuntimeException("Could not create non-existent dir '%s'".formatted(pomDir));
59+
}
60+
}
61+
try {
62+
Files.writeString(pomDir.resolve(pomFile), pomXml);
63+
} catch (IOException e) {
64+
throw new RuntimeException(e);
65+
}
66+
}
67+
}
68+
}
69+
70+
@NotNull
71+
private String buildPomFilename(ResolvedGroupArtifactVersion key) {
72+
return key.getArtifactId() + "-" + key.getVersion() + (key.getDatedSnapshotVersion() != null ? key.getDatedSnapshotVersion() : "") + ".pom";
73+
}
74+
75+
@NotNull
76+
private Path buildPomPath(ResolvedGroupArtifactVersion key) {
77+
return cacheDir
78+
.resolve(key.getGroupId().replace(".", "/"))
79+
.resolve(key.getArtifactId())
80+
.resolve(key.getVersion());
81+
}
82+
83+
@Override
84+
public Optional<Pom> getIfPresent(ResolvedGroupArtifactVersion key) {
85+
86+
Path pomDir = buildPomPath(key);
87+
String pomFilename = buildPomFilename(key);
88+
89+
if(!pomDir.resolve(pomFilename).toFile().exists()) {
90+
return null; // Expected by OR code when no pom exists
91+
}
92+
93+
try {
94+
String pomContent = Files.readString(pomDir.resolve(pomFilename));
95+
RawPom parse = RawPom.parse(new ByteArrayInputStream(pomContent.getBytes()), null);
96+
Pom pom = parse.toPom(pomDir.resolve(pomFilename), null);
97+
return Optional.of(pom);
98+
} catch (IOException e) {
99+
throw new RuntimeException(e);
100+
}
101+
102+
}
103+
}

0 commit comments

Comments
 (0)