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.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  //    private final TestFileManager fileManager = new TestFileManager( "componentsXmlArchiverFileFilter.test", ".zip" );
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 }