blob: dd3f11792fe773eae58b1701b392052639bda6e3 [file] [log] [blame]
Stuart McCullochd00f9712009-07-13 10:06:47 +00001package aQute.bnd.test;
2
3import java.io.*;
4import java.net.*;
5import java.util.*;
6import java.util.regex.*;
7
8import aQute.bnd.build.*;
9import aQute.lib.osgi.*;
10import aQute.libg.header.*;
11
12public class ProjectLauncher extends Processor {
13 final Project project;
14 static File runtime;
15 String report;
16
17 public ProjectLauncher(Project project) {
18 super(project);
19 this.project = project;
20 }
21
22 /**
23 * Calculate the classpath. We include our own runtime.jar which includes
24 * the test framework and we include the first of the test frameworks
25 * specified.
26 */
27 public String[] getClasspath() {
28 try {
29 List<String> classpath = new ArrayList<String>();
30 classpath.add(getRuntime().getAbsolutePath());
31
32 for (Container c : project.getRunpath()) {
33 if (c.getType() != Container.TYPE.ERROR) {
34 if (!c.getFile().getName().startsWith("ee."))
35 classpath.add(c.getFile().getAbsolutePath());
36 } else {
37 error("Invalid entry on the " + Constants.RUNPATH + ": "
38 + c);
39 }
40 }
41 return classpath.toArray(new String[classpath.size()]);
42 } catch (Exception e) {
43 error("Calculating class path", e);
44 }
45 return null;
46 }
47
48 /**
49 * Extract the runtime on the file system so we can refer to it. in the
50 * remote VM.
51 *
52 * @return
53 */
54 public static File getRuntime() {
55 if (runtime == null) {
56 try {
57 URL url = ProjectLauncher.class
58 .getResource("aQute.runtime.jar");
59 if (url == null)
60 throw new IllegalStateException(
61 "Can not find my runtime.jar");
62
63 runtime = File.createTempFile("aQute.runtime", ".jar");
64 // runtime.deleteOnExit();
65 FileOutputStream out = new FileOutputStream(runtime);
66 InputStream in = url.openStream();
67 copy(in, out);
68 out.close();
69 } catch (IOException e) {
70 e.printStackTrace();
71 }
72 }
73 return runtime;
74 }
75
76 public void doRunbundles(List<String> programArguments) throws Exception {
77 // we are going to use this for running, so we want to
78 // use the "best" version. For compile, we should
79 // use the lowest version.
80 Collection<Container> testbundles = project.getRunbundles();
81
82 for (Container c : testbundles) {
83 if (c.getError() != null)
84 error("Invalid bundle on " + Constants.RUNBUNDLES + " "
85 + c.getError());
86 else {
87 // Do we need to build any sub projects?
88 if (c.getVersion() != null && c.getVersion().equals("project")) {
89 Project sub = c.getProject();
90 sub.clear();
91 File[] outputs = sub.build(false);
92 for (File f : outputs) {
93 programArguments.add("-bundle");
94 programArguments.add(f.getAbsolutePath());
95 }
96 getInfo(sub);
97 } else {
98 programArguments.add("-bundle");
99 programArguments.add(c.getFile().getAbsolutePath());
100 }
101 }
102 }
103 }
104
105 private void doRunpath(List<String> programArguments) throws Exception {
106 Collection<Container> testpath = project.getRunpath();
107 Container found = null;
108 for (Container c : testpath) {
109 if (c.getAttributes().containsKey("framework")) {
110 if (found != null) {
111 warning("Specifying multiple framework classes on the "
112 + Constants.RUNPATH + "\n" + "Previous found: "
113 + found.getProject() + " " + found.getAttributes()
114 + "\n" + "Now found : " + c.getProject() + " "
115 + c.getAttributes());
116 }
117 programArguments.add("-framework");
118 programArguments.add(c.getAttributes().get("framework"));
119 found = c;
120 }
121 if (c.getAttributes().containsKey("factory")) {
122 if (found != null) {
123 warning("Specifying multiple framework factories on the "
124 + Constants.RUNPATH + "\n" + "Previous found: "
125 + found.getProject() + " " + found.getAttributes()
126 + "\n" + "Now found : " + c.getProject() + " "
127 + c.getAttributes());
128 }
129 programArguments.add("-framework");
130 programArguments.add(c.getAttributes().get("factory"));
131 found = c;
132 }
133 String exports = c.getAttributes().get("export");
134 if (exports != null) {
135 String parts[] = exports.split("\\s*,\\s*");
136 for (String p : parts) {
137 programArguments.add("-export");
138 programArguments.add(p);
139 }
140 }
141 }
142
143 doSystemPackages(programArguments);
144 doRunProperties(programArguments);
145 }
146
147 private void doRunProperties(List<String> programArguments) {
148 Map<String, String> properties = OSGiHeader
149 .parseProperties(getProperty(RUNPROPERTIES));
150 for (Map.Entry<String, String> entry : properties.entrySet()) {
151 programArguments.add("-set");
152 programArguments.add(entry.getKey());
153 programArguments.add(entry.getValue());
154 }
155 }
156
157 private void doSystemPackages(List<String> programArguments) {
158 Map<String, Map<String, String>> systemPackages = parseHeader(getProperty(RUNSYSTEMPACKAGES));
159 for (Map.Entry<String, Map<String, String>> entry : systemPackages
160 .entrySet()) {
161 programArguments.add("-export");
162 StringBuffer sb = new StringBuffer();
163 sb.append(entry.getKey());
164 printClause(entry.getValue(), null, sb);
165 programArguments.add(sb.toString());
166 }
167 }
168
169 private void doStorage(List<String> programArguments) throws Exception {
170 File tmp = new File(project.getTarget(), "fwtmp");
171 tmp.mkdirs();
172 tmp.deleteOnExit();
173
174 programArguments.add("-storage");
175 programArguments.add(tmp.getAbsolutePath());
176 }
177
178 /**
179 * Utility to copy a file from a resource.
180 *
181 * @param in
182 * @param out
183 * @throws IOException
184 */
185 private static void copy(InputStream in, FileOutputStream out)
186 throws IOException {
187 byte buf[] = new byte[8192];
188 int size = in.read(buf);
189 while (size > 0) {
190 out.write(buf, 0, size);
191 size = in.read(buf);
192 }
193 in.close();
194 }
195
196 private Process launch(File[] targets) throws Exception {
197 List<String> arguments = newList();
198 List<String> vmArguments = newList();
199
200 vmArguments.add(getProperty("java", "java"));
201 doClasspath(vmArguments);
202
203 getArguments(targets, vmArguments, arguments);
204
205 vmArguments.add("aQute.junit.runtime.Target");
206 arguments.add("-report");
207 arguments.add(getTestreport());
208
209 List<String> all = newList();
210 all.addAll(vmArguments);
211 all.addAll(arguments);
212
213 System.out.println("Cmd: " + all);
214
215 String[] cmdarray = all.toArray(new String[all.size()]);
216 if (getErrors().size() > 0)
217 return null;
218
219 return Runtime.getRuntime().exec(cmdarray, null, project.getBase());
220 }
221/*
222 static Pattern ARGUMENT = Pattern.compile("[-a-zA-Z0-9\\._]+");
223 private void doVMArguments(List<String> arguments) {
224 Map<String,String> map = OSGiHeader.parseProperties( getProperty(RUNVM));
225 for ( String key : map.keySet() ) {
226 if ( ARGUMENT.matcher(key).matches())
227 if ( key.startsWith("-"))
228 arguments.add(key);
229 else
230 arguments.add("-D" + key.trim() + "=" + map.get(key));
231 else
232 warning("VM Argument is not a proper property key: " + key );
233 }
234 }
235*/
236 private void doVMArguments(List<String> arguments) {
237 Map<String, String> map = OSGiHeader
238 .parseProperties(getProperty(RUNVM));
239 for (String key : map.keySet()) {
240 if (key.startsWith("-"))
241 arguments.add(key);
242 else
243 arguments.add("-D" + key.trim() + "=" + map.get(key));
244 }
245 }
246 private void doClasspath(List<String> arguments) {
247 Collection<String> cp = Arrays.asList(getClasspath());
248 if (!cp.isEmpty()) {
249 arguments.add("-classpath");
250 arguments.add(join(cp, File.pathSeparator));
251 }
252 }
253
254 public int run(File f) throws Exception {
255 final Process process = launch(new File[] { f });
256
257 Thread killer = new Thread() {
258 public void run() {
259 process.destroy();
260 }
261 };
262 Runtime.getRuntime().addShutdownHook(killer);
263 Streamer sin = new Streamer(process.getInputStream(), System.out);
264 Streamer serr = new Streamer(process.getErrorStream(), System.out);
265 try {
266 sin.start();
267 serr.start();
268 return process.waitFor();
269 } finally {
270 Runtime.getRuntime().removeShutdownHook(killer);
271 sin.join();
272 serr.join();
273 }
274 }
275
276 static class Streamer extends Thread {
277 final InputStream in;
278 final OutputStream out;
279
280 Streamer(InputStream in, OutputStream out) {
281 this.in = in;
282 this.out = out;
283 }
284
285 public void run() {
286 try {
287 int c;
288 while ((c = in.read()) > 0) {
289 this.out.write(c);
290 }
291 } catch (IOException ioe) {
292 // Ignore
293 }
294 };
295
296 };
297
298 public String getTestreport() {
299 if (report != null)
300 return report;
301 return report = getProperty(Constants.TESTREPORT,
302 "${target}/test-report.xml");
303
304 }
305
306 public void getArguments(List<String> vmArguments,
307 List<String> programArguments, boolean undertest) throws Exception {
308 File files[] = project.build(undertest);
309 getInfo(project);
310 if (files == null)
311 return;
312
313 getArguments(files, vmArguments, programArguments);
314 }
315
316 public void getArguments(File files[], List<String> vmArguments,
317 List<String> programArguments) throws Exception {
318 doVMArguments(vmArguments);
319 doStorage(programArguments);
320 doRunpath(programArguments);
321 doRunbundles(programArguments);
322 for (File file : files) {
323 programArguments.add("-target");
324 programArguments.add(file.getAbsolutePath());
325 }
326 }
327
328 public String getReport() {
329 return report;
330 }
331
332 public void setReport(String report) {
333 this.report = report;
334 }
335
336}