1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package com.qulice.maven;
32
33 import com.google.common.base.Function;
34 import com.google.common.base.Predicate;
35 import com.google.common.base.Predicates;
36 import com.google.common.collect.Collections2;
37 import com.google.common.collect.Iterables;
38 import com.jcabi.log.Logger;
39 import java.io.File;
40 import java.net.MalformedURLException;
41 import java.net.URI;
42 import java.net.URL;
43 import java.net.URLClassLoader;
44 import java.nio.charset.Charset;
45 import java.security.PrivilegedAction;
46 import java.util.Collection;
47 import java.util.LinkedList;
48 import java.util.List;
49 import java.util.Properties;
50 import javax.annotation.Nullable;
51 import org.apache.commons.io.FileUtils;
52 import org.apache.commons.io.FilenameUtils;
53 import org.apache.commons.io.filefilter.DirectoryFileFilter;
54 import org.apache.commons.io.filefilter.IOFileFilter;
55 import org.apache.commons.io.filefilter.WildcardFileFilter;
56 import org.apache.maven.artifact.Artifact;
57 import org.apache.maven.artifact.DependencyResolutionRequiredException;
58 import org.apache.maven.project.MavenProject;
59 import org.codehaus.plexus.context.Context;
60
61
62
63
64
65
66
67 @SuppressWarnings("PMD.TooManyMethods")
68 public final class DefaultMavenEnvironment implements MavenEnvironment {
69
70
71
72
73 private MavenProject iproject;
74
75
76
77
78 private Context icontext;
79
80
81
82
83 private final Properties iproperties = new Properties();
84
85
86
87
88 private MojoExecutor exectr;
89
90
91
92
93 private final Collection<String> exc = new LinkedList<>();
94
95
96
97
98 private final Collection<String> asser = new LinkedList<>();
99
100
101
102
103 private String charset = "UTF-8";
104
105 @Override
106 public String param(final String name, final String value) {
107 String ret = this.iproperties.getProperty(name);
108 if (ret == null) {
109 ret = value;
110 }
111 return ret;
112 }
113
114 @Override
115 public File basedir() {
116 return this.iproject.getBasedir();
117 }
118
119 @Override
120 public File tempdir() {
121 return new File(this.iproject.getBuild().getOutputDirectory());
122 }
123
124 @Override
125 public File outdir() {
126 return new File(this.iproject.getBuild().getOutputDirectory());
127 }
128
129 @Override
130 @SuppressWarnings({"PMD.AvoidInstantiatingObjectsInLoops", "deprecation"})
131 public Collection<String> classpath() {
132 final Collection<String> paths = new LinkedList<>();
133 final String blank = "%20";
134 final String whitespace = " ";
135 try {
136 for (final String name
137 : this.iproject.getRuntimeClasspathElements()) {
138 paths.add(
139 name.replace(
140 File.separatorChar, '/'
141 ).replaceAll(whitespace, blank)
142 );
143 }
144 for (final Artifact artifact
145 : this.iproject.getDependencyArtifacts()) {
146 if (artifact.getFile() != null) {
147 paths.add(
148 artifact.getFile().getAbsolutePath()
149 .replace(File.separatorChar, '/')
150 .replaceAll(whitespace, blank)
151 );
152 }
153 }
154 } catch (final DependencyResolutionRequiredException ex) {
155 throw new IllegalStateException("Failed to read classpath", ex);
156 }
157 return paths;
158 }
159
160 @Override
161 public ClassLoader classloader() {
162 final List<URL> urls = new LinkedList<>();
163 for (final String path : this.classpath()) {
164 try {
165 urls.add(
166 URI.create(String.format("file:///%s", path)).toURL()
167 );
168 } catch (final MalformedURLException ex) {
169 throw new IllegalStateException("Failed to build URL", ex);
170 }
171 }
172 final URLClassLoader loader =
173 new DefaultMavenEnvironment.PrivilegedClassLoader(urls).run();
174 for (final URL url : loader.getURLs()) {
175 Logger.debug(this, "Classpath: %s", url);
176 }
177 return loader;
178 }
179
180 @Override
181 public MavenProject project() {
182 return this.iproject;
183 }
184
185 @Override
186 public Properties properties() {
187 return this.iproperties;
188 }
189
190 @Override
191 public Context context() {
192 return this.icontext;
193 }
194
195 @Override
196 public Properties config() {
197 return this.iproperties;
198 }
199
200 @Override
201 public MojoExecutor executor() {
202 return this.exectr;
203 }
204
205 @Override
206 public Collection<String> asserts() {
207 return this.asser;
208 }
209
210 @Override
211 @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
212 public Collection<File> files(final String pattern) {
213 final Collection<File> files = new LinkedList<>();
214 final IOFileFilter filter = WildcardFileFilter.builder().setWildcards(pattern).get();
215 final String[] dirs = {
216 "src",
217 };
218 for (final String dir : dirs) {
219 final File sources = new File(this.basedir(), dir);
220 if (sources.exists()) {
221 files.addAll(
222 FileUtils.listFiles(
223 sources,
224 filter,
225 DirectoryFileFilter.INSTANCE
226 )
227 );
228 }
229 }
230 return files;
231 }
232
233 @Override
234 public boolean exclude(final String check, final String name) {
235 return Iterables.any(
236 this.excludes(check),
237 new DefaultMavenEnvironment.PathPredicate(name)
238 );
239 }
240
241 @Override
242 public Collection<String> excludes(final String checker) {
243 final Collection<String> excludes = Collections2.transform(
244 this.exc,
245 new DefaultMavenEnvironment.CheckerExcludes(checker)
246 );
247 return Collections2.filter(excludes, Predicates.notNull());
248 }
249
250
251
252
253
254 public void setProject(final MavenProject proj) {
255 this.iproject = proj;
256 }
257
258
259
260
261
262 public void setContext(final Context ctx) {
263 this.icontext = ctx;
264 }
265
266
267
268
269
270 public void setMojoExecutor(final MojoExecutor exec) {
271 this.exectr = exec;
272 }
273
274
275
276
277
278
279 public void setProperty(final String name, final String value) {
280 this.iproperties.setProperty(name, value);
281 }
282
283
284
285
286
287 public void setExcludes(final Collection<String> exprs) {
288 this.exc.clear();
289 this.exc.addAll(exprs);
290 }
291
292
293
294
295
296 public void setAsser(final Collection<String> ass) {
297 this.asser.clear();
298 this.asser.addAll(ass);
299 }
300
301 public void setEncoding(final String encoding) {
302 this.charset = encoding;
303 }
304
305
306
307
308
309 public Charset encoding() {
310 if (this.charset == null || this.charset.isEmpty()) {
311 this.charset = "UTF-8";
312 }
313 return Charset.forName(this.charset);
314 }
315
316
317
318
319
320
321 private static final class PrivilegedClassLoader implements
322 PrivilegedAction<URLClassLoader> {
323
324
325
326 private final List<URL> urls;
327
328
329
330
331
332 private PrivilegedClassLoader(final List<URL> urls) {
333 this.urls = urls;
334 }
335
336 @Override
337 public URLClassLoader run() {
338 return new URLClassLoader(
339 this.urls.toArray(new URL[this.urls.size()]),
340 Thread.currentThread().getContextClassLoader()
341 );
342 }
343 }
344
345
346
347
348
349
350 private static class PathPredicate implements Predicate<String> {
351
352
353
354 private final String name;
355
356
357
358
359
360 PathPredicate(final String name) {
361 this.name = name;
362 }
363
364 @Override
365 public boolean apply(@Nullable final String input) {
366 return input != null
367 && FilenameUtils.normalize(this.name, true).matches(input);
368 }
369 }
370
371
372
373
374
375
376
377
378 private static class CheckerExcludes implements Function<String, String> {
379
380
381
382
383 private final String checker;
384
385
386
387
388
389 CheckerExcludes(final String checker) {
390 this.checker = checker;
391 }
392
393 @Nullable
394 @Override
395 public String apply(@Nullable final String input) {
396 String result = null;
397 if (input != null) {
398 final String[] exclude = input.split(":", 2);
399 if (this.checker.equals(exclude[0]) && exclude.length > 1) {
400 result = exclude[1];
401 }
402 }
403 return result;
404 }
405 }
406 }