/**************************************************************************************
* Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. *
* http://aspectwerkz.codehaus.org *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the LGPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package org.codehaus.aspectwerkz.hook;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
/**
* Starts a target process adding JDWP option to have a listening connector and be in suspend mode <p/>Target process is
* launched using <i>$JAVA_HOME/bin/java [opt] [main] </i> <br/>and [opt] is patched to use <i>-Xdebug
* -Xrunjdwp:transport=..,address=..,server=y,suspend=y </i> <br/>
*
* @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
*/
public class JDWPStarter extends AbstractStarter {
private String transport;
private String address;
public JDWPStarter(String opt, String main, String transport, String address) {
super(opt, main);
Map jdwpOpt = parseJdwp();
if (jdwpOpt.containsKey("transport")) {
this.transport = (String) jdwpOpt.get("transport");
} else {
this.transport = transport;
jdwpOpt.put("transport", this.transport);
}
if (jdwpOpt.containsKey("address")) {
this.address = (String) jdwpOpt.get("address");
} else {
this.address = address;
jdwpOpt.put("address", this.address);
}
patchOptions(jdwpOpt);
}
public String getTransport() {
return transport;
}
public String getAddress() {
return address;
}
/**
* Patch JDWP options if any to include necessary information Preserve JDWP options excepted server and suspend.
* <br/>If transport and address are already specified it uses them.
*/
private void patchOptions(Map jdwpOpt) {
if (opt.indexOf("-Xdebug") < 0) {
opt = "-Xdebug " + opt;
}
jdwpOpt.put("server", "y");
jdwpOpt.put("suspend", "y");
StringBuffer jdwp = new StringBuffer("-Xrunjdwp:");
List keys = new ArrayList(jdwpOpt.keySet());
// JDWP options should start with transport=..,address=..
// or it fails strangely
//Collections.reverse(keys);
keys = jdwpOptionSort(keys);
for (Iterator i = keys.iterator(); i.hasNext();) {
String key = (String) i.next();
jdwp.append(key).append("=").append((String) jdwpOpt.get(key));
if (i.hasNext()) {
jdwp.append(",");
}
}
if (opt.indexOf("-Xrunjdwp:") < 0) {
opt = jdwp + " " + opt;
} else {
int from = opt.indexOf("-Xrunjdwp:");
int to = Math.min(opt.length(), opt.indexOf(' ', from));
StringBuffer newOpt = new StringBuffer("");
if (from > 0) {
newOpt.append(opt.substring(0, from));
}
newOpt.append(" ").append(jdwp);
if (to < opt.length()) {
newOpt.append(" ").append(opt.substring(to, opt.length()));
}
opt = newOpt.toString();
}
}
/**
* return a Map(String=>String) of JDWP options
*/
private Map parseJdwp() {
if (opt.indexOf("-Xrunjdwp:") < 0) {
return new HashMap();
}
String jdwp = opt.substring(
opt.indexOf("-Xrunjdwp:") + "-Xrunjdwp:".length(), Math.min(
opt.length(), opt
.indexOf(' ', opt.indexOf("-Xrunjdwp:"))
)
);
HashMap jdwpOpt = new HashMap();
StringTokenizer stz = new StringTokenizer(jdwp, ",");
while (stz.hasMoreTokens()) {
String jdwpo = stz.nextToken();
if (jdwpo.indexOf('=') < 0) {
System.err.println("WARN - unrecognized JDWP option: " + jdwpo);
continue;
}
jdwpOpt.put(jdwpo.substring(0, jdwpo.indexOf('=')), jdwpo.substring(jdwpo.indexOf('=') + 1));
}
return jdwpOpt;
}
/**
* Sort list of String for "transport" to be in first position
*/
private List jdwpOptionSort(List opt) {
Comparator c = new Comparator() {
public int compare(Object o1, Object o2) {
if (o1 instanceof String && o2 instanceof String) {
if ("transport".equals((String) o1)) {
return -1000;
}
if ("transport".equals((String) o2)) {
return 1000;
}
return 0;
}
return 0;
}
};
Collections.sort(opt, c);
return opt;
}
}