Skip to content

Commit 6d1a29b

Browse files
committed
CORE-20557: Fix issue in CPB and CPK plugins preventing dependencies of transitive dependencies from being included
1 parent aeb324e commit 6d1a29b

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed

changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
### Version 7.0.5
66

7+
* `cordapp-cpk2`: Include transitive dependencies in list of dependencies
8+
* `cordapp-cpb2`: Include transitive dependencies in CPB archive
9+
710
### Version 7.0.4
811

912
* `cordapp-cpk2`: Upgrade to Bndlib 6.4.1.

cordapp-cpk2/src/main/java/net/corda/plugins/cpb2/CpbPlugin.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public void apply(@NotNull Project project) {
7373
cpbTask.getArchiveVersion().convention(cpkTask.flatMap(Jar::getArchiveVersion));
7474

7575
cpbTask.doFirst(task -> cpbTask.checkForDuplicateCpkCordappNames());
76+
cpbTask.doFirst(task -> cpbTask.extractTransitiveDeps());
7677

7778
cpbTask.doLast(task -> {
7879
if (cordappExtension.getSigning().getEnabled().get()) {

cordapp-cpk2/src/main/java/net/corda/plugins/cpb2/CpbTask.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,16 @@
1313
import java.io.BufferedInputStream;
1414
import java.io.File;
1515
import java.io.IOException;
16+
import java.io.InputStream;
1617
import java.nio.file.Files;
1718
import java.nio.file.Path;
19+
import java.nio.file.Paths;
20+
import java.util.Arrays;
21+
import java.util.Enumeration;
1822
import java.util.HashSet;
1923
import java.util.Set;
24+
import java.util.jar.JarEntry;
25+
import java.util.jar.JarFile;
2026
import java.util.jar.JarInputStream;
2127

2228
import static java.util.Collections.singleton;
@@ -29,12 +35,15 @@
2935
public class CpbTask extends Jar {
3036
private static final String CPB_ARTIFACT_CLASSIFIER = "package";
3137
public static final String CPB_FILE_EXTENSION = "cpb";
38+
private static final String CPB_FILE_SUFFIX = "." + CPB_FILE_EXTENSION;
3239
private static final String CPK_FILE_SUFFIX = '.' + CPK_FILE_EXTENSION;
3340
private static final Set<String> EXCLUDED_CPK_TYPES = singleton("corda-api");
3441
public static final String CPB_NAME_ATTRIBUTE = "Corda-CPB-Name";
3542
public static final String CPB_VERSION_ATTRIBUTE = "Corda-CPB-Version";
3643
public static final String CPB_FORMAT_VERSION = "Corda-CPB-Format";
3744
public static final String CPB_CURRENT_FORMAT_VERSION = "2.0";
45+
private static File jarDir;
46+
Set<String> cordappFileNames = new HashSet<>();
3847

3948
public CpbTask() {
4049
setGroup(CORDAPP_TASK_GROUP);
@@ -59,11 +68,21 @@ public CpbTask() {
5968
m.getAttributes().put(CPB_NAME_ATTRIBUTE, getArchiveBaseName());
6069
m.getAttributes().put(CPB_VERSION_ATTRIBUTE, getArchiveVersion());
6170
});
71+
72+
try {
73+
jarDir = Files.createTempDirectory("").toFile();
74+
jarDir.deleteOnExit();
75+
} catch (IOException e) {
76+
getLogger().warn("Could not create jar directory: {}", e.getMessage());
77+
jarDir = null;
78+
}
6279
}
6380

6481
@Override
6582
@NotNull
6683
public AbstractCopyTask from(@NotNull Object... args) {
84+
args = Arrays.copyOf(args, args.length + 1);
85+
args[args.length - 1] = jarDir;
6786
return super.from(args, copySpec ->
6887
copySpec.exclude(this::isCPK)
6988
);
@@ -104,4 +123,57 @@ public void checkForDuplicateCpkCordappNames() {
104123
}
105124
}
106125
}
126+
127+
public void extractTransitiveDeps() {
128+
if (jarDir != null) {
129+
FileCollection jars = getInputs().getFiles();
130+
Set<String> jarNames = new HashSet<>();
131+
for (File file : jars) {
132+
jarNames.add(file.getName());
133+
}
134+
Set<File> cpbs = new HashSet<>();
135+
for (File file : jars) {
136+
File parent = file.getParentFile();
137+
for (File sibling : parent.listFiles()) {
138+
if (sibling.isFile() && sibling.getName().endsWith(CPB_FILE_SUFFIX)) {
139+
cpbs.add(sibling);
140+
}
141+
}
142+
}
143+
for (File cpb : cpbs) {
144+
extractJarsFromCPB(cpb, jarNames);
145+
}
146+
}
147+
}
148+
149+
private void extractJarsFromCPB(File cpb, Set<String> jarNames) {
150+
try (JarFile jarFile = new JarFile(cpb)) {
151+
Enumeration<JarEntry> jarEntries = jarFile.entries();
152+
while (jarEntries.hasMoreElements()) {
153+
JarEntry jarEntry = jarEntries.nextElement();
154+
if (!cordappFileNames.contains(jarEntry.getName())) {
155+
cordappFileNames.add(jarEntry.getName());
156+
String jarName = jarEntry.getName();
157+
if (jarName.endsWith(".jar") && !jarNames.contains(jarName)) {
158+
extractJarEntry(jarFile, jarEntry);
159+
}
160+
}
161+
}
162+
} catch (IOException e) {
163+
getLogger().warn("Could not extract cpb: {}", e.getMessage());
164+
}
165+
}
166+
167+
private void extractJarEntry(JarFile jarFile, JarEntry jarEntry) {
168+
try {
169+
Path path = Paths.get(jarDir.getAbsolutePath(), jarEntry.getName());
170+
if (!Files.exists(path)) {
171+
InputStream inputStream = jarFile.getInputStream(jarEntry);
172+
Files.copy(inputStream, path);
173+
path.toFile().deleteOnExit();
174+
}
175+
} catch (IOException e) {
176+
getLogger().error("Could not copy jar: {}", e.getMessage());
177+
}
178+
}
107179
}

cordapp-cpk2/src/main/java/net/corda/plugins/cpk2/DependencyCalculator.java

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,26 @@
2020
import org.gradle.work.DisableCachingByDefault;
2121
import org.jetbrains.annotations.NotNull;
2222
import org.jetbrains.annotations.Nullable;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
2325

2426
import java.io.File;
27+
import java.io.IOException;
28+
import java.io.InputStream;
29+
import java.nio.file.Files;
30+
import java.nio.file.Path;
31+
import java.nio.file.Paths;
2532
import java.util.Arrays;
2633
import java.util.Collection;
34+
import java.util.Enumeration;
35+
import java.util.HashSet;
2736
import java.util.LinkedHashSet;
2837
import java.util.List;
2938
import java.util.Map;
39+
import java.util.Objects;
3040
import java.util.Set;
41+
import java.util.jar.JarEntry;
42+
import java.util.jar.JarFile;
3143
import javax.inject.Inject;
3244

3345
import static java.util.Collections.emptySet;
@@ -69,6 +81,7 @@ public class DependencyCalculator extends DefaultTask {
6981
{ "co.paralleluniverse", "quasar-core" },
7082
{ "co.paralleluniverse", "quasar-core-osgi" }
7183
};
84+
private static final Logger log = LoggerFactory.getLogger(DependencyCalculator.class);
7285

7386
/**
7487
* Gradle's configuration cache forbids invoking {@link org.gradle.api.Task#getProject}
@@ -224,6 +237,18 @@ public void calculate() {
224237
final Set<File> cordappFiles = resolveFirstLevelFilesFor(externalConfiguration, cordappDeps);
225238
final List<ProjectDependency> projectCordappDeps = filterIsInstance(cordappDeps, ProjectDependency.class);
226239
final Set<File> projectCordappFiles = toFiles(resolveFirstLevel(externalConfiguration, projectCordappDeps));
240+
Set<String> cordappFileNames = new HashSet<>();
241+
for(File file: cordappFiles) {
242+
cordappFileNames.add(file.getName());
243+
}
244+
Set<File> cpbs = getCpbs(externalConfiguration);
245+
Set<File> transitives = new HashSet<>();
246+
try {
247+
transitives = extractJarsFromCpb(cpbs, cordappFileNames);
248+
} catch (IOException e) {
249+
log.warn("Could not resolve transitive dependencies from CPBs: {}", e.getMessage());
250+
}
251+
cordappFiles.addAll(transitives);
227252
_projectCordapps.setFrom(projectCordappFiles);
228253
_projectCordapps.disallowChanges();
229254

@@ -236,6 +261,58 @@ public void calculate() {
236261
_providedJars.disallowChanges();
237262
}
238263

264+
@NotNull
265+
private static Set<File> getCpbs(ResolvedConfiguration externalConfiguration) {
266+
Set<File> cpbs = new HashSet<>();
267+
for (File file: externalConfiguration.getFiles()) {
268+
if (!file.getAbsolutePath().contains("/.")) {
269+
File dir = file.getAbsoluteFile().getParentFile();
270+
for (File siblingFile: Objects.requireNonNull(dir.listFiles())) {
271+
if (siblingFile.isFile() && siblingFile.getAbsolutePath().endsWith(".cpb")) {
272+
cpbs.add(siblingFile);
273+
}
274+
}
275+
}
276+
}
277+
return cpbs;
278+
}
279+
280+
@NotNull
281+
private static Set<File> extractJarsFromCpb(Set<File> cpbs, Set<String> cordappFileNames) throws IOException {
282+
Path pathToDir = Files.createTempDirectory("jars");
283+
pathToDir.toFile().deleteOnExit();
284+
Set<File> transitives = new HashSet<>();
285+
for (File cpb: cpbs) {
286+
JarFile jarFile = new JarFile(cpb);
287+
Enumeration<JarEntry> jarEntries = jarFile.entries();
288+
while (jarEntries.hasMoreElements()) {
289+
JarEntry jarEntry = jarEntries.nextElement();
290+
if (!cordappFileNames.contains(jarEntry.getName())) {
291+
if (jarEntry.getName().endsWith(".jar")) {
292+
transitives.add(extractJarEntry(jarFile, jarEntry, pathToDir));
293+
}
294+
}
295+
}
296+
}
297+
return transitives;
298+
}
299+
300+
private static File extractJarEntry(JarFile jarFile, JarEntry jarEntry, Path pathToDir) throws IOException {
301+
File file;
302+
Path path = Paths.get(pathToDir.toString(), jarEntry.getName());
303+
if (!Files.exists(pathToDir)) {
304+
Files.createDirectories(pathToDir);
305+
}
306+
if (!Files.exists(path)) {
307+
InputStream inputStream = jarFile.getInputStream(jarEntry);
308+
Files.copy(inputStream, path);
309+
path.toFile().deleteOnExit();
310+
}
311+
file = path.toFile();
312+
file.deleteOnExit();
313+
return file;
314+
}
315+
239316
@NotNull
240317
private static Set<File> resolveAllFilesFor(
241318
@NotNull ResolvedConfiguration resolved,

0 commit comments

Comments
 (0)