File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\maven-plugin\src\main\java\hudson\maven\AbstractMavenBuilder.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Olivier Lamy
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 package hudson.maven;
25
26 import hudson.Launcher;
27 import hudson.maven.MavenBuild.ProxyImpl2;
28 import hudson.model.BuildListener;
29 import hudson.model.Executor;
30 import hudson.model.Result;
31 import hudson.remoting.Channel;
32 import hudson.remoting.DelegatingCallable;
33 import hudson.remoting.Future;
34
35 import java.io.IOException;
36 import java.io.Serializable;
37 import java.text.NumberFormat;
38 import java.util.Collection;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.concurrent.CopyOnWriteArrayList;
43 import java.util.concurrent.ExecutionException;
44
45 import jenkins.model.Jenkins;
46
47 /**
48 * @author Olivier Lamy
49 * @author Christoph Kutzinski
50 *
51 */
52 public abstract class AbstractMavenBuilder implements DelegatingCallable<Result,IOException> {
53
54 private static final long serialVersionUID = -2687215937784908860L;
55 /**
56 * Goals to be executed in this Maven execution.
57 */
58 protected final List<String> goals;
59 /**
60 * Hudson-defined system properties. These will be made available to Maven,
61 * and accessible as if they are specified as -Dkey=value
62 */
63 protected final Map<String,String> systemProps;
64 /**
65 * Where error messages and so on are sent.
66 */
67 protected final BuildListener listener;
68
69 protected Map<ModuleName,FilterImpl> proxies;
70
71 /**
72 * Kept so that we can finalize them in the end method.
73 */
74 protected final transient Map<ModuleName,ProxyImpl2> sourceProxies = new HashMap<ModuleName, MavenBuild.ProxyImpl2>();
75
76 protected final Map<ModuleName,List<MavenReporter>> reporters = new HashMap<ModuleName,List<MavenReporter>>();
77
78 /**
79 * Record all asynchronous executions as they are scheduled,
80 * to make sure they are all completed before we finish.
81 */
82 protected transient /*final*/ List<Future<?>> futures;
83
84 protected AbstractMavenBuilder(BuildListener listener, Collection<MavenModule> modules, List<String> goals, Map<String, String> systemProps) {
85 this.listener = listener;
86 this.goals = goals;
87 this.systemProps = systemProps;
88
89 for (MavenModule m : modules) {
90 reporters.put(m.getModuleName(),m.createReporters());
91 }
92 }
93
94 /**
95 * Invoked after the maven has finished running, and in the master, not in the maven process.
96 */
97 void end(Launcher launcher) throws IOException, InterruptedException {
98 for (Map.Entry<ModuleName,ProxyImpl2> e : sourceProxies.entrySet()) {
99 ProxyImpl2 p = e.getValue();
100 for (MavenReporter r : reporters.get(e.getKey())) {
101 // we'd love to do this when the module build ends, but doing so requires
102 // we know how many task segments are in the current build.
103 r.end(p.owner(),launcher,listener);
104 p.appendLastLog();
105 }
106 p.close();
107 }
108 }
109
110 protected String formatArgs(List<String> args) {
111 StringBuilder buf = new StringBuilder("Executing Maven: ");
112 for (String arg : args) {
113 final String argPassword = "-Dpassword=" ;
114 String filteredArg = arg ;
115 // check if current arg is password arg. Then replace password by *****
116 if (arg.startsWith(argPassword)) {
117 filteredArg=argPassword+"*********";
118 }
119 buf.append(' ').append(filteredArg);
120 }
121 return buf.toString();
122 }
123
124 /**
125 * Add all the {@link #systemProps jenkins environment variables} into the {@link System#getProperties() system properties}
126 * Ignores {@link #systemProps jenkins environment variables} with empty keys.
127 * @throws IllegalArgumentException if a {@link #systemProps jenkins environment variable} has null value
128 * as it blows up Maven.
129 * @see http://jenkins.361315.n4.nabble.com/Upgrade-to-1-424-broke-our-Maven-builds-due-to-empty-system-property-key-td3726460.html
130 */
131 protected void registerSystemProperties() {
132 for (Map.Entry<String,String> e : systemProps.entrySet()) {
133 if ("".equals(e.getKey()))
134 continue;
135 if (e.getValue()==null)
136 throw new IllegalArgumentException("Global Environment Variable "+e.getKey()+" has a null value");
137 System.getProperties().put(e.getKey(), e.getValue());
138 }
139 }
140
141 protected String format(NumberFormat n, long nanoTime) {
142 return n.format(nanoTime/1000000);
143 }
144
145 // since reporters might be from plugins, use the uberjar to resolve them.
146 public ClassLoader getClassLoader() {
147 return Jenkins.getInstance().getPluginManager().uberClassLoader;
148 }
149
150 /**
151 * Initialize the collection of the asynchronous executions.
152 * The method must be called in the Maven jail process i.e. inside the call method!
153 */
154 protected void initializeAsynchronousExecutions() {
155 futures = new CopyOnWriteArrayList<Future<?>>();
156 if (this.proxies != null) {
157 for(FilterImpl proxy : this.proxies.values()) {
158 proxy.setFutures(futures);
159 }
160 }
161 }
162
163 /**
164 * Records a new asynchronous exection.
165 */
166 protected void recordAsynchronousExecution(Future<?> future) {
167 futures.add(future);
168 }
169
170 /**
171 * Waits until all asynchronous executions are finished.
172 *
173 * @return null in success case; returns an ABORT result if we were interrupted while waiting
174 */
175 protected Result waitForAsynchronousExecutions() {
176 try {
177 boolean messageReported = false;
178
179 for (Future<?> f : futures) {
180 try {
181 if(!messageReported && !f.isDone()) {
182 messageReported = true;
183 listener.getLogger().println(Messages.MavenBuilder_Waiting());
184 }
185 f.get();
186 } catch (InterruptedException e) {
187 // attempt to cancel all asynchronous tasks
188 for (Future<?> g : futures)
189 g.cancel(true);
190 listener.getLogger().println(Messages.MavenBuilder_Aborted());
191 return Executor.currentExecutor().abortResult();
192 } catch (ExecutionException e) {
193 e.printStackTrace(listener.error(Messages.MavenBuilder_AsyncFailed()));
194 }
195 }
196 return null;
197 } finally {
198 futures.clear();
199 }
200 }
201
202 protected boolean isDebug() {
203 for(String goal : goals) {
204 if (goal.equals("-X") || goal.equals("--debug")) return true;
205 }
206 return false;
207 }
208
209 protected boolean isQuiet() {
210 for(String goal : goals) {
211 if (goal.equals("-q") || goal.equals("--quiet")) return true;
212 }
213 return false;
214 }
215
216 protected static class FilterImpl extends MavenBuildProxy2.Filter<MavenBuildProxy2> implements Serializable {
217
218 private MavenBuildInformation mavenBuildInformation;
219
220 /**
221 * Maven can internally use multiple threads to call {@link #executeAsync(BuildCallable)},
222 * making it impossible to rely on {@code Channel#current()} at the point of call, so
223 * instead we capture it when we get deserialized into Maven JVM.
224 * In other cases, we create FilterImpl inside Maven JVM, so we take it as a constructor.
225 * See JENKINS-11458
226 */
227 private transient Channel channel;
228
229 private transient List<Future<?>> futures;
230
231 public FilterImpl(MavenBuildProxy2 core, MavenBuildInformation mavenBuildInformation) {
232 super(core);
233 this.mavenBuildInformation = mavenBuildInformation;
234 }
235
236 public FilterImpl(MavenBuildProxy2 core, MavenBuildInformation mavenBuildInformation, Channel channel) {
237 super(core);
238 this.mavenBuildInformation = mavenBuildInformation;
239 if (channel == null) {
240 throw new NullPointerException("channel must not be null!");
241 }
242 this.channel = channel;
243 }
244
245 @Override
246 public void executeAsync(final BuildCallable<?,?> program) throws IOException {
247 futures.add(
248 channel.callAsync(
249 new AsyncInvoker(core,program)));
250 }
251
252 public MavenBuildInformation getMavenBuildInformation() {
253 return mavenBuildInformation;
254 }
255
256 public void setFutures(List<Future<?>> futures) {
257 this.futures = futures;
258 }
259
260 public Object readResolve() {
261 channel = Channel.current();
262 return this;
263 }
264
265 private static final long serialVersionUID = 1L;
266 }
267
268 }
269