1
2
3
4
5 package com.qulice.maven;
6
7 import com.jcabi.log.Logger;
8 import com.qulice.spi.ValidationException;
9 import java.util.Collection;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Properties;
13 import org.apache.maven.execution.MavenSession;
14 import org.apache.maven.model.Plugin;
15 import org.apache.maven.plugin.InvalidPluginDescriptorException;
16 import org.apache.maven.plugin.MavenPluginManager;
17 import org.apache.maven.plugin.Mojo;
18 import org.apache.maven.plugin.MojoExecution;
19 import org.apache.maven.plugin.MojoExecutionException;
20 import org.apache.maven.plugin.MojoFailureException;
21 import org.apache.maven.plugin.PluginConfigurationException;
22 import org.apache.maven.plugin.PluginContainerException;
23 import org.apache.maven.plugin.PluginDescriptorParsingException;
24 import org.apache.maven.plugin.PluginResolutionException;
25 import org.apache.maven.plugin.descriptor.MojoDescriptor;
26 import org.apache.maven.reporting.exec.DefaultMavenPluginManagerHelper;
27 import org.codehaus.plexus.configuration.PlexusConfiguration;
28 import org.codehaus.plexus.configuration.PlexusConfigurationException;
29 import org.codehaus.plexus.util.xml.Xpp3Dom;
30
31
32
33
34
35 public final class MojoExecutor {
36
37
38
39
40 private final MavenPluginManager manager;
41
42
43
44
45 private final MavenSession session;
46
47
48
49
50
51
52 public MojoExecutor(final MavenPluginManager mngr,
53 final MavenSession sesn) {
54 this.manager = mngr;
55 this.session = sesn;
56 }
57
58
59
60
61
62
63
64
65
66 public void execute(final String coords, final String goal,
67 final Properties config) throws ValidationException {
68 final Plugin plugin = new Plugin();
69 final String[] sectors = coords.split(":");
70 plugin.setGroupId(sectors[0]);
71 plugin.setArtifactId(sectors[1]);
72 plugin.setVersion(sectors[2]);
73 final MojoDescriptor descriptor = this.descriptor(plugin, goal);
74 try {
75 new DefaultMavenPluginManagerHelper(this.manager).setupPluginRealm(
76 descriptor.getPluginDescriptor(),
77 this.session,
78 Thread.currentThread().getContextClassLoader(),
79 List.of(),
80 List.of()
81 );
82 } catch (final PluginResolutionException ex) {
83 throw new IllegalStateException("Plugin resolution problem", ex);
84 } catch (final PluginContainerException ex) {
85 throw new IllegalStateException("Can't setup realm", ex);
86 }
87 final MojoExecution execution = new MojoExecution(
88 descriptor,
89 Xpp3Dom.mergeXpp3Dom(
90 this.toXppDom(config, "configuration"),
91 this.toXppDom(descriptor.getMojoConfiguration())
92 )
93 );
94 final Mojo mojo = this.mojo(execution);
95 try {
96 Logger.info(this, "Calling %s:%s...", coords, goal);
97 mojo.execute();
98 } catch (final MojoExecutionException ex) {
99 throw new IllegalArgumentException(ex);
100 } catch (final MojoFailureException ex) {
101 throw new ValidationException(ex);
102 } finally {
103 this.manager.releaseMojo(mojo, execution);
104 }
105 }
106
107
108
109
110
111
112
113
114 Xpp3Dom toXppDom(final Properties config, final String name) {
115 final Xpp3Dom xpp = new Xpp3Dom(name);
116 for (final Map.Entry<?, ?> entry : config.entrySet()) {
117 xpp.addChild(
118 this.toNode(entry.getKey().toString(), entry.getValue())
119 );
120 }
121 return xpp;
122 }
123
124
125
126
127
128
129
130 private MojoDescriptor descriptor(final Plugin plugin, final String goal) {
131 try {
132 return new DefaultMavenPluginManagerHelper(this.manager)
133 .getPluginDescriptor(plugin, this.session)
134 .getMojo(goal);
135 } catch (final PluginResolutionException ex) {
136 throw new IllegalStateException("Can't resolve plugin", ex);
137 } catch (final PluginDescriptorParsingException ex) {
138 throw new IllegalStateException("Can't parse descriptor", ex);
139 } catch (final InvalidPluginDescriptorException ex) {
140 throw new IllegalStateException("Invalid plugin descriptor", ex);
141 }
142 }
143
144
145
146
147
148
149 private Mojo mojo(final MojoExecution execution) {
150 final Mojo mojo;
151 try {
152 mojo = this.manager.getConfiguredMojo(
153 Mojo.class, this.session, execution
154 );
155 } catch (final PluginConfigurationException ex) {
156 throw new IllegalStateException("Can't configure MOJO", ex);
157 } catch (final PluginContainerException ex) {
158 throw new IllegalStateException("Plugin container failure", ex);
159 }
160 return mojo;
161 }
162
163
164
165
166
167
168
169 private Xpp3Dom toNode(final String name, final Object value) {
170 final Xpp3Dom node;
171 if (value instanceof String) {
172 node = new Xpp3Dom(name);
173 node.setValue(String.class.cast(value));
174 } else if (value instanceof String[]) {
175 node = new Xpp3Dom(name);
176 for (final String val : String[].class.cast(value)) {
177 final Xpp3Dom row = new Xpp3Dom(name);
178 row.setValue(val);
179 node.addChild(row);
180 }
181 } else if (value instanceof Collection) {
182 node = new Xpp3Dom(name);
183 for (final Object item : Collection.class.cast(value)) {
184 this.appendItem(node, name, item);
185 }
186 } else if (value instanceof Properties) {
187 node = this.toXppDom(Properties.class.cast(value), name);
188 } else {
189 throw new IllegalArgumentException(
190 String.format("Invalid properties value at '%s'", name)
191 );
192 }
193 return node;
194 }
195
196
197
198
199
200
201
202 private void appendItem(
203 final Xpp3Dom parent, final String name, final Object item
204 ) {
205 if (item instanceof Properties) {
206 final Xpp3Dom converted = this.toXppDom(
207 Properties.class.cast(item), name
208 );
209 final int count = converted.getChildCount();
210 for (int idx = 0; idx < count; idx += 1) {
211 parent.addChild(converted.getChild(idx));
212 }
213 } else if (item != null) {
214 parent.addChild(this.toNode(name, item));
215 }
216 }
217
218
219
220
221
222
223
224 private Xpp3Dom toXppDom(final PlexusConfiguration config) {
225 final Xpp3Dom result = new Xpp3Dom(config.getName());
226 result.setValue(config.getValue(null));
227 for (final String name : config.getAttributeNames()) {
228 try {
229 result.setAttribute(name, config.getAttribute(name));
230 } catch (final PlexusConfigurationException ex) {
231 throw new IllegalArgumentException(ex);
232 }
233 }
234 for (final PlexusConfiguration child : config.getChildren()) {
235 result.addChild(this.toXppDom(child));
236 }
237 return result;
238 }
239 }