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.apache.maven.plugins.assembly.utils.AssemblyFileUtils;
23  import org.codehaus.plexus.archiver.Archiver;
24  import org.codehaus.plexus.archiver.ArchiverException;
25  import org.codehaus.plexus.archiver.UnArchiver;
26  import org.codehaus.plexus.components.io.fileselectors.FileInfo;
27  import org.codehaus.plexus.util.IOUtil;
28  
29  import javax.inject.Named;
30  
31  import java.io.File;
32  import java.io.FileNotFoundException;
33  import java.io.FileOutputStream;
34  import java.io.IOException;
35  import java.io.InputStreamReader;
36  import java.io.OutputStreamWriter;
37  import java.io.Reader;
38  import java.io.StringWriter;
39  import java.io.Writer;
40  import java.nio.charset.StandardCharsets;
41  import java.nio.file.Files;
42  import java.util.ArrayList;
43  import java.util.Collections;
44  import java.util.Date;
45  import java.util.List;
46  
47  /**
48   * <code>file-aggregator</code>: Generic aggregating handler, configured with filePattern and outputPath.
49   */
50  @Named( "file-aggregator" )
51  public class SimpleAggregatingDescriptorHandler implements ContainerDescriptorHandler
52  {
53      // component configuration.
54  
55      @SuppressWarnings( "FieldCanBeLocal" )
56      private final String commentChars = "#";
57  
58      private final StringWriter aggregateWriter = new StringWriter();
59  
60      private final List<String> filenames = new ArrayList<>();
61  
62      // calculated, temporary values.
63  
64      private String filePattern;
65  
66      private String outputPath;
67  
68      private boolean overrideFilterAction;
69  
70      @Override
71      public void finalizeArchiveCreation( final Archiver archiver )
72      {
73          checkConfig();
74  
75          if ( outputPath.endsWith( "/" ) )
76          {
77              throw new ArchiverException( "Cannot write aggregated properties to a directory. "
78                                               + "You must specify a file name in the outputPath configuration for this"
79                                               + " handler. (handler: " + getClass().getName() );
80          }
81  
82          if ( outputPath.startsWith( "/" ) )
83          {
84              outputPath = outputPath.substring( 1 );
85          }
86  
87          final File temp = writePropertiesFile();
88  
89          overrideFilterAction = true;
90  
91          archiver.addFile( temp, outputPath );
92  
93          overrideFilterAction = false;
94      }
95  
96      private File writePropertiesFile()
97      {
98          File f;
99          try
100         {
101             f = Files.createTempFile( "maven-assembly-plugin", "tmp" ).toFile();
102             f.deleteOnExit();
103 
104             try ( Writer writer = getWriter( f ) )
105             {
106                 writer.write( commentChars + " Aggregated on " + new Date() + " from: " );
107 
108                 for ( final String filename : filenames )
109                 {
110                     writer.write( "\n" + commentChars + " " + filename );
111                 }
112 
113                 writer.write( "\n\n" );
114                 writer.write( aggregateWriter.toString() );
115             }
116         }
117         catch ( final IOException e )
118         {
119             throw new ArchiverException(
120                 "Error adding aggregated properties to finalize archive creation. Reason: " + e.getMessage(), e );
121         }
122 
123         return f;
124     }
125 
126     private Writer getWriter( File f )
127         throws FileNotFoundException
128     {
129         Writer writer;
130         writer = AssemblyFileUtils.isPropertyFile( f )
131                      ? new OutputStreamWriter( new FileOutputStream( f ), StandardCharsets.ISO_8859_1 )
132                      : new OutputStreamWriter( new FileOutputStream( f ) ); // Still platform encoding
133         return writer;
134     }
135 
136     @Override
137     public void finalizeArchiveExtraction( final UnArchiver unarchiver )
138     {
139     }
140 
141     @Override
142     public List<String> getVirtualFiles()
143     {
144         checkConfig();
145 
146         return Collections.singletonList( outputPath );
147     }
148 
149     @Override
150     public boolean isSelected( final FileInfo fileInfo )
151         throws IOException
152     {
153         checkConfig();
154 
155         if ( overrideFilterAction )
156         {
157             return true;
158         }
159 
160         String name = AssemblyFileUtils.normalizeFileInfo( fileInfo );
161 
162         if ( fileInfo.isFile() && name.matches( filePattern ) )
163         {
164             readProperties( fileInfo );
165             filenames.add( name );
166 
167             return false;
168         }
169 
170         return true;
171     }
172 
173     private void checkConfig()
174     {
175         if ( filePattern == null || outputPath == null )
176         {
177             throw new IllegalStateException(
178                 "You must configure filePattern and outputPath in your containerDescriptorHandler declaration." );
179         }
180     }
181 
182     private void readProperties( final FileInfo fileInfo )
183         throws IOException
184     {
185         try ( StringWriter writer = new StringWriter();
186             Reader reader = AssemblyFileUtils.isPropertyFile( fileInfo.getName() )
187                 ? new InputStreamReader( fileInfo.getContents(), StandardCharsets.ISO_8859_1 )
188                 : new InputStreamReader( fileInfo.getContents() ) ) // platform encoding
189         {
190             IOUtil.copy( reader, writer );
191             final String content = writer.toString();
192             aggregateWriter.write( "\n" );
193             aggregateWriter.write( content );
194         }
195     }
196 
197     @SuppressWarnings( "UnusedDeclaration" )
198     public String getFilePattern()
199     {
200         return filePattern;
201     }
202 
203     @SuppressWarnings( "UnusedDeclaration" )
204     public void setFilePattern( final String filePattern )
205     {
206         this.filePattern = filePattern;
207     }
208 
209     @SuppressWarnings( "UnusedDeclaration" )
210     public String getOutputPath()
211     {
212         return outputPath;
213     }
214 
215     @SuppressWarnings( "UnusedDeclaration" )
216     public void setOutputPath( final String outputPath )
217     {
218         this.outputPath = outputPath;
219     }
220 
221 }