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(
    106                 opt.indexOf("-Xrunjdwp:") + "-Xrunjdwp:".length(), Math.min(
    107                         opt.length(), opt
    108                                       .indexOf(' ', opt.indexOf("-Xrunjdwp:"))
    109                 )
    110         );
    111         HashMap jdwpOpt = new HashMap();
    112         StringTokenizer stz = new StringTokenizer(jdwp, ",");
    113         while (stz.hasMoreTokens()) {
    114             String jdwpo = stz.nextToken();
    115             if (jdwpo.indexOf('=') < 0) {
    116                 System.err.println("WARN - unrecognized JDWP option: " + jdwpo);
    117                 continue;
    118             }
    119             jdwpOpt.put(jdwpo.substring(0, jdwpo.indexOf('=')), jdwpo.substring(jdwpo.indexOf('=') + 1));
    120         }
    121         return jdwpOpt;
    122     }
    123
    124     /***
    125      * Sort list of String for "transport" to be in first position
    126      */
    127     private List jdwpOptionSort(List opt) {
    128         Comparator c = new Comparator() {
    129             public int compare(Object o1, Object o2) {
    130                 if (o1 instanceof String && o2 instanceof String) {
    131                     if ("transport".equals((String) o1)) {
    132                         return -1000;
    133                     }
    134                     if ("transport".equals((String) o2)) {
    135                         return 1000;
    136                     }
    137                     return 0;
    138                 }
    139                 return 0;
    140             }
    141         };
    142         Collections.sort(opt, c);
    143         return opt;
    144     }
    145 }