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.FileOutputStream;
36  import java.io.IOException;
37  import java.io.InputStreamReader;
38  import java.io.OutputStreamWriter;
39  import java.io.Reader;
40  import java.io.StringWriter;
41  import java.io.Writer;
42  import java.nio.charset.StandardCharsets;
43  import java.util.ArrayList;
44  import java.util.Collections;
45  import java.util.Date;
46  import java.util.List;
47  
48  /**
49   *
50   */
51  @Component( role = ContainerDescriptorHandler.class, hint = "file-aggregator", instantiationStrategy = "per-lookup" )
52  public class SimpleAggregatingDescriptorHandler
53      implements ContainerDescriptorHandler, LogEnabled
54  {
55  
56      // component configuration.
57  
58      @SuppressWarnings( "FieldCanBeLocal" )
59      private final String commentChars = "#";
60  
61      private final StringWriter aggregateWriter = new StringWriter();
62  
63      private final List<String> filenames = new ArrayList<>();
64  
65      // calculated, temporary values.
66  
67      private String filePattern;
68  
69      private String outputPath;
70  
71      private boolean overrideFilterAction;
72  
73      // injected by the container.
74  
75      private Logger logger;
76  
77      @Override
78      public void finalizeArchiveCreation( final Archiver archiver )
79      {
80          checkConfig();
81  
82          if ( outputPath.endsWith( "/" ) )
83          {
84              throw new ArchiverException( "Cannot write aggregated properties to a directory. "
85                                               + "You must specify a file name in the outputPath configuration for this"
86                                               + " handler. (handler: " + getClass().getName() );
87          }
88  
89          if ( outputPath.startsWith( "/" ) )
90          {
91              outputPath = outputPath.substring( 1 );
92          }
93  
94          final File temp = writePropertiesFile();
95  
96          overrideFilterAction = true;
97  
98          archiver.addFile( temp, outputPath );
99  
100         overrideFilterAction = false;
101     }
102 
103     private File writePropertiesFile()
104     {
105         File f;
106 
107         Writer writer = null;
108         try
109         {
110             f = File.createTempFile( "maven-assembly-plugin", "tmp" );
111             f.deleteOnExit();
112 
113             writer = AssemblyFileUtils.isPropertyFile( f )
114                          ? new OutputStreamWriter( new FileOutputStream( f ), StandardCharsets.ISO_8859_1 )
115                          : new OutputStreamWriter( new FileOutputStream( f ) ); // Still platform encoding
116 
117             writer.write( commentChars + " Aggregated on " + new Date() + " from: " );
118 
119             for ( final String filename : filenames )
120             {
121                 writer.write( "\n" + commentChars + " " + filename );
122             }
123 
124             writer.write( "\n\n" );
125 
126             writer.write( aggregateWriter.toString() );
127 
128             writer.close();
129             writer = null;
130         }
131         catch ( final IOException e )
132         {
133             throw new ArchiverException(
134                 "Error adding aggregated properties to finalize archive creation. Reason: " + e.getMessage(), e );
135         }
136         finally
137         {
138             IOUtil.close( writer );
139         }
140 
141         return f;
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 }