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