static Properties parseUrl()

in src/main/java/com/microsoft/sqlserver/jdbc/Util.java [241:523]


    /* L0 */ static Properties parseUrl(String url, Logger logger) throws SQLServerException {
        Properties p = new Properties();
        String tmpUrl = url;
        String sPrefix = "jdbc:sqlserver://";
        StringBuilder result = new StringBuilder();
        String name = "";
        String value = "";

        if (!tmpUrl.startsWith(sPrefix))
            return null;

        tmpUrl = tmpUrl.substring(sPrefix.length());
        int i;

        // Simple finite state machine.
        // always look at one char at a time
        final int inStart = 0;
        final int inServerName = 1;
        final int inPort = 2;
        final int inInstanceName = 3;
        final int inEscapedValueStart = 4;
        final int inEscapedValueEnd = 5;
        final int inValue = 6;
        final int inName = 7;

        int state = inStart;
        char ch;
        i = 0;
        while (i < tmpUrl.length()) {
            ch = tmpUrl.charAt(i);
            switch (state) {
                case inStart: {
                    if (ch == ';') {
                        // done immediately
                        state = inName;
                    } else {
                        result.append(ch);
                        state = inServerName;
                    }
                    break;
                }

                case inServerName: {
                    if (ch == ';' || ch == ':' || ch == '\\') {
                        // non escaped trim the string
                        String property = result.toString().trim();
                        if (property.length() > 0) {
                            p.put(SQLServerDriverStringProperty.SERVER_NAME.toString(), property);
                            if (logger.isLoggable(Level.FINE)) {
                                logger.fine("Property:serverName " + "Value:" + property);
                            }
                        }
                        result.setLength(0);

                        if (ch == ';')
                            state = inName;
                        else if (ch == ':')
                            state = inPort;
                        else
                            state = inInstanceName;
                    } else {
                        result.append(ch);
                        // same state
                    }
                    break;
                }

                case inPort: {
                    if (ch == ';') {
                        String property = result.toString().trim();
                        if (logger.isLoggable(Level.FINE)) {
                            logger.fine("Property:portNumber " + "Value:" + property);
                        }
                        p.put(SQLServerDriverIntProperty.PORT_NUMBER.toString(), property);
                        result.setLength(0);
                        state = inName;
                    } else {
                        result.append(ch);
                        // same state
                    }
                    break;
                }
                case inInstanceName: {
                    if (ch == ';' || ch == ':') {
                        // non escaped trim the string
                        String property = result.toString().trim();
                        if (logger.isLoggable(Level.FINE)) {
                            logger.fine("Property:instanceName " + "Value:" + property);
                        }
                        p.put(SQLServerDriverStringProperty.INSTANCE_NAME.toString(), property.toLowerCase(Locale.US));
                        result.setLength(0);

                        if (ch == ';')
                            state = inName;
                        else
                            state = inPort;
                    } else {
                        result.append(ch);
                        // same state
                    }
                    break;
                }
                case inName: {
                    if (ch == '=') {
                        // name is never escaped!
                        name = name.trim();
                        if (name.length() <= 0) {
                            SQLServerException.makeFromDriverError(null, null,
                                    SQLServerException.getErrString("R_errorConnectionString"), null, true);
                        }
                        state = inValue;
                    } else if (ch == ';') {
                        name = name.trim();
                        if (name.length() > 0) {
                            SQLServerException.makeFromDriverError(null, null,
                                    SQLServerException.getErrString("R_errorConnectionString"), null, true);
                        }
                        // same state
                    } else {
                        StringBuilder builder = new StringBuilder();
                        builder.append(name);
                        builder.append(ch);
                        name = builder.toString();
                        // same state
                    }
                    break;
                }
                case inValue: {
                    if (ch == ';') {
                        // simple value trim
                        value = value.trim();
                        name = SQLServerDriver.getNormalizedPropertyName(name, logger);
                        if (null != name) {
                            if (logger.isLoggable(Level.FINE)) {
                                if (!name.equals(SQLServerDriverStringProperty.USER.toString())) {
                                    if (!name.toLowerCase(Locale.ENGLISH).contains("password")
                                            && !name.toLowerCase(Locale.ENGLISH).contains("keystoresecret")) {
                                        logger.fine("Property:" + name + " Value:" + value);
                                    } else {
                                        logger.fine("Property:" + name);
                                    }
                                }
                            }
                            p.put(name, value);
                        }
                        name = "";
                        value = "";
                        state = inName;

                    } else if (ch == '{') {
                        state = inEscapedValueStart;
                        value = value.trim();
                        if (value.length() > 0) {
                            SQLServerException.makeFromDriverError(null, null,
                                    SQLServerException.getErrString("R_errorConnectionString"), null, true);
                        }
                    } else {
                        StringBuilder builder = new StringBuilder();
                        builder.append(value);
                        builder.append(ch);
                        value = builder.toString();
                        // same state
                    }
                    break;
                }
                case inEscapedValueStart: {
                    /*
                     * check for escaped }. when we see a }, first check to see if this is before the end of the string
                     * to avoid index out of range exception then check if the character immediately after is also a }.
                     * if it is, then we have a }}, which is not the closing of the escaped state.
                     */
                    if (ch == '}' && i + 1 < tmpUrl.length() && tmpUrl.charAt(i + 1) == '}') {
                        StringBuilder builder = new StringBuilder();
                        builder.append(value);
                        builder.append(ch);
                        value = builder.toString();
                        i++; // escaped }} into a }, so increment the counter once more
                        // same state
                    } else {
                        if (ch == '}') {
                            // no trimming use the value as it is.
                            name = SQLServerDriver.getNormalizedPropertyName(name, logger);
                            if (null != name) {
                                if (logger.isLoggable(Level.FINE)) {
                                    if (!name.equals(SQLServerDriverStringProperty.USER.toString())
                                            && !name.equals(SQLServerDriverStringProperty.PASSWORD.toString()))
                                        logger.fine("Property:" + name + " Value:" + value);
                                }
                                p.put(name, value);
                            }

                            name = "";
                            value = "";
                            // to eat the spaces until the ; potentially we could do without the state but
                            // it would not be clean
                            state = inEscapedValueEnd;
                        } else {
                            StringBuilder builder = new StringBuilder();
                            builder.append(value);
                            builder.append(ch);
                            value = builder.toString();
                            // same state
                        }
                    }
                    break;
                }
                case inEscapedValueEnd: {
                    if (ch == ';') // eat space chars till ; anything else is an error
                    {
                        state = inName;
                    } else if (ch != ' ') {
                        // error if the chars are not space
                        SQLServerException.makeFromDriverError(null, null,
                                SQLServerException.getErrString("R_errorConnectionString"), null, true);
                    }
                    break;
                }

                default:
                    assert false : "parseURL: Invalid state " + state;
            }
            i++;
        }

        // Exit
        switch (state) {
            case inServerName:
                String property = result.toString().trim();
                if (property.length() > 0) {
                    if (logger.isLoggable(Level.FINE)) {
                        logger.fine("Property:serverName " + "Value:" + property);
                    }
                    p.put(SQLServerDriverStringProperty.SERVER_NAME.toString(), property);
                }
                break;
            case inPort:
                property = result.toString().trim();
                if (logger.isLoggable(Level.FINE)) {
                    logger.fine("Property:portNumber " + "Value:" + property);
                }
                p.put(SQLServerDriverIntProperty.PORT_NUMBER.toString(), property);
                break;
            case inInstanceName:
                property = result.toString().trim();
                if (logger.isLoggable(Level.FINE)) {
                    logger.fine("Property:instanceName " + "Value:" + property);
                }
                p.put(SQLServerDriverStringProperty.INSTANCE_NAME.toString(), property);
                break;
            case inValue:
                // simple value trim
                value = value.trim();
                name = SQLServerDriver.getNormalizedPropertyName(name, logger);
                if (null != name) {
                    if (logger.isLoggable(Level.FINE)) {
                        if (!name.equals(SQLServerDriverStringProperty.USER.toString())
                                && !name.equals(SQLServerDriverStringProperty.PASSWORD.toString())
                                && !name.equals(SQLServerDriverStringProperty.KEY_STORE_SECRET.toString()))
                            logger.fine("Property:" + name + " Value:" + value);
                    }
                    p.put(name, value);
                }

                break;
            case inEscapedValueEnd:
            case inStart:
                // do nothing!
                break;
            case inName: {
                name = name.trim();
                if (name.length() > 0) {
                    SQLServerException.makeFromDriverError(null, null,
                            SQLServerException.getErrString("R_errorConnectionString"), null, true);
                }

                break;
            }
            default:
                SQLServerException.makeFromDriverError(null, null,
                        SQLServerException.getErrString("R_errorConnectionString"), null, true);
        }
        return p;
    }