1818
1919import java .io .File ;
2020import java .io .IOException ;
21+ import java .net .URL ;
22+ import java .net .URLClassLoader ;
2123import java .nio .file .Files ;
2224import java .nio .file .Path ;
2325import java .nio .file .StandardOpenOption ;
26+ import java .util .ArrayList ;
2427import java .util .Collections ;
2528import java .util .List ;
29+ import java .util .concurrent .Callable ;
2630import java .util .function .Supplier ;
2731import java .util .stream .Stream ;
2832
3337import org .gradle .api .DefaultTask ;
3438import org .gradle .api .Task ;
3539import org .gradle .api .Transformer ;
40+ import org .gradle .api .file .ConfigurableFileCollection ;
3641import org .gradle .api .file .DirectoryProperty ;
3742import org .gradle .api .file .FileCollection ;
3843import org .gradle .api .file .FileTree ;
3944import org .gradle .api .provider .ListProperty ;
4045import org .gradle .api .provider .Property ;
46+ import org .gradle .api .tasks .Classpath ;
4147import org .gradle .api .tasks .IgnoreEmptyDirectories ;
4248import org .gradle .api .tasks .Input ;
4349import org .gradle .api .tasks .InputFiles ;
5864 * @author Scott Frederick
5965 * @author Ivan Malutin
6066 * @author Phillip Webb
67+ * @author Dmytro Nosan
6168 */
6269public abstract class ArchitectureCheck extends DefaultTask {
6370
@@ -80,14 +87,17 @@ private List<String> asDescriptions(List<ArchRule> rules) {
8087 }
8188
8289 @ TaskAction
83- void checkArchitecture () throws IOException {
84- JavaClasses javaClasses = new ClassFileImporter ().importPaths (classFilesPaths ());
85- List <EvaluationResult > violations = evaluate (javaClasses ).filter (EvaluationResult ::hasViolation ).toList ();
86- File outputFile = getOutputDirectory ().file ("failure-report.txt" ).get ().getAsFile ();
87- writeViolationReport (violations , outputFile );
88- if (!violations .isEmpty ()) {
89- throw new VerificationException ("Architecture check failed. See '" + outputFile + "' for details." );
90- }
90+ void checkArchitecture () throws Exception {
91+ withCompileClasspath (() -> {
92+ JavaClasses javaClasses = new ClassFileImporter ().importPaths (classFilesPaths ());
93+ List <EvaluationResult > violations = evaluate (javaClasses ).filter (EvaluationResult ::hasViolation ).toList ();
94+ File outputFile = getOutputDirectory ().file ("failure-report.txt" ).get ().getAsFile ();
95+ writeViolationReport (violations , outputFile );
96+ if (!violations .isEmpty ()) {
97+ throw new VerificationException ("Architecture check failed. See '" + outputFile + "' for details." );
98+ }
99+ return null ;
100+ });
91101 }
92102
93103 private List <Path > classFilesPaths () {
@@ -98,6 +108,22 @@ private Stream<EvaluationResult> evaluate(JavaClasses javaClasses) {
98108 return getRules ().get ().stream ().map ((rule ) -> rule .evaluate (javaClasses ));
99109 }
100110
111+ private void withCompileClasspath (Callable <?> callable ) throws Exception {
112+ ClassLoader previous = Thread .currentThread ().getContextClassLoader ();
113+ try {
114+ List <URL > urls = new ArrayList <>();
115+ for (File file : getCompileClasspath ().getFiles ()) {
116+ urls .add (file .toURI ().toURL ());
117+ }
118+ ClassLoader classLoader = new URLClassLoader (urls .toArray (new URL [0 ]), getClass ().getClassLoader ());
119+ Thread .currentThread ().setContextClassLoader (classLoader );
120+ callable .call ();
121+ }
122+ finally {
123+ Thread .currentThread ().setContextClassLoader (previous );
124+ }
125+ }
126+
101127 private void writeViolationReport (List <EvaluationResult > violations , File outputFile ) throws IOException {
102128 outputFile .getParentFile ().mkdirs ();
103129 StringBuilder report = new StringBuilder ();
@@ -126,6 +152,10 @@ final FileTree getInputClasses() {
126152 return this .classes .getAsFileTree ();
127153 }
128154
155+ @ InputFiles
156+ @ Classpath
157+ public abstract ConfigurableFileCollection getCompileClasspath ();
158+
129159 @ Optional
130160 @ InputFiles
131161 @ PathSensitive (PathSensitivity .RELATIVE )
0 commit comments