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