1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.configuration.internal;
20
21 import javax.inject.Named;
22 import javax.inject.Singleton;
23
24 import java.io.File;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.Objects;
30
31 import org.apache.maven.api.xml.XmlNode;
32 import org.apache.maven.configuration.BeanConfigurationException;
33 import org.apache.maven.configuration.BeanConfigurationPathTranslator;
34 import org.apache.maven.configuration.BeanConfigurationRequest;
35 import org.apache.maven.configuration.BeanConfigurationValuePreprocessor;
36 import org.apache.maven.configuration.BeanConfigurator;
37 import org.apache.maven.internal.xml.XmlNodeImpl;
38 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
39 import org.codehaus.plexus.component.configurator.ConfigurationListener;
40 import org.codehaus.plexus.component.configurator.converters.AbstractConfigurationConverter;
41 import org.codehaus.plexus.component.configurator.converters.basic.AbstractBasicConverter;
42 import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter;
43 import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup;
44 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
45 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
46 import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator;
47 import org.codehaus.plexus.configuration.PlexusConfiguration;
48 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
49 import org.codehaus.plexus.util.xml.Xpp3Dom;
50
51
52
53
54
55
56 @Named
57 @Singleton
58 public class DefaultBeanConfigurator implements BeanConfigurator {
59
60 private final ConverterLookup converterLookup;
61
62 public DefaultBeanConfigurator() {
63 converterLookup = new EnhancedConverterLookup();
64 }
65
66 public void configureBean(BeanConfigurationRequest request) throws BeanConfigurationException {
67 Objects.requireNonNull(request, "request cannot be null");
68 Objects.requireNonNull(request.getBean(), "request.bean cannot be null");
69
70 Object configuration = request.getConfiguration();
71 if (configuration == null) {
72 return;
73 }
74
75 PlexusConfiguration plexusConfig;
76 if (configuration instanceof PlexusConfiguration) {
77 plexusConfig = (PlexusConfiguration) configuration;
78 } else if (configuration instanceof Xpp3Dom) {
79 plexusConfig = new XmlPlexusConfiguration((Xpp3Dom) configuration);
80 } else {
81 throw new BeanConfigurationException("unsupported bean configuration source ("
82 + configuration.getClass().getName() + ")");
83 }
84
85 if (request.getConfigurationElement() != null) {
86 plexusConfig = plexusConfig.getChild(request.getConfigurationElement());
87 }
88
89 ClassLoader classLoader = request.getClassLoader();
90 if (classLoader == null) {
91 classLoader = request.getBean().getClass().getClassLoader();
92 }
93
94 BeanExpressionEvaluator evaluator = new BeanExpressionEvaluator(request);
95
96 ObjectWithFieldsConverter converter = new EnhancedConfigurationConverter();
97
98 try {
99 converter.processConfiguration(
100 converterLookup, request.getBean(), classLoader, plexusConfig, evaluator, null);
101 } catch (ComponentConfigurationException e) {
102 throw new BeanConfigurationException(e.getMessage(), e);
103 }
104 }
105
106 static class BeanExpressionEvaluator implements TypeAwareExpressionEvaluator {
107
108 private final BeanConfigurationValuePreprocessor preprocessor;
109
110 private final BeanConfigurationPathTranslator translator;
111
112 BeanExpressionEvaluator(BeanConfigurationRequest request) {
113 preprocessor = request.getValuePreprocessor();
114 translator = request.getPathTranslator();
115 }
116
117 public Object evaluate(String expression, Class<?> type) throws ExpressionEvaluationException {
118 if (preprocessor != null) {
119 try {
120 return preprocessor.preprocessValue(expression, type);
121 } catch (BeanConfigurationException e) {
122 throw new ExpressionEvaluationException(e.getMessage(), e);
123 }
124 }
125 return expression;
126 }
127
128 public Object evaluate(String expression) throws ExpressionEvaluationException {
129 return evaluate(expression, null);
130 }
131
132 public File alignToBaseDirectory(File file) {
133 if (translator != null) {
134 return translator.translatePath(file);
135 }
136 return file;
137 }
138 }
139
140 static class XmlConverter extends AbstractConfigurationConverter {
141 @Override
142 public boolean canConvert(Class<?> type) {
143 return XmlNode.class.equals(type);
144 }
145
146 @Override
147 public Object fromConfiguration(
148 final ConverterLookup lookup,
149 final PlexusConfiguration configuration,
150 final Class<?> type,
151 final Class<?> enclosingType,
152 final ClassLoader loader,
153 final ExpressionEvaluator evaluator,
154 final ConfigurationListener listener)
155 throws ComponentConfigurationException {
156
157 try {
158 return toXml(configuration, evaluator);
159 } catch (ExpressionEvaluationException e) {
160 throw new ComponentConfigurationException("Unable to convert configuration to xml node", e);
161 }
162 }
163
164 XmlNode toXml(PlexusConfiguration config, ExpressionEvaluator evaluator) throws ExpressionEvaluationException {
165 List<XmlNode> children = new ArrayList<>();
166 for (PlexusConfiguration c : config.getChildren()) {
167 children.add(toXml(c, evaluator));
168 }
169 String name = config.getName();
170 Object value = evaluator.evaluate(config.getValue());
171 return new XmlNodeImpl(name, value != null ? value.toString() : null, null, children, null);
172 }
173 }
174
175 static class PathConverter extends AbstractBasicConverter {
176 @Override
177 public boolean canConvert(Class<?> type) {
178 return Path.class.equals(type);
179 }
180
181 @Override
182 protected Object fromString(String value) throws ComponentConfigurationException {
183 return Paths.get(value.replace('/' == File.separatorChar ? '\\' : '/', File.separatorChar));
184 }
185
186 @Override
187 public Object fromConfiguration(
188 final ConverterLookup lookup,
189 final PlexusConfiguration configuration,
190 final Class<?> type,
191 final Class<?> enclosingType,
192 final ClassLoader loader,
193 final ExpressionEvaluator evaluator,
194 final ConfigurationListener listener)
195 throws ComponentConfigurationException {
196 final Object result =
197 super.fromConfiguration(lookup, configuration, type, enclosingType, loader, evaluator, listener);
198
199 return result instanceof Path
200 ? evaluator.alignToBaseDirectory(((Path) result).toFile()).toPath()
201 : result;
202 }
203 }
204 }