View Javadoc

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          // JDWP options should start with transport=..,address=..
71          // or it fails strangely
72          //Collections.reverse(keys);
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 }