1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.launcher;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.io.PrintStream;
23 import java.net.URL;
24 import java.net.URLClassLoader;
25 import java.net.URLDecoder;
26 import java.util.ResourceBundle;
27
28 import org.apache.commons.launcher.types.ArgumentSet;
29 import org.apache.commons.launcher.types.JVMArgumentSet;
30 import org.apache.commons.launcher.types.SysPropertySet;
31 import org.apache.tools.ant.Main;
32 import org.apache.tools.ant.Project;
33 import org.apache.tools.ant.ProjectHelper;
34 import org.apache.tools.ant.taskdefs.Ant;
35 import org.apache.tools.ant.taskdefs.Available;
36 import org.apache.tools.ant.taskdefs.CallTarget;
37 import org.apache.tools.ant.taskdefs.ConditionTask;
38 import org.apache.tools.ant.taskdefs.ExecTask;
39 import org.apache.tools.ant.taskdefs.Exit;
40 import org.apache.tools.ant.taskdefs.Property;
41 import org.apache.tools.ant.taskdefs.Mkdir;
42 import org.apache.tools.ant.taskdefs.Copy;
43 import org.apache.tools.ant.taskdefs.Delete;
44 import org.apache.tools.ant.taskdefs.Taskdef;
45 import org.apache.tools.ant.taskdefs.WaitFor;
46 import org.apache.tools.ant.types.Description;
47 import org.apache.tools.ant.types.FileList;
48 import org.apache.tools.ant.types.FileSet;
49 import org.apache.tools.ant.types.Path;
50 import org.apache.tools.ant.types.PatternSet;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public class Launcher implements Runnable {
76
77
78
79
80
81
82
83 private static File bootstrapFile = null;
84
85
86
87
88 private static String javaCmd = null;
89
90
91
92
93 private static String jdbCmd = null;
94
95
96
97
98 private final static String DEFAULT_XML_FILE_NAME = "launcher.xml";
99
100
101
102
103 private static Object lock = new Object();
104
105
106
107
108 private static PrintStream log = System.err;
109
110
111
112
113 private static ResourceBundle resourceBundle = null;
114
115
116
117
118 private static boolean started = false;
119
120
121
122
123 private static boolean stopped = false;
124
125
126
127
128 public final static Object[] SUPPORTED_ANT_TASKS = new Object[] {
129 LaunchTask.TASK_NAME, LaunchTask.class,
130 "ant", Ant.class,
131 "antcall", CallTarget.class,
132 "available", Available.class,
133 "condition", ConditionTask.class,
134 "fail", Exit.class,
135 "property", Property.class,
136 "mkdir", Mkdir.class,
137 "delete", Delete.class,
138 "copy", Copy.class,
139 "exec", ExecTask.class,
140 "waitfor", WaitFor.class,
141 "taskdef", Taskdef.class
142 };
143
144
145
146
147 public final static Object[] SUPPORTED_ANT_TYPES = new Object[] {
148 ArgumentSet.TYPE_NAME, ArgumentSet.class,
149 JVMArgumentSet.TYPE_NAME, JVMArgumentSet.class,
150 SysPropertySet.TYPE_NAME, SysPropertySet.class,
151 "description", Description.class,
152 "fileset", FileSet.class,
153 "filelist", FileList.class,
154 "path", Path.class,
155 "patternset", PatternSet.class
156 };
157
158
159
160
161 private static String toolsClasspath = null;
162
163
164
165
166 private static boolean verbose = false;
167
168
169
170
171
172
173
174
175
176 public static synchronized boolean isStarted() {
177
178 return Launcher.started;
179
180 }
181
182
183
184
185
186
187 public static synchronized boolean isStopped() {
188
189 return Launcher.stopped;
190
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206 public static int start(String[] args) throws IllegalArgumentException {
207
208
209
210 synchronized (Launcher.lock) {
211 if (Launcher.isStarted() || Launcher.isStopped())
212 return 1;
213 Launcher.setStarted(true);
214 }
215
216 int returnValue = 0;
217 ClassLoader parentLoader = null;
218 Thread shutdownHook = new Thread(new Launcher());
219 Runtime runtime = Runtime.getRuntime();
220
221 try {
222
223
224
225
226
227 parentLoader = Thread.currentThread().getContextClassLoader();
228 boolean lessThan14 = true;
229 try {
230 Class.forName("java.lang.CharSequence");
231 lessThan14 = false;
232 } catch (ClassNotFoundException cnfe) {
233
234 }
235 if (lessThan14)
236 Thread.currentThread().setContextClassLoader(Launcher.class.getClassLoader());
237
238 Project project = new Project();
239
240
241 project.setCoreLoader(Launcher.class.getClassLoader());
242
243
244
245
246
247
248
249 for (int i = 0; i < Launcher.SUPPORTED_ANT_TASKS.length; i++) {
250
251 String taskName = (String)Launcher.SUPPORTED_ANT_TASKS[i];
252
253 Class taskClass = (Class)Launcher.SUPPORTED_ANT_TASKS[++i];
254 project.addTaskDefinition(taskName, taskClass);
255 }
256 for (int i = 0; i < Launcher.SUPPORTED_ANT_TYPES.length; i++) {
257
258 String typeName = (String)Launcher.SUPPORTED_ANT_TYPES[i];
259
260 Class typeClass = (Class)Launcher.SUPPORTED_ANT_TYPES[++i];
261 project.addDataTypeDefinition(typeName, typeClass);
262 }
263
264
265 project.setSystemProperties();
266
267
268 int currentArg = 0;
269
270
271 File launchFile = new File(Launcher.getBootstrapDir(), Launcher.DEFAULT_XML_FILE_NAME);
272
273
274 for ( ; currentArg < args.length; currentArg++) {
275
276
277 if ("-".equals(args[currentArg])) {
278 currentArg++;
279 break;
280 } else if (args[currentArg].length() > 0 && !"-".equals(args[currentArg].substring(0, 1))) {
281 break;
282 } else if ("-help".equals(args[currentArg])) {
283 throw new IllegalArgumentException();
284 } else if ("-launchfile".equals(args[currentArg])) {
285 if (currentArg + 1 < args.length){
286 String fileArg = args[++currentArg];
287 launchFile = new File(fileArg);
288 if (!launchFile.isAbsolute())
289 launchFile = new File(Launcher.getBootstrapDir(), fileArg);
290 } else {
291 throw new IllegalArgumentException(args[currentArg] + " " + Launcher.getLocalizedString("missing.arg"));
292 }
293 } else if ("-executablename".equals(args[currentArg])) {
294 if (currentArg + 1 < args.length)
295 System.setProperty(ChildMain.EXECUTABLE_PROP_NAME, args[++currentArg]);
296 else
297 throw new IllegalArgumentException(args[currentArg] + " " + Launcher.getLocalizedString("missing.arg"));
298 } else if ("-verbose".equals(args[currentArg])) {
299 Launcher.setVerbose(true);
300 } else {
301 throw new IllegalArgumentException(args[currentArg] + " " + Launcher.getLocalizedString("invalid.arg"));
302 }
303 }
304
305
306 String target = null;
307 if (currentArg < args.length)
308 target = args[currentArg++];
309 else
310 throw new IllegalArgumentException(Launcher.getLocalizedString("missing.target"));
311
312
313 for ( ; currentArg < args.length; currentArg++) {
314
315
316 if ("-".equals(args[currentArg])) {
317 currentArg++;
318 break;
319 } else if (args[currentArg].length() <= 2 || !"-D".equals(args[currentArg].substring(0, 2))) {
320 break;
321 }
322 int delimiter = args[currentArg].indexOf('=', 2);
323 String key = null;
324 String value = null;
325 if (delimiter >= 2) {
326 key = args[currentArg].substring(2, delimiter);
327 value = args[currentArg].substring(delimiter + 1);
328 } else {
329
330
331
332
333
334 key = args[currentArg].substring(2);
335 if (currentArg + 1 < args.length &&
336 !"-D".equals(args[currentArg + 1].substring(0, 2)))
337 {
338 value = args[++currentArg];
339 } else {
340 value = "";
341 }
342 }
343 project.setUserProperty(key, value);
344 }
345
346
347 String[] appArgs = new String[args.length - currentArg];
348 for (int i = 0; i < appArgs.length; i++) {
349 appArgs[i] = args[i + currentArg];
350 project.setUserProperty(LaunchTask.ARG_PROP_NAME + Integer.toString(i), appArgs[i]);
351 }
352
353
354 project.setUserProperty("ant.version", Main.getAntVersion());
355 project.setUserProperty("ant.file", launchFile.getCanonicalPath());
356 project.setUserProperty("ant.java.version", System.getProperty("java.specification.version"));
357
358
359 ProjectHelper.configureProject(project, launchFile);
360
361
362 if (!project.getTargets().containsKey(target))
363 throw new IllegalArgumentException(target + " " + Launcher.getLocalizedString("invalid.target"));
364
365
366 try {
367 runtime.addShutdownHook(shutdownHook);
368 } catch (NoSuchMethodError nsme) {
369
370 }
371 project.executeTarget(target);
372
373 } catch (Throwable t) {
374
375 returnValue = 1;
376 String message = t.getMessage();
377 if (t instanceof IllegalArgumentException) {
378 Launcher.error(message, true);
379 } else {
380 if (Launcher.verbose)
381 Launcher.error(t);
382 else
383 Launcher.error(message, false);
384 }
385 } finally {
386 synchronized (Launcher.lock) {
387
388 try {
389 runtime.removeShutdownHook(shutdownHook);
390 } catch (NoSuchMethodError nsme) {
391
392 }
393
394 Thread.currentThread().setContextClassLoader(parentLoader);
395
396 Launcher.setStarted(false);
397
398 Launcher.lock.notifyAll();
399 }
400 }
401
402
403 Process[] childProcesses = LaunchTask.getChildProcesses();
404 if (childProcesses.length > 0)
405 returnValue = childProcesses[childProcesses.length - 1].exitValue();
406
407 return returnValue;
408
409 }
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428 public static boolean stop() {
429
430 synchronized (Launcher.lock) {
431
432
433 if (Launcher.isStopped())
434 return false;
435
436
437
438 if (Launcher.isStarted())
439 Launcher.setStopped(true);
440 else
441 return false;
442 }
443
444 boolean returnValue = true;
445
446 try {
447
448
449 killChildProcesses();
450
451
452 synchronized (Launcher.lock) {
453 if (Launcher.isStarted())
454 Launcher.lock.wait();
455 }
456
457
458 if (Launcher.isStarted())
459 returnValue = true;
460
461 } catch (Throwable t) {
462
463 returnValue = false;
464 String message = t.getMessage();
465 if (Launcher.verbose)
466 Launcher.error(t);
467 else
468 Launcher.error(message, false);
469 } finally {
470
471 Launcher.setStopped(false);
472 }
473
474 return returnValue;
475
476 }
477
478
479
480
481
482
483
484 public static void error(String message, boolean usage) {
485
486 if (message != null)
487 Launcher.getLog().println(Launcher.getLocalizedString("error") + ": " + message);
488 if (usage)
489 Launcher.getLog().println(Launcher.getLocalizedString("usage"));
490
491 }
492
493
494
495
496
497
498 public static void error(Throwable t) {
499
500 String message = t.getMessage();
501 if (!Launcher.verbose && message != null)
502 Launcher.getLog().println(Launcher.getLocalizedString("error") + ": " + message);
503 else
504 t.printStackTrace(Launcher.getLog());
505
506 }
507
508
509
510
511
512
513
514
515
516
517
518 public static File getBootstrapDir() throws IOException {
519
520 File file = Launcher.getBootstrapFile();
521 if (file.isDirectory())
522 return file;
523 else
524 return file.getParentFile();
525
526 }
527
528
529
530
531
532
533
534
535
536
537 public static File getBootstrapFile() throws IOException {
538
539 if (bootstrapFile == null) {
540
541
542 String classResourceName = "/" + Launcher.class.getName().replace('.', '/') + ".class";
543 URL resource = Launcher.class.getResource(classResourceName);
544 if (resource == null)
545 throw new IOException(Launcher.getLocalizedString("bootstrap.file.not.found") + ": " + Launcher.class.getName());
546 String resourcePath = null;
547 String embeddedClassName = null;
548 boolean isJar = false;
549 String protocol = resource.getProtocol();
550 if ((protocol != null) &&
551 (protocol.indexOf("jar") >= 0)) {
552 isJar = true;
553 }
554 if (isJar) {
555 resourcePath = URLDecoder.decode(resource.getFile());
556 embeddedClassName = "!" + classResourceName;
557 } else {
558 resourcePath = URLDecoder.decode(resource.toExternalForm());
559 embeddedClassName = classResourceName;
560 }
561 int sep = resourcePath.lastIndexOf(embeddedClassName);
562 if (sep >= 0)
563 resourcePath = resourcePath.substring(0, sep);
564
565
566
567 if (resourcePath.indexOf("file:") == 0)
568 resourcePath = resourcePath.substring(5);
569 else
570 throw new IOException(Launcher.getLocalizedString("bootstrap.file.not.found") + ": " + Launcher.class.getName());
571
572
573
574
575
576
577 File file = new File(resourcePath);
578 if (!file.exists() || !file.canRead())
579 throw new IOException(Launcher.getLocalizedString("bootstrap.file.not.found") + ": " + Launcher.class.getName());
580 bootstrapFile = file.getCanonicalFile();
581
582 }
583
584 return bootstrapFile;
585
586 }
587
588
589
590
591
592
593 public static synchronized String getJavaCommand() {
594
595 if (javaCmd == null) {
596
597 String osname = System.getProperty("os.name").toLowerCase();
598 String commandName = null;
599 if (osname.indexOf("windows") >= 0) {
600
601
602 commandName = "javaw.exe";
603 } else {
604 commandName = "java";
605 }
606 javaCmd = System.getProperty("java.home") + File.separator + "bin" + File.separator + commandName;
607
608 }
609
610 return javaCmd;
611
612 }
613
614
615
616
617
618
619 public static synchronized String getJDBCommand() {
620
621 if (jdbCmd == null) {
622
623 String osname = System.getProperty("os.name").toLowerCase();
624 String commandName = null;
625 if (osname.indexOf("windows") >= 0)
626 commandName = "jdb.exe";
627 else
628 commandName = "jdb";
629 jdbCmd = new File(System.getProperty("java.home")).getParent() + File.separator + "bin" + File.separator + commandName;
630
631 }
632
633 return jdbCmd;
634
635 }
636
637
638
639
640
641
642
643 public static synchronized PrintStream getLog() {
644
645 return Launcher.log;
646
647 }
648
649
650
651
652
653
654
655 public static synchronized String getToolsClasspath() throws IOException {
656
657 if (toolsClasspath == null) {
658
659 File javaHome = null;
660 javaHome = new File(System.getProperty("java.home")).getCanonicalFile();
661 Class clazz = null;
662 String[] toolsPaths = new String[2];
663 toolsPaths[0] = javaHome.getParent() + File.separator +
664 "lib" + File.separator + "tools.jar";
665 toolsPaths[1] = javaHome.getPath() + File.separator +
666 "lib" + File.separator + "tools.jar";
667 File toolsFile = null;
668 for (int i = 0; i < toolsPaths.length; i++) {
669 ClassLoader loader = ClassLoader.getSystemClassLoader();
670 toolsFile = new File(toolsPaths[i]);
671
672 if (!toolsFile.isFile() || !toolsFile.canRead())
673 toolsFile = null;
674 if (toolsFile != null) {
675 try {
676 URL toolsURL = toolsFile.toURL();
677 loader = new URLClassLoader(new URL[]{toolsURL}, loader);
678 } catch (Exception e) {
679 toolsFile = null;
680 }
681 }
682
683
684
685
686 try {
687 clazz = loader.loadClass("sun.tools.javac.Main");
688 if (clazz != null)
689 break;
690 } catch (Exception e) {}
691 }
692
693 if (clazz == null)
694 throw new IOException(Launcher.getLocalizedString("sdk.tools.not.found"));
695
696
697 if (toolsFile != null)
698 toolsClasspath = toolsFile.getPath();
699 else
700 toolsClasspath = "";
701
702 }
703
704 return toolsClasspath;
705
706 }
707
708
709
710
711
712
713
714
715 public static String getLocalizedString(String key) {
716
717 return Launcher.getLocalizedString(key, Launcher.class.getName());
718
719 }
720
721
722
723
724
725
726
727
728
729 public static String getLocalizedString(String key, String className) {
730
731 try {
732 ResourceBundle resourceBundle = ResourceBundle.getBundle(className);
733 return Launcher.resolveString(resourceBundle.getString(key));
734 } catch (Exception e) {
735
736
737 return "<" + key + " property>";
738 }
739
740 }
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763 private static String resolveString(String unresolved) throws IOException {
764
765 if (unresolved == null)
766 return null;
767
768
769 StringBuffer buf = new StringBuffer();
770 int tokenEnd = 0;
771 int tokenStart = 0;
772 char token = '$';
773 boolean escapeChar = false;
774 boolean firstToken = true;
775 boolean lastToken = false;
776
777 while (!lastToken) {
778
779 tokenEnd = unresolved.indexOf(token, tokenStart);
780
781
782 if (firstToken) {
783 firstToken = false;
784
785 if (tokenEnd - tokenStart == 0) {
786 tokenStart = ++tokenEnd;
787 continue;
788 }
789 }
790
791 if (tokenEnd < 0) {
792 lastToken = true;
793 tokenEnd = unresolved.length();
794 }
795
796 if (escapeChar) {
797
798
799 buf.append(token + unresolved.substring(tokenStart, tokenEnd));
800 escapeChar = !escapeChar;
801
802 } else {
803
804
805 int openProp = unresolved.indexOf('{', tokenStart);
806 int closeProp = unresolved.indexOf('}', tokenStart + 1);
807 String prop = null;
808
809
810
811 if (openProp != tokenStart ||
812 closeProp < tokenStart + 1 ||
813 closeProp >= tokenEnd)
814 {
815 buf.append(unresolved.substring(tokenStart, tokenEnd));
816 } else {
817
818 String propName = unresolved.substring(tokenStart + 1, closeProp);
819 if ("launcher.executable.name".equals(propName)) {
820 prop = System.getProperty(ChildMain.EXECUTABLE_PROP_NAME);
821 if (prop != null) {
822
823 prop = "\"" + prop + "\"";
824 } else {
825
826 String classpath = Launcher.getBootstrapFile().getPath();
827 prop = "\"" + System.getProperty("java.home") + File.separator + "bin" + File.separator + "java\" -classpath \"" + classpath + "\" LauncherBootstrap";
828 }
829 } else if ("launcher.bootstrap.file".equals(propName)) {
830 prop = Launcher.getBootstrapFile().getPath();
831 } else if ("launcher.bootstrap.dir".equals(propName)) {
832 prop = Launcher.getBootstrapDir().getPath();
833 } else {
834 prop = System.getProperty(unresolved.substring(tokenStart + 1, closeProp));
835 }
836 if (prop == null)
837 prop = "";
838 buf.append(prop + unresolved.substring(++closeProp, tokenEnd));
839 }
840
841 }
842
843
844
845
846 if (tokenEnd - tokenStart == 0)
847 escapeChar = !escapeChar;
848
849 tokenStart = ++tokenEnd;
850
851 }
852
853 return buf.toString();
854
855 }
856
857
858
859
860
861
862 public static synchronized void setLog(PrintStream log) {
863
864 if (log != null)
865 Launcher.log = log;
866 else
867 Launcher.log = System.err;
868
869 }
870
871
872
873
874
875
876 private static synchronized void setStarted(boolean started) {
877
878 Launcher.started = started;
879
880 }
881
882
883
884
885
886
887 private static synchronized void setStopped(boolean stopped) {
888
889 Launcher.stopped = stopped;
890
891 }
892
893
894
895
896
897
898 public static synchronized void setVerbose(boolean verbose) {
899
900 Launcher.verbose = verbose;
901
902 }
903
904
905
906
907
908 public static void killChildProcesses() {
909
910 Process[] procs = LaunchTask.getChildProcesses();
911 for (int i = 0; i < procs.length; i++)
912 procs[i].destroy();
913
914 }
915
916
917
918
919
920
921
922 public void run() {
923
924 Launcher.killChildProcesses();
925
926 }
927
928 }