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