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