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