Skip to content

Commit

Permalink
Merge pull request #531 from eclipse/instr-spring-boot
Browse files Browse the repository at this point in the history
Added SpringBootAnalyzer
  • Loading branch information
henrikplate authored Mar 14, 2022
2 parents 48af2ca + 49d4bf8 commit aa8d212
Show file tree
Hide file tree
Showing 111 changed files with 1,584 additions and 423 deletions.
16 changes: 11 additions & 5 deletions .travis/check_code_style.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#!/bin/bash

# Download Google formatter
executable=google-java-format-1.8-all-deps.jar
executable=google-java-format-1.14.0-all-deps.jar
if [[ ! -f $executable ]]; then
curl -L https://github.com/google/google-java-format/releases/download/google-java-format-1.8/google-java-format-1.8-all-deps.jar --output $executable
printf "Downloaded [%s]\n" $executable
curl -L https://github.com/google/google-java-format/releases/download/v1.14.0/$executable --fail --output $executable
res=$?
if [[ ! $res == 0 ]]; then
printf "Could not download [%s], skipping format check...\n" $executable
exit 0
else
printf "Downloaded [%s]\n" $executable
fi
fi

# Java files below src/main
Expand All @@ -21,7 +27,7 @@ printf "Found [%s] Java files in all modules' source directories\n" $count
if [[ $1 == "format" ]]; then

printf "Formatting... "
java -jar google-java-format-1.8-all-deps.jar -r --skip-sorting-imports --skip-javadoc-formatting --set-exit-if-changed @java-files.txt
java -jar $executable -r --skip-sorting-imports --skip-javadoc-formatting --set-exit-if-changed @java-files.txt
status=$?

if [[ $status -eq 0 ]]; then
Expand All @@ -33,7 +39,7 @@ if [[ $1 == "format" ]]; then
fi
else
printf "Checking... "
java -jar google-java-format-1.8-all-deps.jar -n --skip-sorting-imports --skip-javadoc-formatting --set-exit-if-changed @java-files.txt > non-compliant-files.txt
java -jar $executable -n --skip-sorting-imports --skip-javadoc-formatting --set-exit-if-changed @java-files.txt > non-compliant-files.txt
status=$?

if [[ $status -eq 0 ]]; then
Expand Down
4 changes: 2 additions & 2 deletions docker/readme-pages/Java.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ mvn package
mvn -Dvulas initialize vulas:instr
```

**Result:** A new JAR/WAR with suffix "-vulas-instr" will be created in folder "target/vulas/target".
**Result:** A new JAR/WAR with suffix "-steady-instr" will be created in folder "target/vulas/target".

**How does it work:** The bytecode of all the Java classes found in the JAR (WAR) will be modified as to collect information about, for instance, method execution and stack traces. This information will be uploaded to the Steady backend. Note: The modified code in the new JAR with suffix "-vulas-instr" can be inspected with decompilers such as [JD-GUI](http://jd.benow.ca/).
**How does it work:** The bytecode of all the Java classes found in the JAR (WAR) will be modified as to collect information about, for instance, method execution and stack traces. This information will be uploaded to the Steady backend. Note: The modified code in the new JAR with suffix "-steady-instr" can be inspected with decompilers such as [JD-GUI](http://jd.benow.ca/).

**Troubleshooting:**

Expand Down
4 changes: 2 additions & 2 deletions docs/public/content/user/manuals/analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,11 +425,11 @@ An application's JAR or WAR, e.g., as created with `mvn package` in folder `targ

#### Result

A new JAR/WAR with suffix `-vulas-instr` will be created in folder `target/vulas/target`.
A new JAR/WAR with suffix `-steady-instr` will be created in folder `target/vulas/target`.

#### How does it work

The bytecode of all the Java classes found in the JAR (WAR) will be modified as to collect information about, for instance, method execution and stack traces. This information will be uploaded to the backend if the JAR (WAR) is executed. Note: The modified code in the new JAR with suffix `-vulas-instr` can be inspected with decompilers such as [JD-GUI](http://jd.benow.ca/).
The bytecode of all the Java classes found in the JAR (WAR) will be modified as to collect information about, for instance, method execution and stack traces. This information will be uploaded to the backend if the JAR (WAR) is executed. Note: The modified code in the new JAR with suffix `-steady-instr` can be inspected with decompilers such as [JD-GUI](http://jd.benow.ca/).

#### Run as follows

Expand Down
53 changes: 49 additions & 4 deletions lang-java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@
</filters>
</configuration>
</execution>
<!-- For instrumentation with the -agent option, incl. a repackaged
version of httpclient -->
<!-- Used for static and dynamic (-agent option)
instrumentation. -->
<execution>
<id>self-contained-agent-jar</id>
<phase>package</phase>
Expand All @@ -157,12 +157,22 @@
<shadedClassifierName>jar-with-dependencies</shadedClassifierName>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<!-- Required to be used with the -agent option-->
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<premain-class>org.eclipse.steady.java.monitor.DynamicTransformer</premain-class>
</manifestEntries>
</transformer>
<!-- Required for re-packaged Log4j2 services-->
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<!-- Required to adjust Log4j2Plugins.dat, see:
https://github.com/edwgiz/maven-shaded-log4j-transformer
https://stackoverflow.com/questions/67133027/error-statuslogger-unrecognized-format-specifier
-->
<transformer
implementation="io.github.edwgiz.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer">
</transformer>
</transformers>
<artifactSet>
<includes>
Expand All @@ -179,12 +189,40 @@
<exclude>META-INF/MANIFEST.MF</exclude>
</excludes>
</filter>
<!-- Apparently, the multi-release class files
do not pose any problem. -->
<!-- <filter>
<artifact>org.apache.logging.log4j:*</artifact>
<excludes>
<exclude>META-INF/versions/**</exclude>
</excludes>
</filter> -->
</filters>
<relocations>
<relocation>
<pattern>org.apache.http</pattern>
<shadedPattern>org.eclipse.steady.repackaged.org.apache.http</shadedPattern>
<pattern>org.apache</pattern>
<shadedPattern>org.eclipse.steady.repackaged.org.apache</shadedPattern>
</relocation>
<relocation>
<pattern>org.slf4j</pattern>
<shadedPattern>org.eclipse.steady.repackaged.org.slf4j</shadedPattern>
</relocation>
<relocation>
<pattern>org.antlr</pattern>
<shadedPattern>org.eclipse.steady.repackaged.org.antlr</shadedPattern>
</relocation>
<relocation>
<pattern>org.aopalliance</pattern>
<shadedPattern>org.eclipse.steady.repackaged.org.aopalliance</shadedPattern>
</relocation>
<relocation>
<pattern>com</pattern>
<shadedPattern>org.eclipse.steady.repackaged.com</shadedPattern>
</relocation>
<!-- <relocation>
<pattern>javax</pattern>
<shadedPattern>org.eclipse.steady.repackaged.javax</shadedPattern>
</relocation> -->
<relocation>
<pattern>javassist</pattern>
<shadedPattern>org.eclipse.steady.repackaged.javassist</shadedPattern>
Expand All @@ -193,6 +231,13 @@
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>io.github.edwgiz</groupId>
<artifactId>log4j-maven-shade-plugin-extensions</artifactId>
<version>2.17.1</version>
</dependency>
</dependencies>
</plugin>
<!-- Flatten a 2nd time after shade, in order to process the dependency-reduced-pom, see
https://stackoverflow.com/questions/52552329/use-maven-flatten-plugin-and-maven-shade-plugin-at-the-same-time
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
@NotThreadSafe
public class AarAnalyzer extends JarAnalyzer {

private static final Logger log = org.apache.logging.log4j.LogManager.getLogger();
private static final Logger log =
org.apache.logging.log4j.LogManager.getLogger(AarAnalyzer.class);

private static final String CLASSES_JAR = "classes.jar";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
Expand All @@ -47,7 +48,8 @@
*/
public class ArchiveAnalysisManager {

private static final Logger log = org.apache.logging.log4j.LogManager.getLogger();
private static final Logger log =
org.apache.logging.log4j.LogManager.getLogger(ArchiveAnalysisManager.class);

private ExecutorService pool;

Expand Down Expand Up @@ -290,10 +292,14 @@ public void startAnalysis(@NotNull Set<Path> _paths, JarAnalyzer parent) {
try {
JarAnalyzer ja = null;
if (p.toString().endsWith("jar")) {
ja = new JarAnalyzer();
final JarWriter jw = new JarWriter(p);
if (jw.hasEntry("BOOT-INF/")) {
ja = new SpringBootAnalyzer();
} else {
ja = new JarAnalyzer();
}
} else if (p.toString().endsWith("war")) {
ja = new WarAnalyzer();
((WarAnalyzer) ja).setIncludeDir(this.inclDir);
} else if (p.toString().endsWith("aar")) {
ja = new AarAnalyzer();
} else {
Expand All @@ -314,6 +320,15 @@ public void startAnalysis(@NotNull Set<Path> _paths, JarAnalyzer parent) {
ja.setInstrument(
this.instrument); // To be called after analyze, since instrument uses the URL member

// Set include dir for some archive types (after setInstrument)
if (this.instrument) {
if (ja instanceof SpringBootAnalyzer) {
((SpringBootAnalyzer) ja).setIncludeDir(this.inclDir);
} else if (ja instanceof WarAnalyzer) {
((WarAnalyzer) ja).setIncludeDir(this.inclDir);
}
}

this.analyzers.put(p, ja);

// Execute the analyzer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
*/
public class ClassFileAnalyzer implements FileAnalyzer {

private static final Logger log = org.apache.logging.log4j.LogManager.getLogger();
private static final Logger log =
org.apache.logging.log4j.LogManager.getLogger(ClassFileAnalyzer.class);

/** The file to be analyzed. */
private File file = null;
Expand Down
52 changes: 38 additions & 14 deletions lang-java/src/main/java/org/eclipse/steady/java/JarAnalyzer.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@
@NotThreadSafe
public class JarAnalyzer implements Callable<FileAnalyzer>, JarEntryWriter, FileAnalyzer {

private static final Logger log = org.apache.logging.log4j.LogManager.getLogger();
private static final Logger log =
org.apache.logging.log4j.LogManager.getLogger(JarAnalyzer.class);

private static final ClassPool CLASSPOOL = ClassPool.getDefault();

Expand Down Expand Up @@ -117,13 +118,27 @@ public String[] getSupportedFileExtensions() {
return new String[] {"jar"};
}

/** {@inheritDoc} */
/**
* Returns true if the archive has file extension 'jar' and does not contain
* a {@link JarEntry} 'BOOT-INF/', false otherwise.
*/
@Override
public final boolean canAnalyze(File _file) {
public boolean canAnalyze(File _file) {
final String ext = FileUtil.getFileExtension(_file);
if (ext == null || ext.equals("")) return false;
for (String supported_ext : this.getSupportedFileExtensions()) {
if (supported_ext.equalsIgnoreCase(ext)) return true;
if (supported_ext.equalsIgnoreCase(ext)) {
try {
final JarWriter jw = new JarWriter(_file.toPath());
if (jw.hasEntry("BOOT-INF/")) {
return false;
} else {
return true;
}
} catch (IOException ioe) {
log.error(ioe.getMessage());
}
}
}
return false;
}
Expand Down Expand Up @@ -157,7 +172,9 @@ public synchronized void analyze(final File _file) throws FileAnalysisException
*/
public void setInstrument(boolean _instrument) {
this.instrument = _instrument;
if (this.instrument) this.instrControl = InstrumentationControl.getInstance(this.url);
if (this.instrument) {
this.instrControl = InstrumentationControl.getInstance(this.url);
}
}

/**
Expand Down Expand Up @@ -219,7 +236,7 @@ public void setWorkDir(Path _p) {
/**
* Determines whether the instrumented JAR is renamed or not. If yes, the new file name follows the following format:
* - If app context is provided: [originalJarName]-vulas-[appGroupId]-[appArtifactId]-[appVersion].jar
* - Otherwise: [originalJarName]-vulas-instr.jar
* - Otherwise: [originalJarName]-steady-instr.jar
*
* @param _b a boolean.
*/
Expand Down Expand Up @@ -331,7 +348,7 @@ protected void createInstrumentedArchive() throws JarAnalysisException {
this.jarWriter.addManifestEntry(
"Steady-classInstrStats",
"["
+ this.classCount
+ this.instrControl.countClassesTotal()
+ " total, "
+ this.instrControl.countClassesInstrumentedAlready()
+ " existed, "
Expand All @@ -354,7 +371,9 @@ protected void createInstrumentedArchive() throws JarAnalysisException {
this.jarWriter.register(".*.class$", this);

// Rename
if (this.rename) this.jarWriter.setClassifier("vulas-instr");
if (this.rename) {
this.jarWriter.setClassifier("steady-instr");
}

// Rewrite
this.jarWriter.rewrite(this.workDir);
Expand Down Expand Up @@ -596,8 +615,8 @@ else if (je.getName().endsWith("pom.xml")) {
if (this.instrument)
JarAnalyzer.log.info(
this.toString()
+ ": classes comprised/already-instr/instr/not-instr ["
+ this.classCount
+ ": classes and enums comprised/already-instr/instr/not-instr ["
+ this.instrControl.countClassesTotal()
+ "/"
+ this.instrControl.countClassesInstrumentedAlready()
+ "/"
Expand Down Expand Up @@ -665,8 +684,10 @@ public InstrumentationControl getInstrumentationControl() {
* The callback registration takes place in {@link #createInstrumentedArchive()}.
*/
@Override
public InputStream getInputStream(String _regex, JarEntry _entry) {
public RewrittenJarEntry getInputStream(String _regex, JarEntry _entry) {
InputStream is = null;
long size = -1;
long crc32 = -1;

if (_regex.equals(".*.class$")) {
JavaId jid = null;
Expand All @@ -685,12 +706,15 @@ public InputStream getInputStream(String _regex, JarEntry _entry) {

// Create input stream
if (jid != null && this.instrumentedClasses.get(jid) != null) {
// new_entry.setSize(this.instrumentedClasses.get(jid).getBytecode().length);
is = new ByteArrayInputStream(this.instrumentedClasses.get(jid).getBytecode());
final byte[] bytecode = this.instrumentedClasses.get(jid).getBytecode();
crc32 = FileUtil.getCRC32(bytecode);
size = bytecode.length;
is = new ByteArrayInputStream(bytecode);
return new RewrittenJarEntry(is, size, crc32);
}
}

return is;
return null;
}

/** {@inheritDoc} */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,29 @@
*/
public interface JarEntryWriter {

/**
* Carries the {@link InputStream} as well as the size and CRC-32 checksum of
* rewritten JAR entries. The latter are required to write non-compressed JAR
* entries in {@link JarWriter}).
*/
public final class RewrittenJarEntry {
final InputStream is;
final long size;
final long crc32;

public RewrittenJarEntry(InputStream _is, long _size, long _crc32) {
this.is = _is;
this.size = _size;
this.crc32 = _crc32;
}
}

/**
* Callback used for rewriting particular JAR entries. Return null to rewrite the original JAR entry.
*
* @param _entry a {@link java.util.jar.JarEntry} object.
* @param _regex a {@link java.lang.String} object.
* @return a {@link java.io.InputStream} object.
*/
public InputStream getInputStream(String _regex, JarEntry _entry);
public RewrittenJarEntry getInputStream(String _regex, JarEntry _entry);
}
Loading

0 comments on commit aa8d212

Please sign in to comment.