Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Html without xml #389

Merged
merged 7 commits into from
Mar 6, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 29 additions & 8 deletions japicmp-ant-task/src/main/java/japicmp/ant/JApiCmpTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import japicmp.config.Options;
import japicmp.exception.JApiCmpException;
import japicmp.model.JApiClass;
import japicmp.output.html.HtmlOutput;
import japicmp.output.html.HtmlOutputGenerator;
import japicmp.output.html.HtmlOutputGeneratorOptions;
import japicmp.output.incompatible.IncompatibleErrorOutput;
import japicmp.output.semver.SemverOut;
import japicmp.output.stdout.StdoutOutputGenerator;
Expand All @@ -18,6 +21,10 @@
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -280,14 +287,28 @@ private void generateOutput(Options options, List<JApiClass> jApiClasses, JarArc
}

SemverOut semverOut = new SemverOut(options, jApiClasses);
XmlOutputGeneratorOptions xmlOutputGeneratorOptions = new XmlOutputGeneratorOptions();
xmlOutputGeneratorOptions.setCreateSchemaFile(true);
xmlOutputGeneratorOptions.setSemanticVersioningInformation(semverOut.generate());
XmlOutputGenerator xmlGenerator = new XmlOutputGenerator(jApiClasses, options, xmlOutputGeneratorOptions);
try (XmlOutput xmlOutput = xmlGenerator.generate()) {
XmlOutputGenerator.writeToFiles(options, xmlOutput);
} catch (Exception e) {
throw new BuildException("Could not close output streams: " + e.getMessage(), e);
String semanticVersioningInformation = semverOut.generate();
if (options.getXmlOutputFile().isPresent()) {
XmlOutputGeneratorOptions xmlOutputGeneratorOptions = new XmlOutputGeneratorOptions();
xmlOutputGeneratorOptions.setCreateSchemaFile(true);
xmlOutputGeneratorOptions.setSemanticVersioningInformation(semanticVersioningInformation);
XmlOutputGenerator xmlGenerator = new XmlOutputGenerator(jApiClasses, options, xmlOutputGeneratorOptions);
try (XmlOutput xmlOutput = xmlGenerator.generate()) {
XmlOutputGenerator.writeToFiles(options, xmlOutput);
} catch (Exception e) {
throw new BuildException("Writing XML report failed: " + e.getMessage(), e);
}
}
if (options.getHtmlOutputFile().isPresent()) {
HtmlOutputGeneratorOptions htmlOutputGeneratorOptions = new HtmlOutputGeneratorOptions();
htmlOutputGeneratorOptions.setSemanticVersioningInformation(semanticVersioningInformation);
HtmlOutputGenerator htmlOutputGenerator = new HtmlOutputGenerator(jApiClasses, options, htmlOutputGeneratorOptions);
HtmlOutput htmlOutput = htmlOutputGenerator.generate();
try {
Files.write(Paths.get(options.getHtmlOutputFile().get()), htmlOutput.getHtml().getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
throw new BuildException("Writing HTML report failed: " + e.getMessage(), e);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import org.junit.Test;

import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThat;
import static org.hamcrest.MatcherAssert.assertThat;

public class JApiCmpTaskTest {
@Rule
Expand Down
104 changes: 68 additions & 36 deletions japicmp-maven-plugin/src/main/java/japicmp/maven/JApiCmpMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import japicmp.model.JApiClass;
import japicmp.model.JApiCompatibilityChangeType;
import japicmp.model.JApiSemanticVersionLevel;
import japicmp.output.html.HtmlOutput;
import japicmp.output.html.HtmlOutputGenerator;
import japicmp.output.html.HtmlOutputGeneratorOptions;
import japicmp.output.incompatible.IncompatibleErrorOutput;
import japicmp.output.semver.SemverOut;
import japicmp.output.stdout.StdoutOutputGenerator;
Expand Down Expand Up @@ -42,6 +45,10 @@
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -112,7 +119,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
executeWithParameters(pluginParameters, mavenParameters);
}

Optional<XmlOutput> executeWithParameters(PluginParameters pluginParameters, MavenParameters mavenParameters) throws MojoFailureException, MojoExecutionException {
Optional<HtmlOutput> executeWithParameters(PluginParameters pluginParameters, MavenParameters mavenParameters) throws MojoFailureException, MojoExecutionException {
if (pluginParameters.getSkipParam()) {
getLog().info("Skipping execution because parameter 'skip' was set to true.");
return Optional.absent();
Expand All @@ -138,16 +145,30 @@ Optional<XmlOutput> executeWithParameters(PluginParameters pluginParameters, Mav
PostAnalysisScriptExecutor postAnalysisScriptExecutor = new PostAnalysisScriptExecutor();
jApiClasses = postAnalysisScriptExecutor.apply(pluginParameters.getParameterParam(), jApiClasses, getLog());
File jApiCmpBuildDir = createJapiCmpBaseDir(pluginParameters);
generateDiffOutput(mavenParameters, pluginParameters, options, jApiClasses, jApiCmpBuildDir);
XmlOutput xmlOutput = generateXmlOutput(jApiClasses, jApiCmpBuildDir, options, mavenParameters, pluginParameters);
if (pluginParameters.isWriteToFiles()) {
List<File> filesWritten = XmlOutputGenerator.writeToFiles(options, xmlOutput);
for (File file : filesWritten) {
getLog().info("Written file '" + file.getAbsolutePath() + "'.");
SemverOut semverOut = new SemverOut(options, jApiClasses);
String semanticVersioningInformation = semverOut.generate();
generateDiffOutput(mavenParameters, pluginParameters, options, jApiClasses, jApiCmpBuildDir, semanticVersioningInformation);
if (!skipXmlReport(pluginParameters)) {
XmlOutput xmlOutput = generateXmlOutput(jApiClasses, jApiCmpBuildDir, options, mavenParameters, pluginParameters, semanticVersioningInformation);
if (pluginParameters.isWriteToFiles()) {
List<File> filesWritten = XmlOutputGenerator.writeToFiles(options, xmlOutput);
for (File file : filesWritten) {
getLog().info("Written file '" + file.getAbsolutePath() + "'.");
}
}
}
Optional<HtmlOutput> retVal = Optional.absent();
if (!skipHtmlReport(pluginParameters)) {
HtmlOutput htmlOutput = generateHtmlOutput(jApiClasses, jApiCmpBuildDir, options, mavenParameters, pluginParameters, semanticVersioningInformation);
retVal = Optional.of(htmlOutput);
if (pluginParameters.isWriteToFiles() && options.getHtmlOutputFile().isPresent()) {
Path path = Paths.get(options.getHtmlOutputFile().get());
Files.write(path, htmlOutput.getHtml().getBytes(StandardCharsets.UTF_8));
getLog().info("Written file '" + path + "'.");
}
}
breakBuildIfNecessary(jApiClasses, pluginParameters.getParameterParam(), options, jarArchiveComparator);
return Optional.of(xmlOutput);
return retVal;
} catch (IOException e) {
throw new MojoFailureException(String.format("Failed to construct output directory: %s", e.getMessage()), e);
}
Expand Down Expand Up @@ -197,19 +218,19 @@ private enum ConfigurationVersion {
}

private static DefaultArtifact createDefaultArtifact(MavenProject mavenProject, String version) {
org.apache.maven.artifact.Artifact artifact = mavenProject.getArtifact();
return createDefaultArtifact(artifact.getGroupId(), artifact.getArtifactId(), artifact.getClassifier(), artifact.getType(), version);
org.apache.maven.artifact.Artifact artifact = mavenProject.getArtifact();
return createDefaultArtifact(artifact.getGroupId(), artifact.getArtifactId(), artifact.getClassifier(), artifact.getType(), version);
}

private static DefaultArtifact createDefaultArtifact(String groupId, String artifactId, String classifier, String type, String version) {
String mappedType = type;
if("bundle".equals(type) || "ejb".equals(type)) {
mappedType ="jar";
}
DefaultArtifact artifactVersion = new DefaultArtifact(groupId, artifactId, classifier, mappedType,
version);
return artifactVersion;
}
private static DefaultArtifact createDefaultArtifact(String groupId, String artifactId, String classifier, String type, String version) {
String mappedType = type;
if ("bundle".equals(type) || "ejb".equals(type)) {
mappedType = "jar";
}
DefaultArtifact artifactVersion = new DefaultArtifact(groupId, artifactId, classifier, mappedType,
version);
return artifactVersion;
}

private Artifact getComparisonArtifact(final MavenParameters mavenParameters, final PluginParameters pluginParameters,
final ConfigurationVersion configurationVersion) throws MojoFailureException, MojoExecutionException {
Expand All @@ -223,19 +244,19 @@ private Artifact getComparisonArtifact(final MavenParameters mavenParameters, fi
filterSnapshots(versions, pluginParameters);
filterVersionPattern(versions, pluginParameters);
if (!versions.isEmpty()) {
DefaultArtifact artifactVersion = createDefaultArtifact(mavenProject, versions.get(versions.size()-1).toString());
DefaultArtifact artifactVersion = createDefaultArtifact(mavenProject, versions.get(versions.size() - 1).toString());
ArtifactRequest artifactRequest = new ArtifactRequest(artifactVersion, mavenParameters.getRemoteRepos(), null);
ArtifactResult artifactResult = mavenParameters.getRepoSystem().resolveArtifact(mavenParameters.getRepoSession(), artifactRequest);
processArtifactResult(artifactVersion, artifactResult, pluginParameters, configurationVersion);
return artifactResult.getArtifact();
} else {
if (ignoreMissingOldVersion(pluginParameters, configurationVersion)) {
getLog().warn("Ignoring missing old artifact version: " +
artifactVersionRange.getGroupId() + ":" + artifactVersionRange.getArtifactId());
artifactVersionRange.getGroupId() + ":" + artifactVersionRange.getArtifactId());
return null;
} else {
throw new MojoFailureException("Could not find previous version for artifact: " + artifactVersionRange.getGroupId() + ":"
+ artifactVersionRange.getArtifactId());
+ artifactVersionRange.getArtifactId());
}
}
} catch (final VersionRangeResolutionException | ArtifactResolutionException e) {
Expand All @@ -252,7 +273,7 @@ private void processArtifactResult(DefaultArtifact artifactVersion, ArtifactResu
getLog().debug(exception.getMessage(), exception);
}
}
if (artifactResult.isMissing()){
if (artifactResult.isMissing()) {
if (ignoreMissingArtifact(pluginParameters, configurationVersion)) {
getLog().warn("Ignoring missing artifact: " + artifactResult.getArtifact());
} else {
Expand Down Expand Up @@ -539,39 +560,50 @@ private File createJapiCmpBaseDir(PluginParameters pluginParameters) throws Mojo
}
}

private void generateDiffOutput(MavenParameters mavenParameters, PluginParameters pluginParameters, Options options, List<JApiClass> jApiClasses, File jApiCmpBuildDir) throws IOException, MojoFailureException {
private void generateDiffOutput(MavenParameters mavenParameters, PluginParameters pluginParameters, Options options,
List<JApiClass> jApiClasses, File jApiCmpBuildDir, String semanticVersioningInformation) throws IOException, MojoFailureException {
boolean skipDiffReport = false;
if (pluginParameters.getParameterParam() != null) {
skipDiffReport = pluginParameters.getParameterParam().isSkipDiffReport();
}
if (!skipDiffReport) {
StdoutOutputGenerator stdoutOutputGenerator = new StdoutOutputGenerator(options, jApiClasses);
String diffOutput = stdoutOutputGenerator.generate();
diffOutput += "\nSemantic versioning suggestion: " + semanticVersioningInformation;
File output = new File(jApiCmpBuildDir.getCanonicalPath() + File.separator + createFilename(mavenParameters) + ".diff");
writeToFile(diffOutput, output);
}
}

private XmlOutput generateXmlOutput(List<JApiClass> jApiClasses, File jApiCmpBuildDir, Options options, MavenParameters mavenParameters, PluginParameters pluginParameters) throws IOException {
private XmlOutput generateXmlOutput(List<JApiClass> jApiClasses, File jApiCmpBuildDir, Options options, MavenParameters mavenParameters,
PluginParameters pluginParameters, String semanticVersioningInformation) throws IOException {
String filename = createFilename(mavenParameters);
if (!skipXmlReport(pluginParameters)) {
options.setXmlOutputFile(Optional.of(jApiCmpBuildDir.getCanonicalPath() + File.separator + filename + ".xml"));
}
if (!skipHtmlReport(pluginParameters)) {
options.setHtmlOutputFile(Optional.of(jApiCmpBuildDir.getCanonicalPath() + File.separator + filename + ".html"));
}
SemverOut semverOut = new SemverOut(options, jApiClasses);
options.setXmlOutputFile(Optional.of(jApiCmpBuildDir.getCanonicalPath() + File.separator + filename + ".xml"));
XmlOutputGeneratorOptions xmlOutputGeneratorOptions = new XmlOutputGeneratorOptions();
xmlOutputGeneratorOptions.setCreateSchemaFile(true);
xmlOutputGeneratorOptions.setSemanticVersioningInformation(semverOut.generate());
xmlOutputGeneratorOptions.setSemanticVersioningInformation(semanticVersioningInformation);
if (pluginParameters.getParameterParam() != null) {
String optionalTitle = pluginParameters.getParameterParam().getHtmlTitle();
xmlOutputGeneratorOptions.setTitle(optionalTitle!=null ?optionalTitle :options.getDifferenceDescription());
xmlOutputGeneratorOptions.setTitle(optionalTitle != null ? optionalTitle : options.getDifferenceDescription());
}
XmlOutputGenerator xmlGenerator = new XmlOutputGenerator(jApiClasses, options, xmlOutputGeneratorOptions);
return xmlGenerator.generate();
}

private HtmlOutput generateHtmlOutput(List<JApiClass> jApiClasses, File jApiCmpBuildDir, Options options, MavenParameters mavenParameters,
PluginParameters pluginParameters, String semanticVersioningInformation) throws IOException {
String filename = createFilename(mavenParameters);
options.setHtmlOutputFile(Optional.of(jApiCmpBuildDir.getCanonicalPath() + File.separator + filename + ".html"));
HtmlOutputGeneratorOptions htmlOutputGeneratorOptions = new HtmlOutputGeneratorOptions();
htmlOutputGeneratorOptions.setSemanticVersioningInformation(semanticVersioningInformation);
if (pluginParameters.getParameterParam() != null) {
String title = pluginParameters.getParameterParam().getHtmlTitle();
htmlOutputGeneratorOptions.setTitle(title != null ? title : options.getDifferenceDescription());
}
HtmlOutputGenerator htmlOutputGenerator = new HtmlOutputGenerator(jApiClasses, options, htmlOutputGeneratorOptions);
return htmlOutputGenerator.generate();
}

private boolean skipHtmlReport(PluginParameters pluginParameters) {
boolean skipReport = false;
if (pluginParameters.getParameterParam() != null) {
Expand Down Expand Up @@ -682,8 +714,8 @@ private Set<Artifact> getCompileArtifacts(final MavenProject mavenProject) {
for (org.apache.maven.artifact.Artifact dep : projectDependencies) {
if (dep.getArtifactHandler().isAddedToClasspath()) {
if (org.apache.maven.artifact.Artifact.SCOPE_COMPILE.equals(dep.getScope())
|| org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(dep.getScope())
|| org.apache.maven.artifact.Artifact.SCOPE_SYSTEM.equals(dep.getScope())) {
|| org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(dep.getScope())
|| org.apache.maven.artifact.Artifact.SCOPE_SYSTEM.equals(dep.getScope())) {
result.add(RepositoryUtils.toArtifact(dep));
}
}
Expand Down
66 changes: 37 additions & 29 deletions japicmp-maven-plugin/src/main/java/japicmp/maven/JApiCmpReport.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package japicmp.maven;

import japicmp.config.Options;
import japicmp.output.xml.XmlOutput;
import japicmp.output.html.HtmlOutput;
import japicmp.util.Optional;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.doxia.sink.Sink;
Expand All @@ -17,7 +17,6 @@
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.repository.RemoteRepository;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -72,29 +71,12 @@ protected void executeReport(Locale locale) throws MavenReportException {
getLog().info("japicmp module set to skip");
return;
}
Optional<XmlOutput> xmlOutputOptional = mojo.executeWithParameters(this.pluginParameters, this.mavenParameters);
if (xmlOutputOptional.isPresent()) {
XmlOutput xmlOutput = xmlOutputOptional.get();
if (xmlOutput.getHtmlOutputStream().isPresent()) {
ByteArrayOutputStream htmlOutputStream = xmlOutput.getHtmlOutputStream().get();
String htmlString = htmlOutputStream.toString("UTF-8");
htmlString = htmlString.replaceAll("</?html>", "");
htmlString = htmlString.replaceAll("</?body>", "");
htmlString = htmlString.replaceAll("</?head>", "");
htmlString = htmlString.replaceAll("<title>[^<]*</title>", "");
htmlString = htmlString.replaceAll("<META[^>]*>", "");
Sink sink = getSink();
String htmlTitle = getHtmlTitle();
if (htmlTitle != null) {
sink.head();
sink.title();
sink.text(pluginParameters.getParameterParam().getHtmlTitle());
sink.title_();
sink.head_();
}
sink.rawText(htmlString);
sink.close();
}
Optional<HtmlOutput> htmlOutputOptional = mojo.executeWithParameters(this.pluginParameters, this.mavenParameters);
if (htmlOutputOptional.isPresent()) {
HtmlOutput htmlOutput = htmlOutputOptional.get();
String htmlString = htmlOutput.getHtml();
htmlString = replaceHtmlTags(htmlString);
writeToSink(htmlString);
}
} catch (Exception e) {
String msg = "Failed to generate report: " + e.getMessage();
Expand All @@ -105,16 +87,42 @@ protected void executeReport(Locale locale) throws MavenReportException {
}
}

private void writeToSink(String htmlString) {
Sink sink = getSink();
try {
String htmlTitle = getHtmlTitle();
if (htmlTitle != null) {
sink.head();
sink.title();
sink.text(pluginParameters.getParameterParam().getHtmlTitle());
sink.title_();
sink.head_();
}
sink.rawText(htmlString);
} finally {
sink.close();
}
}

private static String replaceHtmlTags(String html) {
html = html.replaceAll("</?html>", "");
html = html.replaceAll("</?body>", "");
html = html.replaceAll("</?head>", "");
html = html.replaceAll("<title>[^<]*</title>", "");
html = html.replaceAll("<META[^>]*>", "");
return html;
}

private JApiCmpMojo getMojo() {
if (this.mojo != null) {
return this.mojo;
}
this.mojo = new JApiCmpMojo();
this.mavenParameters = new MavenParameters(this.artifactRepositories,
this.mavenProject, this.mojoExecution, this.versionRangeWithProjectVersion, this.repoSystem, this.repoSession,
this.remoteRepos);
this.mavenProject, this.mojoExecution, this.versionRangeWithProjectVersion, this.repoSystem, this.repoSession,
this.remoteRepos);
this.pluginParameters = new PluginParameters(this.skip, this.newVersion, this.oldVersion, this.parameter, this.dependencies, Optional.<File>absent(), Optional.of(
this.outputDirectory), false, this.oldVersions, this.newVersions, this.oldClassPathDependencies, this.newClassPathDependencies);
this.outputDirectory), false, this.oldVersions, this.newVersions, this.oldClassPathDependencies, this.newClassPathDependencies);
return this.mojo;
}

Expand Down Expand Up @@ -165,6 +173,6 @@ public String getDescription(Locale locale) {

private boolean isPomModuleNeedingSkip() {
return this.pluginParameters.getParameterParam().getSkipPomModules()
&& "pom".equalsIgnoreCase(this.mavenProject.getArtifact().getType());
&& "pom".equalsIgnoreCase(this.mavenProject.getArtifact().getType());
}
}