Skip to content

Commit

Permalink
moditect#19 Creating config template and dot file in output dir
Browse files Browse the repository at this point in the history
  • Loading branch information
gunnarmorling committed Jan 5, 2019
1 parent b24a65b commit c55b14b
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ See _integration-test/pom.xml_ for a complete example.
* `-Adeptective.config_file=path/to/deptective.json`: Path of the configuration file in the file system
* `-Adeptective.reporting_policy=(ERROR|WARN)`: Whether to fail the build or just raise a warning when spotting any illegal package dependencies (defaults to `ERROR`)
* `-Adeptective.unconfigured_package_reporting_policy=(ERROR|WARN)`: Whether to fail the build or just raise a warning when detecting a package that's not configured in the config file (defaults to `WARN`)
* `-Adeptective.mode=(ANALYZE|VALIDATE|VISUALIZE)`: Whether the plug-in should validate the packages of the compiled package against the _deptective.json_ file (`VALIDATE`), whether the plug-in should visualize the configured _deptective.json_ file in DOT/GraphViz format (`VISUALIZE`) or whether it should generate a template for that file based on the current actual package relationships (`ANALYZE`). The latter can be useful when introducing Deptective into an existing code base where writing the configuration from scratch might be too tedious. Generating the configuration from the current "is" state and iteratively refining it into an intended target state can be a useful approach in that case. Note then when using Deptective via the Maven compiler plug-in, you should make sure to set `<fork>` to `false` and `<showWarnings>` to `true` as otherwise the Maven compiler plug-in will not display the output produced by Deptective. Defaults to `VALIDATE`
* `-Adeptective.mode=(ANALYZE|VALIDATE|VISUALIZE)`: Whether the plug-in should validate the packages of the compiled package against the _deptective.json_ file (`VALIDATE`), whether the plug-in should visualize the configured _deptective.json_ file in DOT/GraphViz format (`VISUALIZE`) or whether it should generate a template for that file based on the current actual package relationships (`ANALYZE`). The latter can be useful when introducing Deptective into an existing code base where writing the configuration from scratch might be too tedious. Generating the configuration from the current "is" state and iteratively refining it into an intended target state can be a useful approach in that case. The JSON/DOT files created by `ANALYZE` and `VISUALIZE` are created in the compiler's class output path, e.g. _target/classes_ in case of Maven. Defaults to `VALIDATE`
* `Adeptective.whitelisted=...`: A comma-separated list of whitelist package patterns which will be applied in `ANALYZE` mode. Any reference to a whitelisted package will then not be added to the `reads` section of the referencing package in the generated descriptor template.
The special value `*ALL_EXTERNAL*` can be used to automatically whitelist all packages which are not part of the current compilation (i.e. packages from dependencies). This can be useful if you're only interested in managing the relationships amongst the current project's packages themselves but not the relationships to external packages.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public void init(JavacTask task, String... args) {

PackageReferenceHandler handler = options.getPluginTask()
.getPackageReferenceHandler(
context.get(JavaFileManager.class),
options,
() -> new ConfigLoader().getConfig(options.getConfigFilePath(), context.get(JavaFileManager.class)),
log
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import java.util.function.Supplier;

import javax.tools.JavaFileManager;

import org.moditect.deptective.internal.handler.PackageReferenceCollector;
import org.moditect.deptective.internal.handler.PackageReferenceHandler;
import org.moditect.deptective.internal.handler.PackageReferenceValidator;
Expand All @@ -35,7 +37,7 @@ public enum PluginTask {

VALIDATE {
@Override
public PackageReferenceHandler getPackageReferenceHandler(DeptectiveOptions options, Supplier<PackageDependencies> configSupplier, Log log) {
public PackageReferenceHandler getPackageReferenceHandler(JavaFileManager jfm, DeptectiveOptions options, Supplier<PackageDependencies> configSupplier, Log log) {
return new PackageReferenceValidator(
configSupplier.get(),
options.getReportingPolicy(),
Expand All @@ -46,19 +48,20 @@ public PackageReferenceHandler getPackageReferenceHandler(DeptectiveOptions opti
},
VISUALIZE {
@Override
public PackageReferenceHandler getPackageReferenceHandler(DeptectiveOptions options, Supplier<PackageDependencies> configSupplier, Log log) {
public PackageReferenceHandler getPackageReferenceHandler(JavaFileManager jfm, DeptectiveOptions options, Supplier<PackageDependencies> configSupplier, Log log) {
return new PackageReferenceVisualizer(
jfm,
configSupplier.get(),
log
);
}
},
ANALYZE {
@Override
public PackageReferenceHandler getPackageReferenceHandler(DeptectiveOptions options, Supplier<PackageDependencies> configSupplier, Log log) {
return new PackageReferenceCollector(log, options.getWhitelistedPackagePatterns());
public PackageReferenceHandler getPackageReferenceHandler(JavaFileManager jfm, DeptectiveOptions options, Supplier<PackageDependencies> configSupplier, Log log) {
return new PackageReferenceCollector(jfm, log, options.getWhitelistedPackagePatterns());
}
};

public abstract PackageReferenceHandler getPackageReferenceHandler(DeptectiveOptions options, Supplier<PackageDependencies> configSupplier, Log log);
public abstract PackageReferenceHandler getPackageReferenceHandler(JavaFileManager jfm, DeptectiveOptions options, Supplier<PackageDependencies> configSupplier, Log log);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@
*/
package org.moditect.deptective.internal.handler;

import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.StandardLocation;

import org.moditect.deptective.internal.log.DeptectiveMessages;
import org.moditect.deptective.internal.log.Log;
import org.moditect.deptective.internal.model.PackageDependencies;
Expand All @@ -41,16 +47,18 @@ public class PackageReferenceCollector implements PackageReferenceHandler {
private final Log log;
private final PackageDependencies.Builder builder;

private final JavaFileManager jfm;
private final List<WhitelistedPackagePattern> whitelistPatterns;
private final Set<String> packagesOfCurrentCompilation;
private final Set<String> referencedPackages;

private String currentPackageName;


public PackageReferenceCollector(Log log, List<WhitelistedPackagePattern> whitelistPatterns) {
public PackageReferenceCollector(JavaFileManager jfm, Log log, List<WhitelistedPackagePattern> whitelistPatterns) {
this.log = log;

this.jfm = jfm;
this.whitelistPatterns = Collections.unmodifiableList(whitelistPatterns);
this.packagesOfCurrentCompilation = new HashSet<String>();
this.referencedPackages = new HashSet<String>();
Expand Down Expand Up @@ -99,7 +107,17 @@ public void onCompletingCompilation() {
}

log.useSource(null);
log.note(DeptectiveMessages.GENERATED_CONFIG, System.lineSeparator(), builder.build().toJson());

try {
FileObject output = jfm.getFileForOutput(StandardLocation.CLASS_OUTPUT, "", "deptective.json", null);
log.note(DeptectiveMessages.GENERATED_CONFIG, output.toUri());
Writer writer = output.openWriter();
writer.append(builder.build().toJson());
writer.close();
}
catch (IOException e) {
throw new RuntimeException("Failed to write deptective.json file", e);
}
}

private boolean isWhitelistAllExternal() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
*/
package org.moditect.deptective.internal.handler;

import java.io.IOException;
import java.io.Writer;

import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.StandardLocation;

import org.moditect.deptective.internal.log.DeptectiveMessages;
import org.moditect.deptective.internal.log.Log;
import org.moditect.deptective.internal.model.PackageDependencies;
Expand All @@ -29,8 +36,10 @@ public class PackageReferenceVisualizer implements PackageReferenceHandler {

private final Log log;
private final PackageDependencies packageDependencies;
private final JavaFileManager jfm;

public PackageReferenceVisualizer(PackageDependencies packageDependencies, Log log) {
public PackageReferenceVisualizer( JavaFileManager jfm, PackageDependencies packageDependencies, Log log) {
this.jfm = jfm;
this.log = log;
this.packageDependencies = packageDependencies;
}
Expand All @@ -48,6 +57,16 @@ public boolean configIsValid() {
@Override
public void onCompletingCompilation() {
log.useSource(null);
log.note(DeptectiveMessages.GENERATED_DOT_REPRESENTATION, System.lineSeparator(), packageDependencies.toDot());

try {
FileObject output = jfm.getFileForOutput(StandardLocation.CLASS_OUTPUT, "", "deptective.dot", null);
log.note(DeptectiveMessages.GENERATED_DOT_REPRESENTATION, output.toUri());
Writer writer = output.openWriter();
writer.append(packageDependencies.toDot());
writer.close();
}
catch (IOException e) {
throw new RuntimeException("Failed to write deptective.dot file", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ protected final Object[][] getContents() {
{ ERROR_PREFIX + PACKAGE_NOT_CONFIGURED, "no Deptective configuration found for package {0}" },
{ WARNING_PREFIX + PACKAGE_NOT_CONFIGURED, "no Deptective configuration found for package {0}" },
{ ERROR_PREFIX + NO_DEPTECTIVE_CONFIG_FOUND, "Config file deptective.json was not found" },
{ NOTE_PREFIX + GENERATED_CONFIG, "Generated Deptective configuration:{0}{1}" },
{ NOTE_PREFIX + GENERATED_DOT_REPRESENTATION, "Converted Deptective configuration to Dot graph:{0}{1}" }
{ NOTE_PREFIX + GENERATED_CONFIG, "Generated Deptective configuration template at {0}" },
{ NOTE_PREFIX + GENERATED_DOT_REPRESENTATION, "Created DOT file representing the Deptective configuration at {0}" }
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Copyright 2019 The ModiTect authors
*
* 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.
*/
package org.moditect.deptective.internal.util;

import java.util.Scanner;

public class Strings {

public static String readToString(java.io.InputStream is) {
try (Scanner s = new Scanner(is, "UTF-8")) {
s.useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
import static com.google.testing.compile.CompilationSubject.assertThat;
import static org.assertj.core.api.Assertions.assertThat;

import javax.tools.Diagnostic;
import java.util.Optional;

import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;

import org.junit.Test;
import org.moditect.deptective.internal.util.Strings;
import org.moditect.deptective.plugintest.PluginTestBase;
import org.moditect.deptective.plugintest.analyze.bar.Bar;
import org.moditect.deptective.plugintest.analyze.foo.Foo;
Expand Down Expand Up @@ -50,10 +53,8 @@ public void shouldGenerateConfig() throws Exception {

assertThat(compilation).succeeded();

assertThat(compilation.notes()).hasSize(1);
Diagnostic<? extends JavaFileObject> note = compilation.notes().get(0);
String message = note.getMessage(null);
String generatedConfig = message.substring(message.indexOf(System.lineSeparator()) + 1);
assertThat(compilation).hadNoteContaining("Generated Deptective configuration template at mem:///CLASS_OUTPUT/deptective.json");
assertThat(compilation).hadNoteCount(1);

String expectedConfig = "{\n" +
" \"packages\" : [ {\n" +
Expand All @@ -66,6 +67,10 @@ public void shouldGenerateConfig() throws Exception {
" \"whitelisted\" : [ \"java.math\" ]\n" +
" }]";

Optional<JavaFileObject> deptectiveFile = compilation.generatedFile(StandardLocation.CLASS_OUTPUT, "deptective.json");
assertThat(deptectiveFile.isPresent()).isTrue();
String generatedConfig = Strings.readToString(deptectiveFile.get().openInputStream());

JSONAssert.assertEquals(expectedConfig, generatedConfig, JSONCompareMode.LENIENT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
import static com.google.testing.compile.CompilationSubject.assertThat;
import static org.assertj.core.api.Assertions.assertThat;

import javax.tools.Diagnostic;
import java.util.Optional;

import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;

import org.junit.Test;
import org.moditect.deptective.internal.util.Strings;
import org.moditect.deptective.plugintest.PluginTestBase;
import org.moditect.deptective.plugintest.analyzewhitelistallexternal.bar.Bar;
import org.moditect.deptective.plugintest.analyzewhitelistallexternal.foo.Foo;
Expand All @@ -48,10 +51,8 @@ public void shouldGenerateConfig() throws Exception {

assertThat(compilation).succeeded();

assertThat(compilation.notes()).hasSize(1);
Diagnostic<? extends JavaFileObject> note = compilation.notes().get(0);
String message = note.getMessage(null);
String generatedConfig = message.substring(message.indexOf(System.lineSeparator()) + 1);
assertThat(compilation).hadNoteContaining("Generated Deptective configuration template at mem:///CLASS_OUTPUT/deptective.json");
assertThat(compilation).hadNoteCount(1);

String expectedConfig = "{\n" +
" \"packages\" : [ {\n" +
Expand All @@ -63,6 +64,10 @@ public void shouldGenerateConfig() throws Exception {
" \"whitelisted\" : [ \"java.io\", \"java.math\", \"java.net\" ]\n" +
" }]";

Optional<JavaFileObject> deptectiveFile = compilation.generatedFile(StandardLocation.CLASS_OUTPUT, "deptective.json");
assertThat(deptectiveFile.isPresent()).isTrue();
String generatedConfig = Strings.readToString(deptectiveFile.get().openInputStream());

JSONAssert.assertEquals(expectedConfig, generatedConfig, JSONCompareMode.LENIENT);
}
}

0 comments on commit c55b14b

Please sign in to comment.