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