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

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
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.AbortException;
27 import hudson.FilePath;
28 import hudson.Util;
29 import hudson.model.AbstractBuild;
30 import hudson.model.AbstractProject;
31 import hudson.model.BuildListener;
32 import jenkins.model.Jenkins;
33 import jenkins.mvn.SettingsProvider;
34 import hudson.model.TaskListener;
35 import hudson.tasks.Maven.MavenInstallation;
36 import hudson.tasks.Maven.ProjectWithMaven;
37
38 import java.io.BufferedReader;
39 import java.io.File;
40 import java.io.IOException;
41 import java.io.InputStreamReader;
42 import java.net.URL;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Enumeration;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Properties;
49 import java.util.logging.Logger;
50
51 import org.apache.commons.io.IOUtils;
52 import org.apache.commons.lang.StringUtils;
53 import org.apache.maven.artifact.versioning.ComparableVersion;
54 import org.apache.maven.project.MavenProject;
55 import org.apache.maven.project.ProjectBuildingException;
56
57 import edu.umd.cs.findbugs.annotations.SuppressWarnings;
58
59 /**
60 * @author Kohsuke Kawaguchi
61 */
62 public class MavenUtil {
63 /**
64 * @deprecated
65 * Use {@link #createEmbedder(TaskListener, File, String, Properties)}
66 * or other overloaded versions that infers maven home.
67 */
68 public static MavenEmbedder createEmbedder(TaskListener listener, String profiles) throws MavenEmbedderException, IOException {
69 return createEmbedder(listener,(File)null,profiles);
70 }
71
72 /**
73 * This version tries to infer mavenHome by looking at a project.
74 *
75 * @see #createEmbedder(TaskListener, File, String)
76 */
77 public static MavenEmbedder createEmbedder(TaskListener listener, AbstractProject<?,?> project, String profiles) throws MavenEmbedderException, IOException, InterruptedException {
78 MavenInstallation m=null;
79 if (project instanceof ProjectWithMaven)
80 m = ((ProjectWithMaven) project).inferMavenInstallation().forNode(Jenkins.getInstance(),listener);
81
82 return createEmbedder(listener,m!=null?m.getHomeDir():null,profiles);
83 }
84
85 /**
86 * This version tries to infer mavenHome and other options by looking at a build.
87 *
88 * @see #createEmbedder(TaskListener, File, String)
89 */
90 public static MavenEmbedder createEmbedder(TaskListener listener, AbstractBuild<?,?> build) throws MavenEmbedderException, IOException, InterruptedException {
91 MavenInstallation m=null;
92 File settingsLoc = null;
93 String profiles = null;
94 Properties systemProperties = null;
95 String privateRepository = null;
96
97 AbstractProject<?,?> project = build.getProject();
98
99 if (project instanceof ProjectWithMaven) {
100 m = ((ProjectWithMaven) project).inferMavenInstallation().forNode(Jenkins.getInstance(),listener);
101 }
102 if (project instanceof MavenModuleSet) {
103 String altSet = SettingsProvider.getSettingsRemotePath(((MavenModuleSet) project).getSettings(), build, listener);
104
105 settingsLoc = (altSet == null) ? null
106 : new File(build.getWorkspace().child(altSet).getRemote());
107
108 FilePath localRepo = ((MavenModuleSet) project).getLocalRepository().locate((MavenModuleSetBuild) build);
109 if (localRepo!=null) {
110 privateRepository = localRepo.getRemote();
111 }
112
113 profiles = ((MavenModuleSet) project).getProfiles();
114 systemProperties = ((MavenModuleSet) project).getMavenProperties();
115 }
116
117 return createEmbedder(new MavenEmbedderRequest(listener,
118 m!=null?m.getHomeDir():null,
119 profiles,
120 systemProperties,
121 privateRepository,
122 settingsLoc ));
123 }
124
125 public static MavenEmbedder createEmbedder(TaskListener listener, File mavenHome, String profiles) throws MavenEmbedderException, IOException {
126 return createEmbedder(listener,mavenHome,profiles,new Properties());
127 }
128
129 public static MavenEmbedder createEmbedder(TaskListener listener, File mavenHome, String profiles, Properties systemProperties) throws MavenEmbedderException, IOException {
130 return createEmbedder(listener,mavenHome,profiles,systemProperties,null);
131 }
132
133 public static MavenEmbedder createEmbedder( TaskListener listener, File mavenHome, String profiles,
134 Properties systemProperties, String privateRepository )
135 throws MavenEmbedderException, IOException
136 {
137 return createEmbedder( new MavenEmbedderRequest( listener, mavenHome, profiles, systemProperties,
138 privateRepository, null ) );
139 }
140
141 /**
142 * Creates a fresh {@link MavenEmbedder} instance.
143 *
144 */
145 @SuppressWarnings("RV_RETURN_VALUE_IGNORED_BAD_PRACTICE")
146 public static MavenEmbedder createEmbedder(MavenEmbedderRequest mavenEmbedderRequest) throws MavenEmbedderException, IOException {
147
148
149 MavenRequest mavenRequest = new MavenRequest();
150
151 // make sure ~/.m2 exists to avoid http://www.nabble.com/BUG-Report-tf3401736.html
152 File m2Home = new File(MavenEmbedder.userHome, ".m2");
153 m2Home.mkdirs();
154 if(!m2Home.exists())
155 throw new AbortException("Failed to create "+m2Home);
156
157 if (mavenEmbedderRequest.getPrivateRepository()!=null)
158 mavenRequest.setLocalRepositoryPath( mavenEmbedderRequest.getPrivateRepository() );
159
160 if (mavenEmbedderRequest.getProfiles() != null) {
161 mavenRequest.setProfiles(Arrays.asList( StringUtils.split( mavenEmbedderRequest.getProfiles(), "," ) ));
162 }
163
164
165 if ( mavenEmbedderRequest.getAlternateSettings() != null ) {
166 mavenRequest.setUserSettingsFile( mavenEmbedderRequest.getAlternateSettings().getAbsolutePath() );
167 } else {
168 mavenRequest.setUserSettingsFile( new File( m2Home, "settings.xml" ).getAbsolutePath() );
169 }
170
171 if ( mavenEmbedderRequest.getGlobalSettings() != null) {
172 mavenRequest.setGlobalSettingsFile( mavenEmbedderRequest.getGlobalSettings().getAbsolutePath() );
173 } else {
174 mavenRequest.setGlobalSettingsFile( new File( mavenEmbedderRequest.getMavenHome(), "conf/settings.xml" ).getAbsolutePath() );
175 }
176
177 if (mavenEmbedderRequest.getWorkspaceReader() != null ) {
178 mavenRequest.setWorkspaceReader( mavenEmbedderRequest.getWorkspaceReader() );
179 }
180
181 mavenRequest.setUpdateSnapshots(mavenEmbedderRequest.isUpdateSnapshots());
182
183 // TODO olamy check this sould be userProperties
184 mavenRequest.setSystemProperties(mavenEmbedderRequest.getSystemProperties());
185
186 if (mavenEmbedderRequest.getTransferListener() != null) {
187 if (debugMavenEmbedder) {
188 mavenEmbedderRequest.getListener().getLogger()
189 .println( "use transfertListener " + mavenEmbedderRequest.getTransferListener().getClass().getName() );
190 }
191 mavenRequest.setTransferListener( mavenEmbedderRequest.getTransferListener() );
192 }
193 EmbedderLoggerImpl logger =
194 new EmbedderLoggerImpl( mavenEmbedderRequest.getListener(), debugMavenEmbedder ? org.codehaus.plexus.logging.Logger.LEVEL_DEBUG
195 : org.codehaus.plexus.logging.Logger.LEVEL_INFO );
196 mavenRequest.setMavenLoggerManager( logger );
197
198 ClassLoader mavenEmbedderClassLoader =
199 mavenEmbedderRequest.getClassLoader() == null ? new MaskingClassLoader( MavenUtil.class.getClassLoader() )
200 : mavenEmbedderRequest.getClassLoader();
201
202 {// are we loading the right components.xml? (and not from Maven that's running Jetty, if we are running in "mvn hudson-dev:run" or "mvn hpi:run"?
203 Enumeration<URL> e = mavenEmbedderClassLoader.getResources("META-INF/plexus/components.xml");
204 while (e.hasMoreElements()) {
205 URL url = e.nextElement();
206 LOGGER.fine("components.xml from "+url);
207 }
208 }
209
210 mavenRequest.setProcessPlugins( mavenEmbedderRequest.isProcessPlugins() );
211 mavenRequest.setResolveDependencies( mavenEmbedderRequest.isResolveDependencies() );
212 mavenRequest.setValidationLevel( mavenEmbedderRequest.getValidationLevel() );
213
214 // TODO check this MaskingClassLoader with maven 3 artifacts
215 MavenEmbedder maven = new MavenEmbedder( mavenEmbedderClassLoader, mavenRequest );
216
217 return maven;
218 }
219
220
221 /**
222 * @deprecated MavenEmbedder has now a method to read all projects
223 * Recursively resolves module POMs that are referenced from
224 * the given {@link MavenProject} and parses them into
225 * {@link MavenProject}s.
226 *
227 * @param rel
228 * Used to compute the relative path. Pass in "" to begin.
229 * @param relativePathInfo
230 * Upon the completion of this method, this variable stores the relative path
231 * from the root directory of the given {@link MavenProject} to the root directory
232 * of each of the newly parsed {@link MavenProject}.
233 *
234 * @throws AbortException
235 * errors will be reported to the listener and the exception thrown.
236 * @throws MavenEmbedderException
237 */
238 public static void resolveModules( MavenEmbedder embedder, MavenProject project, String rel,
239 Map<MavenProject, String> relativePathInfo, BuildListener listener,
240 boolean nonRecursive )
241 throws ProjectBuildingException, AbortException, MavenEmbedderException
242 {
243
244 File basedir = project.getFile().getParentFile();
245 relativePathInfo.put( project, rel );
246
247 List<MavenProject> modules = new ArrayList<MavenProject>();
248
249 if ( !nonRecursive ) {
250 for ( String modulePath : project.getModules()) {
251 if ( Util.fixEmptyAndTrim( modulePath ) != null ) {
252 File moduleFile = new File( basedir, modulePath );
253 if ( moduleFile.exists() && moduleFile.isDirectory() ) {
254 moduleFile = new File( basedir, modulePath + "/pom.xml" );
255 }
256 if ( !moduleFile.exists() )
257 throw new AbortException( moduleFile + " is referenced from " + project.getFile()
258 + " but it doesn't exist" );
259
260 String relativePath = rel;
261 if ( relativePath.length() > 0 )
262 relativePath += '/';
263 relativePath += modulePath;
264
265 MavenProject child = embedder.readProject( moduleFile );
266 resolveModules( embedder, child, relativePath, relativePathInfo, listener, nonRecursive );
267 modules.add( child );
268 }
269 }
270 }
271
272 project.setCollectedProjects( modules );
273 }
274
275 /**
276 * When we run in Jetty during development, embedded Maven will end up
277 * seeing some of the Maven class visible through Jetty, and this confuses it.
278 *
279 * <p>
280 * Specifically, embedded Maven will find all the component descriptors
281 * visible through Jetty, yet when it comes to loading classes, classworlds
282 * still load classes from local realms created inside embedder.
283 *
284 * <p>
285 * This classloader prevents this issue by hiding the component descriptor
286 * visible through Jetty.
287 */
288 private static final class MaskingClassLoader extends ClassLoader {
289
290 public MaskingClassLoader(ClassLoader parent) {
291 super(parent);
292 }
293
294 public Enumeration<URL> getResources(String name) throws IOException {
295 final Enumeration<URL> e = super.getResources(name);
296 return new Enumeration<URL>() {
297 URL next;
298
299 public boolean hasMoreElements() {
300 fetch();
301 return next!=null;
302 }
303
304 public URL nextElement() {
305 fetch();
306 URL r = next;
307 next = null;
308 return r;
309 }
310
311 private void fetch() {
312 while(next==null && e.hasMoreElements()) {
313 next = e.nextElement();
314 if(shouldBeIgnored(next))
315 next = null;
316 }
317 }
318
319 private boolean shouldBeIgnored(URL url) {
320 String s = url.toExternalForm();
321 if(s.contains("maven-plugin-tools-api"))
322 return true;
323 // because RemoteClassLoader mangles the path, we can't check for plexus/components.xml,
324 // which would have otherwise made the test cheaper.
325 if(s.endsWith("components.xml")) {
326 BufferedReader r=null;
327 try {
328 // is this designated for interception purpose? If so, don't load them in the MavenEmbedder
329 // earlier I tried to use a marker file in the same directory, but that won't work
330 r = new BufferedReader(new InputStreamReader(url.openStream()));
331 for (int i=0; i<2; i++) {
332 String l = r.readLine();
333 if(l!=null && l.contains("MAVEN-INTERCEPTION-TO-BE-MASKED"))
334 return true;
335 }
336 } catch (IOException _) {
337 // let whoever requesting this resource re-discover an error and report it
338 } finally {
339 IOUtils.closeQuietly(r);
340 }
341 }
342 return false;
343 }
344 };
345 }
346 }
347
348 public static boolean maven3orLater(String mavenVersion) {
349 // null or empty so false !
350 if (StringUtils.isBlank( mavenVersion )) {
351 return false;
352 }
353 return new ComparableVersion (mavenVersion).compareTo( new ComparableVersion ("3.0") ) >= 0;
354 }
355
356
357 /**
358 * If set to true, maximize the logging level of Maven embedder.
359 */
360 public static boolean debugMavenEmbedder = Boolean.getBoolean( "debugMavenEmbedder" );
361
362 private static final Logger LOGGER = Logger.getLogger(MavenUtil.class.getName());
363 }
364