Skip to content

Commit 87c33a2

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

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+
@Disabled
94+
void readFromPathParsesPluginDescriptorCorrectly() throws Exception {
95+
Path xmlFile = tempDir.resolve("plugin.xml");
96+
Files.write(xmlFile, SAMPLE_PLUGIN_XML.getBytes());
97+
assertThat(defaultPluginXmlFactory
98+
.read(XmlReaderRequest.builder().path(xmlFile).build())
99+
.getName())
100+
.isEqualTo(NAME);
101+
}
102+
103+
@Test
104+
void readWithNoInputThrowsIllegalArgumentException() {
105+
assertThatExceptionOfType(IllegalArgumentException.class)
106+
.isThrownBy(() ->
107+
defaultPluginXmlFactory.read(XmlReaderRequest.builder().build()));
108+
}
109+
110+
@Test
111+
void writeToWriterGeneratesValidXml() {
112+
StringWriter writer = new StringWriter();
113+
defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
114+
.writer(writer)
115+
.content(PluginDescriptor.newBuilder()
116+
.name(NAME)
117+
.groupId("org.example")
118+
.artifactId("sample-plugin")
119+
.version("1.0.0")
120+
.build())
121+
.build());
122+
String output = writer.toString();
123+
assertThat(output).contains("<name>" + NAME + "</name>");
124+
assertThat(output).contains("<groupId>org.example</groupId>");
125+
}
126+
127+
@Test
128+
void writeToOutputStreamGeneratesValidXml() {
129+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
130+
defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
131+
.outputStream(outputStream)
132+
.content(PluginDescriptor.newBuilder().name(NAME).build())
133+
.build());
134+
assertThat(outputStream.toString()).contains("<name>" + NAME + "</name>");
135+
}
136+
137+
@Test
138+
void writeToPathGeneratesValidXmlFile() throws Exception {
139+
Path xmlFile = tempDir.resolve("output-plugin.xml");
140+
defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
141+
.path(xmlFile)
142+
.content(PluginDescriptor.newBuilder().name(NAME).build())
143+
.build());
144+
assertThat(Files.readString(xmlFile)).contains("<name>" + NAME + "</name>");
145+
}
146+
147+
@Test
148+
void fromXmlStringParsesValidXml() {
149+
PluginDescriptor descriptor = defaultPluginXmlFactory.fromXmlString(SAMPLE_PLUGIN_XML);
150+
assertThat(descriptor.getName()).isEqualTo(NAME);
151+
assertThat(descriptor.getGroupId()).isEqualTo("org.example");
152+
assertThat(descriptor.getArtifactId()).isEqualTo("sample-plugin");
153+
assertThat(descriptor.getVersion()).isEqualTo("1.0.0");
154+
}
155+
156+
@Test
157+
void toXmlStringGeneratesValidXml() {
158+
String xml = defaultPluginXmlFactory.toXmlString(PluginDescriptor.newBuilder()
159+
.name(NAME)
160+
.groupId("org.example")
161+
.artifactId("sample-plugin")
162+
.version("1.0.0")
163+
.build());
164+
assertThat(xml).contains("<name>" + NAME + "</name>");
165+
assertThat(xml).contains("<groupId>org.example</groupId>");
166+
assertThat(xml).contains("<artifactId>sample-plugin</artifactId>");
167+
assertThat(xml).contains("<version>1.0.0</version>");
168+
}
169+
170+
@Test
171+
void staticFromXmlParsesValidXml() {
172+
PluginDescriptor descriptor = DefaultPluginXmlFactory.fromXml(SAMPLE_PLUGIN_XML);
173+
assertThat(descriptor.getName()).isEqualTo(NAME);
174+
assertThat(descriptor.getGroupId()).isEqualTo("org.example");
175+
assertThat(descriptor.getArtifactId()).isEqualTo("sample-plugin");
176+
assertThat(descriptor.getVersion()).isEqualTo("1.0.0");
177+
}
178+
179+
@Test
180+
void staticToXmlGeneratesValidXml() {
181+
String xml = DefaultPluginXmlFactory.toXml(PluginDescriptor.newBuilder()
182+
.name(NAME)
183+
.groupId("org.example")
184+
.artifactId("sample-plugin")
185+
.version("1.0.0")
186+
.build());
187+
assertThat(xml).contains("<name>" + NAME + "</name>");
188+
assertThat(xml).contains("<name>" + NAME + "</name>");
189+
assertThat(xml).contains("<groupId>org.example</groupId>");
190+
assertThat(xml).contains("<artifactId>sample-plugin</artifactId>");
191+
assertThat(xml).contains("<version>1.0.0</version>");
192+
}
193+
194+
@Test
195+
void writeWithFailingWriterThrowsXmlWriterException() {
196+
String unableToWritePlugin = "Unable to write plugin" + randomUUID();
197+
String ioEx = "ioEx" + randomUUID();
198+
XmlWriterException exception = assertThatExceptionOfType(XmlWriterException.class)
199+
.isThrownBy(() -> defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
200+
.writer(new Writer() {
201+
@Override
202+
public void write(char[] cbuf, int off, int len) {
203+
throw new XmlWriterException(unableToWritePlugin, null, new IOException(ioEx));
204+
}
205+
206+
@Override
207+
public void flush() {}
208+
209+
@Override
210+
public void close() {}
211+
})
212+
.content(PluginDescriptor.newBuilder()
213+
.name("Failing Plugin")
214+
.build())
215+
.build()))
216+
.actual();
217+
assertThat(exception.getMessage()).contains(unableToWritePlugin);
218+
assertThat(exception.getCause()).isInstanceOf(XmlWriterException.class);
219+
assertThat(exception.getCause().getCause().getMessage()).isEqualTo(ioEx);
220+
assertThat(exception.getCause().getMessage()).isEqualTo(unableToWritePlugin);
221+
}
222+
223+
@Test
224+
void writeWithNoTargetThrowsIllegalArgumentException() {
225+
assertThat(assertThrows(
226+
IllegalArgumentException.class,
227+
() -> defaultPluginXmlFactory.write(XmlWriterRequest.<PluginDescriptor>builder()
228+
.content(PluginDescriptor.newBuilder()
229+
.name("No Output Plugin")
230+
.build())
231+
.build()))
232+
.getMessage())
233+
.isEqualTo("writer, outputStream or path must be non null");
234+
}
235+
236+
@Test
237+
void readMalformedXmlThrowsXmlReaderException() {
238+
XmlReaderException exception = assertThatExceptionOfType(XmlReaderException.class)
239+
.isThrownBy(() -> defaultPluginXmlFactory.read(XmlReaderRequest.builder()
240+
.inputStream(new ByteArrayInputStream("<plugin><name>Broken Plugin".getBytes()))
241+
.build()))
242+
.actual();
243+
assertThat(exception.getMessage()).contains("Unable to read plugin");
244+
assertThat(exception.getCause()).isInstanceOf(WstxEOFException.class);
245+
}
246+
247+
@Test
248+
void locateExistingPomWithFilePathShouldReturnSameFileIfRegularFile() throws IOException {
249+
Path pomFile = Files.createTempFile(tempDir, "pom", ".xml");
250+
DefaultModelProcessor processor = new DefaultModelProcessor(mock(ModelXmlFactory.class), List.of());
251+
assertThat(processor.locateExistingPom(pomFile)).isEqualTo(pomFile);
252+
}
253+
254+
@Test
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)