private static void assertValidJcrName()

in vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageId.java [470:590]


    private static void assertValidJcrName(String jcrName) throws IllegalArgumentException {
        // trivial check
        int len = jcrName == null ? 0 : jcrName.length();
        if (len == 0) {
            throw new IllegalArgumentException("empty name");
        }
        if (".".equals(jcrName) || "..".equals(jcrName)) {
            throw new IllegalArgumentException(jcrName);
        }

        // parse the name
        String prefix;
        int nameStart = 0;
        int state = STATE_PREFIX_START;
        boolean trailingSpaces = false;

        for (int i = 0; i < len; i++) {
            char c = jcrName.charAt(i);
            if (c == ':') {
                if (state == STATE_PREFIX_START) {
                    throw new IllegalArgumentException("Prefix must not be empty");
                } else if (state == STATE_PREFIX) {
                    if (trailingSpaces) {
                        throw new IllegalArgumentException("Trailing spaces not allowed");
                    }
                    prefix = jcrName.substring(0, i);
                    if (!XMLChar.isValidNCName(prefix)) {
                        throw new IllegalArgumentException("Invalid name prefix: "+ prefix);
                    }
                    state = STATE_NAME_START;
                } else if (state == STATE_URI) {
                    // ignore -> validation of uri later on.
                } else {
                    throw new IllegalArgumentException("'" + c + "' not allowed in name");
                }
                trailingSpaces = false;
            } else if (c == ' ') {
                if (state == STATE_PREFIX_START || state == STATE_NAME_START) {
                    throw new IllegalArgumentException("'" + c + "' not valid name start");
                }
                trailingSpaces = true;
            } else if (Character.isWhitespace(c) || c == '[' || c == ']' || c == '*' || c == '|') {
                throw new IllegalArgumentException("'" + c + "' not allowed in name");
            } else if (c == '/') {
                if (state == STATE_URI_START) {
                    state = STATE_URI;
                } else if (state != STATE_URI) {
                    throw new IllegalArgumentException("'" + c + "' not allowed in name");
                }
                trailingSpaces = false;
            } else if (c == '{') {
                if (state == STATE_PREFIX_START) {
                    state = STATE_URI_START;
                } else if (state == STATE_URI_START || state == STATE_URI) {
                    // second '{' in the uri-part -> no valid expanded jcr-name.
                    // therefore reset the nameStart and change state.
                    state = STATE_NAME;
                    nameStart = 0;
                } else if (state == STATE_NAME_START) {
                    state = STATE_NAME;
                    nameStart = i;
                }
                trailingSpaces = false;
            } else if (c == '}') {
                if (state == STATE_URI_START || state == STATE_URI) {
                    String tmp = jcrName.substring(1, i);
                    if (tmp.length() == 0 || tmp.indexOf(':') != -1) {
                        // The leading "{...}" part is empty or contains
                        // a colon, so we treat it as a valid namespace URI.
                        // More detailed validity checks (is it well formed,
                        // registered, etc.) are not needed here.
                        state = STATE_NAME_START;
                    } else if ("internal".equals(tmp)) {
                        // As a special Jackrabbit backwards compatibility
                        // feature, support {internal} as a valid URI prefix
                        state = STATE_NAME_START;
                    } else if (tmp.indexOf('/') == -1) {
                        // The leading "{...}" contains neither a colon nor
                        // a slash, so we can interpret it as a a part of a
                        // normal local name.
                        state = STATE_NAME;
                        nameStart = 0;
                    } else {
                        throw new IllegalArgumentException(
                                "The URI prefix of the name " + jcrName
                                        + " is neither a valid URI nor a valid part"
                                        + " of a local name.");
                    }
                } else if (state == STATE_PREFIX_START) {
                    state = STATE_PREFIX; // prefix start -> validation later on will fail.
                } else if (state == STATE_NAME_START) {
                    state = STATE_NAME;
                    nameStart = i;
                }
                trailingSpaces = false;
            } else {
                if (state == STATE_PREFIX_START) {
                    state = STATE_PREFIX; // prefix start
                } else if (state == STATE_NAME_START) {
                    state = STATE_NAME;
                    nameStart = i;
                } else if (state == STATE_URI_START) {
                    state = STATE_URI;
                }
                trailingSpaces = false;
            }
        }

        // take care of qualified jcrNames starting with '{' that are not having
        // a terminating '}' -> make sure there are no illegal characters present.
        if (state == STATE_URI && (jcrName.indexOf(':') > -1 || jcrName.indexOf('/') > -1)) {
            throw new IllegalArgumentException("Local name may not contain ':' nor '/'");
        }

        if (nameStart == len || state == STATE_NAME_START) {
            throw new IllegalArgumentException("Local name must not be empty");
        }
        if (trailingSpaces) {
            throw new IllegalArgumentException("Trailing spaces not allowed");
        }
    }