private Map<String, com.sun.jdi.connect.Connector.Argument> parseConnectorArgs( Connector connector, String argString) { Map<String, com.sun.jdi.connect.Connector.Argument> arguments = connector.defaultArguments(); /* * We are parsing strings of the form: * name1=value1,[name2=value2,...] * However, the value1...valuen substrings may contain * embedded comma(s), so make provision for quoting inside * the value substrings. (Bug ID 4285874) */ String regexPattern = "(quote=[^,]+,)|" + // special case for quote=., "(\\w+=)" + // name= "(((\"[^\"]*\")|" + // ( "l , ue" "('[^']*')|" + // 'l , ue' "([^,'\"]+))+,)"; // v a l u e )+ , Pattern p = Pattern.compile(regexPattern); Matcher m = p.matcher(argString); while (m.find()) { int startPosition = m.start(); int endPosition = m.end(); if (startPosition > 0) { /* * It is an error if parsing skips over any part of argString. */ throw new IllegalArgumentException( MessageOutput.format("Illegal connector argument", argString)); } String token = argString.substring(startPosition, endPosition); int index = token.indexOf('='); String name = token.substring(0, index); String value = token.substring(index + 1, token.length() - 1); // Remove comma delimiter /* * for values enclosed in quotes (single and/or double quotes) * strip off enclosing quote chars * 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()})); } argument.setValue(value); argString = argString.substring(endPosition); // Remove what was just parsed... m = p.matcher(argString); // and parse again on what is left. } if ((!argString.equals(",")) && (argString.length() > 0)) { /* * It is an error if any part of argString is left over, * unless it was empty to begin with. */ throw new IllegalArgumentException( MessageOutput.format("Illegal connector argument", argString)); } return arguments; }
class PatternReferenceTypeSpec implements ReferenceTypeSpec { final String classId, transClassId; boolean anonymous; boolean checkJavaLang; String stem; static final Pattern ANONYMOUS_TAIL = Pattern.compile("[.$]\\d+$"), ANONYMOUS_SEGMENT = Pattern.compile("^\\d+$"); PatternReferenceTypeSpec(String classId, boolean checkJavaLang) throws ClassNotFoundException { if (classId.endsWith(".0")) { classId = classId.substring(0, classId.length() - 2); anonymous = true; } else anonymous = false; this.classId = classId; stem = transClassId = classId.replace('$', '.'); if (classId.startsWith("*")) { stem = stem.substring(1); checkJavaLang = false; } else if (classId.endsWith("*")) { stem = stem.substring(0, classId.length() - 1); checkJavaLang = false; } checkClassName(stem); this.checkJavaLang = checkJavaLang && stem.indexOf('.') == -1; } PatternReferenceTypeSpec(String classId) throws ClassNotFoundException { this(classId, false); } /** Does the specified ReferenceType match this spec. */ public boolean matches(ReferenceType refType) { String refName = refType.name().replace('$', '.'); String compName; compName = refName; if (anonymous) { String anonymousBase = anonymousBaseName(refName); if (anonymousBase != null) compName = anonymousBase; else return false; } if (classId.startsWith("*")) { return compName.endsWith(stem); } else if (classId.endsWith("*")) { return compName.startsWith(stem); } else if (checkJavaLang && compName.startsWith("java.lang.") && compName.substring(10).equals(stem)) { return true; } else { return compName.equals(transClassId); } } public boolean isAnyAnonymous() { return anonymous; } public int hashCode() { return classId.hashCode(); } public boolean equals(Object obj) { if (obj instanceof PatternReferenceTypeSpec) { PatternReferenceTypeSpec spec = (PatternReferenceTypeSpec) obj; return transClassId.equals(spec.transClassId); } else { return false; } } private void checkClassName(String className) throws ClassNotFoundException { // Do stricter checking of class name validity on deferred // because if the name is invalid, it will // never match a future loaded class, and we'll be silent // about it. StringTokenizer tokenizer = new StringTokenizer(className, "."); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); // Each dot-separated piece must be a valid identifier // and the first token can also be "*". if (!isJavaIdentifier(token) && (tokenizer.hasMoreTokens() || !isAnonymousClassSuffix(token))) { throw new ClassNotFoundException(); } } if (!classIsPlausible()) Env.noticeln("Warning: class %s does not seem to exist.", classId); } private boolean isJavaIdentifier(String s) { if (s.length() == 0) { return false; } if (!Character.isJavaIdentifierStart(s.charAt(0))) { return false; } for (int i = 1; i < s.length(); i++) { if (!Character.isJavaIdentifierPart(s.charAt(i))) { return false; } } return true; } private boolean isAnonymousClassSuffix(String suffix) { return ANONYMOUS_SEGMENT.matcher(suffix).find(); } private String anonymousBaseName(String name) { Matcher mat = ANONYMOUS_TAIL.matcher(name); if (mat.find()) return name.substring(0, mat.start()); else return null; } public String toString() { return classId + (isAnyAnonymous() ? ".0" : ""); } /** * False iff there is some evidence that no class described by this pattern exists in the * classpath. Conservatively returns true for patterns containing "*", for cases where the virtual * machine is not a PathSearchingVirtualMachine, and for anonymous classes for a parent class * exists. */ boolean classIsPlausible() { if (classId.startsWith("*") || classId.endsWith("*") || !(Env.vm() instanceof PathSearchingVirtualMachine)) return true; else return Env.classMayExist(transClassId); } }