Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ jobs:
restore-keys: ${{ runner.os }}-java-${{ matrix.java_version }}-m2
- name: Build with Maven
# TODO: use 'verify' to run ITs (https://github.com/spotify/missinglink/issues/130)
run: mvn --batch-mode --update-snapshots package
run: mvn --batch-mode --update-snapshots fmt:check package
- name: Codecov
uses: codecov/codecov-action@v1
6 changes: 5 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ weren't.
With Java 8+ and Maven 3+, simply run `mvn install` in the project directory.

For any patches, please make sure that they pass all tests (and that new tests
are added), and that no Checkstyle rules are violated.
are added).

Code will be automatically formatted by <https://github.com/coveooss/fmt-maven-plugin>
when you run `mvn compile`. The CI build will fail if any code is not formatted
according to the plugin's rules.

New code should be accompanied by tests that increase the overall code coverage
of the project.
Expand Down
6 changes: 3 additions & 3 deletions RELEASE
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ Optional:
</profile>
</profiles>

Activate the 'release' profile when releasing:
then to release:

$ mvn -Prelease release:clean release:prepare
$ mvn -Prelease release:perform
$ mvn release:clean release:prepare
$ mvn release:perform

Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
/*-
* -\-\-
* missinglink-benchmarks
* --
* Copyright (C) 2016 - 2021 Spotify AB
* --
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* -/-/-
*/

/*
* Copyright (c) 2015 Spotify AB
*
Expand All @@ -17,26 +37,23 @@
package com.spotify.missinglink.benchmarks;

import com.spotify.missinglink.datamodel.PrimitiveTypeDescriptor;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;


@State(Scope.Benchmark)
public class PrimitiveTypeDescriptorBenchmark {

/**
* This class holds the raw String value to use to pass to
* {@link PrimitiveTypeDescriptor#fromRaw(String)}. The annotations used set up JMH to use the
* one holder per test thread, and set up a new value for each iteration of the benchmark (not
* each invocation).
* This class holds the raw String value to use to pass to {@link
* PrimitiveTypeDescriptor#fromRaw(String)}. The annotations used set up JMH to use the one holder
* per test thread, and set up a new value for each iteration of the benchmark (not each
* invocation).
*/
@State(Scope.Thread)
public static class RawStringHolder {
Expand Down
108 changes: 0 additions & 108 deletions checkstyle.xml

This file was deleted.

15 changes: 0 additions & 15 deletions copyright-header.txt

This file was deleted.

87 changes: 52 additions & 35 deletions core/src/main/java/com/spotify/missinglink/ArtifactLoader.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
/*-
* -\-\-
* missinglink-core
* --
* Copyright (C) 2016 - 2021 Spotify AB
* --
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* -/-/-
*/

/*
* Copyright (c) 2015 Spotify AB
*
Expand All @@ -15,12 +35,13 @@
*/
package com.spotify.missinglink;

import static java.util.stream.Collectors.toList;

import com.spotify.missinglink.datamodel.Artifact;
import com.spotify.missinglink.datamodel.ArtifactBuilder;
import com.spotify.missinglink.datamodel.ArtifactName;
import com.spotify.missinglink.datamodel.ClassTypeDescriptor;
import com.spotify.missinglink.datamodel.DeclaredClass;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
Expand All @@ -38,8 +59,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.stream.Collectors.toList;

public class ArtifactLoader {

/** Load artifact at path, using path name as artifactId */
Expand All @@ -61,7 +80,8 @@ public Artifact load(ArtifactName artifactName, File path) throws IOException {
return loadFromDirectory(artifactName, path);
}

// This is designed to handle Multi-Release JAR files, where there are class files for multiple versions of JVM in one jar.
// This is designed to handle Multi-Release JAR files, where there are class files for multiple
// versions of JVM in one jar.
// You don't want to end up trying to parse a new class file when running on an old JVM.
// https://openjdk.java.net/jeps/238
private Collection<JarEntry> getClassesForCurrentJavaVersion(Iterable<JarEntry> entries) {
Expand All @@ -70,7 +90,7 @@ private Collection<JarEntry> getClassesForCurrentJavaVersion(Iterable<JarEntry>
SortedMap<Integer, Map<String, JarEntry>> classFilesPerJavaVersion = new TreeMap<>();
String patternString = "META-INF/versions/(\\d+)/";
Pattern pattern = Pattern.compile(patternString);
for (JarEntry entry: entries) {
for (JarEntry entry : entries) {
String fileFullName = entry.getName();
if (fileFullName.endsWith(".class")) {
Matcher m = pattern.matcher(fileFullName);
Expand All @@ -85,7 +105,7 @@ private Collection<JarEntry> getClassesForCurrentJavaVersion(Iterable<JarEntry>
} else {
Integer withoutVersion = 0;
if (!classFilesPerJavaVersion.containsKey(withoutVersion)) {
classFilesPerJavaVersion.put(withoutVersion, new HashMap<>());
classFilesPerJavaVersion.put(withoutVersion, new HashMap<>());
}
classFilesPerJavaVersion.get(withoutVersion).put(fileFullName, entry);
}
Expand All @@ -101,15 +121,16 @@ private Collection<JarEntry> getClassesForCurrentJavaVersion(Iterable<JarEntry>
currentJavaVersion = Integer.parseInt(javaVersionElements[0]);
}

// Start layering the class files from old JVM version to new and thus effectively override the old files by the new ones.
// Start layering the class files from old JVM version to new and thus effectively override the
// old files by the new ones.
Map<String, JarEntry> selectedClassFiles = new HashMap<>();
for (Map.Entry<Integer, Map<String, JarEntry>> entry : classFilesPerJavaVersion.entrySet()) {
Integer targetJavaVersion = entry.getKey();
if (targetJavaVersion > currentJavaVersion) {
break;
}
Map<String, JarEntry> pathToClassfile = entry.getValue();
selectedClassFiles.putAll(pathToClassfile);
Integer targetJavaVersion = entry.getKey();
if (targetJavaVersion > currentJavaVersion) {
break;
}
Map<String, JarEntry> pathToClassfile = entry.getValue();
selectedClassFiles.putAll(pathToClassfile);
}

return selectedClassFiles.values();
Expand All @@ -119,18 +140,17 @@ private Artifact loadFromJar(ArtifactName artifactName, File path) {
try (JarFile jarFile = new JarFile(path)) {
Map<ClassTypeDescriptor, DeclaredClass> classes = new HashMap<>();
Iterable<JarEntry> classFiles =
getClassesForCurrentJavaVersion(Collections.list(jarFile.entries()));
for (JarEntry entry: classFiles) {
try {
DeclaredClass cl = ClassLoader.load(jarFile.getInputStream(entry));
classes.put(cl.className(), cl);
} catch (MissingLinkException e) {
throw e;
} catch (Exception e) {
throw new MissingLinkException("Could not load " + entry.getName() + " from " + path,
e);
}
getClassesForCurrentJavaVersion(Collections.list(jarFile.entries()));
for (JarEntry entry : classFiles) {
try {
DeclaredClass cl = ClassLoader.load(jarFile.getInputStream(entry));
classes.put(cl.className(), cl);
} catch (MissingLinkException e) {
throw e;
} catch (Exception e) {
throw new MissingLinkException("Could not load " + entry.getName() + " from " + path, e);
}
}
return artifact(artifactName, classes);
} catch (IOException e) {
throw new RuntimeException("Could not load " + path, e);
Expand All @@ -140,10 +160,11 @@ private Artifact loadFromJar(ArtifactName artifactName, File path) {
private Artifact loadFromDirectory(ArtifactName artifactName, File dir) throws IOException {
Map<ClassTypeDescriptor, DeclaredClass> classes = new HashMap<>();

List<File> classFilesInDir = Files.walk(dir.toPath())
.map(Path::toFile)
.filter(file -> file.isFile() && file.getName().endsWith(".class"))
.collect(toList());
List<File> classFilesInDir =
Files.walk(dir.toPath())
.map(Path::toFile)
.filter(file -> file.isFile() && file.getName().endsWith(".class"))
.collect(toList());

for (File file : classFilesInDir) {
try (FileInputStream fis = new FileInputStream(file)) {
Expand All @@ -154,17 +175,13 @@ private Artifact loadFromDirectory(ArtifactName artifactName, File dir) throws I
return artifact(artifactName, classes);
}

private static Artifact artifact(ArtifactName name,
Map<ClassTypeDescriptor, DeclaredClass> classes) {
return new ArtifactBuilder()
.name(name)
.classes(classes)
.build();
private static Artifact artifact(
ArtifactName name, Map<ClassTypeDescriptor, DeclaredClass> classes) {
return new ArtifactBuilder().name(name).classes(classes).build();
}

public static void main(String[] args) throws Exception {
ArtifactLoader l = new ArtifactLoader();
System.out.println(l.load(new File("core/src/test/resources/ArtifactLoaderTest.jar")));
}

}
Loading