1 /***************************************************************************************
2 * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3 * http://aspectwerkz.codehaus.org *
4 * ---------------------------------------------------------------------------------- *
5 * The software in this package is published under the terms of the LGPL license *
6 * a copy of which has been included with this distribution in the license.txt file. *
7 **************************************************************************************/
8 package org.codehaus.aspectwerkz.hook;
9
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.Comparator;
13 import java.util.HashMap;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.StringTokenizer;
18
19 /***
20 * Starts a target process adding JDWP option to have a listening connector and be in suspend mode <p/>Target process is
21 * launched using <i>$JAVA_HOME/bin/java [opt] [main] </i> <br/>and [opt] is patched to use <i>-Xdebug
22 * -Xrunjdwp:transport=..,address=..,server=y,suspend=y </i> <br/>
23 *
24 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
25 */
26 public class JDWPStarter extends AbstractStarter {
27 private String transport;
28
29 private String address;
30
31 public JDWPStarter(String opt, String main, String transport, String address) {
32 super(opt, main);
33 Map jdwpOpt = parseJdwp();
34 if (jdwpOpt.containsKey("transport")) {
35 this.transport = (String) jdwpOpt.get("transport");
36 } else {
37 this.transport = transport;
38 jdwpOpt.put("transport", this.transport);
39 }
40 if (jdwpOpt.containsKey("address")) {
41 this.address = (String) jdwpOpt.get("address");
42 } else {
43 this.address = address;
44 jdwpOpt.put("address", this.address);
45 }
46 patchOptions(jdwpOpt);
47 }
48
49 public String getTransport() {
50 return transport;
51 }
52
53 public String getAddress() {
54 return address;
55 }
56
57 /***
58 * Patch JDWP options if any to include necessary information Preserve JDWP options excepted server and suspend.
59 * <br/>If transport and address are already specified it uses them.
60 */
61 private void patchOptions(Map jdwpOpt) {
62 if (opt.indexOf("-Xdebug") < 0) {
63 opt = "-Xdebug " + opt;
64 }
65 jdwpOpt.put("server", "y");
66 jdwpOpt.put("suspend", "y");
67 StringBuffer jdwp = new StringBuffer("-Xrunjdwp:");
68 List keys = new ArrayList(jdwpOpt.keySet());
69
70
71
72
73 keys = jdwpOptionSort(keys);
74 for (Iterator i = keys.iterator(); i.hasNext();) {
75 String key = (String) i.next();
76 jdwp.append(key).append("=").append((String) jdwpOpt.get(key));
77 if (i.hasNext()) {
78 jdwp.append(",");
79 }
80 }
81 if (opt.indexOf("-Xrunjdwp:") < 0) {
82 opt = jdwp + " " + opt;
83 } else {
84 int from = opt.indexOf("-Xrunjdwp:");
85 int to = Math.min(opt.length(), opt.indexOf(' ', from));
86 StringBuffer newOpt = new StringBuffer("");
87 if (from > 0) {
88 newOpt.append(opt.substring(0, from));
89 }
90 newOpt.append(" ").append(jdwp);
91 if (to < opt.length()) {
92 newOpt.append(" ").append(opt.substring(to, opt.length()));
93 }
94 opt = newOpt.toString();
95 }
96 }
97
98 /***
99 * return a Map(String=>String) of JDWP options
100 */
101 private Map parseJdwp() {
102 if (opt.indexOf("-Xrunjdwp:") < 0) {
103 return new HashMap();
104 }
105 String jdwp = opt.substring(opt.indexOf("-Xrunjdwp:") + "-Xrunjdwp:".length(), Math.min(opt.length(), opt
106 .indexOf(' ', opt.indexOf("-Xrunjdwp:"))));
107 HashMap jdwpOpt = new HashMap();
108 StringTokenizer stz = new StringTokenizer(jdwp, ",");
109 while (stz.hasMoreTokens()) {
110 String jdwpo = stz.nextToken();
111 if (jdwpo.indexOf('=') < 0) {
112 System.err.println("WARN - unrecognized JDWP option: " + jdwpo);
113 continue;
114 }
115 jdwpOpt.put(jdwpo.substring(0, jdwpo.indexOf('=')), jdwpo.substring(jdwpo.indexOf('=') + 1));
116 }
117 return jdwpOpt;
118 }
119
120 /***
121 * Sort list of String for "transport" to be in first position
122 */
123 private List jdwpOptionSort(List opt) {
124 Comparator c = new Comparator() {
125 public int compare(Object o1, Object o2) {
126 if (o1 instanceof String && o2 instanceof String) {
127 if ("transport".equals((String) o1)) {
128 return -1000;
129 }
130 if ("transport".equals((String) o2)) {
131 return 1000;
132 }
133 return 0;
134 }
135 return 0;
136 }
137 };
138 Collections.sort(opt, c);
139 return opt;
140 }
141 }