1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.assembly.filter;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.Reader;
24 import java.io.StringReader;
25 import java.io.StringWriter;
26 import java.nio.file.Files;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.LinkedHashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.NoSuchElementException;
33 import java.util.zip.ZipEntry;
34 import java.util.zip.ZipFile;
35
36 import org.codehaus.plexus.archiver.ArchiveEntry;
37 import org.codehaus.plexus.archiver.ArchivedFileSet;
38 import org.codehaus.plexus.archiver.Archiver;
39 import org.codehaus.plexus.archiver.ArchiverException;
40 import org.codehaus.plexus.archiver.FileSet;
41 import org.codehaus.plexus.archiver.ResourceIterator;
42 import org.codehaus.plexus.archiver.diags.NoOpArchiver;
43 import org.codehaus.plexus.archiver.zip.ZipArchiver;
44 import org.codehaus.plexus.components.io.resources.PlexusIoResource;
45 import org.codehaus.plexus.components.io.resources.PlexusIoResourceCollection;
46 import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
47 import org.codehaus.plexus.util.xml.Xpp3Dom;
48 import org.jdom2.Document;
49 import org.jdom2.Text;
50 import org.jdom2.filter.Filters;
51 import org.jdom2.input.SAXBuilder;
52 import org.jdom2.input.sax.XMLReaders;
53 import org.jdom2.xpath.XPathExpression;
54 import org.jdom2.xpath.XPathFactory;
55 import org.junit.Before;
56 import org.junit.Rule;
57 import org.junit.Test;
58 import org.junit.rules.TemporaryFolder;
59
60 import static org.junit.Assert.assertEquals;
61 import static org.junit.Assert.assertFalse;
62 import static org.junit.Assert.assertNotNull;
63 import static org.junit.Assert.assertNull;
64
65 public class ComponentsXmlArchiverFileFilterTest {
66
67 @Rule
68 public TemporaryFolder temporaryFolder = new TemporaryFolder();
69
70 private ComponentsXmlArchiverFileFilter filter;
71
72 @Before
73 public void setUp() {
74 filter = new ComponentsXmlArchiverFileFilter();
75 }
76
77 @Test
78 public void testAddComponentsXml_ShouldAddComponentWithoutRoleHint() throws Exception {
79 final Reader reader =
80 writeComponentsXml(Collections.singletonList(new ComponentDef("role", null, "org.apache.maven.Impl")));
81
82 filter.addComponentsXml(reader);
83
84 assertFalse(filter.components.isEmpty());
85
86 final Xpp3Dom componentDom = filter.components.get("role");
87
88 assertEquals("role", componentDom.getChild("role").getValue());
89 assertNull(componentDom.getChild("role-hint"));
90 assertEquals(
91 "org.apache.maven.Impl", componentDom.getChild("implementation").getValue());
92 }
93
94 @Test
95 public void testAddComponentsXml_ShouldAddComponentWithRoleHint() throws Exception {
96 final Reader reader = writeComponentsXml(
97 Collections.singletonList(new ComponentDef("role", "hint", "org.apache.maven.Impl")));
98
99 filter.addComponentsXml(reader);
100
101 assertFalse(filter.components.isEmpty());
102
103 final Xpp3Dom componentDom = filter.components.get("rolehint");
104
105 assertEquals("role", componentDom.getChild("role").getValue());
106 assertEquals("hint", componentDom.getChild("role-hint").getValue());
107 assertEquals(
108 "org.apache.maven.Impl", componentDom.getChild("implementation").getValue());
109 }
110
111 @Test
112 public void testAddComponentsXml_ShouldAddTwoComponentsWithRoleHints() throws Exception {
113 final List<ComponentDef> defs = new ArrayList<>();
114
115 defs.add(new ComponentDef("role", "hint", "org.apache.maven.Impl"));
116 defs.add(new ComponentDef("role", "hint2", "org.apache.maven.Impl2"));
117
118 final Reader reader = writeComponentsXml(defs);
119
120 filter.addComponentsXml(reader);
121
122 assertFalse(filter.components.isEmpty());
123
124 Xpp3Dom componentDom = filter.components.get("rolehint");
125
126 assertEquals("role", componentDom.getChild("role").getValue());
127 assertEquals("hint", componentDom.getChild("role-hint").getValue());
128 assertEquals(
129 "org.apache.maven.Impl", componentDom.getChild("implementation").getValue());
130
131 componentDom = filter.components.get("rolehint2");
132
133 assertEquals("role", componentDom.getChild("role").getValue());
134 assertEquals("hint2", componentDom.getChild("role-hint").getValue());
135 assertEquals(
136 "org.apache.maven.Impl2",
137 componentDom.getChild("implementation").getValue());
138 }
139
140 @Test
141 public void testAddToArchive_ShouldWriteComponentWithoutHintToFile() throws Exception {
142 final Xpp3Dom dom = createComponentDom(new ComponentDef("role", null, "impl"));
143
144 filter.components = new LinkedHashMap<>();
145 filter.components.put("role", dom);
146
147 final FileCatchingArchiver fca = new FileCatchingArchiver();
148
149 filter.finalizeArchiveCreation(fca);
150
151 assertEquals(ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH, fca.getDestFileName());
152
153 final SAXBuilder builder = new SAXBuilder(XMLReaders.NONVALIDATING);
154
155 final Document doc = builder.build(fca.getFile());
156 XPathFactory xPathFactory = XPathFactory.instance();
157
158 XPathExpression<Text> role = xPathFactory.compile("//component[position()=1]/role/text()", Filters.text());
159 XPathExpression<Text> hint = xPathFactory.compile("//component[position()=1]/role-hint/text()", Filters.text());
160 XPathExpression<Text> implementation =
161 xPathFactory.compile("//component[position()=1]/implementation/text()", Filters.text());
162
163 assertEquals("role", role.evaluateFirst(doc).getText());
164 assertNull(hint.evaluateFirst(doc));
165 assertEquals("impl", implementation.evaluateFirst(doc).getText());
166 }
167
168 @Test
169 public void testAddToArchive_ShouldWriteComponentWithHintToFile() throws Exception {
170 final Xpp3Dom dom = createComponentDom(new ComponentDef("role", "hint", "impl"));
171
172 filter.components = new LinkedHashMap<>();
173 filter.components.put("rolehint", dom);
174
175 final FileCatchingArchiver fca = new FileCatchingArchiver();
176
177 filter.finalizeArchiveCreation(fca);
178
179 assertEquals(ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH, fca.getDestFileName());
180
181 final SAXBuilder builder = new SAXBuilder(XMLReaders.NONVALIDATING);
182
183 final Document doc = builder.build(fca.getFile());
184 XPathFactory xPathFactory = XPathFactory.instance();
185
186 XPathExpression<Text> role = xPathFactory.compile("//component[position()=1]/role/text()", Filters.text());
187 XPathExpression<Text> hint = xPathFactory.compile("//component[position()=1]/role-hint/text()", Filters.text());
188 XPathExpression<Text> implementation =
189 xPathFactory.compile("//component[position()=1]/implementation/text()", Filters.text());
190
191 assertEquals("role", role.evaluateFirst(doc).getText());
192 assertEquals("hint", hint.evaluateFirst(doc).getText());
193 assertEquals("impl", implementation.evaluateFirst(doc).getText());
194 }
195
196 @Test
197 public void testAddToArchive_ShouldWriteTwoComponentToFile() throws Exception {
198 filter.components = new LinkedHashMap<>();
199
200 final Xpp3Dom dom = createComponentDom(new ComponentDef("role", "hint", "impl"));
201
202 filter.components.put("rolehint", dom);
203
204 final Xpp3Dom dom2 = createComponentDom(new ComponentDef("role", "hint2", "impl"));
205
206 filter.components.put("rolehint2", dom2);
207
208 final FileCatchingArchiver fca = new FileCatchingArchiver();
209
210 filter.finalizeArchiveCreation(fca);
211
212 assertEquals(ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH, fca.getDestFileName());
213
214 final SAXBuilder builder = new SAXBuilder(XMLReaders.NONVALIDATING);
215
216 final Document doc = builder.build(fca.getFile());
217 XPathFactory xPathFactory = XPathFactory.instance();
218
219 XPathExpression<Text> role = xPathFactory.compile("//component[position()=1]/role/text()", Filters.text());
220 XPathExpression<Text> hint = xPathFactory.compile("//component[position()=1]/role-hint/text()", Filters.text());
221 XPathExpression<Text> implementation =
222 xPathFactory.compile("//component[position()=1]/implementation/text()", Filters.text());
223
224 assertEquals("role", role.evaluateFirst(doc).getText());
225 assertEquals("hint", hint.evaluateFirst(doc).getText());
226 assertEquals("impl", implementation.evaluateFirst(doc).getText());
227
228 XPathExpression<Text> role2 = xPathFactory.compile("//component[position()=2]/role/text()", Filters.text());
229 XPathExpression<Text> hint2 =
230 xPathFactory.compile("//component[position()=2]/role-hint/text()", Filters.text());
231 XPathExpression<Text> implementation2 =
232 xPathFactory.compile("//component[position()=2]/implementation/text()", Filters.text());
233
234 assertEquals("role", role2.evaluateFirst(doc).getText());
235 assertEquals("hint2", hint2.evaluateFirst(doc).getText());
236 assertEquals("impl", implementation2.evaluateFirst(doc).getText());
237 }
238
239 @Test
240 public void testAddToArchive_ShouldWriteTwoComponentToArchivedFile() throws Exception {
241 filter.components = new LinkedHashMap<>();
242
243 final Xpp3Dom dom = createComponentDom(new ComponentDef("role", "hint", "impl"));
244
245 filter.components.put("rolehint", dom);
246
247 final Xpp3Dom dom2 = createComponentDom(new ComponentDef("role", "hint2", "impl"));
248
249 filter.components.put("rolehint2", dom2);
250
251 final ZipArchiver archiver = new ZipArchiver();
252
253 final File archiveFile = temporaryFolder.newFile("archive");
254
255 archiver.setDestFile(archiveFile);
256
257 final File descriptorFile = new File(temporaryFolder.getRoot(), "descriptor.xml");
258
259 archiver.setArchiveFinalizers(Collections.singletonList(filter));
260
261 archiver.createArchive();
262
263 try (ZipFile zf = new ZipFile(archiveFile)) {
264 final ZipEntry ze = zf.getEntry(ComponentsXmlArchiverFileFilter.COMPONENTS_XML_PATH);
265
266 assertNotNull(ze);
267
268 Files.copy(zf.getInputStream(ze), descriptorFile.toPath());
269 }
270
271 final SAXBuilder builder = new SAXBuilder(XMLReaders.NONVALIDATING);
272
273 final Document doc = builder.build(descriptorFile);
274
275 XPathFactory xPathFactory = XPathFactory.instance();
276 XPathExpression<Text> role = xPathFactory.compile("//component[position()=1]/role/text()", Filters.text());
277 XPathExpression<Text> hint = xPathFactory.compile("//component[position()=1]/role-hint/text()", Filters.text());
278 XPathExpression<Text> implementation =
279 xPathFactory.compile("//component[position()=1]/implementation/text()", Filters.text());
280
281 assertEquals("role", role.evaluateFirst(doc).getText());
282 assertEquals("hint", hint.evaluateFirst(doc).getText());
283 assertEquals("impl", implementation.evaluateFirst(doc).getText());
284
285 XPathExpression<Text> role2 = xPathFactory.compile("//component[position()=2]/role/text()", Filters.text());
286 XPathExpression<Text> hint2 =
287 xPathFactory.compile("//component[position()=2]/role-hint/text()", Filters.text());
288 XPathExpression<Text> implementation2 =
289 xPathFactory.compile("//component[position()=2]/implementation/text()", Filters.text());
290
291 assertEquals("role", role2.evaluateFirst(doc).getText());
292 assertEquals("hint2", hint2.evaluateFirst(doc).getText());
293 assertEquals("impl", implementation2.evaluateFirst(doc).getText());
294 }
295
296 private Xpp3Dom createComponentDom(final ComponentDef def) {
297 final Xpp3Dom dom = new Xpp3Dom("component");
298
299 final Xpp3Dom role = new Xpp3Dom("role");
300 role.setValue(def.role);
301 dom.addChild(role);
302
303 final String hint = def.roleHint;
304 if (hint != null) {
305 final Xpp3Dom roleHint = new Xpp3Dom("role-hint");
306 roleHint.setValue(hint);
307 dom.addChild(roleHint);
308 }
309
310 final Xpp3Dom impl = new Xpp3Dom("implementation");
311 impl.setValue(def.implementation);
312 dom.addChild(impl);
313
314 return dom;
315 }
316
317 private Reader writeComponentsXml(final List<ComponentDef> componentDefs) throws IOException {
318 final StringWriter writer = new StringWriter();
319
320 final PrettyPrintXMLWriter xmlWriter = new PrettyPrintXMLWriter(writer);
321
322 xmlWriter.startElement("component-set");
323 xmlWriter.startElement("components");
324
325 for (final ComponentDef def : componentDefs) {
326 xmlWriter.startElement("component");
327
328 xmlWriter.startElement("role");
329 xmlWriter.writeText(def.role);
330 xmlWriter.endElement();
331
332 final String roleHint = def.roleHint;
333 if (roleHint != null) {
334 xmlWriter.startElement("role-hint");
335 xmlWriter.writeText(roleHint);
336 xmlWriter.endElement();
337 }
338
339 xmlWriter.startElement("implementation");
340 xmlWriter.writeText(def.implementation);
341 xmlWriter.endElement();
342
343 xmlWriter.endElement();
344 }
345
346 xmlWriter.endElement();
347 xmlWriter.endElement();
348
349 return new StringReader(writer.toString());
350 }
351
352 private static final class ComponentDef {
353 final String role;
354
355 final String roleHint;
356
357 final String implementation;
358
359 ComponentDef(final String role, final String roleHint, final String implementation) {
360 this.role = role;
361 this.roleHint = roleHint;
362 this.implementation = implementation;
363 }
364 }
365
366 private static final class FileCatchingArchiver extends NoOpArchiver {
367
368 private File inputFile;
369
370 private String destFileName;
371
372 public void addDirectory(final File directory) throws ArchiverException {
373 throw new UnsupportedOperationException("not supported");
374 }
375
376 public void addDirectory(final File directory, final String prefix) throws ArchiverException {
377 throw new UnsupportedOperationException("not supported");
378 }
379
380 public void addDirectory(final File directory, final String[] includes, final String[] excludes)
381 throws ArchiverException {
382 throw new UnsupportedOperationException("not supported");
383 }
384
385 public void addDirectory(
386 final File directory, final String prefix, final String[] includes, final String[] excludes)
387 throws ArchiverException {
388 throw new UnsupportedOperationException("not supported");
389 }
390
391 public void addFile(final File inputFile, final String destFileName) throws ArchiverException {
392 this.inputFile = inputFile;
393 this.destFileName = destFileName;
394 }
395
396 File getFile() {
397 return inputFile;
398 }
399
400 String getDestFileName() {
401 return destFileName;
402 }
403
404 public void addFile(final File inputFile, final String destFileName, final int permissions)
405 throws ArchiverException {
406 throw new UnsupportedOperationException("not supported");
407 }
408
409 public void createArchive() throws ArchiverException, IOException {
410 throw new UnsupportedOperationException("not supported");
411 }
412
413 public int getDefaultDirectoryMode() {
414 throw new UnsupportedOperationException("not supported");
415 }
416
417 public void setDefaultDirectoryMode(final int mode) {
418 throw new UnsupportedOperationException("not supported");
419 }
420
421 public int getDefaultFileMode() {
422 throw new UnsupportedOperationException("not supported");
423 }
424
425 public void setDefaultFileMode(final int mode) {
426 throw new UnsupportedOperationException("not supported");
427 }
428
429 public File getDestFile() {
430 throw new UnsupportedOperationException("not supported");
431 }
432
433 public void setDestFile(final File destFile) {
434 throw new UnsupportedOperationException("not supported");
435 }
436
437 public void addSymlink(String s, String s2) throws ArchiverException {
438 throw new UnsupportedOperationException("not supported");
439 }
440
441 public void addSymlink(String s, int i, String s2) throws ArchiverException {
442 throw new UnsupportedOperationException("not supported");
443 }
444
445 public Map<String, ArchiveEntry> getFiles() {
446 throw new UnsupportedOperationException("not supported");
447 }
448
449 public boolean getIncludeEmptyDirs() {
450 throw new UnsupportedOperationException("not supported");
451 }
452
453 public void setIncludeEmptyDirs(final boolean includeEmptyDirs) {
454 throw new UnsupportedOperationException("not supported");
455 }
456
457 public void addArchivedFileSet(final File archiveFile) throws ArchiverException {
458 throw new UnsupportedOperationException("not supported");
459 }
460
461 public void addArchivedFileSet(final File archiveFile, final String prefix) throws ArchiverException {
462 throw new UnsupportedOperationException("not supported");
463 }
464
465 public void addArchivedFileSet(final File archiveFile, final String[] includes, final String[] excludes)
466 throws ArchiverException {
467 throw new UnsupportedOperationException("not supported");
468 }
469
470 public void addArchivedFileSet(
471 final File archiveFile, final String prefix, final String[] includes, final String[] excludes)
472 throws ArchiverException {
473 throw new UnsupportedOperationException("not supported");
474 }
475
476 public boolean isForced() {
477 throw new UnsupportedOperationException("not supported");
478 }
479
480 public void setForced(final boolean forced) {
481 throw new UnsupportedOperationException("not supported");
482 }
483
484 public boolean isSupportingForced() {
485 throw new UnsupportedOperationException("not supported");
486 }
487
488 public void setDotFileDirectory(final File dotFileDirectory) {}
489
490 public void addArchivedFileSet(final ArchivedFileSet fileSet) throws ArchiverException {
491 throw new UnsupportedOperationException("not supported");
492 }
493
494 public void addFileSet(final FileSet fileSet) throws ArchiverException {
495 throw new UnsupportedOperationException("not supported");
496 }
497
498 public void addResource(final PlexusIoResource resource, final String destFileName, final int permissions)
499 throws ArchiverException {
500 throw new UnsupportedOperationException("not supported");
501 }
502
503 public void addResources(final PlexusIoResourceCollection resources) throws ArchiverException {
504 throw new UnsupportedOperationException("not supported");
505 }
506
507 public ResourceIterator getResources() throws ArchiverException {
508 return new ResourceIterator() {
509
510 public boolean hasNext() throws ArchiverException {
511 return false;
512 }
513
514 public ArchiveEntry next() throws ArchiverException {
515 throw new NoSuchElementException();
516 }
517
518 public void remove() {
519 throw new NoSuchElementException();
520 }
521 };
522 }
523
524 public String getDuplicateBehavior() {
525 return Archiver.DUPLICATES_ADD;
526 }
527
528 public void setDuplicateBehavior(final String duplicate) {}
529
530 public int getDirectoryMode() {
531 throw new UnsupportedOperationException("not supported");
532 }
533
534 public void setDirectoryMode(final int mode) {
535 throw new UnsupportedOperationException("not supported");
536 }
537
538 public int getFileMode() {
539 throw new UnsupportedOperationException("not supported");
540 }
541
542 public void setFileMode(final int mode) {
543 throw new UnsupportedOperationException("not supported");
544 }
545
546 public int getOverrideDirectoryMode() {
547 throw new UnsupportedOperationException("not supported");
548 }
549
550 public int getOverrideFileMode() {
551 throw new UnsupportedOperationException("not supported");
552 }
553 }
554 }