1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package net.alchim31.maven.yuicompressor;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.nio.charset.StandardCharsets;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.List;
33 import java.util.Set;
34
35 import org.codehaus.plexus.build.BuildContext;
36 import org.codehaus.plexus.util.DirectoryScanner;
37 import org.codehaus.plexus.util.IOUtil;
38
39
40
41
42 public class Aggregation {
43
44
45 private File inputDir;
46
47
48 private File output;
49
50
51 private String[] includes;
52
53
54 private String[] excludes;
55
56
57 private boolean removeIncluded;
58
59
60 private boolean insertNewLine;
61
62
63 private boolean insertFileHeader;
64
65
66 private boolean fixLastSemicolon;
67
68
69 private boolean autoExcludeWildcards;
70
71
72
73
74
75
76 public File getOutput() {
77 return output;
78 }
79
80
81
82
83
84
85
86 public void setOutput(File output) {
87 this.output = output;
88 }
89
90
91
92
93
94
95
96 public void setIncludes(String[] includes) {
97 this.includes = includes;
98 }
99
100
101
102
103
104
105
106 public void setInsertNewLine(boolean insertNewLine) {
107 this.insertNewLine = insertNewLine;
108 }
109
110
111
112
113
114
115
116 public void setAutoExcludeWildcards(boolean autoExcludeWildcards) {
117 this.autoExcludeWildcards = autoExcludeWildcards;
118 }
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 public List<File> run(Collection<File> previouslyIncludedFiles, BuildContext buildContext) throws IOException {
134 return this.run(previouslyIncludedFiles, buildContext, null);
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 public List<File> run(Collection<File> previouslyIncludedFiles, BuildContext buildContext,
153 Set<String> incrementalFiles) throws IOException {
154 defineInputDir();
155
156 List<File> files;
157 if (autoExcludeWildcards) {
158 files = getIncludedFiles(previouslyIncludedFiles, buildContext, incrementalFiles);
159 } else {
160 files = getIncludedFiles(null, buildContext, incrementalFiles);
161 }
162
163 if (!files.isEmpty()) {
164 output = output.getCanonicalFile();
165 output.getParentFile().mkdirs();
166 try (OutputStream out = buildContext.newFileOutputStream(output)) {
167 for (File file : files) {
168 if (file.getCanonicalPath().equals(output.getCanonicalPath())) {
169 continue;
170 }
171 try (InputStream in = Files.newInputStream(file.toPath())) {
172 if (insertFileHeader) {
173 out.write(createFileHeader(file).getBytes(StandardCharsets.UTF_8));
174 }
175 IOUtil.copy(in, out);
176 if (fixLastSemicolon) {
177 out.write(';');
178 }
179 if (insertNewLine) {
180 out.write('\n');
181 }
182 }
183 if (removeIncluded) {
184 if (file.exists()) {
185 Files.delete(file.toPath());
186 }
187 buildContext.refresh(file);
188 }
189 }
190 }
191 }
192 return files;
193 }
194
195
196
197
198
199
200
201
202
203 private String createFileHeader(File file) {
204 StringBuilder header = new StringBuilder();
205 header.append("/*");
206 header.append(file.getName());
207 header.append("*/");
208
209 if (insertNewLine) {
210 header.append('\n');
211 }
212
213 return header.toString();
214 }
215
216
217
218
219
220
221
222 private void defineInputDir() throws IOException {
223 if (inputDir == null) {
224 inputDir = output.getParentFile();
225 }
226 inputDir = inputDir.getCanonicalFile();
227 if (!inputDir.isDirectory()) {
228 throw new IllegalStateException("input directory not found: " + inputDir);
229 }
230 }
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247 private List<File> getIncludedFiles(Collection<File> previouslyIncludedFiles, BuildContext buildContext,
248 Set<String> incrementalFiles) throws IOException {
249 List<File> filesToAggregate = new ArrayList<>();
250 if (includes != null) {
251 for (String include : includes) {
252 addInto(include, filesToAggregate, previouslyIncludedFiles);
253 }
254 }
255
256
257 if (!buildContext.isIncremental()) {
258 return filesToAggregate;
259 }
260 if (incrementalFiles != null) {
261 boolean aggregateMustBeUpdated = false;
262 for (File file : filesToAggregate) {
263 if (incrementalFiles.contains(file.getCanonicalPath())) {
264 aggregateMustBeUpdated = true;
265 break;
266 }
267 }
268
269 if (aggregateMustBeUpdated) {
270 return filesToAggregate;
271 }
272 }
273 return new ArrayList<>();
274
275 }
276
277
278
279
280
281
282
283
284
285
286
287 private void addInto(String include, List<File> includedFiles, Collection<File> previouslyIncludedFiles) {
288 if (include.indexOf('*') > -1) {
289 DirectoryScanner scanner = newScanner();
290 scanner.setIncludes(new String[] { include });
291 scanner.scan();
292 String[] rpaths = scanner.getIncludedFiles();
293 Arrays.sort(rpaths);
294 for (String rpath : rpaths) {
295 File file = scanner.getBasedir().toPath().resolve(rpath).toFile();
296 if (!includedFiles.contains(file)
297 && (previouslyIncludedFiles == null || !previouslyIncludedFiles.contains(file))) {
298 includedFiles.add(file);
299 }
300 }
301 } else {
302 File file = Path.of(include).toFile();
303 if (!file.isAbsolute()) {
304 file = inputDir.toPath().resolve(include).toFile();
305 }
306 if (!includedFiles.contains(file)) {
307 includedFiles.add(file);
308 }
309 }
310 }
311
312
313
314
315
316
317 private DirectoryScanner newScanner() {
318 DirectoryScanner scanner = new DirectoryScanner();
319 scanner.setBasedir(inputDir);
320 if (excludes != null && excludes.length != 0) {
321 scanner.setExcludes(excludes);
322 }
323 scanner.addDefaultExcludes();
324 return scanner;
325 }
326 }