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", (Class<?>) null );
97 Object classWorld = getWorld.invoke( launcher, (Class<?>) null );
98
99 Method getMainClass = launcherClass.getMethod( "getMainClass", (Class<?>) null );
100 Class<?> cliClass = (Class<?>) getMainClass.invoke( launcher, (Class<?>) 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 ( ReflectiveOperationException | IOException e )
111 {
112 throw new LauncherException( "Invalid Maven home directory " + mavenHome, e );
113 }
114 finally
115 {
116 Thread.currentThread().setContextClassLoader( oldClassLoader );
117 }
118 }
119
120
121
122
123
124 public static Embedded3xLauncher createFromClasspath()
125 throws LauncherException
126 {
127 ClassLoader coreLoader = Thread.currentThread().getContextClassLoader();
128
129 try
130 {
131 Class<?> cliClass = coreLoader.loadClass( "org.apache.maven.cli.MavenCli" );
132
133 Object mavenCli = cliClass.newInstance();
134
135 Class<?>[] parameterTypes = { String[].class, String.class, PrintStream.class, PrintStream.class };
136 Method doMain = cliClass.getMethod( "doMain", parameterTypes );
137
138 return new Embedded3xLauncher( mavenCli, doMain );
139 }
140 catch ( ReflectiveOperationException e )
141 {
142 throw new LauncherException( e.getMessage(), e );
143 }
144 }
145
146 private static ClassLoader getBootLoader( String mavenHome, List<URL> classpath )
147 {
148 List<URL> urls = classpath;
149
150 if ( urls == null )
151 {
152 urls = new ArrayList<URL>();
153
154 File bootDir = new File( mavenHome, "boot" );
155 addUrls( urls, bootDir );
156 }
157
158 if ( urls.isEmpty() )
159 {
160 throw new IllegalArgumentException( "Invalid Maven home directory " + mavenHome );
161 }
162
163 URL[] ucp = (URL[]) urls.toArray( new URL[urls.size()] );
164
165 return new URLClassLoader( ucp, ClassLoader.getSystemClassLoader().getParent() );
166 }
167
168 private static void addUrls( List<URL> urls, File directory )
169 {
170 File[] jars = directory.listFiles();
171
172 if ( jars != null )
173 {
174 for ( int i = 0; i < jars.length; i++ )
175 {
176 File jar = jars[i];
177
178 if ( jar.getName().endsWith( ".jar" ) )
179 {
180 try
181 {
182 urls.add( jar.toURI().toURL() );
183 }
184 catch ( MalformedURLException e )
185 {
186 throw (RuntimeException) new IllegalStateException().initCause( e );
187 }
188 }
189 }
190 }
191 }
192
193 public int run( String[] cliArgs, Properties systemProperties, String workingDirectory, File logFile )
194 throws IOException, LauncherException
195 {
196 PrintStream out = ( logFile != null ) ? new PrintStream( new FileOutputStream( logFile ) ) : System.out;
197 try
198 {
199 Properties originalProperties = System.getProperties();
200 System.setProperties( null );
201 System.setProperty( "maven.home", originalProperties.getProperty( "maven.home", "" ) );
202 System.setProperty( "user.dir", new File( workingDirectory ).getAbsolutePath() );
203
204 for ( Object o : systemProperties.keySet() )
205 {
206 String key = (String) o;
207 String value = systemProperties.getProperty( key );
208 System.setProperty( key, value );
209 }
210
211 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
212 Thread.currentThread().setContextClassLoader( mavenCli.getClass().getClassLoader() );
213 try
214 {
215 Object result = doMain.invoke( mavenCli, new Object[] { cliArgs, workingDirectory, out, out } );
216
217 return ( (Number) result ).intValue();
218 }
219 finally
220 {
221 Thread.currentThread().setContextClassLoader( originalClassLoader );
222
223 System.setProperties( originalProperties );
224 }
225 }
226 catch ( IllegalAccessException | InvocationTargetException e )
227 {
228 throw new LauncherException( "Failed to run Maven: " + e.getMessage(), e );
229 }
230 finally
231 {
232 if ( logFile != null )
233 {
234 out.close();
235 }
236 }
237 }
238
239 public String getMavenVersion()
240 throws LauncherException
241 {
242 Properties props = new Properties();
243
244 InputStream is =
245 mavenCli.getClass().getResourceAsStream( "/META-INF/maven/org.apache.maven/maven-core/pom.properties" );
246 if ( is != null )
247 {
248 try
249 {
250 props.load( is );
251 }
252 catch ( IOException e )
253 {
254 throw new LauncherException( "Failed to read Maven version", e );
255 }
256 finally
257 {
258 IOUtil.close( is );
259 }
260 }
261
262 String version = props.getProperty( "version" );
263 if ( version != null )
264 {
265 return version;
266 }
267
268 throw new LauncherException( "Could not determine embedded Maven version" );
269 }
270
271 }