1 package org.apache.maven.it;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.PrintStream;
28 import java.lang.reflect.Constructor;
29 import java.lang.reflect.InvocationTargetException;
30 import java.lang.reflect.Method;
31 import java.net.MalformedURLException;
32 import java.net.URL;
33 import java.net.URLClassLoader;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.Properties;
37
38 import org.apache.maven.shared.utils.io.IOUtil;
39
40
41
42
43
44
45 class Embedded3xLauncher
46 implements MavenLauncher
47 {
48
49 private final Object mavenCli;
50
51 private final Method doMain;
52
53 private Embedded3xLauncher( Object mavenCli, Method doMain )
54 {
55 this.mavenCli = mavenCli;
56 this.doMain = doMain;
57 }
58
59
60
61
62 public static Embedded3xLauncher createFromMavenHome( String mavenHome, String classworldConf, List<URL> classpath )
63 throws LauncherException
64 {
65 if ( mavenHome == null || mavenHome.length() <= 0 )
66 {
67 throw new LauncherException( "Invalid Maven home directory " + mavenHome );
68 }
69
70 System.setProperty( "maven.home", mavenHome );
71
72 File config;
73 if ( classworldConf != null )
74 {
75 config = new File( classworldConf );
76 }
77 else
78 {
79 config = new File( mavenHome, "bin/m2.conf" );
80 }
81
82 ClassLoader bootLoader = getBootLoader( mavenHome, classpath );
83
84 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
85 Thread.currentThread().setContextClassLoader( bootLoader );
86 try
87 {
88 Class<?> launcherClass = bootLoader.loadClass( "org.codehaus.plexus.classworlds.launcher.Launcher" );
89
90 Object launcher = launcherClass.newInstance();
91
92 Method configure = launcherClass.getMethod( "configure", new Class[] { InputStream.class } );
93
94 configure.invoke( launcher, new Object[] { new FileInputStream( config ) } );
95
96 Method getWorld = launcherClass.getMethod( "getWorld", null );
97 Object classWorld = getWorld.invoke( launcher, null );
98
99 Method getMainClass = launcherClass.getMethod( "getMainClass", null );
100 Class<?> cliClass = (Class<?>) getMainClass.invoke( launcher, null );
101
102 Constructor<?> newMavenCli = cliClass.getConstructor( new Class[] { classWorld.getClass() } );
103 Object mavenCli = newMavenCli.newInstance( new Object[] { classWorld } );
104
105 Class<?>[] parameterTypes = { String[].class, String.class, PrintStream.class, PrintStream.class };
106 Method doMain = cliClass.getMethod( "doMain", parameterTypes );
107
108 return new Embedded3xLauncher( mavenCli, doMain );
109 }
110 catch ( ClassNotFoundException e )
111 {
112 throw new LauncherException( "Invalid Maven home directory " + mavenHome, e );
113 }
114 catch ( InstantiationException e )
115 {
116 throw new LauncherException( "Invalid Maven home directory " + mavenHome, e );
117 }
118 catch ( IllegalAccessException e )
119 {
120 throw new LauncherException( "Invalid Maven home directory " + mavenHome, e );
121 }
122 catch ( NoSuchMethodException e )
123 {
124 throw new LauncherException( "Invalid Maven home directory " + mavenHome, e );
125 }
126 catch ( InvocationTargetException e )
127 {
128 throw new LauncherException( "Invalid Maven home directory " + mavenHome, e );
129 }
130 catch ( IOException e )
131 {
132 throw new LauncherException( "Invalid Maven home directory " + mavenHome, e );
133 }
134 finally
135 {
136 Thread.currentThread().setContextClassLoader( oldClassLoader );
137 }
138 }
139
140
141
142
143
144 public static Embedded3xLauncher createFromClasspath()
145 throws LauncherException
146 {
147 ClassLoader coreLoader = Thread.currentThread().getContextClassLoader();
148
149 try
150 {
151 Class<?> cliClass = coreLoader.loadClass( "org.apache.maven.cli.MavenCli" );
152
153 Object mavenCli = cliClass.newInstance();
154
155 Class<?>[] parameterTypes = { String[].class, String.class, PrintStream.class, PrintStream.class };
156 Method doMain = cliClass.getMethod( "doMain", parameterTypes );
157
158 return new Embedded3xLauncher( mavenCli, doMain );
159 }
160 catch ( ClassNotFoundException e )
161 {
162 throw new LauncherException( e.getMessage(), e );
163 }
164 catch ( NoSuchMethodException e )
165 {
166 throw new LauncherException( e.getMessage(), e );
167 }
168 catch ( InstantiationException e )
169 {
170 throw new LauncherException( e.getMessage(), e );
171 }
172 catch ( IllegalAccessException e )
173 {
174 throw new LauncherException( e.getMessage(), e );
175 }
176 }
177
178 private static ClassLoader getBootLoader( String mavenHome, List<URL> classpath )
179 {
180 List<URL> urls = classpath;
181
182 if ( urls == null )
183 {
184 urls = new ArrayList<URL>();
185
186 File bootDir = new File( mavenHome, "boot" );
187 addUrls( urls, bootDir );
188 }
189
190 if ( urls.isEmpty() )
191 {
192 throw new IllegalArgumentException( "Invalid Maven home directory " + mavenHome );
193 }
194
195 URL[] ucp = (URL[]) urls.toArray( new URL[urls.size()] );
196
197 return new URLClassLoader( ucp, ClassLoader.getSystemClassLoader().getParent() );
198 }
199
200 private static void addUrls( List<URL> urls, File directory )
201 {
202 File[] jars = directory.listFiles();
203
204 if ( jars != null )
205 {
206 for ( int i = 0; i < jars.length; i++ )
207 {
208 File jar = jars[i];
209
210 if ( jar.getName().endsWith( ".jar" ) )
211 {
212 try
213 {
214 urls.add( jar.toURI().toURL() );
215 }
216 catch ( MalformedURLException e )
217 {
218 throw (RuntimeException) new IllegalStateException().initCause( e );
219 }
220 }
221 }
222 }
223 }
224
225 public int run( String[] cliArgs, String workingDirectory, File logFile )
226 throws IOException, LauncherException
227 {
228 PrintStream out = ( logFile != null ) ? new PrintStream( new FileOutputStream( logFile ) ) : System.out;
229 try
230 {
231 Properties originalProperties = System.getProperties();
232 System.setProperties( null );
233 System.setProperty( "maven.home", originalProperties.getProperty( "maven.home", "" ) );
234 System.setProperty( "user.dir", new File( workingDirectory ).getAbsolutePath() );
235
236 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
237 Thread.currentThread().setContextClassLoader( mavenCli.getClass().getClassLoader() );
238 try
239 {
240 Object result = doMain.invoke( mavenCli, new Object[] { cliArgs, workingDirectory, out, out } );
241
242 return ( (Number) result ).intValue();
243 }
244 finally
245 {
246 Thread.currentThread().setContextClassLoader( originalClassLoader );
247
248 System.setProperties( originalProperties );
249 }
250 }
251 catch ( IllegalAccessException e )
252 {
253 throw new LauncherException( "Failed to run Maven: " + e.getMessage(), e );
254 }
255 catch ( InvocationTargetException e )
256 {
257 throw new LauncherException( "Failed to run Maven: " + e.getMessage(), e );
258 }
259 finally
260 {
261 if ( logFile != null )
262 {
263 out.close();
264 }
265 }
266 }
267
268 public String getMavenVersion()
269 throws LauncherException
270 {
271 Properties props = new Properties();
272
273 InputStream is =
274 mavenCli.getClass().getResourceAsStream( "/META-INF/maven/org.apache.maven/maven-core/pom.properties" );
275 if ( is != null )
276 {
277 try
278 {
279 props.load( is );
280 }
281 catch ( IOException e )
282 {
283 throw new LauncherException( "Failed to read Maven version", e );
284 }
285 finally
286 {
287 IOUtil.close( is );
288 }
289 }
290
291 String version = props.getProperty( "version" );
292 if ( version != null )
293 {
294 return version;
295 }
296
297 throw new LauncherException( "Could not determine embedded Maven version" );
298 }
299
300 }