src/share/classes/com/sun/tools/example/debug/tty/VMConnection.java

Print this page
rev 5157 : 7154809: JDI: update JDI/JDB debugee commandline option parsing (allow
nested comma delimited options)
Summary: update debugee commandline parsing to allow for delimited
suboptions
Reviewed-by:

@@ -112,10 +112,26 @@
             int index = token.indexOf('=');
             String name = token.substring(0, index);
             String value = token.substring(index + 1,
                                            token.length() - 1); // Remove comma delimiter
 
+            /*
+             *  unquote values for options (single and/or double quotes)
+             *  needed for quote enclosed delimited substrings
+             */
+            if (name.equals("options")) {
+                StringBuilder sb = new StringBuilder();
+                for (String s : splitStringAtNonEnclosedWhiteSpace(value)) {
+                    while (isEnclosed(s, "\"") || isEnclosed(s, "'")) {
+                        s = s.substring(1, s.length() - 1);
+                    }
+                    sb.append(s);
+                    sb.append(" ");
+                }
+                value = sb.toString();
+            }
+
             Connector.Argument argument = arguments.get(name);
             if (argument == null) {
                 throw new IllegalArgumentException
                     (MessageOutput.format("Argument is not defined for connector:",
                                           new Object [] {name, connector.name()}));

@@ -134,10 +150,184 @@
                 (MessageOutput.format("Illegal connector argument", argString));
         }
         return arguments;
     }
 
+    private static boolean isEnclosed(String value, String enclosingChar) {
+        if (value.indexOf(enclosingChar) == 0) {
+            int lastIndex = value.lastIndexOf(enclosingChar);
+            if (lastIndex > 0 && lastIndex  == value.length() - 1) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static ArrayList<String> splitStringAtNonEnclosedWhiteSpace(String value) throws IllegalArgumentException {
+        ArrayList<String> al = new ArrayList<String>();
+        char[] arr;
+        int startPosition = 0;
+        int endPosition = 0;
+        final char SPACE = ' ';
+        final char DOUBLEQ = '"';
+        final char SINGLEQ = '\'';
+        boolean activeEnclose = false;
+        char enclosingTargetChar = '"';
+
+        if (value == null) {
+            throw new IllegalArgumentException
+                (MessageOutput.format("Illegal option values",
+                    value));
+        }
+
+        //split parameter string into individual chars
+        arr = value.toCharArray();
+
+        for (int i = 0; i < arr.length; i++) {
+            switch (arr[i]) {
+                case SPACE: {
+                    // default is to do nothing for spaces
+                    // just check if last in string
+                    if (!isLastChar(arr, i)) {
+                        //if not last, skip to next
+                        continue;
+                    } else {
+                        //last char in string, need to end here
+                        endPosition = i;
+                        //break out for substring creation
+                        break;
+                    }
+                }
+                case DOUBLEQ: {
+                    //is there an active enclose?
+                    if (activeEnclose) {
+                        //enclose is active
+                        if (enclosingTargetChar != DOUBLEQ) {
+                            //not our target, skip
+                            continue;
+                        }
+                        //our enclosure target end
+                        if (isNextCharWhitespace(arr, i)) {
+                            //if whitespace peek next
+                            //then a complete enclosing
+                            endPosition = i;
+                            activeEnclose = false;
+                            //break out for substring creation
+                            break;
+                        }
+                        // skip to next
+                        continue;
+                    }
+                    // no active enclosing
+                    if (isPreviousCharWhitespace(arr, i)) {
+                        // start a new enclosing
+                        startPosition = i;
+                        //set up target char enclosing
+                        enclosingTargetChar = DOUBLEQ;
+                        // activate
+                        activeEnclose = true;
+                    }
+                    //skip to next
+                    continue;
+                }
+                case SINGLEQ: {
+                    //an active enclose?
+                    if (activeEnclose) {
+                        //enclose is active
+                        if (enclosingTargetChar != SINGLEQ) {
+                            //not our target, continue
+                            continue;
+                        }
+                        //our enclosure target end
+                        if (isNextCharWhitespace(arr, i)) {
+                            //if whitespace peek next
+                            //then a complete enclosing
+                            activeEnclose = false;
+                            endPosition = i;
+                            //break out for substring creation
+                            break;
+                        }
+                        //skip to next
+                        continue;
+                    }
+                    //no active enclosing
+                    if (isPreviousCharWhitespace(arr, i)) {
+                        // starting a new enclosing
+                        startPosition = i;
+                        //set up the target char for ending enclosing
+                        enclosingTargetChar = SINGLEQ;
+                        // activate
+                        activeEnclose = true;
+                    }
+                    //skip to next
+                    continue;
+                }
+                default: {
+                    // normal non-space , non-" and non-' chars
+                    if (!activeEnclose) {
+                        // might be start of a string (if prev was whitespace)
+                        if (isPreviousCharWhitespace(arr, i)) {
+                            // no enclosure is active, start here
+                            startPosition = i;
+                            //skip to next
+                            continue;
+                        }
+                        if (isNextCharWhitespace(arr, i)) {
+                            endPosition = i;
+                            //break for substring creation
+                            break;
+                        }
+                    }
+                    //skip to next
+                    continue;
+                }
+            }
+            // break's end up here
+            // handle the substring extraction
+            if (startPosition > endPosition) {
+                throw new IllegalArgumentException
+                    (MessageOutput.format("Illegal option values",
+                        value));
+            }
+            // skip
+            if (startPosition == endPosition) {
+                continue;
+            }
+
+            // take out substring from parameter string and add
+            // to ArrayList<String>
+            al.add(value.substring(startPosition, endPosition + 1));
+            // set new start position
+            startPosition = endPosition + 1;
+        } // for loop
+        // return split strings in arraylist
+        return al;
+    }
+
+    static private boolean isPreviousCharWhitespace(char[] arr, int curr_pos) {
+        return isCharWhitespace(arr, curr_pos - 1);
+    }
+
+    static private boolean isNextCharWhitespace(char[] arr, int curr_pos) {
+        return isCharWhitespace(arr, curr_pos + 1);
+    }
+
+    static private boolean isCharWhitespace(char[] arr, int position) {
+        if (position < 0 || position >= arr.length) {
+            //outside arraybounds is considered an implicit space
+            return true;
+        }
+        if (arr[position] == ' ') {
+            return true;
+        }
+        return false;
+    }
+
+    static private boolean isLastChar(char[] arr, int position) {
+        return (position + 1 == arr.length);
+    }
+
     VMConnection(String connectSpec, int traceFlags) {
         String nameString;
         String argString;
         int index = connectSpec.indexOf(':');
         if (index == -1) {