Skip to content

Commit 503f4c0

Browse files
committed
load SortPom from JarState
1 parent 22ddb38 commit 503f4c0

File tree

8 files changed

+234
-58
lines changed

8 files changed

+234
-58
lines changed

lib-extra/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ dependencies {
1616
implementation "com.googlecode.concurrent-trees:concurrent-trees:2.6.1"
1717
// used for xml parsing in EclipseFormatter
1818
implementation "org.codehaus.groovy:groovy-xml:3.0.9"
19-
// used for pom sorting
20-
implementation 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0'
2119

2220
// testing
2321
testImplementation project(':testlib')

lib/build.gradle

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,35 @@ version = rootProject.spotlessChangelog.versionNext
66
apply from: rootProject.file('gradle/java-setup.gradle')
77
apply from: rootProject.file('gradle/java-publish.gradle')
88

9+
sourceSets {
10+
sortPom {
11+
compileClasspath += sourceSets.main.output
12+
runtimeClasspath += sourceSets.main.output
13+
14+
java {
15+
}
16+
}
17+
}
18+
919
dependencies {
1020
// zero runtime reqs is a hard requirements for spotless-lib
1121
// if you need a dep, put it in lib-extra
1222
testImplementation "org.junit.jupiter:junit-jupiter:${VER_JUNIT}"
1323
testImplementation "org.assertj:assertj-core:${VER_ASSERTJ}"
1424
testImplementation "com.diffplug.durian:durian-testlib:${VER_DURIAN}"
25+
26+
// used for pom sorting
27+
sortPomCompileOnly 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0'
1528
}
1629

1730
// we'll hold the core lib to a high standard
1831
spotbugs { reportLevel = 'low' } // low|medium|high (low = sensitive to even minor mistakes)
1932

2033
test { useJUnitPlatform() }
34+
35+
jar {
36+
// Add directories with generated sources (might be several - one for every supported language).
37+
from sourceSets.sortPom.output.classesDirs
38+
// Add output directories of the sourceset's resources.
39+
from sourceSets.sortPom.output.resourcesDir
40+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2021 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.pom;
17+
18+
import java.io.ByteArrayOutputStream;
19+
import java.io.IOException;
20+
import java.io.InputStream;
21+
import java.net.URL;
22+
import java.nio.ByteBuffer;
23+
import java.util.Enumeration;
24+
import java.util.Vector;
25+
26+
public class DelegatingClassLoader extends ClassLoader {
27+
28+
private final ClassLoader[] delegateClassLoaders;
29+
30+
public DelegatingClassLoader(ClassLoader... delegateClassLoaders) {
31+
super(null);
32+
this.delegateClassLoaders = delegateClassLoaders;
33+
}
34+
35+
protected Class<?> findClass(String name) throws ClassNotFoundException {
36+
String path = name.replace('.', '/') + ".class";
37+
URL url = findResource(path);
38+
if (url == null) {
39+
throw new ClassNotFoundException(name);
40+
}
41+
try {
42+
ByteBuffer byteCode = loadResource(url);
43+
return defineClass(name, byteCode, null);
44+
} catch (IOException e) {
45+
throw new ClassNotFoundException(name, e);
46+
}
47+
}
48+
49+
private ByteBuffer loadResource(URL url) throws IOException {
50+
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
51+
52+
int nRead;
53+
byte[] data = new byte[1024];
54+
55+
InputStream inputStream = url.openStream();
56+
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
57+
buffer.write(data, 0, nRead);
58+
}
59+
60+
buffer.flush();
61+
62+
return ByteBuffer.wrap(buffer.toByteArray());
63+
}
64+
65+
protected URL findResource(String name) {
66+
for (ClassLoader delegate : delegateClassLoaders) {
67+
URL resource = delegate.getResource(name);
68+
if (resource != null) {
69+
return resource;
70+
}
71+
}
72+
return null;
73+
}
74+
75+
protected Enumeration<URL> findResources(String name) throws IOException {
76+
Vector<URL> vector = new Vector<>();
77+
for (ClassLoader delegate : delegateClassLoaders) {
78+
Enumeration<URL> enumeration = delegate.getResources(name);
79+
while (enumeration.hasMoreElements()) {
80+
vector.add(enumeration.nextElement());
81+
}
82+
}
83+
return vector.elements();
84+
}
85+
86+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2021 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.pom;
17+
18+
import java.io.File;
19+
import java.io.FileReader;
20+
import java.io.FileWriter;
21+
import java.util.logging.Logger;
22+
23+
import org.apache.commons.io.IOUtils;
24+
25+
import com.diffplug.spotless.FormatterFunc;
26+
27+
import sortpom.SortPomImpl;
28+
import sortpom.logger.SortPomLogger;
29+
import sortpom.parameter.PluginParameters;
30+
31+
class SortPomFormatterFunc implements FormatterFunc {
32+
private static final Logger logger = Logger.getLogger(SortPomStep.class.getName());
33+
private final SortPomStep.InternalState state;
34+
35+
public SortPomFormatterFunc(SortPomStep.InternalState state) {
36+
this.state = state;
37+
}
38+
39+
@Override
40+
public String apply(String input) throws Exception {
41+
// SortPom expects a file to sort, so we write the inpout into a temporary file
42+
File pom = File.createTempFile("pom", ".xml");
43+
pom.deleteOnExit();
44+
try (FileWriter fw = new FileWriter(pom)) {
45+
fw.write(input);
46+
}
47+
SortPomImpl sortPom = new SortPomImpl();
48+
sortPom.setup(new SortPomLogger() {
49+
@Override
50+
public void warn(String content) {
51+
logger.warning(content);
52+
}
53+
54+
@Override
55+
public void info(String content) {
56+
logger.info(content);
57+
}
58+
59+
@Override
60+
public void error(String content) {
61+
logger.severe(content);
62+
}
63+
}, PluginParameters.builder()
64+
.setPomFile(pom)
65+
.setFileOutput(false, null, null, false)
66+
.setEncoding(state.encoding)
67+
.setFormatting(state.lineSeparator, state.expandEmptyElements, state.spaceBeforeCloseEmptyElement, state.keepBlankLines)
68+
.setIndent(state.nrOfIndentSpace, state.indentBlankLines, state.indentSchemaLocation)
69+
.setSortOrder(state.sortOrderFile, state.predefinedSortOrder)
70+
.setSortEntities(state.sortDependencies, state.sortDependencyExclusions, state.sortPlugins, state.sortProperties, state.sortModules, state.sortExecutions)
71+
.setTriggers(false)
72+
.build());
73+
sortPom.sortPom();
74+
return IOUtils.toString(new FileReader(pom));
75+
}
76+
}

lib-extra/src/main/java/com/diffplug/spotless/extra/pom/SortPomStep.java renamed to lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java

Lines changed: 47 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,37 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.diffplug.spotless.extra.pom;
17-
18-
import java.io.File;
19-
import java.io.FileReader;
20-
import java.io.FileWriter;
16+
package com.diffplug.spotless.pom;
17+
18+
import java.io.ByteArrayInputStream;
19+
import java.io.ByteArrayOutputStream;
20+
import java.io.IOException;
21+
import java.io.ObjectInputStream;
22+
import java.io.ObjectOutputStream;
23+
import java.io.ObjectStreamClass;
2124
import java.io.Serializable;
22-
import java.util.logging.Logger;
23-
24-
import org.apache.commons.io.IOUtils;
25+
import java.lang.reflect.Constructor;
26+
import java.lang.reflect.InvocationTargetException;
27+
import java.lang.reflect.Method;
2528

2629
import com.diffplug.spotless.FormatterFunc;
2730
import com.diffplug.spotless.FormatterStep;
28-
29-
import sortpom.SortPomImpl;
30-
import sortpom.logger.SortPomLogger;
31-
import sortpom.parameter.PluginParameters;
31+
import com.diffplug.spotless.JarState;
32+
import com.diffplug.spotless.Provisioner;
3233

3334
public class SortPomStep {
3435

3536
public static final String NAME = "sortPom";
36-
private static final Logger logger = Logger.getLogger(SortPomStep.class.getName());
3737

3838
private SortPomStep() {}
3939

40-
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) {
41-
return FormatterStep.createLazy(NAME, () -> new State(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions), State::createFormat);
40+
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) {
41+
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);
4242
}
4343

44-
static final class State implements Serializable {
44+
static final class InternalState implements Serializable {
4545
private static final long serialVersionUID = 1L;
46+
4647
final String encoding;
4748

4849
final String lineSeparator;
@@ -75,7 +76,7 @@ static final class State implements Serializable {
7576

7677
final boolean sortExecutions;
7778

78-
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) {
79+
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) {
7980
this.encoding = encoding;
8081
this.lineSeparator = lineSeparator;
8182
this.expandEmptyElements = expandEmptyElements;
@@ -93,44 +94,38 @@ static final class State implements Serializable {
9394
this.sortModules = sortModules;
9495
this.sortExecutions = sortExecutions;
9596
}
97+
}
9698

97-
FormatterFunc createFormat() {
98-
return input -> {
99-
// SortPom expects a file to sort, so we write the inpout into a temporary file
100-
File pom = File.createTempFile("pom", ".xml");
101-
pom.deleteOnExit();
102-
try (FileWriter fw = new FileWriter(pom)) {
103-
fw.write(input);
99+
static final class State implements Serializable {
100+
private static final long serialVersionUID = 1L;
101+
final JarState jarState;
102+
103+
final InternalState internalState;
104+
105+
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 {
106+
this.jarState = JarState.from("com.github.ekryd.sortpom:sortpom-sorter:3.0.0", provisioner);
107+
this.internalState = new InternalState(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions);
108+
}
109+
110+
FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
111+
ClassLoader classLoader = new DelegatingClassLoader(this.getClass().getClassLoader(), jarState.getClassLoader());
112+
Constructor<?> constructor = classLoader.loadClass(SortPomFormatterFunc.class.getName()).getConstructor(classLoader.loadClass(InternalState.class.getName()));
113+
constructor.setAccessible(true);
114+
ByteArrayOutputStream out = new ByteArrayOutputStream();
115+
ObjectOutputStream oos = new ObjectOutputStream(out);
116+
oos.writeObject(internalState);
117+
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())) {
118+
@Override
119+
protected Class<?> resolveClass(ObjectStreamClass desc) throws ClassNotFoundException {
120+
return classLoader.loadClass(desc.getName());
104121
}
105-
SortPomImpl sortPom = new SortPomImpl();
106-
sortPom.setup(new SortPomLogger() {
107-
@Override
108-
public void warn(String content) {
109-
logger.warning(content);
110-
}
111-
112-
@Override
113-
public void info(String content) {
114-
logger.info(content);
115-
}
116-
117-
@Override
118-
public void error(String content) {
119-
logger.severe(content);
120-
}
121-
}, PluginParameters.builder()
122-
.setPomFile(pom)
123-
.setFileOutput(false, null, null, false)
124-
.setEncoding(encoding)
125-
.setFormatting(lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines)
126-
.setIndent(nrOfIndentSpace, indentBlankLines, indentSchemaLocation)
127-
.setSortOrder(sortOrderFile, predefinedSortOrder)
128-
.setSortEntities(sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions)
129-
.setTriggers(false)
130-
.build());
131-
sortPom.sortPom();
132-
return IOUtils.toString(new FileReader(pom));
133122
};
123+
Object state = ois.readObject();
124+
Object formatterFunc = constructor.newInstance(state);
125+
Method apply = formatterFunc.getClass().getMethod("apply", String.class);
126+
apply.setAccessible(true);
127+
return input -> (String) apply.invoke(formatterFunc, input);
134128
}
129+
135130
}
136131
}

plugin-maven/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ String libVersion = version.endsWith('-SNAPSHOT') ?
6363
dependencies {
6464
if (version.endsWith('-SNAPSHOT') || (rootProject.spotlessChangelog.versionNext == rootProject.spotlessChangelog.versionLast)) {
6565
implementation project(':lib')
66+
implementation project(':lib').sourceSets.sortPom.output
6667
implementation project(':lib-extra')
6768
} else {
6869
implementation "com.diffplug.spotless:spotless-lib:${libVersion}"

plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
import org.apache.maven.plugins.annotations.Parameter;
1919

2020
import com.diffplug.spotless.FormatterStep;
21-
import com.diffplug.spotless.extra.pom.SortPomStep;
2221
import com.diffplug.spotless.maven.FormatterStepConfig;
2322
import com.diffplug.spotless.maven.FormatterStepFactory;
23+
import com.diffplug.spotless.pom.SortPomStep;
2424

2525
public class SortPom implements FormatterStepFactory {
2626
@Parameter
@@ -73,6 +73,6 @@ public class SortPom implements FormatterStepFactory {
7373

7474
@Override
7575
public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) {
76-
return SortPomStep.create(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions);
76+
return SortPomStep.create(encoding, lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines, nrOfIndentSpace, indentBlankLines, indentSchemaLocation, predefinedSortOrder, sortOrderFile, sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions, stepConfig.getProvisioner());
7777
}
7878
}

plugin-maven/src/test/java/com/diffplug/spotless/maven/pom/SortPomTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
*/
1616
package com.diffplug.spotless.maven.pom;
1717

18-
import com.diffplug.spotless.maven.MavenIntegrationHarness;
19-
2018
import org.junit.jupiter.api.Test;
2119

20+
import com.diffplug.spotless.maven.MavenIntegrationHarness;
21+
2222
public class SortPomTest extends MavenIntegrationHarness {
2323
@Test
2424
public void testSortPomWithDefaultConfig() throws Exception {

0 commit comments

Comments
 (0)