Skip to content

Commit 717b959

Browse files
author
Vincent Potucek
committed
Fix: Use correct outputStream destination; request instead of path in DefaultPluginXmlFactory#write
1 parent ffd30a3 commit 717b959

File tree

2 files changed

+297
-1
lines changed

2 files changed

+297
-1
lines changed

impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultPluginXmlFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public void write(XmlWriterRequest<PluginDescriptor> request) throws XmlWriterEx
9393
new PluginDescriptorStaxWriter().write(outputStream, content);
9494
} else {
9595
try (OutputStream os = Files.newOutputStream(path)) {
96-
new PluginDescriptorStaxWriter().write(outputStream, content);
96+
new PluginDescriptorStaxWriter().write(os, content);
9797
}
9898
}
9999
} catch (Exception e) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.impl;
20+
21+
import java.io.ByteArrayInputStream;
22+
import java.io.ByteArrayOutputStream;
23+
import java.io.IOException;
24+
import java.io.StringReader;
25+
import java.io.StringWriter;
26+
import java.io.Writer;
27+
import java.nio.file.Files;
28+
import java.nio.file.Path;
29+
import java.util.List;
30+
31+
import com.ctc.wstx.exc.WstxEOFException;
32+
import org.apache.maven.api.plugin.descriptor.PluginDescriptor;
33+
import org.apache.maven.api.services.xml.ModelXmlFactory;
34+
import org.apache.maven.api.services.xml.XmlReaderException;
35+
import org.apache.maven.api.services.xml.XmlReaderRequest;
36+
import org.apache.maven.api.services.xml.XmlWriterException;
37+
import org.apache.maven.api.services.xml.XmlWriterRequest;
38+
import org.apache.maven.impl.model.DefaultModelProcessor;
39+
import org.junit.jupiter.api.Disabled;
40+
import org.junit.jupiter.api.Test;
41+
import org.junit.jupiter.api.io.TempDir;
42+
43+
import static java.util.UUID.randomUUID;
44+
import static org.assertj.core.api.Assertions.assertThat;
45+
import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
46+
import static org.junit.jupiter.api.Assertions.assertNotNull;
47+
import static org.junit.jupiter.api.Assertions.assertThrows;
48+
import static org.mockito.Mockito.mock;
49+
import static org.mockito.Mockito.when;
50+
51+
class DefaultPluginXmlFactoryReadWriteTest {
52+
53+
private static final String NAME = "sample-plugin-" + randomUUID();
54+
private static final String SAMPLE_PLUGIN_XML =
55+
"""
56+
<?xml version="1.0" encoding="UTF-8"?>
57+
<plugin>
58+
<name>%s</name>
59+
<groupId>org.example</groupId>
60+
<artifactId>sample-plugin</artifactId>
61+
<version>1.0.0</version>
62+
</plugin>
63+
"""
64+
.formatted(NAME);
65+
66+
private final DefaultPluginXmlFactory defaultPluginXmlFactory = new DefaultPluginXmlFactory();
67+
68+
@TempDir
69+
Path tempDir;
70+
71+
@Test
72+
void readFromInputStreamParsesPluginDescriptorCorrectly() {
73+
PluginDescriptor descriptor = defaultPluginXmlFactory.read(XmlReaderRequest.builder()
74+
.inputStream(new ByteArrayInputStream(SAMPLE_PLUGIN_XML.getBytes()))
75+
.build());
76+
assertThat(descriptor.getName()).isEqualTo(NAME);
77+
assertThat(descriptor.getGroupId()).isEqualTo("org.example");
78+
assertThat(descriptor.getArtifactId()).isEqualTo("sample-plugin");
79+
assertThat(descriptor.getVersion()).isEqualTo("1.0.0");
80+
}
81+
82+
@Test
83+
void parsePlugin() {
84+
assertThat(defaultPluginXmlFactory
85+
.read(XmlReaderRequest.builder()
86+
.reader(new StringReader(SAMPLE_PLUGIN_XML))
87+
.build())
88+
.getName())
89+
.isEqualTo(NAME);
90+
}
91+
92+
@Test
93+
void readFromPathParsesPluginDescriptorCorrectly() throws Exception {
94+
Path xmlFile = tempDir.resolve("plugin.xml");
95+
Files.write(xmlFile, SAMPLE_PLUGIN_XML.getBytes());
96+
assertThat(defaultPluginXmlFactory
97+
.read(XmlReaderRequest.builder().path(xmlFile).build())
98+
.getName())
99+
.isEqualTo(NAME);
100+
}
101+
102+
@Test
103+
void readWithNoInputThrowsIllegalArgumentException() {
104+
assertThatExceptionOfType(IllegalArgumentException.class)
105+
.isThrownBy(() ->
106+
defaultPluginXmlFactory.read(XmlReaderRequest.builder().build()));
107+
}
108+
109+
@Test
110+
void writeToWriterGeneratesValidXml() {
111+
StringWriter writer = new StringWriter();
112+
defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
113+
.writer(writer)
114+
.content(PluginDescriptor.newBuilder()
115+
.name(NAME)
116+
.groupId("org.example")
117+
.artifactId("sample-plugin")
118+
.version("1.0.0")
119+
.build())
120+
.build());
121+
String output = writer.toString();
122+
assertThat(output).contains("<name>" + NAME + "</name>");
123+
assertThat(output).contains("<groupId>org.example</groupId>");
124+
}
125+
126+
@Test
127+
void writeToOutputStreamGeneratesValidXml() {
128+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
129+
defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
130+
.outputStream(outputStream)
131+
.content(PluginDescriptor.newBuilder().name(NAME).build())
132+
.build());
133+
assertThat(outputStream.toString()).contains("<name>" + NAME + "</name>");
134+
}
135+
136+
@Test
137+
void writeToPathGeneratesValidXmlFile() throws Exception {
138+
Path xmlFile = tempDir.resolve("output-plugin.xml");
139+
defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
140+
.path(xmlFile)
141+
.content(PluginDescriptor.newBuilder().name(NAME).build())
142+
.build());
143+
assertThat(Files.readString(xmlFile)).contains("<name>" + NAME + "</name>");
144+
}
145+
146+
@Test
147+
void fromXmlStringParsesValidXml() {
148+
PluginDescriptor descriptor = defaultPluginXmlFactory.fromXmlString(SAMPLE_PLUGIN_XML);
149+
assertThat(descriptor.getName()).isEqualTo(NAME);
150+
assertThat(descriptor.getGroupId()).isEqualTo("org.example");
151+
assertThat(descriptor.getArtifactId()).isEqualTo("sample-plugin");
152+
assertThat(descriptor.getVersion()).isEqualTo("1.0.0");
153+
}
154+
155+
@Test
156+
void toXmlStringGeneratesValidXml() {
157+
String xml = defaultPluginXmlFactory.toXmlString(PluginDescriptor.newBuilder()
158+
.name(NAME)
159+
.groupId("org.example")
160+
.artifactId("sample-plugin")
161+
.version("1.0.0")
162+
.build());
163+
assertThat(xml).contains("<name>" + NAME + "</name>");
164+
assertThat(xml).contains("<groupId>org.example</groupId>");
165+
assertThat(xml).contains("<artifactId>sample-plugin</artifactId>");
166+
assertThat(xml).contains("<version>1.0.0</version>");
167+
}
168+
169+
@Test
170+
void staticFromXmlParsesValidXml() {
171+
PluginDescriptor descriptor = DefaultPluginXmlFactory.fromXml(SAMPLE_PLUGIN_XML);
172+
assertThat(descriptor.getName()).isEqualTo(NAME);
173+
assertThat(descriptor.getGroupId()).isEqualTo("org.example");
174+
assertThat(descriptor.getArtifactId()).isEqualTo("sample-plugin");
175+
assertThat(descriptor.getVersion()).isEqualTo("1.0.0");
176+
}
177+
178+
@Test
179+
void staticToXmlGeneratesValidXml() {
180+
String xml = DefaultPluginXmlFactory.toXml(PluginDescriptor.newBuilder()
181+
.name(NAME)
182+
.groupId("org.example")
183+
.artifactId("sample-plugin")
184+
.version("1.0.0")
185+
.build());
186+
assertThat(xml).contains("<name>" + NAME + "</name>");
187+
assertThat(xml).contains("<name>" + NAME + "</name>");
188+
assertThat(xml).contains("<groupId>org.example</groupId>");
189+
assertThat(xml).contains("<artifactId>sample-plugin</artifactId>");
190+
assertThat(xml).contains("<version>1.0.0</version>");
191+
}
192+
193+
@Test
194+
void writeWithFailingWriterThrowsXmlWriterException() {
195+
String unableToWritePlugin = "Unable to write plugin" + randomUUID();
196+
String ioEx = "ioEx" + randomUUID();
197+
XmlWriterException exception = assertThatExceptionOfType(XmlWriterException.class)
198+
.isThrownBy(() -> defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
199+
.writer(new Writer() {
200+
@Override
201+
public void write(char[] cbuf, int off, int len) {
202+
throw new XmlWriterException(unableToWritePlugin, null, new IOException(ioEx));
203+
}
204+
205+
@Override
206+
public void flush() {}
207+
208+
@Override
209+
public void close() {}
210+
})
211+
.content(PluginDescriptor.newBuilder()
212+
.name("Failing Plugin")
213+
.build())
214+
.build()))
215+
.actual();
216+
assertThat(exception.getMessage()).contains(unableToWritePlugin);
217+
assertThat(exception.getCause()).isInstanceOf(XmlWriterException.class);
218+
assertThat(exception.getCause().getCause().getMessage()).isEqualTo(ioEx);
219+
assertThat(exception.getCause().getMessage()).isEqualTo(unableToWritePlugin);
220+
}
221+
222+
@Test
223+
void writeWithNoTargetThrowsIllegalArgumentException() {
224+
assertThat(assertThrows(
225+
IllegalArgumentException.class,
226+
() -> defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
227+
.content(PluginDescriptor.newBuilder()
228+
.name("No Output Plugin")
229+
.build())
230+
.build()))
231+
.getMessage())
232+
.isEqualTo("writer, outputStream or path must be non null");
233+
}
234+
235+
@Test
236+
void readMalformedXmlThrowsXmlReaderException() {
237+
XmlReaderException exception = assertThatExceptionOfType(XmlReaderException.class)
238+
.isThrownBy(() -> defaultPluginXmlFactory.read(XmlReaderRequest.builder()
239+
.inputStream(new ByteArrayInputStream("<plugin><name>Broken Plugin".getBytes()))
240+
.build()))
241+
.actual();
242+
assertThat(exception.getMessage()).contains("Unable to read plugin");
243+
assertThat(exception.getCause()).isInstanceOf(WstxEOFException.class);
244+
}
245+
246+
@Test
247+
void locateExistingPomWithFilePathShouldReturnSameFileIfRegularFile() throws IOException {
248+
Path pomFile = Files.createTempFile(tempDir, "pom", ".xml");
249+
DefaultModelProcessor processor = new DefaultModelProcessor(mock(ModelXmlFactory.class), List.of());
250+
assertThat(processor.locateExistingPom(pomFile)).isEqualTo(pomFile);
251+
}
252+
253+
@Test
254+
@Disabled("maybe bug in JUnit, as MS-DOS only https://github.com/apache/maven/pull/2312#issuecomment-2876291814")
255+
void readFromUrlParsesPluginDescriptorCorrectly() throws Exception {
256+
Path xmlFile = tempDir.resolve("plugin.xml");
257+
Files.write(xmlFile, SAMPLE_PLUGIN_XML.getBytes());
258+
PluginDescriptor descriptor = defaultPluginXmlFactory.read(XmlReaderRequest.builder()
259+
.inputStream(xmlFile.toUri().toURL().openStream())
260+
.build());
261+
assertThat(descriptor.getName()).isEqualTo(NAME);
262+
assertThat(descriptor.getGroupId()).isEqualTo("org.example");
263+
assertThat(descriptor.getArtifactId()).isEqualTo("sample-plugin");
264+
assertThat(descriptor.getVersion()).isEqualTo("1.0.0");
265+
}
266+
267+
@Test
268+
void testReadWithPath() throws Exception {
269+
Path tempPath = Files.createTempFile("plugin", ".xml");
270+
Files.writeString(tempPath, "<plugin/>");
271+
XmlReaderRequest request = mock(XmlReaderRequest.class);
272+
when(request.getPath()).thenReturn(tempPath);
273+
when(request.getInputStream()).thenReturn(null);
274+
when(request.getReader()).thenReturn(null);
275+
when(request.getURL()).thenReturn(null);
276+
when(request.isAddDefaultEntities()).thenReturn(false);
277+
when(request.isStrict()).thenReturn(false);
278+
assertNotNull(new DefaultPluginXmlFactory().read(request));
279+
Files.deleteIfExists(tempPath);
280+
}
281+
282+
@Test
283+
void testReadWithPathUrlDefault() throws Exception {
284+
Path tempPath = Files.createTempFile("plugin", ".xml");
285+
Files.writeString(tempPath, "<plugin/>");
286+
XmlReaderRequest request = mock(XmlReaderRequest.class);
287+
when(request.getPath()).thenReturn(null);
288+
when(request.getInputStream()).thenReturn(null);
289+
when(request.getReader()).thenReturn(null);
290+
when(request.getURL()).thenReturn(tempPath.toUri().toURL());
291+
when(request.isAddDefaultEntities()).thenReturn(false);
292+
when(request.isStrict()).thenReturn(false);
293+
assertNotNull(new DefaultPluginXmlFactory().read(request));
294+
Files.deleteIfExists(tempPath);
295+
}
296+
}

0 commit comments

Comments
 (0)