/* * Copyright 2009-2016 Weibo, Inc. * * 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 com.networknt.registry.support.command; import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.networknt.config.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RpcCommandUtil { private static final Logger logger = LoggerFactory.getLogger(RpcCommand.class); /** * String to Command * * @param commandString string representation of rpc command * @return RpcCommand rpc command */ public static RpcCommand stringToCommand(String commandString) { try { return Config.getInstance().getMapper().readValue(commandString, RpcCommand.class); } catch (Exception e) { logger.error("Invalid JSON format " + commandString); return null; } } /** * Command to String * * @param command rpc command object * @return a string presentation of rpc command * @throws JsonProcessingException exception while processing JSON */ public static String commandToString(RpcCommand command) throws JsonProcessingException { return Config.getInstance().getMapper().writeValueAsString(command); } private static PatternEvaluator evaluator = new PatternEvaluator(); public static boolean match(String expression, String path) { if (expression == null || expression.length() == 0) { return false; } return evaluator.match(expression, path); } private static class PatternEvaluator { Pattern pattern = Pattern.compile("[a-zA-Z0-9_$.*]+"); Set<Character> all = ImmutableSet.of('(', ')', '0', '1', '!', '&', '|'); Map<Character, ImmutableSet<Character>> following = ImmutableMap.<Character, ImmutableSet<Character>>builder() .put('(', ImmutableSet.of('0', '1', '!')).put(')', ImmutableSet.of('|', '&', ')')).put('0', ImmutableSet.of('|', '&', ')')) .put('1', ImmutableSet.of('|', '&', ')')).put('!', ImmutableSet.of('(', '0', '1', '!')) .put('&', ImmutableSet.of('(', '0', '1', '!')).put('|', ImmutableSet.of('(', '0', '1', '!')).build(); boolean match(String expression, String path) { // match each item and replace with 0 or 1 Matcher matcher = pattern.matcher(expression.replaceAll("\\s+", "")); StringBuffer buffer = new StringBuffer(); while (matcher.find()) { String s = matcher.group(); int idx = s.indexOf('*'); if (idx != -1) { matcher.appendReplacement(buffer, path.startsWith(s.substring(0, idx)) ? "1" : "0"); } else { matcher.appendReplacement(buffer, s.equals(path) ? "1" : "0"); } } matcher.appendTail(buffer); String result1 = buffer.toString(); LinkedList<LinkedList<Character>> outer = new LinkedList<LinkedList<Character>>(); LinkedList<Character> inner = new LinkedList<Character>(); inner.push('#'); outer.push(inner); int i = 0; int len = result1.length(); while (outer.size() > 0 && i < len) { LinkedList<Character> sub = outer.peekLast(); while (sub.size() > 0 && i < len) { char curr = result1.charAt(i++); support(curr); char prev = sub.peekFirst(); if (prev != '#') { supportFollowing(prev, curr); } switch (curr) { case '(': sub = new LinkedList<Character>(); sub.push('#'); outer.push(sub); break; case ')': outer.removeFirst(); outer.peekFirst().push(evalWithinParentheses(sub)); sub = outer.peekFirst(); break; default: sub.push(curr); } } } if (outer.size() != 1) { throw new IllegalArgumentException("Syntax error!"); } char result = evalWithinParentheses(outer.peekLast()); return result == '1'; } /** * eval within parentheses * * @param list * @return char */ char evalWithinParentheses(LinkedList<Character> list) { char operand = list.pop(); if (operand != '0' && operand != '1') { syntaxError(); } // 处理! while (!list.isEmpty()) { char curr = list.pop(); if (curr == '!') { operand = operand == '0' ? '1' : '0'; } else if (curr == '#') { break; } else { if (operand == '0' || operand == '1') { list.addLast(operand); list.addLast(curr); operand = '\0'; } else { operand = curr; } } } list.addLast(operand); // handle & list.addLast('#'); operand = list.pop(); while (!list.isEmpty()) { char curr = list.pop(); if (curr == '&') { char c = list.pop(); operand = (operand == '1' && c == '1') ? '1' : '0'; } else if (curr == '#') { break; } else { if (operand == '0' || operand == '1') { list.addLast(operand); list.addLast(curr); operand = '\0'; } else { operand = curr; } } } list.addLast(operand); // handle | operand = '0'; while (!list.isEmpty() && (operand = list.pop()) != '1'); return operand; } void syntaxError() { throw new IllegalArgumentException("Syntax error! only support ()!&| in priority."); } void syntaxError(String s) { throw new IllegalArgumentException("Syntax error: " + s); } void support(char c) { if (!all.contains(c)) { syntaxError("Unsupported Character " + c); } } void supportFollowing(char prev, char c) { if (!following.get(prev).contains(c)) { syntaxError("prev=" + prev + ", c=" + c); } } } }