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