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