From 22ddb388443287026bd45e2e4efc3f3c170a47a6 Mon Sep 17 00:00:00 2001 From: Markus Heberling Date: Fri, 24 Sep 2021 06:59:27 +0200 Subject: [PATCH 01/14] Added support for Maven POM sorting/formatting --- lib-extra/build.gradle | 2 + .../spotless/extra/pom/SortPomStep.java | 136 ++++++++++++++++++ .../spotless/maven/AbstractSpotlessMojo.java | 6 +- .../com/diffplug/spotless/maven/pom/Pom.java | 45 ++++++ .../diffplug/spotless/maven/pom/SortPom.java | 78 ++++++++++ .../maven/MavenIntegrationHarness.java | 4 + .../spotless/maven/pom/SortPomTest.java | 31 ++++ .../main/resources/pom/pom_clean_default.xml | 40 ++++++ testlib/src/main/resources/pom/pom_dirty.xml | 41 ++++++ 9 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 lib-extra/src/main/java/com/diffplug/spotless/extra/pom/SortPomStep.java create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/Pom.java create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java create mode 100644 plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java create mode 100644 testlib/src/main/resources/pom/pom_clean_default.xml create mode 100644 testlib/src/main/resources/pom/pom_dirty.xml diff --git a/lib-extra/build.gradle b/lib-extra/build.gradle index 1f6fdd8962..bd3bded2b4 100644 --- a/lib-extra/build.gradle +++ b/lib-extra/build.gradle @@ -16,6 +16,8 @@ dependencies { implementation "com.googlecode.concurrent-trees:concurrent-trees:2.6.1" // used for xml parsing in EclipseFormatter implementation "org.codehaus.groovy:groovy-xml:3.0.9" + // used for pom sorting + implementation 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0' // testing testImplementation project(':testlib') diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/pom/SortPomStep.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/pom/SortPomStep.java new file mode 100644 index 0000000000..d70605acf7 --- /dev/null +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/pom/SortPomStep.java @@ -0,0 +1,136 @@ +/* + * Copyright 2021 DiffPlug + * + * 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 com.diffplug.spotless.extra.pom; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.Serializable; +import java.util.logging.Logger; + +import org.apache.commons.io.IOUtils; + +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.FormatterStep; + +import sortpom.SortPomImpl; +import sortpom.logger.SortPomLogger; +import sortpom.parameter.PluginParameters; + +public class SortPomStep { + + public static final String NAME = "sortPom"; + private static final Logger logger = Logger.getLogger(SortPomStep.class.getName()); + + private SortPomStep() {} + + public static FormatterStep create(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions) { + return FormatterStep.createLazy(NAME, () -> new State(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions), State::createFormat); + } + + static final class State implements Serializable { + private static final long serialVersionUID = 1L; + final String encoding; + + final String lineSeparator; + + final boolean expandEmptyElements; + + final boolean spaceBeforeCloseEmptyElement; + + final boolean keepBlankLines; + + final int nrOfIndentSpace; + + final boolean indentBlankLines; + + final boolean indentSchemaLocation; + + final String predefinedSortOrder; + + final String sortOrderFile; + + final String sortDependencies; + + final String sortDependencyExclusions; + + final String sortPlugins; + + final boolean sortProperties; + + final boolean sortModules; + + final boolean sortExecutions; + + State(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions) { + this.encoding = encoding; + this.lineSeparator = lineSeparator; + this.expandEmptyElements = expandEmptyElements; + this.spaceBeforeCloseEmptyElement = spaceBeforeCloseEmptyElement; + this.keepBlankLines = keepBlankLines; + this.nrOfIndentSpace = nrOfIndentSpace; + this.indentBlankLines = indentBlankLines; + this.indentSchemaLocation = indentSchemaLocation; + this.predefinedSortOrder = predefinedSortOrder; + this.sortOrderFile = sortOrderFile; + this.sortDependencies = sortDependencies; + this.sortDependencyExclusions = sortDependencyExclusions; + this.sortPlugins = sortPlugins; + this.sortProperties = sortProperties; + this.sortModules = sortModules; + this.sortExecutions = sortExecutions; + } + + FormatterFunc createFormat() { + return input -> { + // SortPom expects a file to sort, so we write the inpout into a temporary file + File pom = File.createTempFile("pom", ".xml"); + pom.deleteOnExit(); + try (FileWriter fw = new FileWriter(pom)) { + fw.write(input); + } + SortPomImpl sortPom = new SortPomImpl(); + sortPom.setup(new SortPomLogger() { + @Override + public void warn(String content) { + logger.warning(content); + } + + @Override + public void info(String content) { + logger.info(content); + } + + @Override + public void error(String content) { + logger.severe(content); + } + }, PluginParameters.builder() + .setPomFile(pom) + .setFileOutput(false, null, null, false) + .setEncoding(encoding) + .setFormatting(lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines) + .setIndent(nrOfIndentSpace, indentBlankLines, indentSchemaLocation) + .setSortOrder(sortOrderFile, predefinedSortOrder) + .setSortEntities(sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions) + .setTriggers(false) + .build()); + sortPom.sortPom(); + return IOUtils.toString(new FileReader(pom)); + }; + } + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index c39fc0a30c..245ab80a3a 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -56,6 +56,7 @@ import com.diffplug.spotless.maven.groovy.Groovy; import com.diffplug.spotless.maven.java.Java; import com.diffplug.spotless.maven.kotlin.Kotlin; +import com.diffplug.spotless.maven.pom.Pom; import com.diffplug.spotless.maven.python.Python; import com.diffplug.spotless.maven.scala.Scala; import com.diffplug.spotless.maven.sql.Sql; @@ -120,6 +121,9 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo { @Parameter private Antlr4 antlr4; + @Parameter + private Pom pom; + @Parameter private Sql sql; @@ -258,7 +262,7 @@ private FileLocator getFileLocator() { } private List getFormatterFactories() { - return Stream.concat(formats.stream(), Stream.of(groovy, java, scala, kotlin, cpp, typescript, antlr4, sql, python)) + return Stream.concat(formats.stream(), Stream.of(groovy, java, scala, kotlin, cpp, typescript, antlr4, pom, sql, python)) .filter(Objects::nonNull) .collect(toList()); } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/Pom.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/Pom.java new file mode 100644 index 0000000000..f083a17c89 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/Pom.java @@ -0,0 +1,45 @@ +/* + * Copyright 2021 DiffPlug + * + * 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 com.diffplug.spotless.maven.pom; + +import java.util.Set; + +import com.diffplug.common.collect.ImmutableSet; +import com.diffplug.spotless.maven.FormatterFactory; +import com.diffplug.spotless.maven.generic.LicenseHeader; + +/** + * A {@link FormatterFactory} implementation that corresponds to {@code ...} configuration element. + *

+ * It defines a formatter for Maven pom files that can execute both language agnostic (e.g. {@link LicenseHeader}) + * and pom-specific (e.g. {@link SortPom}) steps. + */ +public class Pom extends FormatterFactory { + @Override + public Set defaultIncludes() { + return ImmutableSet.of("pom.xml"); + } + + @Override + public String licenseHeaderDelimiter() { + return null; + } + + public void addSortPom(SortPom sortPom) { + addStepFactory(sortPom); + } + +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java new file mode 100644 index 0000000000..3fbe06f3dd --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java @@ -0,0 +1,78 @@ +/* + * Copyright 2021 DiffPlug + * + * 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 com.diffplug.spotless.maven.pom; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.extra.pom.SortPomStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class SortPom implements FormatterStepFactory { + @Parameter + String encoding = "UTF-8"; + + @Parameter + String lineSeparator = System.getProperty("line.separator"); + + @Parameter + boolean expandEmptyElements = true; + + @Parameter + boolean spaceBeforeCloseEmptyElement = false; + + @Parameter + boolean keepBlankLines = true; + + @Parameter + int nrOfIndentSpace = 2; + + @Parameter + boolean indentBlankLines = false; + + @Parameter + boolean indentSchemaLocation = false; + + @Parameter + String predefinedSortOrder = "recommended_2008_06"; + + @Parameter + String sortOrderFile; + + @Parameter + String sortDependencies; + + @Parameter + String sortDependencyExclusions; + + @Parameter + String sortPlugins; + + @Parameter + boolean sortProperties = false; + + @Parameter + boolean sortModules = false; + + @Parameter + boolean sortExecutions = false; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { + return SortPomStep.create(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java index a7dd49b2fb..fa5224bb8d 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java @@ -134,6 +134,10 @@ protected void writePomWithPrettierSteps(String includes, String... steps) throw writePom(formats(groupWithSteps("format", including(includes), steps))); } + protected void writePomWithPomSteps(String... steps) throws IOException { + writePom(groupWithSteps("pom", including("pom_test.xml"), steps)); + } + protected void writePom(String... configuration) throws IOException { writePom(null, configuration); } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java new file mode 100644 index 0000000000..8df667ce44 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2021 DiffPlug + * + * 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 com.diffplug.spotless.maven.pom; + +import com.diffplug.spotless.maven.MavenIntegrationHarness; + +import org.junit.jupiter.api.Test; + +public class SortPomTest extends MavenIntegrationHarness { + @Test + public void testSortPomWithDefaultConfig() throws Exception { + writePomWithPomSteps(""); + + setFile("pom_test.xml").toResource("pom/pom_dirty.xml"); + System.out.println(mavenRunner().withArguments("spotless:apply").runNoError().error()); + assertFile("pom_test.xml").sameAsResource("pom/pom_clean_default.xml"); + } +} diff --git a/testlib/src/main/resources/pom/pom_clean_default.xml b/testlib/src/main/resources/pom/pom_clean_default.xml new file mode 100644 index 0000000000..b4173f3b49 --- /dev/null +++ b/testlib/src/main/resources/pom/pom_clean_default.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + spotless.test + minimal-pom + 1.0-SNAPSHOT + jar + + minimal-pom + http://maven.apache.org + + + UTF-8 + 1.8 + + + + + junit + junit + 4.11 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + + + + + diff --git a/testlib/src/main/resources/pom/pom_dirty.xml b/testlib/src/main/resources/pom/pom_dirty.xml new file mode 100644 index 0000000000..6d019c7df6 --- /dev/null +++ b/testlib/src/main/resources/pom/pom_dirty.xml @@ -0,0 +1,41 @@ + + minimal-pom + 4.0.0 + + spotless.test + jar + 1.0-SNAPSHOT + + minimal-pom + http://maven.apache.org + + + UTF-8 + 1.8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + + + + + + + + junit + junit + 4.11 + test + + + From 503f4c0aa6c398f46d1ad006670672e7cfe2910e Mon Sep 17 00:00:00 2001 From: Markus Heberling Date: Sat, 25 Sep 2021 21:00:31 +0200 Subject: [PATCH 02/14] load SortPom from JarState --- lib-extra/build.gradle | 2 - lib/build.gradle | 20 ++++ .../spotless/pom/DelegatingClassLoader.java | 86 ++++++++++++++++ .../spotless/pom/SortPomFormatterFunc.java | 76 ++++++++++++++ .../diffplug/spotless}/pom/SortPomStep.java | 99 +++++++++---------- plugin-maven/build.gradle | 1 + .../diffplug/spotless/maven/pom/SortPom.java | 4 +- .../spotless/maven/pom/SortPomTest.java | 4 +- 8 files changed, 234 insertions(+), 58 deletions(-) create mode 100644 lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java create mode 100644 lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java rename {lib-extra/src/main/java/com/diffplug/spotless/extra => lib/src/sortPom/java/com/diffplug/spotless}/pom/SortPomStep.java (53%) diff --git a/lib-extra/build.gradle b/lib-extra/build.gradle index bd3bded2b4..1f6fdd8962 100644 --- a/lib-extra/build.gradle +++ b/lib-extra/build.gradle @@ -16,8 +16,6 @@ dependencies { implementation "com.googlecode.concurrent-trees:concurrent-trees:2.6.1" // used for xml parsing in EclipseFormatter implementation "org.codehaus.groovy:groovy-xml:3.0.9" - // used for pom sorting - implementation 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0' // testing testImplementation project(':testlib') diff --git a/lib/build.gradle b/lib/build.gradle index d8685a5acd..88745a42ac 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -6,15 +6,35 @@ version = rootProject.spotlessChangelog.versionNext apply from: rootProject.file('gradle/java-setup.gradle') apply from: rootProject.file('gradle/java-publish.gradle') +sourceSets { + sortPom { + compileClasspath += sourceSets.main.output + runtimeClasspath += sourceSets.main.output + + java { + } + } +} + dependencies { // zero runtime reqs is a hard requirements for spotless-lib // if you need a dep, put it in lib-extra testImplementation "org.junit.jupiter:junit-jupiter:${VER_JUNIT}" testImplementation "org.assertj:assertj-core:${VER_ASSERTJ}" testImplementation "com.diffplug.durian:durian-testlib:${VER_DURIAN}" + + // used for pom sorting + sortPomCompileOnly 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0' } // we'll hold the core lib to a high standard spotbugs { reportLevel = 'low' } // low|medium|high (low = sensitive to even minor mistakes) test { useJUnitPlatform() } + +jar { + // Add directories with generated sources (might be several - one for every supported language). + from sourceSets.sortPom.output.classesDirs + // Add output directories of the sourceset's resources. + from sourceSets.sortPom.output.resourcesDir +} diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java new file mode 100644 index 0000000000..416fce01ed --- /dev/null +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java @@ -0,0 +1,86 @@ +/* + * Copyright 2021 DiffPlug + * + * 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 com.diffplug.spotless.pom; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.ByteBuffer; +import java.util.Enumeration; +import java.util.Vector; + +public class DelegatingClassLoader extends ClassLoader { + + private final ClassLoader[] delegateClassLoaders; + + public DelegatingClassLoader(ClassLoader... delegateClassLoaders) { + super(null); + this.delegateClassLoaders = delegateClassLoaders; + } + + protected Class findClass(String name) throws ClassNotFoundException { + String path = name.replace('.', '/') + ".class"; + URL url = findResource(path); + if (url == null) { + throw new ClassNotFoundException(name); + } + try { + ByteBuffer byteCode = loadResource(url); + return defineClass(name, byteCode, null); + } catch (IOException e) { + throw new ClassNotFoundException(name, e); + } + } + + private ByteBuffer loadResource(URL url) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + int nRead; + byte[] data = new byte[1024]; + + InputStream inputStream = url.openStream(); + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + + buffer.flush(); + + return ByteBuffer.wrap(buffer.toByteArray()); + } + + protected URL findResource(String name) { + for (ClassLoader delegate : delegateClassLoaders) { + URL resource = delegate.getResource(name); + if (resource != null) { + return resource; + } + } + return null; + } + + protected Enumeration findResources(String name) throws IOException { + Vector vector = new Vector<>(); + for (ClassLoader delegate : delegateClassLoaders) { + Enumeration enumeration = delegate.getResources(name); + while (enumeration.hasMoreElements()) { + vector.add(enumeration.nextElement()); + } + } + return vector.elements(); + } + +} diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java new file mode 100644 index 0000000000..e056f4ed36 --- /dev/null +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java @@ -0,0 +1,76 @@ +/* + * Copyright 2021 DiffPlug + * + * 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 com.diffplug.spotless.pom; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.util.logging.Logger; + +import org.apache.commons.io.IOUtils; + +import com.diffplug.spotless.FormatterFunc; + +import sortpom.SortPomImpl; +import sortpom.logger.SortPomLogger; +import sortpom.parameter.PluginParameters; + +class SortPomFormatterFunc implements FormatterFunc { + private static final Logger logger = Logger.getLogger(SortPomStep.class.getName()); + private final SortPomStep.InternalState state; + + public SortPomFormatterFunc(SortPomStep.InternalState state) { + this.state = state; + } + + @Override + public String apply(String input) throws Exception { + // SortPom expects a file to sort, so we write the inpout into a temporary file + File pom = File.createTempFile("pom", ".xml"); + pom.deleteOnExit(); + try (FileWriter fw = new FileWriter(pom)) { + fw.write(input); + } + SortPomImpl sortPom = new SortPomImpl(); + sortPom.setup(new SortPomLogger() { + @Override + public void warn(String content) { + logger.warning(content); + } + + @Override + public void info(String content) { + logger.info(content); + } + + @Override + public void error(String content) { + logger.severe(content); + } + }, PluginParameters.builder() + .setPomFile(pom) + .setFileOutput(false, null, null, false) + .setEncoding(state.encoding) + .setFormatting(state.lineSeparator, state.expandEmptyElements, state.spaceBeforeCloseEmptyElement, state.keepBlankLines) + .setIndent(state.nrOfIndentSpace, state.indentBlankLines, state.indentSchemaLocation) + .setSortOrder(state.sortOrderFile, state.predefinedSortOrder) + .setSortEntities(state.sortDependencies, state.sortDependencyExclusions, state.sortPlugins, state.sortProperties, state.sortModules, state.sortExecutions) + .setTriggers(false) + .build()); + sortPom.sortPom(); + return IOUtils.toString(new FileReader(pom)); + } +} diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/pom/SortPomStep.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java similarity index 53% rename from lib-extra/src/main/java/com/diffplug/spotless/extra/pom/SortPomStep.java rename to lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java index d70605acf7..9a5cf081c5 100644 --- a/lib-extra/src/main/java/com/diffplug/spotless/extra/pom/SortPomStep.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java @@ -13,36 +13,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.diffplug.spotless.extra.pom; - -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; +package com.diffplug.spotless.pom; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; import java.io.Serializable; -import java.util.logging.Logger; - -import org.apache.commons.io.IOUtils; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; - -import sortpom.SortPomImpl; -import sortpom.logger.SortPomLogger; -import sortpom.parameter.PluginParameters; +import com.diffplug.spotless.JarState; +import com.diffplug.spotless.Provisioner; public class SortPomStep { public static final String NAME = "sortPom"; - private static final Logger logger = Logger.getLogger(SortPomStep.class.getName()); private SortPomStep() {} - public static FormatterStep create(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions) { - return FormatterStep.createLazy(NAME, () -> new State(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions), State::createFormat); + public static FormatterStep create(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions, Provisioner provisioner) { + return FormatterStep.createLazy(NAME, () -> new State(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions, provisioner), State::createFormat); } - static final class State implements Serializable { + static final class InternalState implements Serializable { private static final long serialVersionUID = 1L; + final String encoding; final String lineSeparator; @@ -75,7 +76,7 @@ static final class State implements Serializable { final boolean sortExecutions; - State(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions) { + InternalState(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions) { this.encoding = encoding; this.lineSeparator = lineSeparator; this.expandEmptyElements = expandEmptyElements; @@ -93,44 +94,38 @@ static final class State implements Serializable { this.sortModules = sortModules; this.sortExecutions = sortExecutions; } + } - FormatterFunc createFormat() { - return input -> { - // SortPom expects a file to sort, so we write the inpout into a temporary file - File pom = File.createTempFile("pom", ".xml"); - pom.deleteOnExit(); - try (FileWriter fw = new FileWriter(pom)) { - fw.write(input); + static final class State implements Serializable { + private static final long serialVersionUID = 1L; + final JarState jarState; + + final InternalState internalState; + + State(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions, Provisioner provisioner) throws IOException { + this.jarState = JarState.from("com.github.ekryd.sortpom:sortpom-sorter:3.0.0", provisioner); + this.internalState = new InternalState(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions); + } + + FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { + ClassLoader classLoader = new DelegatingClassLoader(this.getClass().getClassLoader(), jarState.getClassLoader()); + Constructor constructor = classLoader.loadClass(SortPomFormatterFunc.class.getName()).getConstructor(classLoader.loadClass(InternalState.class.getName())); + constructor.setAccessible(true); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(out); + oos.writeObject(internalState); + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())) { + @Override + protected Class resolveClass(ObjectStreamClass desc) throws ClassNotFoundException { + return classLoader.loadClass(desc.getName()); } - SortPomImpl sortPom = new SortPomImpl(); - sortPom.setup(new SortPomLogger() { - @Override - public void warn(String content) { - logger.warning(content); - } - - @Override - public void info(String content) { - logger.info(content); - } - - @Override - public void error(String content) { - logger.severe(content); - } - }, PluginParameters.builder() - .setPomFile(pom) - .setFileOutput(false, null, null, false) - .setEncoding(encoding) - .setFormatting(lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines) - .setIndent(nrOfIndentSpace, indentBlankLines, indentSchemaLocation) - .setSortOrder(sortOrderFile, predefinedSortOrder) - .setSortEntities(sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions) - .setTriggers(false) - .build()); - sortPom.sortPom(); - return IOUtils.toString(new FileReader(pom)); }; + Object state = ois.readObject(); + Object formatterFunc = constructor.newInstance(state); + Method apply = formatterFunc.getClass().getMethod("apply", String.class); + apply.setAccessible(true); + return input -> (String) apply.invoke(formatterFunc, input); } + } } diff --git a/plugin-maven/build.gradle b/plugin-maven/build.gradle index f5257e065c..44b7d7222d 100644 --- a/plugin-maven/build.gradle +++ b/plugin-maven/build.gradle @@ -63,6 +63,7 @@ String libVersion = version.endsWith('-SNAPSHOT') ? dependencies { if (version.endsWith('-SNAPSHOT') || (rootProject.spotlessChangelog.versionNext == rootProject.spotlessChangelog.versionLast)) { implementation project(':lib') + implementation project(':lib').sourceSets.sortPom.output implementation project(':lib-extra') } else { implementation "com.diffplug.spotless:spotless-lib:${libVersion}" diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java index 3fbe06f3dd..ddd3fb6fbc 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java @@ -18,9 +18,9 @@ import org.apache.maven.plugins.annotations.Parameter; import com.diffplug.spotless.FormatterStep; -import com.diffplug.spotless.extra.pom.SortPomStep; import com.diffplug.spotless.maven.FormatterStepConfig; import com.diffplug.spotless.maven.FormatterStepFactory; +import com.diffplug.spotless.pom.SortPomStep; public class SortPom implements FormatterStepFactory { @Parameter @@ -73,6 +73,6 @@ public class SortPom implements FormatterStepFactory { @Override public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { - return SortPomStep.create(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions); + return SortPomStep.create(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions, stepConfig.getProvisioner()); } } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java index 8df667ce44..4b26127cc0 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java @@ -15,10 +15,10 @@ */ package com.diffplug.spotless.maven.pom; -import com.diffplug.spotless.maven.MavenIntegrationHarness; - import org.junit.jupiter.api.Test; +import com.diffplug.spotless.maven.MavenIntegrationHarness; + public class SortPomTest extends MavenIntegrationHarness { @Test public void testSortPomWithDefaultConfig() throws Exception { From 8b7c3eb894d013feb4c8fbaca62a69d3854c4bb7 Mon Sep 17 00:00:00 2001 From: Markus Heberling Date: Tue, 28 Sep 2021 08:11:37 +0200 Subject: [PATCH 03/14] use FormatterFunc and SortPomState from current ClassLoader --- .../spotless/pom/DelegatingClassLoader.java | 32 ++++-- .../spotless/pom/SortPomFormatterFunc.java | 4 +- .../diffplug/spotless/pom/SortPomState.java | 91 ++++++++++++++++ .../diffplug/spotless/pom/SortPomStep.java | 103 +----------------- 4 files changed, 117 insertions(+), 113 deletions(-) create mode 100644 lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java index 416fce01ed..75bcb9c32b 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java @@ -20,8 +20,12 @@ import java.io.InputStream; import java.net.URL; import java.nio.ByteBuffer; +import java.util.Collections; import java.util.Enumeration; -import java.util.Vector; +import java.util.LinkedList; +import java.util.List; + +import com.diffplug.spotless.FormatterFunc; public class DelegatingClassLoader extends ClassLoader { @@ -32,15 +36,23 @@ public DelegatingClassLoader(ClassLoader... delegateClassLoaders) { this.delegateClassLoaders = delegateClassLoaders; } + @Override protected Class findClass(String name) throws ClassNotFoundException { + // these classes need to be loaded from the current classloader, since they may not be attached to this classloader + if (name.equals(FormatterFunc.class.getName())) { + return FormatterFunc.class; + } + if (name.equals(SortPomState.class.getName())) { + return SortPomState.class; + } + // all other loaded classes need to be associated with this classloader, so we need to load them as resources String path = name.replace('.', '/') + ".class"; URL url = findResource(path); if (url == null) { throw new ClassNotFoundException(name); } try { - ByteBuffer byteCode = loadResource(url); - return defineClass(name, byteCode, null); + return defineClass(name, loadResource(url), null); } catch (IOException e) { throw new ClassNotFoundException(name, e); } @@ -52,9 +64,10 @@ private ByteBuffer loadResource(URL url) throws IOException { int nRead; byte[] data = new byte[1024]; - InputStream inputStream = url.openStream(); - while ((nRead = inputStream.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); + try (InputStream inputStream = url.openStream()) { + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } } buffer.flush(); @@ -62,6 +75,7 @@ private ByteBuffer loadResource(URL url) throws IOException { return ByteBuffer.wrap(buffer.toByteArray()); } + @Override protected URL findResource(String name) { for (ClassLoader delegate : delegateClassLoaders) { URL resource = delegate.getResource(name); @@ -73,14 +87,14 @@ protected URL findResource(String name) { } protected Enumeration findResources(String name) throws IOException { - Vector vector = new Vector<>(); + List resources = new LinkedList<>(); for (ClassLoader delegate : delegateClassLoaders) { Enumeration enumeration = delegate.getResources(name); while (enumeration.hasMoreElements()) { - vector.add(enumeration.nextElement()); + resources.add(enumeration.nextElement()); } } - return vector.elements(); + return Collections.enumeration(resources); } } diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java index e056f4ed36..83f835633f 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java @@ -30,9 +30,9 @@ class SortPomFormatterFunc implements FormatterFunc { private static final Logger logger = Logger.getLogger(SortPomStep.class.getName()); - private final SortPomStep.InternalState state; + private final SortPomState state; - public SortPomFormatterFunc(SortPomStep.InternalState state) { + public SortPomFormatterFunc(SortPomState state) { this.state = state; } diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java new file mode 100644 index 0000000000..1c741b3d1e --- /dev/null +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java @@ -0,0 +1,91 @@ +/* + * Copyright 2021 DiffPlug + * + * 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 com.diffplug.spotless.pom; + +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.JarState; +import com.diffplug.spotless.Provisioner; + +// Class and members must be public, otherwise we get failed to access class com.diffplug.spotless.pom.SortPomInternalState from class com.diffplug.spotless.pom.SortPomFormatterFunc (com.diffplug.spotless.pom.SortPomInternalState is in unnamed module of loader org.codehaus.plexus.classworlds.realm.ClassRealm @682bd3c4; com.diffplug.spotless.pom.SortPomFormatterFunc is in unnamed module of loader com.diffplug.spotless.pom.DelegatingClassLoader @573284a5) +public final class SortPomState implements Serializable { + private static final long serialVersionUID = 1L; + + public final JarState jarState; + + public final String encoding; + + public final String lineSeparator; + + public final boolean expandEmptyElements; + + public final boolean spaceBeforeCloseEmptyElement; + + public final boolean keepBlankLines; + + public final int nrOfIndentSpace; + + public final boolean indentBlankLines; + + public final boolean indentSchemaLocation; + + public final String predefinedSortOrder; + + public final String sortOrderFile; + + public final String sortDependencies; + + public final String sortDependencyExclusions; + + public final String sortPlugins; + + public final boolean sortProperties; + + public final boolean sortModules; + + public final boolean sortExecutions; + + SortPomState(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions, Provisioner provisioner) throws IOException { + this.jarState = JarState.from("com.github.ekryd.sortpom:sortpom-sorter:3.0.0", provisioner); + this.encoding = encoding; + this.lineSeparator = lineSeparator; + this.expandEmptyElements = expandEmptyElements; + this.spaceBeforeCloseEmptyElement = spaceBeforeCloseEmptyElement; + this.keepBlankLines = keepBlankLines; + this.nrOfIndentSpace = nrOfIndentSpace; + this.indentBlankLines = indentBlankLines; + this.indentSchemaLocation = indentSchemaLocation; + this.predefinedSortOrder = predefinedSortOrder; + this.sortOrderFile = sortOrderFile; + this.sortDependencies = sortDependencies; + this.sortDependencyExclusions = sortDependencyExclusions; + this.sortPlugins = sortPlugins; + this.sortProperties = sortProperties; + this.sortModules = sortModules; + this.sortExecutions = sortExecutions; + } + + FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { + ClassLoader classLoader = new DelegatingClassLoader(this.getClass().getClassLoader(), jarState.getClassLoader()); + Constructor constructor = classLoader.loadClass(SortPomFormatterFunc.class.getName()).getConstructor(classLoader.loadClass(SortPomState.class.getName())); + constructor.setAccessible(true); + return (FormatterFunc) constructor.newInstance(this); + } +} diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java index 9a5cf081c5..9138ef650e 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java @@ -15,20 +15,7 @@ */ package com.diffplug.spotless.pom; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.ObjectStreamClass; -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; -import com.diffplug.spotless.JarState; import com.diffplug.spotless.Provisioner; public class SortPomStep { @@ -38,94 +25,6 @@ public class SortPomStep { private SortPomStep() {} public static FormatterStep create(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions, Provisioner provisioner) { - return FormatterStep.createLazy(NAME, () -> new State(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions, provisioner), State::createFormat); - } - - static final class InternalState implements Serializable { - private static final long serialVersionUID = 1L; - - final String encoding; - - final String lineSeparator; - - final boolean expandEmptyElements; - - final boolean spaceBeforeCloseEmptyElement; - - final boolean keepBlankLines; - - final int nrOfIndentSpace; - - final boolean indentBlankLines; - - final boolean indentSchemaLocation; - - final String predefinedSortOrder; - - final String sortOrderFile; - - final String sortDependencies; - - final String sortDependencyExclusions; - - final String sortPlugins; - - final boolean sortProperties; - - final boolean sortModules; - - final boolean sortExecutions; - - InternalState(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions) { - this.encoding = encoding; - this.lineSeparator = lineSeparator; - this.expandEmptyElements = expandEmptyElements; - this.spaceBeforeCloseEmptyElement = spaceBeforeCloseEmptyElement; - this.keepBlankLines = keepBlankLines; - this.nrOfIndentSpace = nrOfIndentSpace; - this.indentBlankLines = indentBlankLines; - this.indentSchemaLocation = indentSchemaLocation; - this.predefinedSortOrder = predefinedSortOrder; - this.sortOrderFile = sortOrderFile; - this.sortDependencies = sortDependencies; - this.sortDependencyExclusions = sortDependencyExclusions; - this.sortPlugins = sortPlugins; - this.sortProperties = sortProperties; - this.sortModules = sortModules; - this.sortExecutions = sortExecutions; - } - } - - static final class State implements Serializable { - private static final long serialVersionUID = 1L; - final JarState jarState; - - final InternalState internalState; - - State(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions, Provisioner provisioner) throws IOException { - this.jarState = JarState.from("com.github.ekryd.sortpom:sortpom-sorter:3.0.0", provisioner); - this.internalState = new InternalState(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions); - } - - FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { - ClassLoader classLoader = new DelegatingClassLoader(this.getClass().getClassLoader(), jarState.getClassLoader()); - Constructor constructor = classLoader.loadClass(SortPomFormatterFunc.class.getName()).getConstructor(classLoader.loadClass(InternalState.class.getName())); - constructor.setAccessible(true); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(out); - oos.writeObject(internalState); - ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())) { - @Override - protected Class resolveClass(ObjectStreamClass desc) throws ClassNotFoundException { - return classLoader.loadClass(desc.getName()); - } - }; - Object state = ois.readObject(); - Object formatterFunc = constructor.newInstance(state); - Method apply = formatterFunc.getClass().getMethod("apply", String.class); - apply.setAccessible(true); - return input -> (String) apply.invoke(formatterFunc, input); - } - + return FormatterStep.createLazy(NAME, () -> new SortPomState(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions, provisioner), SortPomState::createFormat); } } From c0d1b689da41421dd81aebc427cd8c76b3aeb68b Mon Sep 17 00:00:00 2001 From: Markus Heberling Date: Tue, 28 Sep 2021 09:44:25 +0200 Subject: [PATCH 04/14] Fixed SpotBugs errors --- .../spotless/pom/DelegatingClassLoader.java | 7 ++- .../spotless/pom/SortPomFormatterFunc.java | 46 +++++++++---------- .../diffplug/spotless/pom/SortPomState.java | 4 +- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java index 75bcb9c32b..13416c4428 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java @@ -64,10 +64,9 @@ private ByteBuffer loadResource(URL url) throws IOException { int nRead; byte[] data = new byte[1024]; - try (InputStream inputStream = url.openStream()) { - while ((nRead = inputStream.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - } + InputStream inputStream = url.openStream(); + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); } buffer.flush(); diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java index 83f835633f..22606cdf01 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java @@ -16,8 +16,8 @@ package com.diffplug.spotless.pom; import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.util.logging.Logger; import org.apache.commons.io.IOUtils; @@ -29,7 +29,7 @@ import sortpom.parameter.PluginParameters; class SortPomFormatterFunc implements FormatterFunc { - private static final Logger logger = Logger.getLogger(SortPomStep.class.getName()); + private static final Logger logger = Logger.getLogger(SortPomFormatterFunc.class.getName()); private final SortPomState state; public SortPomFormatterFunc(SortPomState state) { @@ -41,26 +41,9 @@ public String apply(String input) throws Exception { // SortPom expects a file to sort, so we write the inpout into a temporary file File pom = File.createTempFile("pom", ".xml"); pom.deleteOnExit(); - try (FileWriter fw = new FileWriter(pom)) { - fw.write(input); - } + IOUtils.write(input, new FileOutputStream(pom), state.encoding); SortPomImpl sortPom = new SortPomImpl(); - sortPom.setup(new SortPomLogger() { - @Override - public void warn(String content) { - logger.warning(content); - } - - @Override - public void info(String content) { - logger.info(content); - } - - @Override - public void error(String content) { - logger.severe(content); - } - }, PluginParameters.builder() + sortPom.setup(new MySortPomLogger(), PluginParameters.builder() .setPomFile(pom) .setFileOutput(false, null, null, false) .setEncoding(state.encoding) @@ -71,6 +54,23 @@ public void error(String content) { .setTriggers(false) .build()); sortPom.sortPom(); - return IOUtils.toString(new FileReader(pom)); + return IOUtils.toString(new FileInputStream(pom), state.encoding); + } + + private static class MySortPomLogger implements SortPomLogger { + @Override + public void warn(String content) { + logger.warning(content); + } + + @Override + public void info(String content) { + logger.info(content); + } + + @Override + public void error(String content) { + logger.severe(content); + } } } diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java index 1c741b3d1e..153196f16f 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java @@ -19,6 +19,8 @@ import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; +import java.security.PrivilegedAction; import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.JarState; @@ -83,7 +85,7 @@ public final class SortPomState implements Serializable { } FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { - ClassLoader classLoader = new DelegatingClassLoader(this.getClass().getClassLoader(), jarState.getClassLoader()); + ClassLoader classLoader = AccessController.doPrivileged((PrivilegedAction) () -> new DelegatingClassLoader(this.getClass().getClassLoader(), jarState.getClassLoader())); Constructor constructor = classLoader.loadClass(SortPomFormatterFunc.class.getName()).getConstructor(classLoader.loadClass(SortPomState.class.getName())); constructor.setAccessible(true); return (FormatterFunc) constructor.newInstance(this); From 680d95c87211462bcacea8766b694547270f7540 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 29 Sep 2021 11:42:24 -0700 Subject: [PATCH 05/14] Rename SortPomTest to SortPomMavenTest. --- .../maven/pom/{SortPomTest.java => SortPomMavenTest.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/{SortPomTest.java => SortPomMavenTest.java} (86%) diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomMavenTest.java similarity index 86% rename from plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java rename to plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomMavenTest.java index 4b26127cc0..ca9d77a6e3 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomMavenTest.java @@ -19,13 +19,13 @@ import com.diffplug.spotless.maven.MavenIntegrationHarness; -public class SortPomTest extends MavenIntegrationHarness { +public class SortPomMavenTest extends MavenIntegrationHarness { @Test public void testSortPomWithDefaultConfig() throws Exception { writePomWithPomSteps(""); setFile("pom_test.xml").toResource("pom/pom_dirty.xml"); - System.out.println(mavenRunner().withArguments("spotless:apply").runNoError().error()); + mavenRunner().withArguments("spotless:apply").runNoError().error(); assertFile("pom_test.xml").sameAsResource("pom/pom_clean_default.xml"); } } From 4a8057666cfe0cde4c4361f09526d2f2d0a5b219 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 29 Sep 2021 11:42:37 -0700 Subject: [PATCH 06/14] Create a no-maven SortPomTest which can run quickly. --- testlib/build.gradle | 1 + .../diffplug/spotless/pom/SortPomTest.java | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 testlib/src/test/java/com/diffplug/spotless/pom/SortPomTest.java diff --git a/testlib/build.gradle b/testlib/build.gradle index 9975a9db26..edf9196d38 100644 --- a/testlib/build.gradle +++ b/testlib/build.gradle @@ -7,6 +7,7 @@ apply from: rootProject.file('gradle/java-setup.gradle') dependencies { api project(':lib') + api files(project(':lib').sourceSets.sortPom.output.classesDirs) api "com.diffplug.durian:durian-core:${VER_DURIAN}" api "com.diffplug.durian:durian-testlib:${VER_DURIAN}" api "org.junit.jupiter:junit-jupiter:${VER_JUNIT}" diff --git a/testlib/src/test/java/com/diffplug/spotless/pom/SortPomTest.java b/testlib/src/test/java/com/diffplug/spotless/pom/SortPomTest.java new file mode 100644 index 0000000000..9f0cb44405 --- /dev/null +++ b/testlib/src/test/java/com/diffplug/spotless/pom/SortPomTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2021 DiffPlug + * + * 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 com.diffplug.spotless.pom; + +import org.junit.jupiter.api.Test; + +import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.StepHarness; +import com.diffplug.spotless.TestProvisioner; + +public class SortPomTest { + @Test + public void testSortPomWithDefaultConfig() throws Exception { + String encoding = "UTF-8"; + String lineSeparator = System.getProperty("line.separator"); + boolean expandEmptyElements = true; + boolean spaceBeforeCloseEmptyElement = false; + boolean keepBlankLines = true; + int nrOfIndentSpace = 2; + boolean indentBlankLines = false; + boolean indentSchemaLocation = false; + String predefinedSortOrder = "recommended_2008_06"; + String sortOrderFile = null; + String sortDependencies = null; + String sortDependencyExclusions = null; + String sortPlugins = null; + boolean sortProperties = false; + boolean sortModules = false; + boolean sortExecutions = false; + Provisioner provisioner = TestProvisioner.mavenCentral(); + StepHarness harness = StepHarness.forStep(SortPomStep.create(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, + keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, + predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, + sortProperties, sortModules, sortExecutions, + provisioner)); + harness.testResource("pom/pom_dirty.xml", "pom/pom_clean_default.xml"); + } +} From f2c0e4ad95fbdf47049fa638b1e442afb9195fd3 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 29 Sep 2021 12:02:49 -0700 Subject: [PATCH 07/14] Rename SortPomState to SortPomCfg, and: - SortPomCfg needs no dependencies, just Strings and booleans - SortPomCfg now has the default values, which simplifies plugin-maven/.../SortPom.java - SortPomStep does the JarState and classloader stuff --- .../com/diffplug/spotless/pom/SortPomCfg.java | 55 +++++++++++ .../spotless/pom/DelegatingClassLoader.java | 4 +- .../spotless/pom/SortPomFormatterFunc.java | 20 ++-- .../diffplug/spotless/pom/SortPomState.java | 93 ------------------- .../diffplug/spotless/pom/SortPomStep.java | 32 ++++++- .../diffplug/spotless/maven/pom/SortPom.java | 54 +++++++---- .../diffplug/spotless/pom/SortPomTest.java | 23 +---- 7 files changed, 136 insertions(+), 145 deletions(-) create mode 100644 lib/src/main/java/com/diffplug/spotless/pom/SortPomCfg.java delete mode 100644 lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java diff --git a/lib/src/main/java/com/diffplug/spotless/pom/SortPomCfg.java b/lib/src/main/java/com/diffplug/spotless/pom/SortPomCfg.java new file mode 100644 index 0000000000..93c11e1e31 --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/pom/SortPomCfg.java @@ -0,0 +1,55 @@ +/* + * Copyright 2021 DiffPlug + * + * 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 com.diffplug.spotless.pom; + +import java.io.Serializable; + +// Class and members must be public, otherwise we get failed to access class com.diffplug.spotless.pom.SortPomInternalState from class com.diffplug.spotless.pom.SortPomFormatterFunc (com.diffplug.spotless.pom.SortPomInternalState is in unnamed module of loader org.codehaus.plexus.classworlds.realm.ClassRealm @682bd3c4; com.diffplug.spotless.pom.SortPomFormatterFunc is in unnamed module of loader com.diffplug.spotless.pom.DelegatingClassLoader @573284a5) +public class SortPomCfg implements Serializable { + private static final long serialVersionUID = 1L; + + public String encoding = "UTF-8"; + + public String lineSeparator = System.getProperty("line.separator"); + + public boolean expandEmptyElements = true; + + public boolean spaceBeforeCloseEmptyElement = false; + + public boolean keepBlankLines = true; + + public int nrOfIndentSpace = 2; + + public boolean indentBlankLines = false; + + public boolean indentSchemaLocation = false; + + public String predefinedSortOrder = "recommended_2008_06"; + + public String sortOrderFile = null; + + public String sortDependencies = null; + + public String sortDependencyExclusions = null; + + public String sortPlugins = null; + + public boolean sortProperties = false; + + public boolean sortModules = false; + + public boolean sortExecutions = false; +} diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java index 13416c4428..fba0c9401b 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java @@ -42,8 +42,8 @@ protected Class findClass(String name) throws ClassNotFoundException { if (name.equals(FormatterFunc.class.getName())) { return FormatterFunc.class; } - if (name.equals(SortPomState.class.getName())) { - return SortPomState.class; + if (name.equals(SortPomCfg.class.getName())) { + return SortPomCfg.class; } // all other loaded classes need to be associated with this classloader, so we need to load them as resources String path = name.replace('.', '/') + ".class"; diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java index 22606cdf01..f28c6bf373 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java @@ -30,10 +30,10 @@ class SortPomFormatterFunc implements FormatterFunc { private static final Logger logger = Logger.getLogger(SortPomFormatterFunc.class.getName()); - private final SortPomState state; + private final SortPomCfg cfg; - public SortPomFormatterFunc(SortPomState state) { - this.state = state; + public SortPomFormatterFunc(SortPomCfg cfg) { + this.cfg = cfg; } @Override @@ -41,20 +41,20 @@ public String apply(String input) throws Exception { // SortPom expects a file to sort, so we write the inpout into a temporary file File pom = File.createTempFile("pom", ".xml"); pom.deleteOnExit(); - IOUtils.write(input, new FileOutputStream(pom), state.encoding); + IOUtils.write(input, new FileOutputStream(pom), cfg.encoding); SortPomImpl sortPom = new SortPomImpl(); sortPom.setup(new MySortPomLogger(), PluginParameters.builder() .setPomFile(pom) .setFileOutput(false, null, null, false) - .setEncoding(state.encoding) - .setFormatting(state.lineSeparator, state.expandEmptyElements, state.spaceBeforeCloseEmptyElement, state.keepBlankLines) - .setIndent(state.nrOfIndentSpace, state.indentBlankLines, state.indentSchemaLocation) - .setSortOrder(state.sortOrderFile, state.predefinedSortOrder) - .setSortEntities(state.sortDependencies, state.sortDependencyExclusions, state.sortPlugins, state.sortProperties, state.sortModules, state.sortExecutions) + .setEncoding(cfg.encoding) + .setFormatting(cfg.lineSeparator, cfg.expandEmptyElements, cfg.spaceBeforeCloseEmptyElement, cfg.keepBlankLines) + .setIndent(cfg.nrOfIndentSpace, cfg.indentBlankLines, cfg.indentSchemaLocation) + .setSortOrder(cfg.sortOrderFile, cfg.predefinedSortOrder) + .setSortEntities(cfg.sortDependencies, cfg.sortDependencyExclusions, cfg.sortPlugins, cfg.sortProperties, cfg.sortModules, cfg.sortExecutions) .setTriggers(false) .build()); sortPom.sortPom(); - return IOUtils.toString(new FileInputStream(pom), state.encoding); + return IOUtils.toString(new FileInputStream(pom), cfg.encoding); } private static class MySortPomLogger implements SortPomLogger { diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java deleted file mode 100644 index 153196f16f..0000000000 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomState.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2021 DiffPlug - * - * 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 com.diffplug.spotless.pom; - -import java.io.IOException; -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; -import java.security.PrivilegedAction; - -import com.diffplug.spotless.FormatterFunc; -import com.diffplug.spotless.JarState; -import com.diffplug.spotless.Provisioner; - -// Class and members must be public, otherwise we get failed to access class com.diffplug.spotless.pom.SortPomInternalState from class com.diffplug.spotless.pom.SortPomFormatterFunc (com.diffplug.spotless.pom.SortPomInternalState is in unnamed module of loader org.codehaus.plexus.classworlds.realm.ClassRealm @682bd3c4; com.diffplug.spotless.pom.SortPomFormatterFunc is in unnamed module of loader com.diffplug.spotless.pom.DelegatingClassLoader @573284a5) -public final class SortPomState implements Serializable { - private static final long serialVersionUID = 1L; - - public final JarState jarState; - - public final String encoding; - - public final String lineSeparator; - - public final boolean expandEmptyElements; - - public final boolean spaceBeforeCloseEmptyElement; - - public final boolean keepBlankLines; - - public final int nrOfIndentSpace; - - public final boolean indentBlankLines; - - public final boolean indentSchemaLocation; - - public final String predefinedSortOrder; - - public final String sortOrderFile; - - public final String sortDependencies; - - public final String sortDependencyExclusions; - - public final String sortPlugins; - - public final boolean sortProperties; - - public final boolean sortModules; - - public final boolean sortExecutions; - - SortPomState(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions, Provisioner provisioner) throws IOException { - this.jarState = JarState.from("com.github.ekryd.sortpom:sortpom-sorter:3.0.0", provisioner); - this.encoding = encoding; - this.lineSeparator = lineSeparator; - this.expandEmptyElements = expandEmptyElements; - this.spaceBeforeCloseEmptyElement = spaceBeforeCloseEmptyElement; - this.keepBlankLines = keepBlankLines; - this.nrOfIndentSpace = nrOfIndentSpace; - this.indentBlankLines = indentBlankLines; - this.indentSchemaLocation = indentSchemaLocation; - this.predefinedSortOrder = predefinedSortOrder; - this.sortOrderFile = sortOrderFile; - this.sortDependencies = sortDependencies; - this.sortDependencyExclusions = sortDependencyExclusions; - this.sortPlugins = sortPlugins; - this.sortProperties = sortProperties; - this.sortModules = sortModules; - this.sortExecutions = sortExecutions; - } - - FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { - ClassLoader classLoader = AccessController.doPrivileged((PrivilegedAction) () -> new DelegatingClassLoader(this.getClass().getClassLoader(), jarState.getClassLoader())); - Constructor constructor = classLoader.loadClass(SortPomFormatterFunc.class.getName()).getConstructor(classLoader.loadClass(SortPomState.class.getName())); - constructor.setAccessible(true); - return (FormatterFunc) constructor.newInstance(this); - } -} diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java index 9138ef650e..caad7467f8 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java @@ -15,7 +15,16 @@ */ package com.diffplug.spotless.pom; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.JarState; import com.diffplug.spotless.Provisioner; public class SortPomStep { @@ -24,7 +33,26 @@ public class SortPomStep { private SortPomStep() {} - public static FormatterStep create(String encoding, String lineSeparator, boolean expandEmptyElements, boolean spaceBeforeCloseEmptyElement, boolean keepBlankLines, int nrOfIndentSpace, boolean indentBlankLines, boolean indentSchemaLocation, String predefinedSortOrder, String sortOrderFile, String sortDependencies, String sortDependencyExclusions, String sortPlugins, boolean sortProperties, boolean sortModules, boolean sortExecutions, Provisioner provisioner) { - return FormatterStep.createLazy(NAME, () -> new SortPomState(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions, provisioner), SortPomState::createFormat); + private SortPomCfg cfg; + + public static FormatterStep create(SortPomCfg cfg, Provisioner provisioner) { + return FormatterStep.createLazy(NAME, () -> new State(cfg, provisioner), State::createFormat); + } + + static class State implements Serializable { + SortPomCfg cfg; + JarState jarState; + + public State(SortPomCfg cfg, Provisioner provisioner) throws IOException { + this.cfg = cfg; + this.jarState = JarState.from("com.github.ekryd.sortpom:sortpom-sorter:3.0.0", provisioner); + } + + FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { + ClassLoader classLoader = AccessController.doPrivileged((PrivilegedAction) () -> new DelegatingClassLoader(this.getClass().getClassLoader(), jarState.getClassLoader())); + Constructor constructor = classLoader.loadClass(SortPomFormatterFunc.class.getName()).getConstructor(classLoader.loadClass(SortPomCfg.class.getName())); + constructor.setAccessible(true); + return (FormatterFunc) constructor.newInstance(cfg); + } } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java index ddd3fb6fbc..f4fe8cb96b 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java @@ -20,59 +20,79 @@ import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.maven.FormatterStepConfig; import com.diffplug.spotless.maven.FormatterStepFactory; +import com.diffplug.spotless.pom.SortPomCfg; import com.diffplug.spotless.pom.SortPomStep; public class SortPom implements FormatterStepFactory { + private final SortPomCfg defaultValues = new SortPomCfg(); + @Parameter - String encoding = "UTF-8"; + String encoding = defaultValues.encoding; @Parameter - String lineSeparator = System.getProperty("line.separator"); + String lineSeparator = defaultValues.lineSeparator; @Parameter - boolean expandEmptyElements = true; + boolean expandEmptyElements = defaultValues.expandEmptyElements; @Parameter - boolean spaceBeforeCloseEmptyElement = false; + boolean spaceBeforeCloseEmptyElement = defaultValues.spaceBeforeCloseEmptyElement; @Parameter - boolean keepBlankLines = true; + boolean keepBlankLines = defaultValues.keepBlankLines; @Parameter - int nrOfIndentSpace = 2; + int nrOfIndentSpace = defaultValues.nrOfIndentSpace; @Parameter - boolean indentBlankLines = false; + boolean indentBlankLines = defaultValues.indentBlankLines; @Parameter - boolean indentSchemaLocation = false; + boolean indentSchemaLocation = defaultValues.indentSchemaLocation; @Parameter - String predefinedSortOrder = "recommended_2008_06"; + String predefinedSortOrder = defaultValues.predefinedSortOrder; @Parameter - String sortOrderFile; + String sortOrderFile = defaultValues.sortOrderFile; @Parameter - String sortDependencies; + String sortDependencies = defaultValues.sortDependencies; @Parameter - String sortDependencyExclusions; + String sortDependencyExclusions = defaultValues.sortDependencyExclusions; @Parameter - String sortPlugins; + String sortPlugins = defaultValues.sortPlugins; @Parameter - boolean sortProperties = false; + boolean sortProperties = defaultValues.sortProperties; @Parameter - boolean sortModules = false; + boolean sortModules = defaultValues.sortModules; @Parameter - boolean sortExecutions = false; + boolean sortExecutions = defaultValues.sortExecutions; @Override public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { - return SortPomStep.create(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions, stepConfig.getProvisioner()); + SortPomCfg cfg = new SortPomCfg(); + cfg.encoding = encoding; + cfg.lineSeparator = lineSeparator; + cfg.expandEmptyElements = expandEmptyElements; + cfg.spaceBeforeCloseEmptyElement = spaceBeforeCloseEmptyElement; + cfg.keepBlankLines = keepBlankLines; + cfg.nrOfIndentSpace = nrOfIndentSpace; + cfg.indentBlankLines = indentBlankLines; + cfg.indentSchemaLocation = indentSchemaLocation; + cfg.predefinedSortOrder = predefinedSortOrder; + cfg.sortOrderFile = sortOrderFile; + cfg.sortDependencies = sortDependencies; + cfg.sortDependencyExclusions = sortDependencyExclusions; + cfg.sortPlugins = sortPlugins; + cfg.sortProperties = sortProperties; + cfg.sortModules = sortModules; + cfg.sortExecutions = sortExecutions; + return SortPomStep.create(cfg, stepConfig.getProvisioner()); } } diff --git a/testlib/src/test/java/com/diffplug/spotless/pom/SortPomTest.java b/testlib/src/test/java/com/diffplug/spotless/pom/SortPomTest.java index 9f0cb44405..f397962086 100644 --- a/testlib/src/test/java/com/diffplug/spotless/pom/SortPomTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/pom/SortPomTest.java @@ -24,28 +24,9 @@ public class SortPomTest { @Test public void testSortPomWithDefaultConfig() throws Exception { - String encoding = "UTF-8"; - String lineSeparator = System.getProperty("line.separator"); - boolean expandEmptyElements = true; - boolean spaceBeforeCloseEmptyElement = false; - boolean keepBlankLines = true; - int nrOfIndentSpace = 2; - boolean indentBlankLines = false; - boolean indentSchemaLocation = false; - String predefinedSortOrder = "recommended_2008_06"; - String sortOrderFile = null; - String sortDependencies = null; - String sortDependencyExclusions = null; - String sortPlugins = null; - boolean sortProperties = false; - boolean sortModules = false; - boolean sortExecutions = false; + SortPomCfg cfg = new SortPomCfg(); Provisioner provisioner = TestProvisioner.mavenCentral(); - StepHarness harness = StepHarness.forStep(SortPomStep.create(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, - keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, - predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, - sortProperties, sortModules, sortExecutions, - provisioner)); + StepHarness harness = StepHarness.forStep(SortPomStep.create(cfg, provisioner)); harness.testResource("pom/pom_dirty.xml", "pom/pom_clean_default.xml"); } } From bcd3735be064a5b9f283b09181a108238c3c34ec Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 29 Sep 2021 16:42:54 -0700 Subject: [PATCH 08/14] FeatureClassLoader now loads `com.diffplug.spotless.glue.*` via `defineClass`, and `com.diffplug.spotless` with `buildToolClassLoader`. This unifies FeatureClassLoader with DelegatingClassLoader. --- .../diffplug/spotless/FeatureClassLoader.java | 45 ++++++++- .../spotless/pom/DelegatingClassLoader.java | 99 ------------------- 2 files changed, 43 insertions(+), 101 deletions(-) delete mode 100644 lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java diff --git a/lib/src/main/java/com/diffplug/spotless/FeatureClassLoader.java b/lib/src/main/java/com/diffplug/spotless/FeatureClassLoader.java index c0d8163b05..52eba514df 100644 --- a/lib/src/main/java/com/diffplug/spotless/FeatureClassLoader.java +++ b/lib/src/main/java/com/diffplug/spotless/FeatureClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 DiffPlug + * Copyright 2016-2021 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,8 +15,13 @@ */ package com.diffplug.spotless; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; +import java.nio.ByteBuffer; +import java.security.ProtectionDomain; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -73,7 +78,43 @@ protected Class findClass(String name) throws ClassNotFoundException { return buildToolClassLoader.loadClass(name); } } - return super.findClass(name); + if (name.startsWith("com.diffplug.spotless.glue.")) { + String path = name.replace('.', '/') + ".class"; + URL url = findResource(path); + if (url == null) { + throw new ClassNotFoundException(name); + } + try { + return defineClass(name, urlToByteBuffer(url), (ProtectionDomain) null); + } catch (IOException e) { + throw new ClassNotFoundException(name, e); + } + } else if (name.startsWith("com.diffplug.spotless.")) { + return buildToolClassLoader.loadClass(name); + } else { + return super.findClass(name); + } + } + + @Override + public URL findResource(String name) { + URL resource = super.findResource(name); + if (resource != null) { + return resource; + } + return buildToolClassLoader.getResource(name); + } + + private static ByteBuffer urlToByteBuffer(URL url) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[1024]; + InputStream inputStream = url.openStream(); + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + buffer.flush(); + return ByteBuffer.wrap(buffer.toByteArray()); } /** diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java b/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java deleted file mode 100644 index fba0c9401b..0000000000 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2021 DiffPlug - * - * 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 com.diffplug.spotless.pom; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.Enumeration; -import java.util.LinkedList; -import java.util.List; - -import com.diffplug.spotless.FormatterFunc; - -public class DelegatingClassLoader extends ClassLoader { - - private final ClassLoader[] delegateClassLoaders; - - public DelegatingClassLoader(ClassLoader... delegateClassLoaders) { - super(null); - this.delegateClassLoaders = delegateClassLoaders; - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - // these classes need to be loaded from the current classloader, since they may not be attached to this classloader - if (name.equals(FormatterFunc.class.getName())) { - return FormatterFunc.class; - } - if (name.equals(SortPomCfg.class.getName())) { - return SortPomCfg.class; - } - // all other loaded classes need to be associated with this classloader, so we need to load them as resources - String path = name.replace('.', '/') + ".class"; - URL url = findResource(path); - if (url == null) { - throw new ClassNotFoundException(name); - } - try { - return defineClass(name, loadResource(url), null); - } catch (IOException e) { - throw new ClassNotFoundException(name, e); - } - } - - private ByteBuffer loadResource(URL url) throws IOException { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - - int nRead; - byte[] data = new byte[1024]; - - InputStream inputStream = url.openStream(); - while ((nRead = inputStream.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - } - - buffer.flush(); - - return ByteBuffer.wrap(buffer.toByteArray()); - } - - @Override - protected URL findResource(String name) { - for (ClassLoader delegate : delegateClassLoaders) { - URL resource = delegate.getResource(name); - if (resource != null) { - return resource; - } - } - return null; - } - - protected Enumeration findResources(String name) throws IOException { - List resources = new LinkedList<>(); - for (ClassLoader delegate : delegateClassLoaders) { - Enumeration enumeration = delegate.getResources(name); - while (enumeration.hasMoreElements()) { - resources.add(enumeration.nextElement()); - } - } - return Collections.enumeration(resources); - } - -} From 4b780c00e62deac6589f555a3dcb11c7360254cc Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 29 Sep 2021 16:43:46 -0700 Subject: [PATCH 09/14] SortPomStep can now live within the normal `src/main/java`, and only `SortPomFormatterFunc` needs `src/sortPom/java`. --- .../java/com/diffplug/spotless/pom/SortPomStep.java | 10 +++------- .../spotless/{ => glue}/pom/SortPomFormatterFunc.java | 5 +++-- 2 files changed, 6 insertions(+), 9 deletions(-) rename lib/src/{sortPom => main}/java/com/diffplug/spotless/pom/SortPomStep.java (77%) rename lib/src/sortPom/java/com/diffplug/spotless/{ => glue}/pom/SortPomFormatterFunc.java (94%) diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java b/lib/src/main/java/com/diffplug/spotless/pom/SortPomStep.java similarity index 77% rename from lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java rename to lib/src/main/java/com/diffplug/spotless/pom/SortPomStep.java index caad7467f8..518a6ec32d 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java +++ b/lib/src/main/java/com/diffplug/spotless/pom/SortPomStep.java @@ -19,8 +19,6 @@ import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; -import java.security.PrivilegedAction; import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; @@ -28,7 +26,6 @@ import com.diffplug.spotless.Provisioner; public class SortPomStep { - public static final String NAME = "sortPom"; private SortPomStep() {} @@ -48,10 +45,9 @@ public State(SortPomCfg cfg, Provisioner provisioner) throws IOException { this.jarState = JarState.from("com.github.ekryd.sortpom:sortpom-sorter:3.0.0", provisioner); } - FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { - ClassLoader classLoader = AccessController.doPrivileged((PrivilegedAction) () -> new DelegatingClassLoader(this.getClass().getClassLoader(), jarState.getClassLoader())); - Constructor constructor = classLoader.loadClass(SortPomFormatterFunc.class.getName()).getConstructor(classLoader.loadClass(SortPomCfg.class.getName())); - constructor.setAccessible(true); + FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { + Class formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.ext.pom.SortPomFormatterFunc"); + Constructor constructor = formatterFunc.getConstructor(SortPomCfg.class); return (FormatterFunc) constructor.newInstance(cfg); } } diff --git a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java b/lib/src/sortPom/java/com/diffplug/spotless/glue/pom/SortPomFormatterFunc.java similarity index 94% rename from lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java rename to lib/src/sortPom/java/com/diffplug/spotless/glue/pom/SortPomFormatterFunc.java index f28c6bf373..4a72c48fa9 100644 --- a/lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomFormatterFunc.java +++ b/lib/src/sortPom/java/com/diffplug/spotless/glue/pom/SortPomFormatterFunc.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.diffplug.spotless.pom; +package com.diffplug.spotless.glue.pom; import java.io.File; import java.io.FileInputStream; @@ -23,12 +23,13 @@ import org.apache.commons.io.IOUtils; import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.pom.SortPomCfg; import sortpom.SortPomImpl; import sortpom.logger.SortPomLogger; import sortpom.parameter.PluginParameters; -class SortPomFormatterFunc implements FormatterFunc { +public class SortPomFormatterFunc implements FormatterFunc { private static final Logger logger = Logger.getLogger(SortPomFormatterFunc.class.getName()); private final SortPomCfg cfg; From 6d6ab667b738b3ae8506699fddb57c446a8d05e4 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 29 Sep 2021 16:58:30 -0700 Subject: [PATCH 10/14] Fix typo. --- lib/src/main/java/com/diffplug/spotless/pom/SortPomStep.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/java/com/diffplug/spotless/pom/SortPomStep.java b/lib/src/main/java/com/diffplug/spotless/pom/SortPomStep.java index 518a6ec32d..76965394a5 100644 --- a/lib/src/main/java/com/diffplug/spotless/pom/SortPomStep.java +++ b/lib/src/main/java/com/diffplug/spotless/pom/SortPomStep.java @@ -46,7 +46,7 @@ public State(SortPomCfg cfg, Provisioner provisioner) throws IOException { } FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { - Class formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.ext.pom.SortPomFormatterFunc"); + Class formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.pom.SortPomFormatterFunc"); Constructor constructor = formatterFunc.getConstructor(SortPomCfg.class); return (FormatterFunc) constructor.newInstance(cfg); } From 24bc908fa88645ac087914999b9eee04283da454 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 29 Sep 2021 18:06:57 -0700 Subject: [PATCH 11/14] Fix FeatureClassLoader for eclipse entries. --- .../diffplug/spotless/FeatureClassLoader.java | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/FeatureClassLoader.java b/lib/src/main/java/com/diffplug/spotless/FeatureClassLoader.java index 52eba514df..506e29f49c 100644 --- a/lib/src/main/java/com/diffplug/spotless/FeatureClassLoader.java +++ b/lib/src/main/java/com/diffplug/spotless/FeatureClassLoader.java @@ -22,9 +22,6 @@ import java.net.URLClassLoader; import java.nio.ByteBuffer; import java.security.ProtectionDomain; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; import java.util.Objects; import javax.annotation.Nullable; @@ -34,37 +31,31 @@ * path of URLs.
* Features shall be independent from build tools. Hence the class loader of the * underlying build tool is e.g. skipped during the the search for classes.
- * Only {@link #BUILD_TOOLS_PACKAGES } are explicitly looked up from the class loader of - * the build tool and the provided URLs are ignored. This allows the feature to use - * distinct functionality of the build tool. + * + * For `com.diffplug.spotless.glue.`, classes are redefined from within the lib jar + * but linked against the `Url[]`. This allows us to ship classfiles which function as glue + * code but delay linking/definition to runtime after the user has specified which version + * of the formatter they want. + * + * For `"org.slf4j.` and (`com.diffplug.spotless.` but not `com.diffplug.spotless.extra.`) + * the classes are loaded from the buildToolClassLoader. */ class FeatureClassLoader extends URLClassLoader { static { ClassLoader.registerAsParallelCapable(); } - /** - * The following packages must be provided by the build tool or the corresponding Spotless plugin: - *

- */ - static final List BUILD_TOOLS_PACKAGES = Collections.unmodifiableList(Arrays.asList("org.slf4j.")); - // NOTE: if this changes, you need to also update the `JarState.getClassLoader` methods. - private final ClassLoader buildToolClassLoader; /** * Constructs a new FeatureClassLoader for the given URLs, based on an {@code URLClassLoader}, - * using the system class loader as parent. For {@link #BUILD_TOOLS_PACKAGES }, the build - * tool class loader is used. + * using the system class loader as parent. * * @param urls the URLs from which to load classes and resources * @param buildToolClassLoader The build tool class loader * @exception SecurityException If a security manager exists and prevents the creation of a class loader. * @exception NullPointerException if {@code urls} is {@code null}. */ - FeatureClassLoader(URL[] urls, ClassLoader buildToolClassLoader) { super(urls, getParentClassLoader()); Objects.requireNonNull(buildToolClassLoader); @@ -73,11 +64,6 @@ class FeatureClassLoader extends URLClassLoader { @Override protected Class findClass(String name) throws ClassNotFoundException { - for (String buildToolPackage : BUILD_TOOLS_PACKAGES) { - if (name.startsWith(buildToolPackage)) { - return buildToolClassLoader.loadClass(name); - } - } if (name.startsWith("com.diffplug.spotless.glue.")) { String path = name.replace('.', '/') + ".class"; URL url = findResource(path); @@ -89,13 +75,23 @@ protected Class findClass(String name) throws ClassNotFoundException { } catch (IOException e) { throw new ClassNotFoundException(name, e); } - } else if (name.startsWith("com.diffplug.spotless.")) { + } else if (useBuildToolClassLoader(name)) { return buildToolClassLoader.loadClass(name); } else { return super.findClass(name); } } + private static boolean useBuildToolClassLoader(String name) { + if (name.startsWith("org.slf4j.")) { + return true; + } else if (!name.startsWith("com.diffplug.spotless.extra") && name.startsWith("com.diffplug.spotless.")) { + return true; + } else { + return false; + } + } + @Override public URL findResource(String name) { URL resource = super.findResource(name); From 2b85d84d129a294ce085878423e50ec6b39f962c Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 29 Sep 2021 18:07:25 -0700 Subject: [PATCH 12/14] plugin-maven doesn't need any special dependency on the lib jar. --- plugin-maven/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin-maven/build.gradle b/plugin-maven/build.gradle index 44b7d7222d..f5257e065c 100644 --- a/plugin-maven/build.gradle +++ b/plugin-maven/build.gradle @@ -63,7 +63,6 @@ String libVersion = version.endsWith('-SNAPSHOT') ? dependencies { if (version.endsWith('-SNAPSHOT') || (rootProject.spotlessChangelog.versionNext == rootProject.spotlessChangelog.versionLast)) { implementation project(':lib') - implementation project(':lib').sourceSets.sortPom.output implementation project(':lib-extra') } else { implementation "com.diffplug.spotless:spotless-lib:${libVersion}" From b95e93bca242d6a3ec898604d214d4ed0de37017 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Wed, 29 Sep 2021 18:18:40 -0700 Subject: [PATCH 13/14] Generalize the `sortPom` stuff to facilitate #524 (glue code). --- lib/build.gradle | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/build.gradle b/lib/build.gradle index 88745a42ac..7120c21aea 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -6,13 +6,14 @@ version = rootProject.spotlessChangelog.versionNext apply from: rootProject.file('gradle/java-setup.gradle') apply from: rootProject.file('gradle/java-publish.gradle') -sourceSets { - sortPom { +def NEEDS_GLUE = [ + 'sortPom' +] +for (glue in NEEDS_GLUE) { + sourceSets.register(glue) { compileClasspath += sourceSets.main.output runtimeClasspath += sourceSets.main.output - - java { - } + java {} } } @@ -33,8 +34,7 @@ spotbugs { reportLevel = 'low' } // low|medium|high (low = sensitive to even min test { useJUnitPlatform() } jar { - // Add directories with generated sources (might be several - one for every supported language). - from sourceSets.sortPom.output.classesDirs - // Add output directories of the sourceset's resources. - from sourceSets.sortPom.output.resourcesDir + for (glue in NEEDS_GLUE) { + from sourceSets.getByName(glue).output.classesDirs + } } From 617abf520b883d39cebff1bd0cc1e0970410842d Mon Sep 17 00:00:00 2001 From: Markus Heberling Date: Thu, 30 Sep 2021 06:11:41 +0200 Subject: [PATCH 14/14] Added documentation for sortPom --- CHANGES.md | 1 + README.md | 6 ++-- plugin-maven/CHANGES.md | 1 + plugin-maven/README.md | 62 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 05c07860d9..77fb872344 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added * Added support for custom JSR223 formatters ([#945](https://github.com/diffplug/spotless/pull/945)) +* Added support for formating and sorting Maven POMs ([#946](https://github.com/diffplug/spotless/pull/946)) ## [2.17.0] - 2021-09-27 ### Added diff --git a/README.md b/README.md index 5085cee272..bd83899587 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ lib('generic.EndWithNewlineStep') +'{{yes}} | {{yes}} lib('generic.IndentStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |', lib('generic.Jsr223Step') +'{{no}} | {{yes}} | {{no}} | {{no}} |', lib('generic.LicenseHeaderStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |', -lib('generic.NativeCmdStep') +'{{no}} | {{yes}} | {{no}} | {{no}} |', +lib('generic.NativeCmdStep') +'{{no}} | {{yes}} | {{no}} | {{no}} |', lib('generic.ReplaceRegexStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |', lib('generic.ReplaceStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |', lib('generic.TrimTrailingWhitespaceStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |', @@ -66,6 +66,7 @@ lib('kotlin.DiktatStep') +'{{yes}} | {{yes}} lib('markdown.FreshMarkStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |', lib('npm.PrettierFormatterStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |', lib('npm.TsFmtFormatterStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |', +lib('pom.SortPomStepStep') +'{{no}} | {{yes}} | {{no}} | {{no}} |', lib('python.BlackStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |', lib('scala.ScalaFmtStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |', lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |', @@ -86,7 +87,7 @@ extra('wtp.EclipseWtpFormatterStep') +'{{yes}} | {{yes}} | [`generic.IndentStep`](lib/src/main/java/com/diffplug/spotless/generic/IndentStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: | | [`generic.Jsr223Step`](lib/src/main/java/com/diffplug/spotless/generic/Jsr223Step.java) | :white_large_square: | :+1: | :white_large_square: | :white_large_square: | | [`generic.LicenseHeaderStep`](lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java) | :+1: | :+1: | :+1: | :white_large_square: | -| [`generic.NativeCmdStep`](lib/src/main/java/com/diffplug/spotless/generic/NativeCmdStep.java) | :white_large_square: | :+1: | :white_large_square: | :white_large_square: | +| [`generic.NativeCmdStep`](lib/src/main/java/com/diffplug/spotless/generic/NativeCmdStep.java) | :white_large_square: | :+1: | :white_large_square: | :white_large_square: | | [`generic.ReplaceRegexStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceRegexStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: | | [`generic.ReplaceStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: | | [`generic.TrimTrailingWhitespaceStep`](lib/src/main/java/com/diffplug/spotless/generic/TrimTrailingWhitespaceStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: | @@ -104,6 +105,7 @@ extra('wtp.EclipseWtpFormatterStep') +'{{yes}} | {{yes}} | [`markdown.FreshMarkStep`](lib/src/main/java/com/diffplug/spotless/markdown/FreshMarkStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: | | [`npm.PrettierFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/PrettierFormatterStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: | | [`npm.TsFmtFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/TsFmtFormatterStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: | +| [`pom.SortPomStepStep`](lib/src/main/java/com/diffplug/spotless/pom/SortPomStepStep.java) | :white_large_square: | :+1: | :white_large_square: | :white_large_square: | | [`python.BlackStep`](lib/src/main/java/com/diffplug/spotless/python/BlackStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: | | [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :+1: | :+1: | :white_large_square: | | [`sql.DBeaverSQLFormatterStep`](lib/src/main/java/com/diffplug/spotless/sql/DBeaverSQLFormatterStep.java) | :+1: | :+1: | :+1: | :white_large_square: | diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 7b9aa00a55..c3171ae050 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -5,6 +5,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added * Added support for custom JSR223 formatters ([#945](https://github.com/diffplug/spotless/pull/945)) +* Added support for formating and sorting Maven POMs ([#946](https://github.com/diffplug/spotless/pull/946)) ## [2.14.0] - 2021-09-27 ### Added diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 0136504299..cfff6897d3 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -55,6 +55,7 @@ user@machine repo % mvn spotless:check - [Python](#python) ([black](#black)) - [Antlr4](#antlr4) ([antlr4formatter](#antlr4formatter)) - [Sql](#sql) ([dbeaver](#dbeaver)) + - [Maven Pom](#maven-pom) ([sortPom](#sortpom)) - [Typescript](#typescript) ([tsfmt](#tsfmt), [prettier](#prettier)) - Multiple languages - [Prettier](#prettier) ([plugins](#prettier-plugins), [npm detection](#npm-detection), [`.npmrc` detection](#npmrc-detection)) @@ -511,6 +512,67 @@ sql.formatter.indent.type=space sql.formatter.indent.size=4 ``` +## Maven POM + +[code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/Pom.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java). + +```xml + + + + + pom.xml + + + + + + +``` + +### sortPom + +[homepage](https://github.com/Ekryd/sortpom). [code](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java). + +All configuration settings are optional, they are described in detail [here](https://github.com/Ekryd/sortpom/wiki/Parameters). + +```xml + + + UTF-8 + + ${line.separator} + + true + + false + + true + + 2 + + false + + false + + recommended_2008_06 + + + + + + + + + + false + + false + + false + +``` + ## Typescript