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