1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.api.plugin.testing;
20
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.Reader;
26 import java.io.StringReader;
27 import java.lang.reflect.AccessibleObject;
28 import java.lang.reflect.AnnotatedElement;
29 import java.lang.reflect.Field;
30 import java.net.URL;
31 import java.nio.file.Files;
32 import java.nio.file.Path;
33 import java.nio.file.Paths;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.HashMap;
37 import java.util.LinkedHashSet;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Objects;
41 import java.util.Optional;
42 import java.util.Set;
43 import java.util.stream.Collectors;
44 import java.util.stream.Stream;
45
46 import org.apache.maven.api.MojoExecution;
47 import org.apache.maven.api.Project;
48 import org.apache.maven.api.Session;
49 import org.apache.maven.api.di.Named;
50 import org.apache.maven.api.di.Priority;
51 import org.apache.maven.api.di.Provides;
52 import org.apache.maven.api.di.Singleton;
53 import org.apache.maven.api.di.testing.MavenDIExtension;
54 import org.apache.maven.api.model.Build;
55 import org.apache.maven.api.model.ConfigurationContainer;
56 import org.apache.maven.api.model.Model;
57 import org.apache.maven.api.model.Source;
58 import org.apache.maven.api.plugin.Log;
59 import org.apache.maven.api.plugin.Mojo;
60 import org.apache.maven.api.plugin.descriptor.MojoDescriptor;
61 import org.apache.maven.api.plugin.descriptor.Parameter;
62 import org.apache.maven.api.plugin.descriptor.PluginDescriptor;
63 import org.apache.maven.api.plugin.testing.stubs.MojoExecutionStub;
64 import org.apache.maven.api.plugin.testing.stubs.PluginStub;
65 import org.apache.maven.api.plugin.testing.stubs.ProducedArtifactStub;
66 import org.apache.maven.api.plugin.testing.stubs.ProjectStub;
67 import org.apache.maven.api.plugin.testing.stubs.RepositorySystemSupplier;
68 import org.apache.maven.api.plugin.testing.stubs.SessionMock;
69 import org.apache.maven.api.services.ArtifactDeployer;
70 import org.apache.maven.api.services.ArtifactFactory;
71 import org.apache.maven.api.services.ArtifactInstaller;
72 import org.apache.maven.api.services.ArtifactManager;
73 import org.apache.maven.api.services.LocalRepositoryManager;
74 import org.apache.maven.api.services.ProjectBuilder;
75 import org.apache.maven.api.services.ProjectManager;
76 import org.apache.maven.api.services.RepositoryFactory;
77 import org.apache.maven.api.services.VersionParser;
78 import org.apache.maven.api.services.xml.ModelXmlFactory;
79 import org.apache.maven.api.xml.XmlNode;
80 import org.apache.maven.api.xml.XmlService;
81 import org.apache.maven.configuration.internal.EnhancedComponentConfigurator;
82 import org.apache.maven.di.Injector;
83 import org.apache.maven.di.Key;
84 import org.apache.maven.di.impl.DIException;
85 import org.apache.maven.impl.InternalSession;
86 import org.apache.maven.impl.model.DefaultModelPathTranslator;
87 import org.apache.maven.impl.model.DefaultPathTranslator;
88 import org.apache.maven.internal.impl.DefaultLog;
89 import org.apache.maven.internal.xml.XmlPlexusConfiguration;
90 import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
91 import org.apache.maven.model.v4.MavenMerger;
92 import org.apache.maven.model.v4.MavenStaxReader;
93 import org.apache.maven.plugin.PluginParameterExpressionEvaluatorV4;
94 import org.apache.maven.plugin.descriptor.io.PluginDescriptorStaxReader;
95 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
96 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
97 import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator;
98 import org.codehaus.plexus.util.ReflectionUtils;
99 import org.codehaus.plexus.util.xml.XmlStreamReader;
100 import org.codehaus.plexus.util.xml.Xpp3Dom;
101 import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
102 import org.eclipse.aether.RepositorySystem;
103 import org.junit.jupiter.api.extension.BeforeEachCallback;
104 import org.junit.jupiter.api.extension.ExtensionContext;
105 import org.junit.jupiter.api.extension.ParameterContext;
106 import org.junit.jupiter.api.extension.ParameterResolutionException;
107 import org.junit.jupiter.api.extension.ParameterResolver;
108 import org.junit.platform.commons.support.AnnotationSupport;
109 import org.slf4j.LoggerFactory;
110
111 import static java.util.Objects.requireNonNull;
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166 public class MojoExtension extends MavenDIExtension implements ParameterResolver, BeforeEachCallback {
167
168
169 protected static String pluginBasedir;
170
171
172 protected static String basedir;
173
174
175
176
177
178
179
180 public static String getTestId() {
181 return context.getRequiredTestClass().getSimpleName() + "-"
182 + context.getRequiredTestMethod().getName();
183 }
184
185
186
187
188
189
190
191
192 public static String getBasedir() {
193 return requireNonNull(basedir != null ? basedir : MavenDIExtension.basedir);
194 }
195
196
197
198
199
200
201
202 public static String getPluginBasedir() {
203 return requireNonNull(pluginBasedir);
204 }
205
206
207
208
209
210
211
212
213
214
215 @Override
216 public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
217 throws ParameterResolutionException {
218 return parameterContext.isAnnotated(InjectMojo.class)
219 || parameterContext.getDeclaringExecutable().isAnnotationPresent(InjectMojo.class);
220 }
221
222 @Override
223 public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
224 throws ParameterResolutionException {
225 try {
226 Class<?> holder = parameterContext.getTarget().orElseThrow().getClass();
227 PluginDescriptor descriptor = extensionContext
228 .getStore(ExtensionContext.Namespace.GLOBAL)
229 .get(PluginDescriptor.class, PluginDescriptor.class);
230 Model model =
231 extensionContext.getStore(ExtensionContext.Namespace.GLOBAL).get(Model.class, Model.class);
232 InjectMojo parameterInjectMojo =
233 parameterContext.getAnnotatedElement().getAnnotation(InjectMojo.class);
234 String goal;
235 if (parameterInjectMojo != null) {
236 String pom = parameterInjectMojo.pom();
237 if (pom != null && !pom.isEmpty()) {
238 try (Reader r = openPomUrl(holder, pom, new Path[1])) {
239 Model localModel = new MavenStaxReader().read(r);
240 model = new MavenMerger().merge(localModel, model, false, null);
241 model = new DefaultModelPathTranslator(new DefaultPathTranslator())
242 .alignToBaseDirectory(model, Paths.get(getBasedir()), null);
243 }
244 }
245 goal = parameterInjectMojo.goal();
246 } else {
247 InjectMojo methodInjectMojo = AnnotationSupport.findAnnotation(
248 parameterContext.getDeclaringExecutable(), InjectMojo.class)
249 .orElse(null);
250 if (methodInjectMojo != null) {
251 goal = methodInjectMojo.goal();
252 } else {
253 goal = getGoalFromMojoImplementationClass(
254 parameterContext.getParameter().getType());
255 }
256 }
257
258 Set<MojoParameter> mojoParameters = new LinkedHashSet<>();
259 for (AnnotatedElement ae :
260 Arrays.asList(parameterContext.getDeclaringExecutable(), parameterContext.getAnnotatedElement())) {
261 mojoParameters.addAll(AnnotationSupport.findRepeatableAnnotations(ae, MojoParameter.class));
262 }
263 String[] coord = mojoCoordinates(goal);
264
265 XmlNode pluginConfiguration = model.getBuild().getPlugins().stream()
266 .filter(p ->
267 Objects.equals(p.getGroupId(), coord[0]) && Objects.equals(p.getArtifactId(), coord[1]))
268 .map(ConfigurationContainer::getConfiguration)
269 .findFirst()
270 .orElseGet(() -> XmlNode.newInstance("config"));
271 List<XmlNode> children = mojoParameters.stream()
272 .map(mp -> XmlNode.newInstance(mp.name(), mp.value()))
273 .collect(Collectors.toList());
274 XmlNode config = XmlNode.newInstance("configuration", null, null, children, null);
275 pluginConfiguration = XmlService.merge(config, pluginConfiguration);
276
277
278
279 Mojo mojo = lookup(Mojo.class, coord[0] + ":" + coord[1] + ":" + coord[2] + ":" + coord[3]);
280 for (MojoDescriptor mojoDescriptor : descriptor.getMojos()) {
281 if (Objects.equals(mojoDescriptor.getGoal(), coord[3])) {
282 if (pluginConfiguration != null) {
283 pluginConfiguration = finalizeConfig(pluginConfiguration, mojoDescriptor);
284 }
285 }
286 }
287
288 Session session = getInjector().getInstance(Session.class);
289 Project project = getInjector().getInstance(Project.class);
290 MojoExecution mojoExecution = getInjector().getInstance(MojoExecution.class);
291 ExpressionEvaluator evaluator = new WrapEvaluator(
292 getInjector(), new PluginParameterExpressionEvaluatorV4(session, project, mojoExecution));
293
294 EnhancedComponentConfigurator configurator = new EnhancedComponentConfigurator();
295 configurator.configureComponent(
296 mojo, new XmlPlexusConfiguration(pluginConfiguration), evaluator, null, null);
297 return mojo;
298 } catch (Exception e) {
299 throw new ParameterResolutionException("Unable to resolve mojo", e);
300 }
301 }
302
303
304
305
306
307
308 private static String getGoalFromMojoImplementationClass(Class<?> cl) throws IOException {
309 return cl.getAnnotation(Named.class).value();
310 }
311
312 @Override
313 @SuppressWarnings("checkstyle:MethodLength")
314 public void beforeEach(ExtensionContext context) throws Exception {
315 if (pluginBasedir == null) {
316 pluginBasedir = MavenDIExtension.getBasedir();
317 }
318 basedir = AnnotationSupport.findAnnotation(context.getElement().orElseThrow(), Basedir.class)
319 .map(Basedir::value)
320 .orElse(pluginBasedir);
321 if (basedir != null) {
322 if (basedir.isEmpty()) {
323 basedir = pluginBasedir + "/target/tests/"
324 + context.getRequiredTestClass().getSimpleName() + "/"
325 + context.getRequiredTestMethod().getName();
326 } else {
327 basedir = basedir.replace("${basedir}", pluginBasedir);
328 }
329 }
330
331 setContext(context);
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365 Path basedirPath = Paths.get(getBasedir());
366
367 InjectMojo mojo = AnnotationSupport.findAnnotation(context.getElement().get(), InjectMojo.class)
368 .orElse(null);
369 Model defaultModel = Model.newBuilder()
370 .groupId("myGroupId")
371 .artifactId("myArtifactId")
372 .version("1.0-SNAPSHOT")
373 .packaging("jar")
374 .build(Build.newBuilder()
375 .directory(basedirPath.resolve("target").toString())
376 .outputDirectory(basedirPath.resolve("target/classes").toString())
377 .sources(List.of(
378 Source.newBuilder()
379 .scope("main")
380 .lang("java")
381 .directory(basedirPath
382 .resolve("src/main/java")
383 .toString())
384 .build(),
385 Source.newBuilder()
386 .scope("test")
387 .lang("java")
388 .directory(basedirPath
389 .resolve("src/test/java")
390 .toString())
391 .build()))
392 .testOutputDirectory(
393 basedirPath.resolve("target/test-classes").toString())
394 .build())
395 .build();
396 Path[] modelPath = new Path[] {null};
397 Model tmodel = null;
398 if (mojo != null) {
399 String pom = mojo.pom();
400 if (pom != null && !pom.isEmpty()) {
401 try (Reader r = openPomUrl(context.getRequiredTestClass(), pom, modelPath)) {
402 tmodel = new MavenStaxReader().read(r);
403 }
404 } else {
405 Path pomPath = basedirPath.resolve("pom.xml");
406 if (Files.exists(pomPath)) {
407 try (Reader r = Files.newBufferedReader(pomPath)) {
408 tmodel = new MavenStaxReader().read(r);
409 modelPath[0] = pomPath;
410 }
411 }
412 }
413 }
414 Model model;
415 if (tmodel == null) {
416 model = defaultModel;
417 } else {
418 model = new MavenMerger().merge(tmodel, defaultModel, false, null);
419 }
420 tmodel = new DefaultModelPathTranslator(new DefaultPathTranslator())
421 .alignToBaseDirectory(tmodel, Paths.get(getBasedir()), null);
422 context.getStore(ExtensionContext.Namespace.GLOBAL).put(Model.class, tmodel);
423
424
425
426 PluginDescriptor pluginDescriptor;
427 ClassLoader classLoader = context.getRequiredTestClass().getClassLoader();
428 try (InputStream is = requireNonNull(
429 classLoader.getResourceAsStream(getPluginDescriptorLocation()),
430 "Unable to find plugin descriptor: " + getPluginDescriptorLocation());
431 Reader reader = new BufferedReader(new XmlStreamReader(is))) {
432
433 pluginDescriptor = new PluginDescriptorStaxReader().read(reader);
434 }
435 context.getStore(ExtensionContext.Namespace.GLOBAL).put(PluginDescriptor.class, pluginDescriptor);
436
437
438
439
440 @SuppressWarnings({"unused", "MagicNumber"})
441 class Foo {
442
443 @Provides
444 @Singleton
445 @Priority(-10)
446 private InternalSession createSession() {
447 return SessionMock.getMockSession(getBasedir());
448 }
449
450 @Provides
451 @Singleton
452 @Priority(-10)
453 private Project createProject(InternalSession s) {
454 ProjectStub stub = new ProjectStub();
455 if (!"pom".equals(model.getPackaging())) {
456 ProducedArtifactStub artifact = new ProducedArtifactStub(
457 model.getGroupId(), model.getArtifactId(), "", model.getVersion(), model.getPackaging());
458 stub.setMainArtifact(artifact);
459 }
460 stub.setModel(model);
461 stub.setBasedir(Paths.get(MojoExtension.getBasedir()));
462 stub.setPomPath(modelPath[0]);
463 s.getService(ArtifactManager.class).setPath(stub.getPomArtifact(), modelPath[0]);
464 return stub;
465 }
466
467 @Provides
468 @Singleton
469 @Priority(-10)
470 private MojoExecution createMojoExecution() {
471 MojoExecutionStub mes = new MojoExecutionStub("executionId", null);
472 if (mojo != null) {
473 String goal = mojo.goal();
474 int idx = goal.lastIndexOf(':');
475 if (idx >= 0) {
476 goal = goal.substring(idx + 1);
477 }
478 mes.setGoal(goal);
479 for (MojoDescriptor md : pluginDescriptor.getMojos()) {
480 if (goal.equals(md.getGoal())) {
481 mes.setDescriptor(md);
482 }
483 }
484 requireNonNull(mes.getDescriptor());
485 }
486 PluginStub plugin = new PluginStub();
487 plugin.setDescriptor(pluginDescriptor);
488 mes.setPlugin(plugin);
489 return mes;
490 }
491
492 @Provides
493 @Singleton
494 @Priority(-10)
495 private Log createLog() {
496 return new DefaultLog(LoggerFactory.getLogger("anonymous"));
497 }
498
499 @Provides
500 static RepositorySystemSupplier newRepositorySystemSupplier() {
501 return new RepositorySystemSupplier();
502 }
503
504 @Provides
505 static RepositorySystem newRepositorySystem(RepositorySystemSupplier repositorySystemSupplier) {
506 return repositorySystemSupplier.getRepositorySystem();
507 }
508
509 @Provides
510 @Priority(10)
511 static RepositoryFactory newRepositoryFactory(Session session) {
512 return session.getService(RepositoryFactory.class);
513 }
514
515 @Provides
516 @Priority(10)
517 static VersionParser newVersionParser(Session session) {
518 return session.getService(VersionParser.class);
519 }
520
521 @Provides
522 @Priority(10)
523 static LocalRepositoryManager newLocalRepositoryManager(Session session) {
524 return session.getService(LocalRepositoryManager.class);
525 }
526
527 @Provides
528 @Priority(10)
529 static ArtifactInstaller newArtifactInstaller(Session session) {
530 return session.getService(ArtifactInstaller.class);
531 }
532
533 @Provides
534 @Priority(10)
535 static ArtifactDeployer newArtifactDeployer(Session session) {
536 return session.getService(ArtifactDeployer.class);
537 }
538
539 @Provides
540 @Priority(10)
541 static ArtifactManager newArtifactManager(Session session) {
542 return session.getService(ArtifactManager.class);
543 }
544
545 @Provides
546 @Priority(10)
547 static ProjectManager newProjectManager(Session session) {
548 return session.getService(ProjectManager.class);
549 }
550
551 @Provides
552 @Priority(10)
553 static ArtifactFactory newArtifactFactory(Session session) {
554 return session.getService(ArtifactFactory.class);
555 }
556
557 @Provides
558 @Priority(10)
559 static ProjectBuilder newProjectBuilder(Session session) {
560 return session.getService(ProjectBuilder.class);
561 }
562
563 @Provides
564 @Priority(10)
565 static ModelXmlFactory newModelXmlFactory(Session session) {
566 return session.getService(ModelXmlFactory.class);
567 }
568 }
569
570 getInjector().bindInstance(Foo.class, new Foo());
571
572 getInjector().injectInstance(context.getRequiredTestInstance());
573
574
575
576
577
578
579
580
581
582
583 }
584
585 private Reader openPomUrl(Class<?> holder, String pom, Path[] modelPath) throws IOException {
586 if (pom.startsWith("file:")) {
587 Path path = Paths.get(getBasedir()).resolve(pom.substring("file:".length()));
588 modelPath[0] = path;
589 return Files.newBufferedReader(path);
590 } else if (pom.startsWith("classpath:")) {
591 URL url = holder.getResource(pom.substring("classpath:".length()));
592 if (url == null) {
593 throw new IllegalStateException("Unable to find pom on classpath: " + pom);
594 }
595 return new XmlStreamReader(url.openStream());
596 } else if (pom.contains("<project>")) {
597 return new StringReader(pom);
598 } else {
599 Path path = Paths.get(getBasedir()).resolve(pom);
600 modelPath[0] = path;
601 return Files.newBufferedReader(path);
602 }
603 }
604
605 protected String getPluginDescriptorLocation() {
606 return "META-INF/maven/plugin.xml";
607 }
608
609 protected String[] mojoCoordinates(String goal) throws Exception {
610 if (goal.matches(".*:.*:.*:.*")) {
611 return goal.split(":");
612 } else {
613 Path pluginPom = Paths.get(getPluginBasedir(), "pom.xml");
614 Xpp3Dom pluginPomDom = Xpp3DomBuilder.build(Files.newBufferedReader(pluginPom));
615 String artifactId = pluginPomDom.getChild("artifactId").getValue();
616 String groupId = resolveFromRootThenParent(pluginPomDom, "groupId");
617 String version = resolveFromRootThenParent(pluginPomDom, "version");
618 return new String[] {groupId, artifactId, version, goal};
619 }
620 }
621
622 private XmlNode finalizeConfig(XmlNode config, MojoDescriptor mojoDescriptor) {
623 List<XmlNode> children = new ArrayList<>();
624 if (mojoDescriptor != null) {
625 XmlNode defaultConfiguration;
626 defaultConfiguration = MojoDescriptorCreator.convert(mojoDescriptor);
627 for (Parameter parameter : mojoDescriptor.getParameters()) {
628 XmlNode parameterConfiguration = config.child(parameter.getName());
629 if (parameterConfiguration == null) {
630 parameterConfiguration = config.child(parameter.getAlias());
631 }
632 XmlNode parameterDefaults = defaultConfiguration.child(parameter.getName());
633 parameterConfiguration = XmlNode.merge(parameterConfiguration, parameterDefaults, Boolean.TRUE);
634 if (parameterConfiguration != null) {
635 Map<String, String> attributes = new HashMap<>(parameterConfiguration.attributes());
636
637
638
639
640 parameterConfiguration = XmlNode.newInstance(
641 parameter.getName(),
642 parameterConfiguration.value(),
643 attributes,
644 parameterConfiguration.children(),
645 parameterConfiguration.inputLocation());
646
647 children.add(parameterConfiguration);
648 }
649 }
650 }
651 return XmlNode.newInstance("configuration", null, null, children, null);
652 }
653
654 private static Optional<Xpp3Dom> child(Xpp3Dom element, String name) {
655 return Optional.ofNullable(element.getChild(name));
656 }
657
658 private static Stream<Xpp3Dom> children(Xpp3Dom element) {
659 return Stream.of(element.getChildren());
660 }
661
662 public static XmlNode extractPluginConfiguration(String artifactId, Xpp3Dom pomDom) throws Exception {
663 Xpp3Dom pluginConfigurationElement = child(pomDom, "build")
664 .flatMap(buildElement -> child(buildElement, "plugins"))
665 .map(MojoExtension::children)
666 .orElseGet(Stream::empty)
667 .filter(e -> e.getChild("artifactId").getValue().equals(artifactId))
668 .findFirst()
669 .flatMap(buildElement -> child(buildElement, "configuration"))
670 .orElse(Xpp3DomBuilder.build(new StringReader("<configuration/>")));
671 return pluginConfigurationElement.getDom();
672 }
673
674
675
676
677
678
679 private static String resolveFromRootThenParent(Xpp3Dom pluginPomDom, String element) throws Exception {
680 return Optional.ofNullable(child(pluginPomDom, element).orElseGet(() -> child(pluginPomDom, "parent")
681 .flatMap(e -> child(e, element))
682 .orElse(null)))
683 .map(Xpp3Dom::getValue)
684 .orElseThrow(() -> new Exception("unable to determine " + element));
685 }
686
687
688
689
690
691
692 public static Object getVariableValueFromObject(Object object, String variable) throws IllegalAccessException {
693 Field field = ReflectionUtils.getFieldByNameIncludingSuperclasses(variable, object.getClass());
694 field.setAccessible(true);
695 return field.get(object);
696 }
697
698
699
700
701
702
703 public static Map<String, Object> getVariablesAndValuesFromObject(Object object) throws IllegalAccessException {
704 return getVariablesAndValuesFromObject(object.getClass(), object);
705 }
706
707
708
709
710
711
712
713
714 public static Map<String, Object> getVariablesAndValuesFromObject(Class<?> clazz, Object object)
715 throws IllegalAccessException {
716 Map<String, Object> map = new HashMap<>();
717 Field[] fields = clazz.getDeclaredFields();
718 AccessibleObject.setAccessible(fields, true);
719 for (Field field : fields) {
720 map.put(field.getName(), field.get(object));
721 }
722 Class<?> superclass = clazz.getSuperclass();
723 if (!Object.class.equals(superclass)) {
724 map.putAll(getVariablesAndValuesFromObject(superclass, object));
725 }
726 return map;
727 }
728
729
730
731
732 public static void setVariableValueToObject(Object object, String variable, Object value)
733 throws IllegalAccessException {
734 Field field = ReflectionUtils.getFieldByNameIncludingSuperclasses(variable, object.getClass());
735 requireNonNull(field, "Field " + variable + " not found");
736 field.setAccessible(true);
737 field.set(object, value);
738 }
739
740 static class WrapEvaluator implements TypeAwareExpressionEvaluator {
741
742 private final Injector injector;
743 private final TypeAwareExpressionEvaluator evaluator;
744
745 WrapEvaluator(Injector injector, TypeAwareExpressionEvaluator evaluator) {
746 this.injector = injector;
747 this.evaluator = evaluator;
748 }
749
750 @Override
751 public Object evaluate(String expression) throws ExpressionEvaluationException {
752 return evaluate(expression, null);
753 }
754
755 @Override
756 public Object evaluate(String expression, Class<?> type) throws ExpressionEvaluationException {
757 Object value = evaluator.evaluate(expression, type);
758 if (value == null) {
759 String expr = stripTokens(expression);
760 if (expr != null) {
761 try {
762 value = injector.getInstance(Key.of(type, expr));
763 } catch (DIException e) {
764
765 }
766 }
767 }
768 return value;
769 }
770
771 private String stripTokens(String expr) {
772 if (expr.startsWith("${") && expr.endsWith("}")) {
773 return expr.substring(2, expr.length() - 1);
774 }
775 return null;
776 }
777
778 @Override
779 public File alignToBaseDirectory(File path) {
780 return evaluator.alignToBaseDirectory(path);
781 }
782 }
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814 }