Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2013 Red Hat, Inc., and individual contributors
   * as indicated by the @author tags.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package io.undertow.server.handlers.builder;
 
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;

Parser that can build a handler from a string representation. The underlying syntax is quite simple, and example is shown below:

rewrite[value="/path"] If a handler is only being passed a single parameter then the parameter name can be omitted. Strings can be enclosed in optional double or single quotations marks, and quotation marks can be escaped using \".

Array types are represented via a comma separated list of values enclosed in curly braces.

TODO: some way of

Author(s):
Stuart Douglas
 
 public class HandlerParser {
 
 
     public static final HandlerWrapper parse(String stringfinal ClassLoader classLoader) {
         final Map<StringHandlerBuilderbuilders = loadBuilders(classLoader);
         final ExchangeAttributeParser attributeParser = ExchangeAttributes.parser(classLoader);
         return parse(stringbuildersattributeParser);
     }
 
     private static Map<StringHandlerBuilderloadBuilders(final ClassLoader classLoader) {
         ServiceLoader<HandlerBuilderloader = ServiceLoader.load(HandlerBuilder.classclassLoader);
         final Map<StringHandlerBuilderret = new HashMap<StringHandlerBuilder>();
         for (HandlerBuilder builder : loader) {
             if (ret.containsKey(builder.name())) {
                 if (ret.get(builder.name()).getClass() != builder.getClass()) {
                     throw ..moreThanOneHandlerWithName(builder.name(), builder.getClass(), ret.get(builder.name()).getClass());
                 }
             } else {
                 ret.put(builder.name(), builder);
             }
         }
         return ret;
     }
 
     private static IllegalStateException error(final String stringint posString reason) {
         StringBuilder b = new StringBuilder();
         b.append(string);
         b.append('\n');
         for (int i = 0; i < pos; ++i) {
             b.append(' ');
         }
         b.append('^');
         throw ..errorParsingHandlerString(reasonb.toString());
     }
 
     static HandlerWrapper parse(final String stringfinal Map<StringHandlerBuilderbuildersfinal ExchangeAttributeParser attributeParser) {
 
         //shunting yard algorithm
         //gets rid or parentheses and fixes up operator ordering
         Deque<Tokentokens = tokenize(string);
         return parseBuilder(stringtokens.pop(), tokensbuildersattributeParser);
 
     }
 
    private static HandlerWrapper parseBuilder(final String stringfinal Token tokenfinal Deque<Tokentokensfinal Map<StringHandlerBuilderbuildersfinal ExchangeAttributeParser attributeParser) {
        HandlerBuilder builder = builders.get(token.token);
        if (builder == null) {
            throw error(stringtoken.position"no predicate named " + token.token);
        }
        Token next = tokens.peek();
        if (next.token.equals("[")) {
            final Map<StringObjectvalues = new HashMap<StringObject>();
            tokens.poll();
            next = tokens.poll();
            if (next == null) {
                throw error(stringstring.length(), "Unexpected end of input");
            }
            if (next.token.equals("{")) {
                return handleSingleArrayValue(stringbuildertokensnextattributeParser);
            }
            while (!next.token.equals("]")) {
                Token equals = tokens.poll();
                if (!equals.token.equals("=")) {
                    if (equals.token.equals("]") && values.isEmpty()) {
                        //single value case
                        return handleSingleValue(stringbuildernextattributeParser);
                    } else if (equals.token.equals(",")) {
                        tokens.push(equals);
                        tokens.push(next);
                        return handleSingleVarArgsValue(stringbuildertokensnextattributeParser);
                    }
                    throw error(stringequals.position"Unexpected token");
                }
                Token value = tokens.poll();
                if (value == null) {
                    throw error(stringstring.length(), "Unexpected end of input");
                }
                if (value.token.equals("{")) {
                    values.put(next.tokenreadArrayType(stringtokensnextbuilderattributeParser"}"));
                } else {
                    if (isOperator(value.token) || isSpecialChar(value.token)) {
                        throw error(stringvalue.position"Unexpected token");
                    }
                    Class<?> type = builder.parameters().get(next.token);
                    if (type == null) {
                        throw error(stringnext.position"Unexpected parameter " + next.token);
                    }
                    values.put(next.tokencoerceToType(stringvaluetypeattributeParser));
                }
                next = tokens.poll();
                if (next == null) {
                    throw error(stringstring.length(), "Unexpected end of input");
                }
                if (!next.token.equals("]")) {
                    if (!next.token.equals(",")) {
                        throw error(stringstring.length(), "Expecting , or ]");
                    }
                    next = tokens.poll();
                    if (next == null) {
                        throw error(stringstring.length(), "Unexpected end of input");
                    }
                }
            }
            checkParameters(stringnext.positionvaluesbuilder);
            return builder.build(values);
        } else {
            throw error(stringnext.position"Unexpected character");
        }
    }
    private static HandlerWrapper handleSingleArrayValue(final String stringfinal HandlerBuilder builderfinal Deque<Tokentokensfinal Token tokenfinal ExchangeAttributeParser attributeParser) {
        String sv = builder.defaultParameter();
        if (sv == null) {
            throw error(stringtoken.position"default parameter not supported");
        }
        Object array = readArrayType(stringtokensnew Token(svtoken.position), builderattributeParser"}");
        Token close = tokens.poll();
        if (!close.token.equals("]")) {
            throw error(stringclose.position"expected ]");
        }
        return builder.build(Collections.singletonMap(svarray));
    }
    private static HandlerWrapper handleSingleVarArgsValue(final String stringfinal HandlerBuilder builderfinal Deque<Tokentokensfinal Token tokenfinal ExchangeAttributeParser attributeParser) {
        String sv = builder.defaultParameter();
        if (sv == null) {
            throw error(stringtoken.position"default parameter not supported");
        }
        Object array = readArrayType(stringtokensnew Token(svtoken.position), builderattributeParser"]");
        return builder.build(Collections.singletonMap(svarray));
    }
    private static Object readArrayType(final String stringfinal Deque<TokentokensToken paramNameHandlerBuilder builderfinal ExchangeAttributeParser attributeParserString expectedEndToken) {
        Class<?> type = builder.parameters().get(paramName.token);
        if (type == null) {
            throw error(stringparamName.position"no parameter called " + paramName.token);
        } else if (!type.isArray()) {
            throw error(stringparamName.position"parameter is not an array type " + paramName.token);
        }
        Class<?> componentType = type.getComponentType();
        final List<Objectvalues = new ArrayList<Object>();
        Token token = tokens.poll();
        while (token != null) {
            Token commaOrEnd = tokens.poll();
            values.add(coerceToType(stringtokencomponentTypeattributeParser));
            if (commaOrEnd.token.equals(expectedEndToken)) {
                Object array = Array.newInstance(componentTypevalues.size());
                for (int i = 0; i < values.size(); ++i) {
                    Array.set(arrayivalues.get(i));
                }
                return array;
            } else if (!commaOrEnd.token.equals(",")) {
                throw error(stringcommaOrEnd.position"expected either , or }");
            }
            token = tokens.poll();
        }
        throw error(stringstring.length(), "unexpected end of input in array");
    }
    private static HandlerWrapper handleSingleValue(final String stringfinal HandlerBuilder builderfinal Token nextfinal ExchangeAttributeParser attributeParser) {
        String sv = builder.defaultParameter();
        if (sv == null) {
            throw error(stringnext.position"default parameter not supported");
        }
        Map<StringObjectvalues = Collections.singletonMap(svcoerceToType(stringnextbuilder.parameters().get(sv), attributeParser));
        checkParameters(stringnext.positionvaluesbuilder);
        return builder.build(values);
    }
    private static void checkParameters(final String stringint posfinal Map<StringObjectvaluesfinal HandlerBuilder builder) {
        final Set<Stringrequired = new HashSet<String>(builder.requiredParameters());
        for (String key : values.keySet()) {
            required.remove(key);
        }
        if (!required.isEmpty()) {
            throw error(stringpos"Missing required parameters " + required);
        }
    }
    private static Object coerceToType(final String stringfinal Token tokenfinal Class<?> typefinal ExchangeAttributeParser attributeParser) {
        if (type.isArray()) {
            Object array = Array.newInstance(type.getComponentType(), 1);
            Array.set(array, 0, coerceToType(stringtokentype.getComponentType(), attributeParser));
            return array;
        }
        if (type == String.class) {
            return token.token;
        } else if (type.equals(Boolean.class) || type.equals(boolean.class)) {
            return Boolean.valueOf(token.token);
        } else if (type.equals(Byte.class) || type.equals(byte.class)) {
            return Byte.valueOf(token.token);
        } else if (type.equals(Character.class) || type.equals(char.class)) {
            if (token.token.length() != 1) {
                throw error(stringtoken.position"Cannot coerce " + token.token + " to a Character");
            }
            return Character.valueOf(token.token.charAt(0));
        } else if (type.equals(Short.class) || type.equals(short.class)) {
            return Short.valueOf(token.token);
        } else if (type.equals(Integer.class) || type.equals(int.class)) {
            return Integer.valueOf(token.token);
        } else if (type.equals(Long.class) || type.equals(long.class)) {
            return Long.valueOf(token.token);
        } else if (type.equals(Float.class) || type.equals(float.class)) {
            return Float.valueOf(token.token);
        } else if (type.equals(Double.class) || type.equals(double.class)) {
            return Double.valueOf(token.token);
        } else if (type.equals(ExchangeAttribute.class)) {
            return attributeParser.parse(token.token);
        }
        return token.token;
    }
    private static int precedence(String operator) {
        if (operator.equals("not")) {
            return 3;
        } else if (operator.equals("and")) {
            return 2;
        } else if (operator.equals("or")) {
            return 1;
        }
        throw new IllegalStateException();
    }
    private static boolean isOperator(final String op) {
        return op.equals("and") || op.equals("or") || op.equals("not");
    }
    private static boolean isSpecialChar(String token) {
        if (token.length() != 1) {
            return false;
        }
        char c = token.charAt(0);
        switch (c) {
            case '(':
            case ')':
            case ',':
            case '=':
            case '{':
            case '}':
            case '[':
            case ']':
                return true;
            default:
                return false;
        }
    }
    static Deque<Tokentokenize(final String string) {
        char currentStringDelim = 0;
        boolean inVariable = false;
        int pos = 0;
        StringBuilder current = new StringBuilder();
        Deque<Tokenret = new ArrayDeque<Token>();
        while (pos < string.length()) {
            char c = string.charAt(pos);
            if (currentStringDelim != 0) {
                if (c == currentStringDelim && current.charAt(current.length() - 1) != '\\') {
                    ret.add(new Token(current.toString(), pos));
                    current.setLength(0);
                    currentStringDelim = 0;
                } else {
                    current.append(c);
                }
            } else {
                switch (c) {
                    case ' ':
                    case '\t': {
                        if (current.length() != 0) {
                            ret.add(new Token(current.toString(), pos));
                            current.setLength(0);
                        }
                        break;
                    }
                    case '(':
                    case ')':
                    case ',':
                    case '=':
                    case '[':
                    case ']':
                    case '{':
                    case '}': {
                        if (inVariable) {
                            current.append(c);
                            if (c == '}') {
                                inVariable = false;
                            }
                        } else {
                            if (current.length() != 0) {
                                ret.add(new Token(current.toString(), pos));
                                current.setLength(0);
                            }
                            ret.add(new Token("" + cpos));
                        }
                        break;
                    }
                    case '"':
                    case '\'': {
                        if (current.length() != 0) {
                            throw error(stringpos"Unexpected token");
                        }
                        currentStringDelim = c;
                        break;
                    }
                    case '%': {
                        current.append(c);
                        if (string.charAt(pos + 1) == '{') {
                            inVariable = true;
                        }
                        break;
                    }
                    default:
                        current.append(c);
                }
            }
            ++pos;
        }
        if (current.length() > 0) {
            ret.add(new Token(current.toString(), string.length()));
        }
        return ret;
    }
    static final class Token {
        final String token;
        final int position;
        private Token(final String tokenfinal int position) {
            this. = token;
            this. = position;
        }
    }
New to GrepCode? Check out our FAQ X