/** * Project: dubbo.registry.server * * File Created at Oct 20, 2010 * $Id: RouteRuleUtils.java 181192 2012-06-21 05:05:47Z tony.chenl $ * * Copyright 1999-2100 Alibaba.com Corporation Limited. * All rights reserved. * * This software is the confidential and proprietary information of * Alibaba Company. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Alibaba.com. */ package com.alibaba.dubbo.registry.common.route; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import com.alibaba.dubbo.common.utils.StringUtils; /** * @author william.liangf * @author ding.lid */ public class RouteRuleUtils { private RouteRuleUtils() {} /** * 把条件的一个键值展开后,合并到另外指定的键值中。 * @param <T> 集合类型 * @param condition 条件 * @param srcKeyName 要展开的键值 * @param destKeyName 合并到的键值 * @param expandName2Set 进行展开的值到值的映射 */ public static <T extends Collection<String>> Map<String, RouteRule.MatchPair> expandCondition( Map<String, RouteRule.MatchPair> condition, String srcKeyName, String destKeyName, Map<String, T> expandName2Set) { if(null == condition || StringUtils.isEmpty(srcKeyName) || StringUtils.isEmpty(destKeyName)) { return condition; } RouteRule.MatchPair matchPair = condition.get(srcKeyName); if(matchPair == null) { return condition; } Map<String, RouteRule.MatchPair> ret = new HashMap<String, RouteRule.MatchPair>(); Iterator<Entry<String, RouteRule.MatchPair>> iterator = condition.entrySet().iterator(); for(; iterator.hasNext();) { Entry<String, RouteRule.MatchPair> entry = iterator.next(); String condName = entry.getKey(); // 即不是源也不目的 if(!condName.equals(srcKeyName) && !condName.equals(destKeyName)) { RouteRule.MatchPair p = entry.getValue(); if(p != null) ret.put(condName, p); } // 等于源 else if(condName.equals(srcKeyName)) { RouteRule.MatchPair from = condition.get(srcKeyName); RouteRule.MatchPair to = condition.get(destKeyName); // 没有可Expand条目 if(from == null || from.getMatches().isEmpty() && from.getUnmatches().isEmpty()) { if(to != null) ret.put(destKeyName, to); continue; } Set<String> matches = new HashSet<String>(); Set<String> unmatches = new HashSet<String>(); // 添加上Expand来的条目 for(String s : from.getMatches()) { if(expandName2Set == null || !expandName2Set.containsKey(s)) continue; matches.addAll(expandName2Set.get(s)); } for(String s : from.getUnmatches()) { if(expandName2Set == null || !expandName2Set.containsKey(s)) continue; unmatches.addAll(expandName2Set.get(s)); } // 添加原来的条目 if(to != null) { matches.addAll(to.getMatches()); unmatches.addAll(to.getUnmatches()); } ret.put(destKeyName, new RouteRule.MatchPair(matches, unmatches)); } // else 是 Key == destKeyName 的情况,无操作 } return ret; } /** * 判断KV(即条件对应的样本)是否符合条件。 * * @param condition 条件,可以包含变量声明。 如<code>{key1={matches={value1,value2,$var1},unmatches={Vx,Vy,$var2}}}</code> * @param valueParams 条件中插值变量的值集合 * @param kv 校验条件的样本 * @see RouteRule */ public static boolean isMatchCondition(Map<String, RouteRule.MatchPair> condition, Map<String, String> valueParams, Map<String, String> kv) { if (condition != null && condition.size() > 0) { for (Map.Entry<String, RouteRule.MatchPair> entry : condition.entrySet()) { String condName = entry.getKey(); RouteRule.MatchPair p = entry.getValue(); String value = kv.get(condName); Set<String> matches = p.getMatches(); if (matches != null && matches.size() > 0 && ! ParseUtils.isMatchGlobPatternsNeedInterpolate(matches, valueParams, value)) { // 如何Value为null,返回False // 不满足 匹配 return false; } Set<String> unmatches = p.getUnmatches(); if (unmatches != null && unmatches.size() > 0 && ParseUtils.isMatchGlobPatternsNeedInterpolate(unmatches, valueParams, value)) { // 满足了 不匹配 return false; } } } return true; } /** * 返回被RouteRule的When的service匹配到的Service。使用Glob匹配。 */ public static Set<String> filterServiceByRule(List<String> services, RouteRule rule) { if(null == services || services.isEmpty() || rule == null) { return new HashSet<String>(); } RouteRule.MatchPair p = rule.getWhenCondition().get("service"); if(p == null) { return new HashSet<String>(); } Set<String> filter = ParseUtils.filterByGlobPattern(p.getMatches(), services); Set<String> set = ParseUtils.filterByGlobPattern(p.getUnmatches(), services); filter.addAll(set); return filter; } }