1 package org.apache.maven.plugins.assembly.filter;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
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
67
68 private String filePattern;
69
70 private String outputPath;
71
72 private boolean overrideFilterAction;
73
74
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 ) );
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() ) )
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 }