diff --git a/CHANGES_SINCE_3.1.0.txt b/CHANGES_SINCE_3.1.0.txt index 1e074aaeb..b4f5068c1 100644 --- a/CHANGES_SINCE_3.1.0.txt +++ b/CHANGES_SINCE_3.1.0.txt @@ -109,3 +109,4 @@ * 改进Navigator接口,添加了forwardTo(target, action, actionEvent)方法,使之可内部重定向到指定action。 * Bugfix: 当requestContext初始化失败时,错误处理程序报NPE的问题。 +* 改进:pipeline-conditions: 支持反向pattern:如果以name="!xxx",则表示不匹配xxx。 diff --git a/webx/turbine/src/main/java/com/alibaba/citrus/turbine/pipeline/condition/PathCondition.java b/webx/turbine/src/main/java/com/alibaba/citrus/turbine/pipeline/condition/PathCondition.java index 8e23d01e1..0f3472c2d 100644 --- a/webx/turbine/src/main/java/com/alibaba/citrus/turbine/pipeline/condition/PathCondition.java +++ b/webx/turbine/src/main/java/com/alibaba/citrus/turbine/pipeline/condition/PathCondition.java @@ -20,6 +20,7 @@ import static com.alibaba.citrus.springext.util.SpringExtUtil.*; import static com.alibaba.citrus.util.ObjectUtil.*; import static com.alibaba.citrus.util.StringUtil.*; +import static com.alibaba.citrus.util.regex.MatchResultSubstitution.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -43,6 +44,7 @@ public class PathCondition extends AbstractTurbineCondition { public final static String DEFAULT_VAR = "subst"; private Pattern[] patterns; + private boolean[] negativePatterns; private String[] patternStrings; private String var; @@ -50,13 +52,23 @@ public void setName(String patterns) { if (patterns != null) { this.patternStrings = StringUtil.split(patterns, ", "); this.patterns = new Pattern[patternStrings.length]; + this.negativePatterns = new boolean[patternStrings.length]; for (int i = 0; i < patternStrings.length; i++) { - this.patterns[i] = Pattern.compile(patternStrings[i]); + compilePattern(patternStrings[i], i); } } } + private void compilePattern(String patternString, int index) { + if (patternString.startsWith("!")) { + this.negativePatterns[index] = true; + patternString = patternString.substring(1); + } + + this.patterns[index] = Pattern.compile(patternString); + } + public void setVar(String var) { this.var = trimToNull(var); } @@ -66,12 +78,14 @@ public final boolean isSatisfied(PipelineStates states) { for (int i = 0; i < patterns.length; i++) { Matcher matcher = patterns[i].matcher(path); + boolean matched = matcher.find(); + boolean negative = negativePatterns[i]; - if (matcher.find()) { + if (negative != matched) { log(patternStrings[i]); String var = defaultIfNull(this.var, DEFAULT_VAR); - Substitution subst = new MatchResultSubstitution(matcher); + Substitution subst = new MatchResultSubstitution(negative ? EMPTY_MATCH_RESULT : matcher); states.setAttribute(var, subst); diff --git a/webx/turbine/src/test/config/WEB-INF/webx-app1.xml b/webx/turbine/src/test/config/WEB-INF/webx-app1.xml index 28f997bde..560a24df4 100644 --- a/webx/turbine/src/test/config/WEB-INF/webx-app1.xml +++ b/webx/turbine/src/test/config/WEB-INF/webx-app1.xml @@ -8,6 +8,7 @@ xmlns:valves="http://www.alibaba.com/schema/services/pipeline/valves" xmlns:pull-tools="http://www.alibaba.com/schema/services/pull/factories" xmlns:engines="http://www.alibaba.com/schema/services/template/engines" + xmlns:c="http://www.alibaba.com/schema/services/pipeline/conditions" xsi:schemaLocation=" http://www.alibaba.com/schema/services http://localhost:8080/schema/services.xsd http://www.alibaba.com/schema/services/data-resolver/factories http://localhost:8080/schema/services-data-resolver-factories.xsd @@ -16,11 +17,23 @@ http://www.alibaba.com/schema/services/pipeline/valves http://localhost:8080/schema/services-pipeline-valves.xsd http://www.alibaba.com/schema/services/pull/factories http://localhost:8080/schema/services-pull-factories.xsd http://www.alibaba.com/schema/services/template/engines http://localhost:8080/schema/services-template-engines.xsd + http://www.alibaba.com/schema/services/pipeline/conditions http://localhost:8080/schema/services-pipeline-conditions.xsd http://www.springframework.org/schema/beans http://localhost:8080/schema/www.springframework.org/schema/beans/spring-beans.xsd "> + + + + + + + + + + + diff --git a/webx/turbine/src/test/java/com/alibaba/citrus/turbine/pipeline/valve/PathConditionTests.java b/webx/turbine/src/test/java/com/alibaba/citrus/turbine/pipeline/valve/PathConditionTests.java new file mode 100644 index 000000000..a036e7a7e --- /dev/null +++ b/webx/turbine/src/test/java/com/alibaba/citrus/turbine/pipeline/valve/PathConditionTests.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2002-2013 Alibaba Group Holding Limited. + * All rights reserved. + * + * 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.alibaba.citrus.turbine.pipeline.valve; + +import static org.junit.Assert.*; + +import com.alibaba.citrus.service.pipeline.PipelineContext; +import com.alibaba.citrus.service.pipeline.Valve; +import com.alibaba.citrus.service.pipeline.impl.PipelineImpl; +import com.alibaba.citrus.util.regex.Substitution; +import org.junit.Test; + +public class PathConditionTests extends AbstractValveTests { + private static Substitution subst1; + private static Substitution subst2; + + @Test + public void test_pathCondition_match() throws Exception { + pipeline = (PipelineImpl) factory.getBean("pathCondition"); + assertNotNull(pipeline); + assertNotNull(rundata); + + getInvocationContext("http://localhost/app1/helloworld.jhtml"); + initRequestContext(); + pipeline.newInvocation().invoke(); + + assertNotNull(subst1); + assertNull(subst2); + assertEquals("world", subst1.substitute("$1")); + } + + @Test + public void test_pathCondition_negativeMatch() throws Exception { + pipeline = (PipelineImpl) factory.getBean("pathCondition"); + assertNotNull(pipeline); + assertNotNull(rundata); + + getInvocationContext("http://localhost/app1/xyz.jhtml"); + initRequestContext(); + pipeline.newInvocation().invoke(); + + assertNull(subst1); + assertNotNull(subst2); + assertEquals("$1", subst2.substitute("$1")); + } + + public static class MyClass implements Valve { + public void invoke(PipelineContext pipelineContext) throws Exception { + subst1 = (Substitution) pipelineContext.getAttribute("v1"); + subst2 = (Substitution) pipelineContext.getAttribute("v2"); + } + } +}