From ea6fc0541f78baed9575477c0152da11297caa33 Mon Sep 17 00:00:00 2001 From: Paul Tuckey Date: Mon, 3 Jul 2023 09:38:41 +1200 Subject: [PATCH 1/3] progress --- LICENSE.txt | 76 +- .../annotation/HttpExceptionHandler.java | 96 +- .../urlrewrite/annotation/HttpJson.java | 116 +- .../urlrewrite/annotation/HttpParam.java | 130 +- .../urlrewrite/annotation/HttpUrl.java | 118 +- .../annotation/HttpUrlAPTFactory.java | 196 +- .../HttpUrlAnnotationProcessor.java | 784 +++---- .../UrlRewriteAnnotationProcessor.java | 938 ++++----- .../filters/urlrewrite/json/JSONRPCBean.java | 130 +- .../urlrewrite/json/JSONRPCErrorBean.java | 146 +- .../annotation/SampleMatchAction.java | 242 +-- .../MockRewriteMatch.java | 2 +- .../urlrewriteviacontainer/TestRunObj.java | 2 +- .../web/filters/urlrewrite/CatchElem.java | 330 +-- .../web/filters/urlrewrite/ClassRule.java | 632 +++--- .../web/filters/urlrewrite/Condition.java | 1574 +++++++------- .../filters/urlrewrite/ConditionMatch.java | 112 +- .../tuckey/web/filters/urlrewrite/Conf.java | 1278 ++++++------ .../web/filters/urlrewrite/ConfHandler.java | 288 +-- .../urlrewrite/NormalRewrittenUrl.java | 736 +++---- .../web/filters/urlrewrite/NormalRule.java | 502 ++--- .../web/filters/urlrewrite/OutboundRule.java | 286 +-- .../urlrewrite/RewrittenOutboundUrl.java | 156 +- .../web/filters/urlrewrite/RewrittenUrl.java | 112 +- .../filters/urlrewrite/RewrittenUrlClass.java | 136 +- .../tuckey/web/filters/urlrewrite/Rule.java | 184 +- .../web/filters/urlrewrite/RuleBase.java | 1158 +++++------ .../web/filters/urlrewrite/RuleChain.java | 360 ++-- .../urlrewrite/RuleExecutionOutput.java | 390 ++-- .../tuckey/web/filters/urlrewrite/Run.java | 1432 ++++++------- .../web/filters/urlrewrite/RunConfig.java | 158 +- .../web/filters/urlrewrite/Runnable.java | 88 +- .../web/filters/urlrewrite/SetAttribute.java | 780 +++---- .../tuckey/web/filters/urlrewrite/Status.java | 1132 +++++----- .../web/filters/urlrewrite/TypeConverter.java | 664 +++--- .../filters/urlrewrite/UrlRewriteDocTask.java | 222 +- .../filters/urlrewrite/UrlRewriteFilter.java | 1138 +++++----- .../filters/urlrewrite/UrlRewriteServlet.java | 248 +-- .../urlrewrite/UrlRewriteWrappedRequest.java | 222 +- .../urlrewrite/UrlRewriteWrappedResponse.java | 316 +-- .../web/filters/urlrewrite/UrlRewriter.java | 724 +++---- .../urlrewrite/extend/RewriteMatch.java | 148 +- .../urlrewrite/extend/RewriteRule.java | 148 +- .../urlrewrite/functions/CssVarFunction.java | 240 ++- .../urlrewrite/functions/StringFunctions.java | 366 ++-- .../urlrewrite/json/JsonRewriteMatch.java | 270 +-- .../urlrewrite/sample/SampleConfExt.java | 82 +- .../sample/SampleMultiUrlRewriteFilter.java | 132 +- .../urlrewrite/sample/SampleRewriteMatch.java | 144 +- .../urlrewrite/sample/SampleRewriteRule.java | 136 +- .../substitution/BackReferenceReplacer.java | 270 +-- .../ChainedSubstitutionFilters.java | 144 +- .../substitution/FunctionReplacer.java | 316 +-- .../substitution/MatcherReplacer.java | 234 +-- .../substitution/PatternReplacer.java | 150 +- .../substitution/SubstitutionContext.java | 118 +- .../substitution/SubstitutionFilter.java | 44 +- .../substitution/SubstitutionFilterChain.java | 48 +- .../substitution/UnescapeReplacer.java | 102 +- .../substitution/VariableReplacer.java | 606 +++--- .../web/filters/urlrewrite/utils/Log.java | 996 ++++----- .../utils/ModRewriteConfLoader.java | 1232 +++++------ .../filters/urlrewrite/utils/NumberUtils.java | 138 +- .../urlrewrite/utils/RegexMatcher.java | 202 +- .../urlrewrite/utils/RegexPattern.java | 134 +- .../urlrewrite/utils/ServerNameMatcher.java | 162 +- .../utils/StringMatchingMatcher.java | 122 +- .../utils/StringMatchingPattern.java | 90 +- .../StringMatchingPatternSyntaxException.java | 98 +- .../filters/urlrewrite/utils/StringUtils.java | 204 +- .../filters/urlrewrite/utils/TypeUtils.java | 260 ++- .../filters/urlrewrite/utils/URLDecoder.java | 202 +- .../filters/urlrewrite/utils/URLEncoder.java | 450 ++-- .../urlrewrite/utils/WildcardMatcher.java | 342 +-- .../urlrewrite/utils/WildcardPattern.java | 110 +- .../web/filters/urlrewrite/ConditionTest.java | 2 +- .../web/filters/urlrewrite/ConfTest.java | 294 +-- .../filters/urlrewrite/OutboundRuleTest.java | 438 ++-- .../filters/urlrewrite/RewrittenUrlTest.java | 256 +-- .../web/filters/urlrewrite/RuleTest.java | 1844 ++++++++--------- .../web/filters/urlrewrite/RunTest.java | 724 +++---- .../filters/urlrewrite/SetAttributeTest.java | 466 ++--- .../web/filters/urlrewrite/StatusTest.java | 170 +- .../filters/urlrewrite/TestRewriteMatch.java | 100 +- .../web/filters/urlrewrite/TestRuleObj.java | 102 +- .../web/filters/urlrewrite/TestServlet.java | 256 +-- .../filters/urlrewrite/UrlDecoderTest.java | 184 +- .../urlrewrite/UrlRewriteFilterTest.java | 160 +- .../urlrewrite/UrlRewriteTestCaseTest.java | 102 +- .../UrlRewriteWrappedResponseTest.java | 144 +- .../filters/urlrewrite/UrlRewriterTest.java | 872 ++++---- .../urlrewrite/json/JsonRewriteMatchTest.java | 162 +- .../urlrewrite/test/MockRewriteMatch.java | 140 +- .../filters/urlrewrite/test/TestRunObj.java | 496 ++--- .../urlrewrite/test/UrlRewriteTestCase.java | 2 +- .../web/filters/urlrewrite/utils/LogTest.java | 172 +- .../utils/StringMatchingMatcherTest.java | 214 +- .../web/testhelper/BenchmarkRunner.java | 638 +++--- .../web/testhelper/MockFilterChain.java | 148 +- .../web/testhelper/MockFilterConfig.java | 134 +- .../tuckey/web/testhelper/MockRequest.java | 2 +- .../web/testhelper/MockRequestDispatcher.java | 178 +- .../tuckey/web/testhelper/MockResponse.java | 2 +- .../web/testhelper/MockServletContext.java | 2 +- .../tuckey/web/testhelper/MockSession.java | 2 +- 105 files changed, 17794 insertions(+), 17386 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 88d5c070..4fc48331 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,38 +1,38 @@ - -Copyright (c) 2005-2012, Paul Tuckey -All rights reserved. -==================================================================== -Licensed under the BSD License. Text as follows. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - Neither the name tuckey.org nor the names of its contributors - may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -==================================================================== - -Please note that some code used in UrlRewriteFilter is under other -permissive licenses. - -==================================================================== + +Copyright (c) 2005-2023, Paul Tuckey +All rights reserved. +==================================================================== +Licensed under the BSD License. Text as follows. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + - Neither the name tuckey.org nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +==================================================================== + +Please note that some code used in UrlRewriteFilter is under other +permissive licenses. + +==================================================================== diff --git a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpExceptionHandler.java b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpExceptionHandler.java index 5ef5251b..81522f84 100644 --- a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpExceptionHandler.java +++ b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpExceptionHandler.java @@ -1,48 +1,48 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.METHOD) -public @interface HttpExceptionHandler { - - String value() default "[ unassigned ]"; - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.METHOD) +public @interface HttpExceptionHandler { + + String value() default "[ unassigned ]"; + +} diff --git a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpJson.java b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpJson.java index ab54cd56..ed6e3c96 100644 --- a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpJson.java +++ b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpJson.java @@ -1,59 +1,59 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * A marker annotation for allowing a method to be called via HTTP and the results to be returned as JSON. - */ -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.METHOD) -public @interface HttpJson { - - String value() default "[ unassigned ]"; - - /** - * A weighting to be applied to the url, if higher it will move this url to the "top" if lower more towards the - * "bottom". - * - * @return weight - */ - int weight() default 0; - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A marker annotation for allowing a method to be called via HTTP and the results to be returned as JSON. + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.METHOD) +public @interface HttpJson { + + String value() default "[ unassigned ]"; + + /** + * A weighting to be applied to the url, if higher it will move this url to the "top" if lower more towards the + * "bottom". + * + * @return weight + */ + int weight() default 0; + } \ No newline at end of file diff --git a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpParam.java b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpParam.java index 88518192..90b6f092 100644 --- a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpParam.java +++ b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpParam.java @@ -1,65 +1,65 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation for matching parameters in HTTP requests. - *

- * Usage: - *

- * \@HttpUrl("^/search/(people|objects)/$") - * public void someMethod(@HttpParam("fName") String firstName, @HttpParam String lastName) - * for the request /search/people/?fName=bob&lastName=smith - * will invoke the method with someMethod("bob", "smith", "people") - * to be used in conjunction with @HttpUrl - */ -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.PARAMETER) -public @interface HttpParam { - - /** - * If not set will use the name of the parameter (case insensitive). - * can be a expression ie, $1 (the first group of @HttpUrl regexp), %{header:user-agent} (the user agent header). - * - * @return value - */ - String value() default "[ unassigned ]"; - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for matching parameters in HTTP requests. + *

+ * Usage: + *

+ * \@HttpUrl("^/search/(people|objects)/$") + * public void someMethod(@HttpParam("fName") String firstName, @HttpParam String lastName) + * for the request /search/people/?fName=bob&lastName=smith + * will invoke the method with someMethod("bob", "smith", "people") + * to be used in conjunction with @HttpUrl + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.PARAMETER) +public @interface HttpParam { + + /** + * If not set will use the name of the parameter (case insensitive). + * can be a expression ie, $1 (the first group of @HttpUrl regexp), %{header:user-agent} (the user agent header). + * + * @return value + */ + String value() default "[ unassigned ]"; + +} diff --git a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrl.java b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrl.java index b5bb98b9..8abb049b 100644 --- a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrl.java +++ b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrl.java @@ -1,59 +1,59 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation for matching URL's in HTTP requests. - */ -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.METHOD) -public @interface HttpUrl { - - String value(); - - /** - * A weighting to be applied to the url, if higher it will move this url to the "top" if lower more towards the - * "bottom". - * - * @return weight - */ - int weight() default 0; - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for matching URL's in HTTP requests. + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.METHOD) +public @interface HttpUrl { + + String value(); + + /** + * A weighting to be applied to the url, if higher it will move this url to the "top" if lower more towards the + * "bottom". + * + * @return weight + */ + int weight() default 0; + +} diff --git a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrlAPTFactory.java b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrlAPTFactory.java index 1778e0e0..299dfa19 100644 --- a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrlAPTFactory.java +++ b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrlAPTFactory.java @@ -1,98 +1,98 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.annotation; - -import com.sun.mirror.apt.AnnotationProcessor; -import com.sun.mirror.apt.AnnotationProcessorEnvironment; -import com.sun.mirror.apt.AnnotationProcessorFactory; -import com.sun.mirror.apt.AnnotationProcessors; -import com.sun.mirror.declaration.AnnotationTypeDeclaration; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -/** - * Annotation Processor Factory for UrlRewriteFilter annotations. - * - * @deprecated Use UrlRewriteAnnotationProcessor - */ -public class HttpUrlAPTFactory implements AnnotationProcessorFactory { - - /** - * Returns a note annotation processor. - * - * @return An annotation processor for note annotations if requested, - * otherwise, returns the NO_OP annotation processor. - */ - public AnnotationProcessor getProcessorFor(Set declarations, - AnnotationProcessorEnvironment env) { - AnnotationProcessor result; - if (declarations.isEmpty()) { - result = AnnotationProcessors.NO_OP; - } else { - result = new HttpUrlAnnotationProcessor(env); - } - return result; - - } - - /** - * This factory only builds processors for all UrlRewrite annotations. - * - * @return a collection containing only the note annotation name. - */ - public Collection supportedAnnotationTypes() { - Set set = new HashSet(); - set.add(HttpUrl.class.getName()); - set.add(HttpExceptionHandler.class.getName()); - set.add(HttpParam.class.getName()); - return set; - } - - /** - * Options supported by this annotation processor. - * - * @return collection of options. - */ - public Collection supportedOptions() { - Set set = new HashSet(); - set.add("-AsaveRulesTo"); - set.add("-AshowPositions"); - set.add("-Adebug"); - return set; - } -} - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.annotation; + +import com.sun.mirror.apt.AnnotationProcessor; +import com.sun.mirror.apt.AnnotationProcessorEnvironment; +import com.sun.mirror.apt.AnnotationProcessorFactory; +import com.sun.mirror.apt.AnnotationProcessors; +import com.sun.mirror.declaration.AnnotationTypeDeclaration; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * Annotation Processor Factory for UrlRewriteFilter annotations. + * + * @deprecated Use UrlRewriteAnnotationProcessor + */ +public class HttpUrlAPTFactory implements AnnotationProcessorFactory { + + /** + * Returns a note annotation processor. + * + * @return An annotation processor for note annotations if requested, + * otherwise, returns the NO_OP annotation processor. + */ + public AnnotationProcessor getProcessorFor(Set declarations, + AnnotationProcessorEnvironment env) { + AnnotationProcessor result; + if (declarations.isEmpty()) { + result = AnnotationProcessors.NO_OP; + } else { + result = new HttpUrlAnnotationProcessor(env); + } + return result; + + } + + /** + * This factory only builds processors for all UrlRewrite annotations. + * + * @return a collection containing only the note annotation name. + */ + public Collection supportedAnnotationTypes() { + Set set = new HashSet(); + set.add(HttpUrl.class.getName()); + set.add(HttpExceptionHandler.class.getName()); + set.add(HttpParam.class.getName()); + return set; + } + + /** + * Options supported by this annotation processor. + * + * @return collection of options. + */ + public Collection supportedOptions() { + Set set = new HashSet(); + set.add("-AsaveRulesTo"); + set.add("-AshowPositions"); + set.add("-Adebug"); + return set; + } +} + diff --git a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrlAnnotationProcessor.java b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrlAnnotationProcessor.java index 31802010..d38a0316 100644 --- a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrlAnnotationProcessor.java +++ b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/HttpUrlAnnotationProcessor.java @@ -1,392 +1,392 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.annotation; - -import com.sun.mirror.apt.AnnotationProcessor; -import com.sun.mirror.apt.AnnotationProcessorEnvironment; -import com.sun.mirror.apt.Filer; -import com.sun.mirror.apt.Messager; -import com.sun.mirror.declaration.AnnotationTypeDeclaration; -import com.sun.mirror.declaration.Declaration; -import com.sun.mirror.declaration.MethodDeclaration; -import com.sun.mirror.declaration.ParameterDeclaration; -import com.sun.mirror.util.SourcePosition; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - - -/** - * Annotation processor for UrlRewrite. Will search compiled classes for annotations and generate XML. - *

- * Processor for JDK 1.5. - * - * @deprecated use UrlRewriteAnnotationProcessor. - */ -public class HttpUrlAnnotationProcessor implements AnnotationProcessor { - - private AnnotationProcessorEnvironment environment; - private AnnotationTypeDeclaration httpUrlDeclaration; - private AnnotationTypeDeclaration httpExceptionHandlerDeclaration; - private List processedAnnotations = new ArrayList(); - private List httpExceptionHandlers = new ArrayList(); - private Messager messager; - private boolean showPositionsOfAnnotations = false; - private boolean debug = false; - - public HttpUrlAnnotationProcessor(AnnotationProcessorEnvironment env) { - environment = env; - messager = env.getMessager(); - // get the type declaration for the annotations we are processing for - httpUrlDeclaration = (AnnotationTypeDeclaration) environment.getTypeDeclaration(HttpUrl.class.getName()); - httpExceptionHandlerDeclaration = (AnnotationTypeDeclaration) environment.getTypeDeclaration(HttpExceptionHandler.class.getName()); - } - - public void process() { - Map options = environment.getOptions(); - Set keys = options.keySet(); - String saveRulesTo = null; - for (String key : keys) { - if (key.startsWith("-AsaveRulesTo=")) { - saveRulesTo = key.substring("-AsaveRulesTo=".length()); - } - if (key.startsWith("-AshowPositions=")) { - showPositionsOfAnnotations = "true".equalsIgnoreCase(key.substring("-AshowPositions=".length())); - } - if (key.startsWith("-Adebug=")) { - debug = "true".equalsIgnoreCase(key.substring("-Adebug=".length())); - } - } - debugMsg("Processing"); - if (saveRulesTo == null) { - messager.printError("ERROR: conf option must be specified"); - return; - } - - File confFile = new File(saveRulesTo); - PrintWriter pw; - boolean delFile = false; - try { - if (!confFile.exists()) { - if ( ! confFile.createNewFile() ) { - checkDirsExistMkdir(confFile.getParentFile()); - confFile.createNewFile(); - } - } - if (!confFile.canWrite()) throw new IOException("cannot write to " + confFile.getName()); - pw = environment.getFiler().createTextFile(Filer.Location.CLASS_TREE, "", confFile, null); - } catch (IOException e) { - e.printStackTrace(); - return; - } - try { - - // Get all declarations that use the HttpUrl annotation. - debugMsg("Looking for @HttpUrl"); - Collection urlDeclarations = environment.getDeclarationsAnnotatedWith(httpUrlDeclaration); - for (Declaration declaration : urlDeclarations) { - ProcessedHttpUrlAnnotation pa = processHttpUrlAnnotation(declaration); - if (pa == null) delFile = true; - else processedAnnotations.add(pa); - } - - // Get all declarations that use the HttpExceptionHandler annotation. - debugMsg("Looking for @HttpExceptionHandler"); - Collection exceptionDeclarations = environment.getDeclarationsAnnotatedWith(httpExceptionHandlerDeclaration); - for (Declaration declaration : exceptionDeclarations) { - ProcessedHttpExceptionAnnotation phea = processHttpExceptionHandlerAnnotation(declaration); - if (phea == null) delFile = true; - else httpExceptionHandlers.add(phea); - } - - if (processedAnnotations.size() > 0) { - messager.printNotice("Got " + processedAnnotations.size() + " @HttpUrl annotations"); - Collections.sort(processedAnnotations); - } - if (httpExceptionHandlers.size() > 0) { - messager.printNotice("Got " + httpExceptionHandlers.size() + " @HttpExceptionHandler annotations"); - Collections.sort(httpExceptionHandlers); - } - - if (!delFile) { - environment.getMessager().printNotice("Writing to " + confFile); - outputRules(pw); - outputExceptionHandlers(pw); - - } else { - confFile.delete(); - } - - } catch (Throwable t) { - delFile = true; - t.printStackTrace(); - } - if (delFile) { - messager.printError("Error occured during processing deleting generated file."); - confFile.delete(); - } - - pw.close(); - } - - private void outputRules(PrintWriter pw) { - for (ProcessedHttpUrlAnnotation pa : processedAnnotations) { - pw.println(""); - pw.println(" " + pa.sourceRef + ""); - if (!isBlank(pa.docComment)) { - pw.println(" "); - pw.println(padEachLine(" ", escapeXML(pa.docComment))); - pw.println(" "); - } - pw.println(" " + pa.value + ""); - pw.println(" "); - if (!pa.chainUsed) { - pw.println(" null"); - } - pw.println(""); - pw.flush(); - } - } - - private void outputExceptionHandlers(PrintWriter pw) { - for (ProcessedHttpExceptionAnnotation pa : httpExceptionHandlers) { - pw.println(""); - if (!isBlank(pa.docComment)) { - pw.println(" "); - pw.println(padEachLine(" ", escapeXML(pa.docComment))); - pw.println(" "); - } - pw.println(" "); - pw.println(""); - pw.flush(); - } - } - - private ProcessedHttpUrlAnnotation processHttpUrlAnnotation(Declaration declaration) { - HttpUrl httpUrl = declaration.getAnnotation(HttpUrl.class); - return new ProcessedHttpUrlAnnotation(HttpUrl.class.getName(), declaration, httpUrl.value(), httpUrl.weight()); - } - - private ProcessedHttpExceptionAnnotation processHttpExceptionHandlerAnnotation(Declaration declaration) { - SourcePosition position = declaration.getPosition(); - if (!(declaration instanceof MethodDeclaration)) { - messager.printWarning(declaration.getPosition(), "@HttpExceptionHandler declared on a non-method " + position); - return null; - } - MethodDeclaration methodDeclaration = (MethodDeclaration) declaration; - HttpExceptionHandler httpExceptionHandler = declaration.getAnnotation(HttpExceptionHandler.class); - String className = methodDeclaration.getDeclaringType().getQualifiedName(); - - ProcessedHttpExceptionAnnotation ea = new ProcessedHttpExceptionAnnotation(); - ea.exceptionName = httpExceptionHandler.value(); //.getName(); - ea.methodName = declaration.getSimpleName(); - ea.docComment = declaration.getDocComment(); - ea.className = className; - - ea.setParams(methodDeclaration.getParameters()); - - // out exceptionName might not be set - if ("[ unassigned ]".equals(ea.exceptionName) && methodDeclaration.getParameters().size() > 0) { - // use first param - ea.exceptionName = methodDeclaration.getParameters().iterator().next().getType().toString(); - } - - if (showPositionsOfAnnotations) { - messager.printNotice(position, "@HttpExceptionHandlerUrl value " + ea.value + " weight " + ea.weight); - } - return ea; - } - - class ProcessedHttpUrlAnnotation implements Comparable { - public int weight = 0; - public String value; - public boolean chainUsed; - public String paramsFormatted; - public String methodName; - public String className; - public String docComment; - public String sourceRef; - private static final String FILTER_CHAIN_CLASS_NAME = "javax.servlet.FilterChain"; - - public ProcessedHttpUrlAnnotation() { - // empty - } - - public ProcessedHttpUrlAnnotation(String typeName, Declaration declaration, String value, int weight) { - MethodDeclaration methodDeclaration = (MethodDeclaration) declaration; - String className = methodDeclaration.getDeclaringType().getQualifiedName(); - this.methodName = declaration.getSimpleName(); - this.docComment = declaration.getDocComment(); - this.className = className; - this.value = value; - this.weight = weight; - this.setParams(methodDeclaration.getParameters()); - String typeNameShort = typeName.substring(typeName.lastIndexOf(".")); - SourcePosition positionInCode = declaration.getPosition(); - sourceRef = positionInCode.file().getName() + ":" + positionInCode.line(); - if (!(declaration instanceof MethodDeclaration)) { - messager.printWarning(positionInCode, "@" + typeNameShort + " declared on a non-method " + positionInCode); - } - if (showPositionsOfAnnotations) { - messager.printNotice(positionInCode, "@" + typeNameShort + " value " + value + " weight " + weight); - } - } - - public int compareTo(ProcessedHttpUrlAnnotation other) { - if (this.weight < other.weight) return 1; - if (this.weight > other.weight) return -1; - if (this.className != null && other.className != null) { - int comp = this.className.compareTo(other.className); - if (comp != 0) return comp; - } - if (this.methodName != null && other.methodName != null) { - return this.methodName.compareTo(other.methodName); - } - return 0; - } - - void setParams(Collection params) { - paramsFormatted = "("; - chainUsed = false; - if (params.size() > 0) { - int i = 1; - for (ParameterDeclaration paramDeclaration : params) { - String paramType = paramDeclaration.getType().toString(); - if (FILTER_CHAIN_CLASS_NAME.equals(paramType)) { - chainUsed = true; - } - paramsFormatted += (i == 1 ? "" : ", ") + paramType; - - HttpParam httpParam = paramDeclaration.getAnnotation(HttpParam.class); - if (httpParam != null) { - paramsFormatted += " "; - if (!"[ unassigned ]".equals(httpParam.value())) { - paramsFormatted += httpParam.value(); - } else { - paramsFormatted += paramDeclaration.getSimpleName(); - } - } - i++; - } - } - paramsFormatted += ")"; - } - } - - class ProcessedHttpExceptionAnnotation extends ProcessedHttpUrlAnnotation { - public String exceptionName; - - public int compareTo(ProcessedHttpExceptionAnnotation other) { - int comp = super.compareTo(other); - if (comp == 0) comp = exceptionName.compareTo(other.exceptionName); - return comp; - } - - } - - - /** - * a very very basic xml escaper. - * - * @param s string to escape - * @return the escaped string - */ - private static String escapeXML(String s) { - if (s == null) { - return null; - } - final int length = s.length(); - StringBuffer b = new StringBuffer(); - for (int i = 0; i < length; i++) { - char c = s.charAt(i); - switch (c) { - case '&': - b.append("&"); - break; - case '<': - b.append("<"); - break; - case '>': - b.append(">"); - break; - default: - b.append(c); - break; - } - } - return b.toString(); - } - - private static String padEachLine(String padWith, String str) { - StringBuffer out = new StringBuffer(); - String[] lines = str.split("\n"); - int i = 0; - while (i < lines.length) { - String line = lines[i]; - out.append(padWith); - out.append(line); - i++; - if (i < lines.length) out.append('\n'); - } - return out.toString(); - } - - private static boolean isBlank(final String str) { - return str == null || "".equals(str) || "".equals(str.trim()); - } - - private static void checkDirsExistMkdir(File dir) { - if (!dir.getParentFile().exists()) { - checkDirsExistMkdir(dir.getParentFile()); - } - if (!dir.exists()) { - dir.mkdir(); - } - } - - private void debugMsg(String msg) { - if (!debug) return; - messager.printNotice("Debug: " + msg); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.annotation; + +import com.sun.mirror.apt.AnnotationProcessor; +import com.sun.mirror.apt.AnnotationProcessorEnvironment; +import com.sun.mirror.apt.Filer; +import com.sun.mirror.apt.Messager; +import com.sun.mirror.declaration.AnnotationTypeDeclaration; +import com.sun.mirror.declaration.Declaration; +import com.sun.mirror.declaration.MethodDeclaration; +import com.sun.mirror.declaration.ParameterDeclaration; +import com.sun.mirror.util.SourcePosition; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +/** + * Annotation processor for UrlRewrite. Will search compiled classes for annotations and generate XML. + *

+ * Processor for JDK 1.5. + * + * @deprecated use UrlRewriteAnnotationProcessor. + */ +public class HttpUrlAnnotationProcessor implements AnnotationProcessor { + + private AnnotationProcessorEnvironment environment; + private AnnotationTypeDeclaration httpUrlDeclaration; + private AnnotationTypeDeclaration httpExceptionHandlerDeclaration; + private List processedAnnotations = new ArrayList(); + private List httpExceptionHandlers = new ArrayList(); + private Messager messager; + private boolean showPositionsOfAnnotations = false; + private boolean debug = false; + + public HttpUrlAnnotationProcessor(AnnotationProcessorEnvironment env) { + environment = env; + messager = env.getMessager(); + // get the type declaration for the annotations we are processing for + httpUrlDeclaration = (AnnotationTypeDeclaration) environment.getTypeDeclaration(HttpUrl.class.getName()); + httpExceptionHandlerDeclaration = (AnnotationTypeDeclaration) environment.getTypeDeclaration(HttpExceptionHandler.class.getName()); + } + + public void process() { + Map options = environment.getOptions(); + Set keys = options.keySet(); + String saveRulesTo = null; + for (String key : keys) { + if (key.startsWith("-AsaveRulesTo=")) { + saveRulesTo = key.substring("-AsaveRulesTo=".length()); + } + if (key.startsWith("-AshowPositions=")) { + showPositionsOfAnnotations = "true".equalsIgnoreCase(key.substring("-AshowPositions=".length())); + } + if (key.startsWith("-Adebug=")) { + debug = "true".equalsIgnoreCase(key.substring("-Adebug=".length())); + } + } + debugMsg("Processing"); + if (saveRulesTo == null) { + messager.printError("ERROR: conf option must be specified"); + return; + } + + File confFile = new File(saveRulesTo); + PrintWriter pw; + boolean delFile = false; + try { + if (!confFile.exists()) { + if ( ! confFile.createNewFile() ) { + checkDirsExistMkdir(confFile.getParentFile()); + confFile.createNewFile(); + } + } + if (!confFile.canWrite()) throw new IOException("cannot write to " + confFile.getName()); + pw = environment.getFiler().createTextFile(Filer.Location.CLASS_TREE, "", confFile, null); + } catch (IOException e) { + e.printStackTrace(); + return; + } + try { + + // Get all declarations that use the HttpUrl annotation. + debugMsg("Looking for @HttpUrl"); + Collection urlDeclarations = environment.getDeclarationsAnnotatedWith(httpUrlDeclaration); + for (Declaration declaration : urlDeclarations) { + ProcessedHttpUrlAnnotation pa = processHttpUrlAnnotation(declaration); + if (pa == null) delFile = true; + else processedAnnotations.add(pa); + } + + // Get all declarations that use the HttpExceptionHandler annotation. + debugMsg("Looking for @HttpExceptionHandler"); + Collection exceptionDeclarations = environment.getDeclarationsAnnotatedWith(httpExceptionHandlerDeclaration); + for (Declaration declaration : exceptionDeclarations) { + ProcessedHttpExceptionAnnotation phea = processHttpExceptionHandlerAnnotation(declaration); + if (phea == null) delFile = true; + else httpExceptionHandlers.add(phea); + } + + if (processedAnnotations.size() > 0) { + messager.printNotice("Got " + processedAnnotations.size() + " @HttpUrl annotations"); + Collections.sort(processedAnnotations); + } + if (httpExceptionHandlers.size() > 0) { + messager.printNotice("Got " + httpExceptionHandlers.size() + " @HttpExceptionHandler annotations"); + Collections.sort(httpExceptionHandlers); + } + + if (!delFile) { + environment.getMessager().printNotice("Writing to " + confFile); + outputRules(pw); + outputExceptionHandlers(pw); + + } else { + confFile.delete(); + } + + } catch (Throwable t) { + delFile = true; + t.printStackTrace(); + } + if (delFile) { + messager.printError("Error occured during processing deleting generated file."); + confFile.delete(); + } + + pw.close(); + } + + private void outputRules(PrintWriter pw) { + for (ProcessedHttpUrlAnnotation pa : processedAnnotations) { + pw.println(""); + pw.println(" " + pa.sourceRef + ""); + if (!isBlank(pa.docComment)) { + pw.println(" "); + pw.println(padEachLine(" ", escapeXML(pa.docComment))); + pw.println(" "); + } + pw.println(" " + pa.value + ""); + pw.println(" "); + if (!pa.chainUsed) { + pw.println(" null"); + } + pw.println(""); + pw.flush(); + } + } + + private void outputExceptionHandlers(PrintWriter pw) { + for (ProcessedHttpExceptionAnnotation pa : httpExceptionHandlers) { + pw.println(""); + if (!isBlank(pa.docComment)) { + pw.println(" "); + pw.println(padEachLine(" ", escapeXML(pa.docComment))); + pw.println(" "); + } + pw.println(" "); + pw.println(""); + pw.flush(); + } + } + + private ProcessedHttpUrlAnnotation processHttpUrlAnnotation(Declaration declaration) { + HttpUrl httpUrl = declaration.getAnnotation(HttpUrl.class); + return new ProcessedHttpUrlAnnotation(HttpUrl.class.getName(), declaration, httpUrl.value(), httpUrl.weight()); + } + + private ProcessedHttpExceptionAnnotation processHttpExceptionHandlerAnnotation(Declaration declaration) { + SourcePosition position = declaration.getPosition(); + if (!(declaration instanceof MethodDeclaration)) { + messager.printWarning(declaration.getPosition(), "@HttpExceptionHandler declared on a non-method " + position); + return null; + } + MethodDeclaration methodDeclaration = (MethodDeclaration) declaration; + HttpExceptionHandler httpExceptionHandler = declaration.getAnnotation(HttpExceptionHandler.class); + String className = methodDeclaration.getDeclaringType().getQualifiedName(); + + ProcessedHttpExceptionAnnotation ea = new ProcessedHttpExceptionAnnotation(); + ea.exceptionName = httpExceptionHandler.value(); //.getName(); + ea.methodName = declaration.getSimpleName(); + ea.docComment = declaration.getDocComment(); + ea.className = className; + + ea.setParams(methodDeclaration.getParameters()); + + // out exceptionName might not be set + if ("[ unassigned ]".equals(ea.exceptionName) && methodDeclaration.getParameters().size() > 0) { + // use first param + ea.exceptionName = methodDeclaration.getParameters().iterator().next().getType().toString(); + } + + if (showPositionsOfAnnotations) { + messager.printNotice(position, "@HttpExceptionHandlerUrl value " + ea.value + " weight " + ea.weight); + } + return ea; + } + + class ProcessedHttpUrlAnnotation implements Comparable { + public int weight = 0; + public String value; + public boolean chainUsed; + public String paramsFormatted; + public String methodName; + public String className; + public String docComment; + public String sourceRef; + private static final String FILTER_CHAIN_CLASS_NAME = "javax.servlet.FilterChain"; + + public ProcessedHttpUrlAnnotation() { + // empty + } + + public ProcessedHttpUrlAnnotation(String typeName, Declaration declaration, String value, int weight) { + MethodDeclaration methodDeclaration = (MethodDeclaration) declaration; + String className = methodDeclaration.getDeclaringType().getQualifiedName(); + this.methodName = declaration.getSimpleName(); + this.docComment = declaration.getDocComment(); + this.className = className; + this.value = value; + this.weight = weight; + this.setParams(methodDeclaration.getParameters()); + String typeNameShort = typeName.substring(typeName.lastIndexOf(".")); + SourcePosition positionInCode = declaration.getPosition(); + sourceRef = positionInCode.file().getName() + ":" + positionInCode.line(); + if (!(declaration instanceof MethodDeclaration)) { + messager.printWarning(positionInCode, "@" + typeNameShort + " declared on a non-method " + positionInCode); + } + if (showPositionsOfAnnotations) { + messager.printNotice(positionInCode, "@" + typeNameShort + " value " + value + " weight " + weight); + } + } + + public int compareTo(ProcessedHttpUrlAnnotation other) { + if (this.weight < other.weight) return 1; + if (this.weight > other.weight) return -1; + if (this.className != null && other.className != null) { + int comp = this.className.compareTo(other.className); + if (comp != 0) return comp; + } + if (this.methodName != null && other.methodName != null) { + return this.methodName.compareTo(other.methodName); + } + return 0; + } + + void setParams(Collection params) { + paramsFormatted = "("; + chainUsed = false; + if (params.size() > 0) { + int i = 1; + for (ParameterDeclaration paramDeclaration : params) { + String paramType = paramDeclaration.getType().toString(); + if (FILTER_CHAIN_CLASS_NAME.equals(paramType)) { + chainUsed = true; + } + paramsFormatted += (i == 1 ? "" : ", ") + paramType; + + HttpParam httpParam = paramDeclaration.getAnnotation(HttpParam.class); + if (httpParam != null) { + paramsFormatted += " "; + if (!"[ unassigned ]".equals(httpParam.value())) { + paramsFormatted += httpParam.value(); + } else { + paramsFormatted += paramDeclaration.getSimpleName(); + } + } + i++; + } + } + paramsFormatted += ")"; + } + } + + class ProcessedHttpExceptionAnnotation extends ProcessedHttpUrlAnnotation { + public String exceptionName; + + public int compareTo(ProcessedHttpExceptionAnnotation other) { + int comp = super.compareTo(other); + if (comp == 0) comp = exceptionName.compareTo(other.exceptionName); + return comp; + } + + } + + + /** + * a very very basic xml escaper. + * + * @param s string to escape + * @return the escaped string + */ + private static String escapeXML(String s) { + if (s == null) { + return null; + } + final int length = s.length(); + StringBuffer b = new StringBuffer(); + for (int i = 0; i < length; i++) { + char c = s.charAt(i); + switch (c) { + case '&': + b.append("&"); + break; + case '<': + b.append("<"); + break; + case '>': + b.append(">"); + break; + default: + b.append(c); + break; + } + } + return b.toString(); + } + + private static String padEachLine(String padWith, String str) { + StringBuffer out = new StringBuffer(); + String[] lines = str.split("\n"); + int i = 0; + while (i < lines.length) { + String line = lines[i]; + out.append(padWith); + out.append(line); + i++; + if (i < lines.length) out.append('\n'); + } + return out.toString(); + } + + private static boolean isBlank(final String str) { + return str == null || "".equals(str) || "".equals(str.trim()); + } + + private static void checkDirsExistMkdir(File dir) { + if (!dir.getParentFile().exists()) { + checkDirsExistMkdir(dir.getParentFile()); + } + if (!dir.exists()) { + dir.mkdir(); + } + } + + private void debugMsg(String msg) { + if (!debug) return; + messager.printNotice("Debug: " + msg); + } + +} diff --git a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/UrlRewriteAnnotationProcessor.java b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/UrlRewriteAnnotationProcessor.java index 9405934f..25f7ffd7 100644 --- a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/UrlRewriteAnnotationProcessor.java +++ b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/annotation/UrlRewriteAnnotationProcessor.java @@ -1,469 +1,469 @@ -/** - * Copyright (c) 2005-2008, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.annotation; - - -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.Messager; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.element.*; -import javax.lang.model.util.Elements; -import javax.tools.Diagnostic; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Annotation processor for UrlRewrite. Will search classes for annotations and generate XML fragment. - * JDK 1.6+ - *

- * - * @since 3.2 - */ -@SupportedAnnotationTypes("org.tuckey.web.filters.urlrewrite.*") -public class UrlRewriteAnnotationProcessor extends AbstractProcessor { - - private List processedAnnotations = new ArrayList(); - private List processedJsonAnnotations = new ArrayList(); - private List httpExceptionHandlers = new ArrayList(); - private Messager messager; - private Elements elementUtils; - private boolean showPositions = false; - private boolean debug = false; - private boolean errorDuringProcessing = false; - private String dest = null; - private String rpcBase = "/rpc/"; - - public UrlRewriteAnnotationProcessor() { - // needed - } - - public Set getSupportedOptions() { - HashSet options = new HashSet(); - options.add("urlrewriteDest"); - options.add("urlrewriteShowPositions"); - options.add("urlrewriteDebug"); - options.add("urlrewriteRpcBase"); - return options; - } - - public synchronized void init(ProcessingEnvironment processingEnv) { - this.messager = processingEnv.getMessager(); - this.elementUtils = processingEnv.getElementUtils(); - - Map options = processingEnv.getOptions(); - Set keys = options.keySet(); - for (String key : keys) { - if (key.equalsIgnoreCase("urlrewriteDest")) { - dest = options.get(key); - - } else if (key.equalsIgnoreCase("urlrewriteShowPositions")) { - showPositions = "true".equalsIgnoreCase(options.get(key)); - - } else if (key.equalsIgnoreCase("urlrewriteDebug")) { - debug = "true".equalsIgnoreCase(options.get(key)); - - } else if (key.equalsIgnoreCase("urlrewriteRpcBase")) { - rpcBase = options.get(key); - } - } - debugMsg("init"); - } - - public boolean process(Set annotations, RoundEnvironment roundEnv) { - if (isBlank(dest)) { - if (roundEnv.processingOver()) - infoMsg(getClass().getSimpleName() + ": -AurlrewriteDest not specified, annotations ignored"); - return true; - } - debugMsg("process"); - - Set urlDeclarations = roundEnv.getElementsAnnotatedWith(HttpUrl.class); - for (Element element : urlDeclarations) { - processedAnnotations.add(new ProcessedHttpUrlAnnotation(element)); - } - - Set jsonDeclarations = roundEnv.getElementsAnnotatedWith(HttpJson.class); - for (Element element : jsonDeclarations) { - processedJsonAnnotations.add(new ProcessedHttpJsonAnnotation(element)); - } - - Set exceptionDeclarations = roundEnv.getElementsAnnotatedWith(HttpExceptionHandler.class); - for (Element element : exceptionDeclarations) { - httpExceptionHandlers.add(new ProcessedHttpExceptionAnnotation(element)); - } - - if (roundEnv.processingOver()) { - if (processedAnnotations.size() > 0) { - infoMsg("Got " + processedAnnotations.size() + " @HttpUrl annotations"); - } - if (processedJsonAnnotations.size() > 0) { - infoMsg("Got " + processedJsonAnnotations.size() + " @HttpJson annotations"); - processedAnnotations.addAll(processedJsonAnnotations); - } - Collections.sort(processedAnnotations); - - if (httpExceptionHandlers.size() > 0) { - infoMsg("Got " + httpExceptionHandlers.size() + " @HttpExceptionHandler annotations"); - Collections.sort(httpExceptionHandlers); - } - try { - File destFile = new File(dest); - if (!destFile.exists()){ - if ( destFile.getParentFile() == null ) { - infoMsg("Parent file null for " + destFile); - } - if ( ! destFile.createNewFile() ) { - infoMsg("could not make new file for " + destFile + " trying to mkdirs"); - checkDirsExistMkdir(destFile.getParentFile()); - if ( ! destFile.createNewFile() ) { - errorMsg("could not make new file for " + destFile); - } - } - } - if (!destFile.canWrite()) { - throw new IOException("cannot write to " + destFile.getName()); - } - if (errorDuringProcessing) { - errorMsg("Error occured during processing deleting generated file."); - destFile.delete(); - - } else { - PrintWriter pw = new PrintWriter(destFile); - infoMsg("Writing to " + destFile); - outputRules(pw); - outputExceptionHandlers(pw); - pw.close(); - - } - } catch (FileNotFoundException e) { - errorMsg(e); - e.printStackTrace(); - - } catch (IOException e) { - errorMsg(e); - e.printStackTrace(); - } - } - return true; - } - - private void outputRules(PrintWriter pw) { - for (ProcessedHttpUrlAnnotation pa : processedAnnotations) { - boolean jsonHandler = pa instanceof ProcessedHttpJsonAnnotation; - pw.println(""); - pw.println(" " + pa.className + "." + pa.methodName + ""); - if (!isBlank(pa.docComment)) { - pw.println(" "); - pw.println(padEachLine(" ", escapeXML(pa.docComment))); - pw.println(" "); - } - pw.println(" " + pa.value + ""); - pw.println(" "); - if (!pa.chainUsed) { - pw.println(" null"); - } - pw.println(""); - pw.flush(); - } - } - - private void outputExceptionHandlers(PrintWriter pw) { - for (ProcessedHttpExceptionAnnotation pa : httpExceptionHandlers) { - pw.println(""); - if (!isBlank(pa.docComment)) { - pw.println(" "); - pw.println(padEachLine(" ", escapeXML(pa.docComment))); - pw.println(" "); - } - pw.println(" "); - pw.println(""); - pw.flush(); - } - } - - class ProcessedUrlRewriteFilterAnnotation implements Comparable { - - public String methodName; - public String className; - public String docComment; - public String paramsFormatted; - - public ExecutableElement init(Element declaration) { - if (!ElementKind.METHOD.equals(declaration.getKind())) { - errorMsg("declared on a non-method (type is " + declaration.getKind() + ")", declaration); - return null; - } - ExecutableElement methodDeclaration = (ExecutableElement) declaration; - TypeElement classDeclaration = (TypeElement) methodDeclaration.getEnclosingElement(); - className = classDeclaration.getQualifiedName().toString(); - methodName = declaration.getSimpleName().toString(); - docComment = elementUtils.getDocComment(declaration); - return methodDeclaration; - } - - public int compareTo(ProcessedUrlRewriteFilterAnnotation other) { - if (this.className != null && other.className != null) { - int comp = this.className.compareTo(other.className); - if (comp != 0) return comp; - } - if (this.methodName != null && other.methodName != null) { - return this.methodName.compareTo(other.methodName); - } - return 0; - } - - void setParams(Collection params) { - paramsFormatted = "("; - if (params.size() > 0) { - int i = 1; - for (VariableElement paramDeclaration : params) { - String paramType = paramDeclaration.asType().toString(); - paramsFormatted += (i == 1 ? "" : ", ") + paramType; - HttpParam httpParam = paramDeclaration.getAnnotation(HttpParam.class); - if (httpParam != null) { - paramsFormatted += " "; - if (!"[ unassigned ]".equals(httpParam.value())) { - paramsFormatted += httpParam.value(); - } else { - paramsFormatted += paramDeclaration.getSimpleName(); - } - } - i++; - } - } - paramsFormatted += ")"; - } - - } - - class ProcessedHttpJsonAnnotation extends ProcessedHttpUrlAnnotation { - public ProcessedHttpJsonAnnotation(Element declaration) { - ExecutableElement methodDeclaration = init(declaration); - if (methodDeclaration == null) return; - - HttpJson httpJson = declaration.getAnnotation(HttpJson.class); - if ("[ unassigned ]".equals(httpJson.value()) ) { - this.value = rpcBase + this.className + "/" + this.methodName; - } else { - this.value = httpJson.value(); - } - this.weight = httpJson.weight(); - setParams(methodDeclaration.getParameters()); - - if (showPositions) { - messager.printMessage(Diagnostic.Kind.NOTE, "@HttpJson value " + value + " weight " + weight, methodDeclaration); - } - } - - } - - class ProcessedHttpUrlAnnotation extends ProcessedUrlRewriteFilterAnnotation { - public int weight = 0; - public String value; - public boolean chainUsed; - public String sourceRef; - private static final String FILTER_CHAIN_CLASS_NAME = "javax.servlet.FilterChain"; - - public ProcessedHttpUrlAnnotation() { - // empty - } - - public ProcessedHttpUrlAnnotation(Element declaration) { - ExecutableElement methodDeclaration = init(declaration); - if (methodDeclaration == null) return; - - HttpUrl httpUrl = declaration.getAnnotation(HttpUrl.class); - this.value = httpUrl.value(); - this.weight = httpUrl.weight(); - setParams(methodDeclaration.getParameters()); - - if (showPositions) { - messager.printMessage(Diagnostic.Kind.NOTE, "@HttpUrl value " + value + " weight " + weight, methodDeclaration); - } - } - - public int compareTo(ProcessedHttpUrlAnnotation other) { - if (this.weight < other.weight) return 1; - if (this.weight > other.weight) return -1; - return super.compareTo(other); - } - - protected void setParams(Collection params) { - chainUsed = false; - if (params.size() > 0) { - for (VariableElement paramDeclaration : params) { - String paramType = paramDeclaration.asType().toString(); - if (FILTER_CHAIN_CLASS_NAME.equals(paramType)) { - chainUsed = true; - } - } - } - super.setParams(params); - } - - } - - class ProcessedHttpExceptionAnnotation extends ProcessedUrlRewriteFilterAnnotation { - public String exceptionName; - - public ProcessedHttpExceptionAnnotation(Element declaration) { - ExecutableElement methodDeclaration = init(declaration); - if (methodDeclaration == null) return; - - HttpExceptionHandler httpExceptionHandler = declaration.getAnnotation(HttpExceptionHandler.class); - exceptionName = httpExceptionHandler.value(); - - // out exceptionName might not be set - if ("[ unassigned ]".equals(exceptionName) ) { - // use first param - exceptionName = methodDeclaration.getParameters().get(0).asType().toString(); - } - setParams(methodDeclaration.getParameters()); - - if (showPositions) { - messager.printMessage(Diagnostic.Kind.NOTE, "@HttpExceptionHandlerUrl exceptionName " + exceptionName, methodDeclaration); - } - } - - public int compareTo(ProcessedHttpExceptionAnnotation other) { - int comp = super.compareTo(other); - if (comp == 0) comp = exceptionName.compareTo(other.exceptionName); - return comp; - } - - } - - - /** - * a very very basic xml escaper. - * - * @param s string to escape - * @return the escaped string - */ - private static String escapeXML(String s) { - if (s == null) { - return null; - } - final int length = s.length(); - StringBuffer b = new StringBuffer(); - for (int i = 0; i < length; i++) { - char c = s.charAt(i); - switch (c) { - case '&': - b.append("&"); - break; - case '<': - b.append("<"); - break; - case '>': - b.append(">"); - break; - default: - b.append(c); - break; - } - } - return b.toString(); - } - - private static String padEachLine(String padWith, String str) { - StringBuffer out = new StringBuffer(); - String[] lines = str.split("\n"); - int i = 0; - while (i < lines.length) { - String line = lines[i]; - out.append(padWith); - out.append(line); - i++; - if (i < lines.length) out.append('\n'); - } - return out.toString(); - } - - private static boolean isBlank(final String str) { - return str == null || "".equals(str) || "".equals(str.trim()); - } - - private static void checkDirsExistMkdir(File dir) { - if ( dir == null ) throw new RuntimeException("checkDirsExistMkdir called with null"); - if (dir.getParentFile() == null ) { - checkDirsExistMkdir(dir); - } - if (!dir.getParentFile().exists()) { - checkDirsExistMkdir(dir.getParentFile()); - } - if (!dir.exists()) { - dir.mkdir(); - } - } - - - private void debugMsg(String msg) { - if (!debug) return; - messager.printMessage(Diagnostic.Kind.OTHER, getClass().getSimpleName() + " " + msg); - } - - private void infoMsg(String msg) { - messager.printMessage(Diagnostic.Kind.NOTE, msg); - } - - private void errorMsg(String msg) { - errorDuringProcessing = true; - messager.printMessage(Diagnostic.Kind.ERROR, msg); - } - - private void errorMsg(Exception e) { - errorDuringProcessing = true; - messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage()); - } - - private void errorMsg(String msg, Element element) { - errorDuringProcessing = true; - messager.printMessage(Diagnostic.Kind.ERROR, msg, element); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.annotation; + + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.element.*; +import javax.lang.model.util.Elements; +import javax.tools.Diagnostic; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Annotation processor for UrlRewrite. Will search classes for annotations and generate XML fragment. + * JDK 1.6+ + *

+ * + * @since 3.2 + */ +@SupportedAnnotationTypes("org.tuckey.web.filters.urlrewrite.*") +public class UrlRewriteAnnotationProcessor extends AbstractProcessor { + + private List processedAnnotations = new ArrayList(); + private List processedJsonAnnotations = new ArrayList(); + private List httpExceptionHandlers = new ArrayList(); + private Messager messager; + private Elements elementUtils; + private boolean showPositions = false; + private boolean debug = false; + private boolean errorDuringProcessing = false; + private String dest = null; + private String rpcBase = "/rpc/"; + + public UrlRewriteAnnotationProcessor() { + // needed + } + + public Set getSupportedOptions() { + HashSet options = new HashSet(); + options.add("urlrewriteDest"); + options.add("urlrewriteShowPositions"); + options.add("urlrewriteDebug"); + options.add("urlrewriteRpcBase"); + return options; + } + + public synchronized void init(ProcessingEnvironment processingEnv) { + this.messager = processingEnv.getMessager(); + this.elementUtils = processingEnv.getElementUtils(); + + Map options = processingEnv.getOptions(); + Set keys = options.keySet(); + for (String key : keys) { + if (key.equalsIgnoreCase("urlrewriteDest")) { + dest = options.get(key); + + } else if (key.equalsIgnoreCase("urlrewriteShowPositions")) { + showPositions = "true".equalsIgnoreCase(options.get(key)); + + } else if (key.equalsIgnoreCase("urlrewriteDebug")) { + debug = "true".equalsIgnoreCase(options.get(key)); + + } else if (key.equalsIgnoreCase("urlrewriteRpcBase")) { + rpcBase = options.get(key); + } + } + debugMsg("init"); + } + + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (isBlank(dest)) { + if (roundEnv.processingOver()) + infoMsg(getClass().getSimpleName() + ": -AurlrewriteDest not specified, annotations ignored"); + return true; + } + debugMsg("process"); + + Set urlDeclarations = roundEnv.getElementsAnnotatedWith(HttpUrl.class); + for (Element element : urlDeclarations) { + processedAnnotations.add(new ProcessedHttpUrlAnnotation(element)); + } + + Set jsonDeclarations = roundEnv.getElementsAnnotatedWith(HttpJson.class); + for (Element element : jsonDeclarations) { + processedJsonAnnotations.add(new ProcessedHttpJsonAnnotation(element)); + } + + Set exceptionDeclarations = roundEnv.getElementsAnnotatedWith(HttpExceptionHandler.class); + for (Element element : exceptionDeclarations) { + httpExceptionHandlers.add(new ProcessedHttpExceptionAnnotation(element)); + } + + if (roundEnv.processingOver()) { + if (processedAnnotations.size() > 0) { + infoMsg("Got " + processedAnnotations.size() + " @HttpUrl annotations"); + } + if (processedJsonAnnotations.size() > 0) { + infoMsg("Got " + processedJsonAnnotations.size() + " @HttpJson annotations"); + processedAnnotations.addAll(processedJsonAnnotations); + } + Collections.sort(processedAnnotations); + + if (httpExceptionHandlers.size() > 0) { + infoMsg("Got " + httpExceptionHandlers.size() + " @HttpExceptionHandler annotations"); + Collections.sort(httpExceptionHandlers); + } + try { + File destFile = new File(dest); + if (!destFile.exists()){ + if ( destFile.getParentFile() == null ) { + infoMsg("Parent file null for " + destFile); + } + if ( ! destFile.createNewFile() ) { + infoMsg("could not make new file for " + destFile + " trying to mkdirs"); + checkDirsExistMkdir(destFile.getParentFile()); + if ( ! destFile.createNewFile() ) { + errorMsg("could not make new file for " + destFile); + } + } + } + if (!destFile.canWrite()) { + throw new IOException("cannot write to " + destFile.getName()); + } + if (errorDuringProcessing) { + errorMsg("Error occured during processing deleting generated file."); + destFile.delete(); + + } else { + PrintWriter pw = new PrintWriter(destFile); + infoMsg("Writing to " + destFile); + outputRules(pw); + outputExceptionHandlers(pw); + pw.close(); + + } + } catch (FileNotFoundException e) { + errorMsg(e); + e.printStackTrace(); + + } catch (IOException e) { + errorMsg(e); + e.printStackTrace(); + } + } + return true; + } + + private void outputRules(PrintWriter pw) { + for (ProcessedHttpUrlAnnotation pa : processedAnnotations) { + boolean jsonHandler = pa instanceof ProcessedHttpJsonAnnotation; + pw.println(""); + pw.println(" " + pa.className + "." + pa.methodName + ""); + if (!isBlank(pa.docComment)) { + pw.println(" "); + pw.println(padEachLine(" ", escapeXML(pa.docComment))); + pw.println(" "); + } + pw.println(" " + pa.value + ""); + pw.println(" "); + if (!pa.chainUsed) { + pw.println(" null"); + } + pw.println(""); + pw.flush(); + } + } + + private void outputExceptionHandlers(PrintWriter pw) { + for (ProcessedHttpExceptionAnnotation pa : httpExceptionHandlers) { + pw.println(""); + if (!isBlank(pa.docComment)) { + pw.println(" "); + pw.println(padEachLine(" ", escapeXML(pa.docComment))); + pw.println(" "); + } + pw.println(" "); + pw.println(""); + pw.flush(); + } + } + + class ProcessedUrlRewriteFilterAnnotation implements Comparable { + + public String methodName; + public String className; + public String docComment; + public String paramsFormatted; + + public ExecutableElement init(Element declaration) { + if (!ElementKind.METHOD.equals(declaration.getKind())) { + errorMsg("declared on a non-method (type is " + declaration.getKind() + ")", declaration); + return null; + } + ExecutableElement methodDeclaration = (ExecutableElement) declaration; + TypeElement classDeclaration = (TypeElement) methodDeclaration.getEnclosingElement(); + className = classDeclaration.getQualifiedName().toString(); + methodName = declaration.getSimpleName().toString(); + docComment = elementUtils.getDocComment(declaration); + return methodDeclaration; + } + + public int compareTo(ProcessedUrlRewriteFilterAnnotation other) { + if (this.className != null && other.className != null) { + int comp = this.className.compareTo(other.className); + if (comp != 0) return comp; + } + if (this.methodName != null && other.methodName != null) { + return this.methodName.compareTo(other.methodName); + } + return 0; + } + + void setParams(Collection params) { + paramsFormatted = "("; + if (params.size() > 0) { + int i = 1; + for (VariableElement paramDeclaration : params) { + String paramType = paramDeclaration.asType().toString(); + paramsFormatted += (i == 1 ? "" : ", ") + paramType; + HttpParam httpParam = paramDeclaration.getAnnotation(HttpParam.class); + if (httpParam != null) { + paramsFormatted += " "; + if (!"[ unassigned ]".equals(httpParam.value())) { + paramsFormatted += httpParam.value(); + } else { + paramsFormatted += paramDeclaration.getSimpleName(); + } + } + i++; + } + } + paramsFormatted += ")"; + } + + } + + class ProcessedHttpJsonAnnotation extends ProcessedHttpUrlAnnotation { + public ProcessedHttpJsonAnnotation(Element declaration) { + ExecutableElement methodDeclaration = init(declaration); + if (methodDeclaration == null) return; + + HttpJson httpJson = declaration.getAnnotation(HttpJson.class); + if ("[ unassigned ]".equals(httpJson.value()) ) { + this.value = rpcBase + this.className + "/" + this.methodName; + } else { + this.value = httpJson.value(); + } + this.weight = httpJson.weight(); + setParams(methodDeclaration.getParameters()); + + if (showPositions) { + messager.printMessage(Diagnostic.Kind.NOTE, "@HttpJson value " + value + " weight " + weight, methodDeclaration); + } + } + + } + + class ProcessedHttpUrlAnnotation extends ProcessedUrlRewriteFilterAnnotation { + public int weight = 0; + public String value; + public boolean chainUsed; + public String sourceRef; + private static final String FILTER_CHAIN_CLASS_NAME = "javax.servlet.FilterChain"; + + public ProcessedHttpUrlAnnotation() { + // empty + } + + public ProcessedHttpUrlAnnotation(Element declaration) { + ExecutableElement methodDeclaration = init(declaration); + if (methodDeclaration == null) return; + + HttpUrl httpUrl = declaration.getAnnotation(HttpUrl.class); + this.value = httpUrl.value(); + this.weight = httpUrl.weight(); + setParams(methodDeclaration.getParameters()); + + if (showPositions) { + messager.printMessage(Diagnostic.Kind.NOTE, "@HttpUrl value " + value + " weight " + weight, methodDeclaration); + } + } + + public int compareTo(ProcessedHttpUrlAnnotation other) { + if (this.weight < other.weight) return 1; + if (this.weight > other.weight) return -1; + return super.compareTo(other); + } + + protected void setParams(Collection params) { + chainUsed = false; + if (params.size() > 0) { + for (VariableElement paramDeclaration : params) { + String paramType = paramDeclaration.asType().toString(); + if (FILTER_CHAIN_CLASS_NAME.equals(paramType)) { + chainUsed = true; + } + } + } + super.setParams(params); + } + + } + + class ProcessedHttpExceptionAnnotation extends ProcessedUrlRewriteFilterAnnotation { + public String exceptionName; + + public ProcessedHttpExceptionAnnotation(Element declaration) { + ExecutableElement methodDeclaration = init(declaration); + if (methodDeclaration == null) return; + + HttpExceptionHandler httpExceptionHandler = declaration.getAnnotation(HttpExceptionHandler.class); + exceptionName = httpExceptionHandler.value(); + + // out exceptionName might not be set + if ("[ unassigned ]".equals(exceptionName) ) { + // use first param + exceptionName = methodDeclaration.getParameters().get(0).asType().toString(); + } + setParams(methodDeclaration.getParameters()); + + if (showPositions) { + messager.printMessage(Diagnostic.Kind.NOTE, "@HttpExceptionHandlerUrl exceptionName " + exceptionName, methodDeclaration); + } + } + + public int compareTo(ProcessedHttpExceptionAnnotation other) { + int comp = super.compareTo(other); + if (comp == 0) comp = exceptionName.compareTo(other.exceptionName); + return comp; + } + + } + + + /** + * a very very basic xml escaper. + * + * @param s string to escape + * @return the escaped string + */ + private static String escapeXML(String s) { + if (s == null) { + return null; + } + final int length = s.length(); + StringBuffer b = new StringBuffer(); + for (int i = 0; i < length; i++) { + char c = s.charAt(i); + switch (c) { + case '&': + b.append("&"); + break; + case '<': + b.append("<"); + break; + case '>': + b.append(">"); + break; + default: + b.append(c); + break; + } + } + return b.toString(); + } + + private static String padEachLine(String padWith, String str) { + StringBuffer out = new StringBuffer(); + String[] lines = str.split("\n"); + int i = 0; + while (i < lines.length) { + String line = lines[i]; + out.append(padWith); + out.append(line); + i++; + if (i < lines.length) out.append('\n'); + } + return out.toString(); + } + + private static boolean isBlank(final String str) { + return str == null || "".equals(str) || "".equals(str.trim()); + } + + private static void checkDirsExistMkdir(File dir) { + if ( dir == null ) throw new RuntimeException("checkDirsExistMkdir called with null"); + if (dir.getParentFile() == null ) { + checkDirsExistMkdir(dir); + } + if (!dir.getParentFile().exists()) { + checkDirsExistMkdir(dir.getParentFile()); + } + if (!dir.exists()) { + dir.mkdir(); + } + } + + + private void debugMsg(String msg) { + if (!debug) return; + messager.printMessage(Diagnostic.Kind.OTHER, getClass().getSimpleName() + " " + msg); + } + + private void infoMsg(String msg) { + messager.printMessage(Diagnostic.Kind.NOTE, msg); + } + + private void errorMsg(String msg) { + errorDuringProcessing = true; + messager.printMessage(Diagnostic.Kind.ERROR, msg); + } + + private void errorMsg(Exception e) { + errorDuringProcessing = true; + messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage()); + } + + private void errorMsg(String msg, Element element) { + errorDuringProcessing = true; + messager.printMessage(Diagnostic.Kind.ERROR, msg, element); + } + +} diff --git a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/json/JSONRPCBean.java b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/json/JSONRPCBean.java index 58f2b3ff..d9044a0b 100644 --- a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/json/JSONRPCBean.java +++ b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/json/JSONRPCBean.java @@ -1,65 +1,65 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.json; - -/** - * Bean to encapsulate an RPC result. - */ -public class JSONRPCBean { - - private Object result; - private JSONRPCErrorBean error; - - public String getVersion() { - return "1.1"; - } - - public Object getResult() { - return result; - } - - public void setResult(Object result) { - this.result = result; - } - - public JSONRPCErrorBean getError() { - return error; - } - - public void setError(JSONRPCErrorBean error) { - this.error = error; - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.json; + +/** + * Bean to encapsulate an RPC result. + */ +public class JSONRPCBean { + + private Object result; + private JSONRPCErrorBean error; + + public String getVersion() { + return "1.1"; + } + + public Object getResult() { + return result; + } + + public void setResult(Object result) { + this.result = result; + } + + public JSONRPCErrorBean getError() { + return error; + } + + public void setError(JSONRPCErrorBean error) { + this.error = error; + } + +} diff --git a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/json/JSONRPCErrorBean.java b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/json/JSONRPCErrorBean.java index 15a70dd9..836c9c62 100644 --- a/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/json/JSONRPCErrorBean.java +++ b/annotation/src/main/java/org/tuckey/web/filters/urlrewrite/json/JSONRPCErrorBean.java @@ -1,73 +1,73 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.json; - -/** - * Bean to encapsulate RPC errors. - */ -public class JSONRPCErrorBean { - - private int code; - private String message; - private Object error; - - public String getName() { - return "JSONRPCError"; - } - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public Object getError() { - return error; - } - - public void setError(Object error) { - this.error = error; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.json; + +/** + * Bean to encapsulate RPC errors. + */ +public class JSONRPCErrorBean { + + private int code; + private String message; + private Object error; + + public String getName() { + return "JSONRPCError"; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Object getError() { + return error; + } + + public void setError(Object error) { + this.error = error; + } +} diff --git a/annotation/src/test/java/org/tuckey/web/filters/urlrewrite/annotation/SampleMatchAction.java b/annotation/src/test/java/org/tuckey/web/filters/urlrewrite/annotation/SampleMatchAction.java index d25f00c9..fe101d27 100644 --- a/annotation/src/test/java/org/tuckey/web/filters/urlrewrite/annotation/SampleMatchAction.java +++ b/annotation/src/test/java/org/tuckey/web/filters/urlrewrite/annotation/SampleMatchAction.java @@ -1,121 +1,121 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.annotation; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.sql.SQLException; - - -public class SampleMatchAction { - - @HttpUrl(value = "^/1clientinfo/$") - public void listActive(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException, SQLException { - - } - - /** - * In file 2nd. - */ - @HttpUrl("^/clientinfo/(*)/$") - public void clientDetails(int clientId) - throws SQLException { - - } - - @HttpUrl("^/search/(clients|staff)/$") - public void addClientFilterSecond(String searchType, @HttpParam String firstName, - @HttpParam("lName")String lastName) - throws SQLException { - - } - - /** - * In the file 3rd. Should be 1st. - *

- * Multiline doc. - */ - @HttpUrl(value = "^/clientinfo/(*)/$", weight = 2) - public void addClientFilterFirst(int clientId, FilterChain chain) - throws SQLException { - - } - - /** - * Should be the last item in the processed file. - * In file 4th. Should be last. - */ - @HttpUrl(value = "^/clientinfo/(*)/$", weight = -1) - public void addClientFilterLast(int clientId, FilterChain chain) - throws SQLException { - - } - - /** - * In file 5th. Should be 2nd. - */ - @HttpUrl(value = "^/clientinfo/(*)/$", weight = 1) - public void addClientFilterSecond(int clientId, FilterChain chain) - throws SQLException { - - } - - class ClientBean { - private String name = "Bob"; - } - - @HttpExceptionHandler("java.lang.Exception") - public void addExceptionHandler(Exception e) - throws SQLException { - - } - - @HttpExceptionHandler - public void addExceptionHandlerAuto(Exception e) - throws SQLException { - - } - - @HttpJson - public String clientDetailsRpc(@HttpParam int clientId) - throws SQLException { - return "Hello World"; - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.annotation; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.sql.SQLException; + + +public class SampleMatchAction { + + @HttpUrl(value = "^/1clientinfo/$") + public void listActive(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException, SQLException { + + } + + /** + * In file 2nd. + */ + @HttpUrl("^/clientinfo/(*)/$") + public void clientDetails(int clientId) + throws SQLException { + + } + + @HttpUrl("^/search/(clients|staff)/$") + public void addClientFilterSecond(String searchType, @HttpParam String firstName, + @HttpParam("lName")String lastName) + throws SQLException { + + } + + /** + * In the file 3rd. Should be 1st. + *

+ * Multiline doc. + */ + @HttpUrl(value = "^/clientinfo/(*)/$", weight = 2) + public void addClientFilterFirst(int clientId, FilterChain chain) + throws SQLException { + + } + + /** + * Should be the last item in the processed file. + * In file 4th. Should be last. + */ + @HttpUrl(value = "^/clientinfo/(*)/$", weight = -1) + public void addClientFilterLast(int clientId, FilterChain chain) + throws SQLException { + + } + + /** + * In file 5th. Should be 2nd. + */ + @HttpUrl(value = "^/clientinfo/(*)/$", weight = 1) + public void addClientFilterSecond(int clientId, FilterChain chain) + throws SQLException { + + } + + class ClientBean { + private String name = "Bob"; + } + + @HttpExceptionHandler("java.lang.Exception") + public void addExceptionHandler(Exception e) + throws SQLException { + + } + + @HttpExceptionHandler + public void addExceptionHandlerAuto(Exception e) + throws SQLException { + + } + + @HttpJson + public String clientDetailsRpc(@HttpParam int clientId) + throws SQLException { + return "Hello World"; + } + +} diff --git a/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/MockRewriteMatch.java b/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/MockRewriteMatch.java index 59ae3b6e..cf40d5f6 100644 --- a/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/MockRewriteMatch.java +++ b/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/MockRewriteMatch.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2005-2007, Paul Tuckey + * Copyright (c) 2005-2023, Paul Tuckey * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. diff --git a/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/TestRunObj.java b/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/TestRunObj.java index ffbecebc..5325c6e5 100644 --- a/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/TestRunObj.java +++ b/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/TestRunObj.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2005-2007, Paul Tuckey + * Copyright (c) 2005-2023, Paul Tuckey * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/CatchElem.java b/src/main/java/org/tuckey/web/filters/urlrewrite/CatchElem.java index 02be4f21..512718e9 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/CatchElem.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/CatchElem.java @@ -1,165 +1,165 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.List; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; - -/** - * An item that will allow exceptions during "run" invocation to be caught. - */ -public class CatchElem implements Runnable { - - private static Log log = Log.getLog(CatchElem.class); - - private String classStr; - private String error = null; - private boolean valid = false; - private boolean initialised = false; - private Class exceptionClass; - private ArrayList runs = new ArrayList(); - - /** - * For testing and documentation we don't want to load the classes. - */ - private static boolean loadClass = true; - - public static void setLoadClass(boolean loadClass) { - CatchElem.loadClass = loadClass; - } - - public boolean isValid() { - return valid; - } - - public boolean isInitialised() { - return initialised; - } - - /** - * @return true on success - */ - public boolean initialise(ServletContext servletContext) { - initialised = true; - boolean ok = true; - if (log.isDebugEnabled()) { - log.debug("looking for class " + classStr); - } - if ( loadClass ) { - try { - exceptionClass = Class.forName(classStr); - } catch (ClassNotFoundException e) { - setError("could not find " + classStr + " got a " + e.toString(), e); - return false; - } catch (NoClassDefFoundError e) { - setError("could not find " + classStr + " got a " + e.toString(), e); - return false; - } - } - // now initialise runs - for (int i = 0; i < runs.size(); i++) { - final Run run = (Run) runs.get(i); - if (!run.initialise(servletContext, exceptionClass)) { - ok = false; - } - } - - valid = ok; - - return valid; - } - - public boolean matches(Throwable t) { - return t != null && exceptionClass != null && exceptionClass.isInstance(t); - } - - protected RewrittenUrl execute(final HttpServletRequest hsRequest, final HttpServletResponse hsResponse, - Throwable originalThrowable) - throws IOException, ServletException, InvocationTargetException { - - // make sure the runs are handled - int runsSize = runs.size(); - RewriteMatch lastRunMatch = null; - if (runsSize > 0) { - log.trace("performing runs"); - for (int i = 0; i < runsSize; i++) { - Run run = (Run) runs.get(i); - lastRunMatch = run.execute(hsRequest, hsResponse, originalThrowable); - } - } - if ( lastRunMatch == null ) return null; - return new RewrittenUrlClass(lastRunMatch); - } - - public String getError() { - return error; - } - - public void setError(String error) { - this.error = error; - log.error(error); - } - - public void setError(String error, Throwable t) { - this.error = error; - log.error(error, t); - } - - public String getClassStr() { - return classStr; - } - - public void setClassStr(String classStr) { - this.classStr = classStr; - } - - - public void addRun(final Run run) { - runs.add(run); - } - - public List getRuns() { - return runs; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +/** + * An item that will allow exceptions during "run" invocation to be caught. + */ +public class CatchElem implements Runnable { + + private static Log log = Log.getLog(CatchElem.class); + + private String classStr; + private String error = null; + private boolean valid = false; + private boolean initialised = false; + private Class exceptionClass; + private ArrayList runs = new ArrayList(); + + /** + * For testing and documentation we don't want to load the classes. + */ + private static boolean loadClass = true; + + public static void setLoadClass(boolean loadClass) { + CatchElem.loadClass = loadClass; + } + + public boolean isValid() { + return valid; + } + + public boolean isInitialised() { + return initialised; + } + + /** + * @return true on success + */ + public boolean initialise(ServletContext servletContext) { + initialised = true; + boolean ok = true; + if (log.isDebugEnabled()) { + log.debug("looking for class " + classStr); + } + if ( loadClass ) { + try { + exceptionClass = Class.forName(classStr); + } catch (ClassNotFoundException e) { + setError("could not find " + classStr + " got a " + e.toString(), e); + return false; + } catch (NoClassDefFoundError e) { + setError("could not find " + classStr + " got a " + e.toString(), e); + return false; + } + } + // now initialise runs + for (int i = 0; i < runs.size(); i++) { + final Run run = (Run) runs.get(i); + if (!run.initialise(servletContext, exceptionClass)) { + ok = false; + } + } + + valid = ok; + + return valid; + } + + public boolean matches(Throwable t) { + return t != null && exceptionClass != null && exceptionClass.isInstance(t); + } + + protected RewrittenUrl execute(final HttpServletRequest hsRequest, final HttpServletResponse hsResponse, + Throwable originalThrowable) + throws IOException, ServletException, InvocationTargetException { + + // make sure the runs are handled + int runsSize = runs.size(); + RewriteMatch lastRunMatch = null; + if (runsSize > 0) { + log.trace("performing runs"); + for (int i = 0; i < runsSize; i++) { + Run run = (Run) runs.get(i); + lastRunMatch = run.execute(hsRequest, hsResponse, originalThrowable); + } + } + if ( lastRunMatch == null ) return null; + return new RewrittenUrlClass(lastRunMatch); + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + log.error(error); + } + + public void setError(String error, Throwable t) { + this.error = error; + log.error(error, t); + } + + public String getClassStr() { + return classStr; + } + + public void setClassStr(String classStr) { + this.classStr = classStr; + } + + + public void addRun(final Run run) { + runs.add(run); + } + + public List getRuns() { + return runs; + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/ClassRule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/ClassRule.java index 6e295610..42af9269 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/ClassRule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/ClassRule.java @@ -1,316 +1,316 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; -import org.tuckey.web.filters.urlrewrite.extend.RewriteRule; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - - -public class ClassRule implements Rule { - - private static Log log = Log.getLog(ClassRule.class); - - private String classStr; - private RewriteRule localRule; - private boolean initialised = false; - private int id; - private boolean enabled = true; - private boolean valid = false; - private boolean last = true; - private List errors = new ArrayList(); - - private static final String DEAULT_METHOD_STR = "matches"; - private String methodStr = DEAULT_METHOD_STR; - - - /** - * The parameter types used for run methods. - */ - private static Class[] methodParameterTypesHttp = new Class[2]; - - static { - methodParameterTypesHttp[0] = HttpServletRequest.class; - methodParameterTypesHttp[1] = HttpServletResponse.class; - } - - /** - * For second try. - */ - private static Class[] methodParameterTypes = new Class[2]; - - static { - methodParameterTypes[0] = ServletRequest.class; - methodParameterTypes[1] = ServletResponse.class; - } - - private Method destroyMethod; - private Method initMethod; - private Method matchesMethod; - - - public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse, final RuleChain chain) - throws IOException, ServletException { - return matches(url, hsRequest, hsResponse); - } - - public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse) - throws ServletException, IOException { - if (! initialised) return null; - - Object[] args = new Object[2]; - args[0] = hsRequest; - args[1] = hsResponse; - - Object returnedObj; - if (log.isDebugEnabled()) { - log.debug("running " + classStr + "." + methodStr + "(HttpServletRequest, HttpServletResponse)"); - } - if (matchesMethod == null) return null; - try { - returnedObj = matchesMethod.invoke(localRule, (Object[]) args); - - } catch (IllegalAccessException e) { - if (log.isDebugEnabled()) log.debug(e); - throw new ServletException(e); - - } catch (InvocationTargetException e) { - if (log.isDebugEnabled()) log.debug(e); - Throwable originalThrowable = e.getTargetException(); - if (originalThrowable == null) { - originalThrowable = e.getCause(); - if (originalThrowable == null) { - throw new ServletException(e); - } - } - if (originalThrowable instanceof Error) throw (Error) originalThrowable; - if (originalThrowable instanceof RuntimeException) throw (RuntimeException) originalThrowable; - if (originalThrowable instanceof ServletException) throw (ServletException) originalThrowable; - if (originalThrowable instanceof IOException) throw (IOException) originalThrowable; - throw new ServletException(originalThrowable); - } - - if ( returnedObj != null && returnedObj instanceof RewriteMatch) { - return new RewrittenUrlClass((RewriteMatch) returnedObj); - } - return null; - } - - - - - - - public boolean initialise(ServletContext context) { - // check all the conditions - initialised = true; - - Class ruleClass; - try { - ruleClass = Class.forName(classStr); - } catch (ClassNotFoundException e) { - addError("could not find " + classStr + " got a " + e.toString(), e); - return false; - } catch (NoClassDefFoundError e) { - addError("could not find " + classStr + " got a " + e.toString(), e); - return false; - } - - Constructor constructor; - try { - constructor = ruleClass.getConstructor((Class[]) null); - } catch (NoSuchMethodException e) { - addError("could not get constructor for " + classStr, e); - return false; - } - - if (log.isDebugEnabled()) { - log.debug("looking for " + methodStr + " will try with several arguments"); - } - try { - matchesMethod = ruleClass.getMethod(methodStr, methodParameterTypes); - } catch (NoSuchMethodException e) { - try { - matchesMethod = ruleClass.getMethod(methodStr, methodParameterTypesHttp); - } catch (NoSuchMethodException e2) { - addError("could not find " + methodStr + "(ServletRequest, ServletResponse) on " + classStr, e); - addError("also tried " + methodStr + "(HttpServletRequest, HttpServletResponse)", e2); - } - } - - Method[] methods = ruleClass.getMethods(); - for (int i = 0; i < methods.length; i++) { - Method method = methods[i]; - if ("destroy".equals(method.getName()) && method.getParameterTypes().length == 0) { - log.debug("found destroy methodStr"); - destroyMethod = method; - } - if ("init".equals(method.getName()) && method.getParameterTypes().length == 1 && - ServletContext.class.getName().equals(method.getParameterTypes()[0].getName())) { - log.debug("found init methodStr"); - initMethod = method; - } - if (initMethod != null && destroyMethod != null) break; - } - - Object instance; - log.debug("getting new instance of " + classStr); - try { - instance = constructor.newInstance((Object[]) null); - } catch (InstantiationException e) { - logInvokeException("constructor", e); - return false; - } catch (IllegalAccessException e) { - logInvokeException("constructor", e); - return false; - } catch (InvocationTargetException e) { - logInvokeException("constructor", e); - return false; - } - if (initMethod != null) { - log.debug("about to run init(ServletContext) on " + classStr); - Object[] args = new Object[1]; - args[0] = context; - try { - initMethod.invoke(instance, args); - } catch (IllegalAccessException e) { - logInvokeException("init(ServletContext)", e); - return false; - } catch (InvocationTargetException e) { - logInvokeException("init(ServletContext)", e); - return false; - } - } - - localRule = (RewriteRule) instance; - - valid = true; - return true; - } - - private void logInvokeException(String methodStr, Exception e) { - Throwable cause = e.getCause(); - if (cause == null) { - addError("when invoking " + methodStr + " on " + classStr - + " got an " + e.toString(), e); - } else { - addError("when invoking " + methodStr + " on " + classStr - + " got an " + e.toString() + " caused by " + cause.toString(), cause); - } - } - - public void destroy() { - if (localRule == null) return; - localRule.destroy(); - } - - public String getName() { - return classStr; - } - - public String getDisplayName() { - return "Class Rule " + classStr; - } - - public boolean isLast() { - return last; - } - - public void setLast(boolean last) { - this.last = last; - } - - public void setClassStr(String classStr) { - this.classStr = classStr; - } - - public String getClassStr() { - return classStr; - } - - public void setMethodStr(String methodStr) { - this.methodStr = StringUtils.trimToNull(methodStr); - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public void setId(int i) { - this.id = i; - } - - public int getId() { - return id; - } - - public boolean isValid() { - return valid; - } - - public boolean isFilter() { - return false; - } - - public List getErrors() { - return errors; - } - - private void addError(String s, Throwable t) { - log.error(getDisplayName() + " had error: " + s, t); - errors.add(s); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; +import org.tuckey.web.filters.urlrewrite.extend.RewriteRule; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + + +public class ClassRule implements Rule { + + private static Log log = Log.getLog(ClassRule.class); + + private String classStr; + private RewriteRule localRule; + private boolean initialised = false; + private int id; + private boolean enabled = true; + private boolean valid = false; + private boolean last = true; + private List errors = new ArrayList(); + + private static final String DEAULT_METHOD_STR = "matches"; + private String methodStr = DEAULT_METHOD_STR; + + + /** + * The parameter types used for run methods. + */ + private static Class[] methodParameterTypesHttp = new Class[2]; + + static { + methodParameterTypesHttp[0] = HttpServletRequest.class; + methodParameterTypesHttp[1] = HttpServletResponse.class; + } + + /** + * For second try. + */ + private static Class[] methodParameterTypes = new Class[2]; + + static { + methodParameterTypes[0] = ServletRequest.class; + methodParameterTypes[1] = ServletResponse.class; + } + + private Method destroyMethod; + private Method initMethod; + private Method matchesMethod; + + + public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse, final RuleChain chain) + throws IOException, ServletException { + return matches(url, hsRequest, hsResponse); + } + + public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse) + throws ServletException, IOException { + if (! initialised) return null; + + Object[] args = new Object[2]; + args[0] = hsRequest; + args[1] = hsResponse; + + Object returnedObj; + if (log.isDebugEnabled()) { + log.debug("running " + classStr + "." + methodStr + "(HttpServletRequest, HttpServletResponse)"); + } + if (matchesMethod == null) return null; + try { + returnedObj = matchesMethod.invoke(localRule, (Object[]) args); + + } catch (IllegalAccessException e) { + if (log.isDebugEnabled()) log.debug(e); + throw new ServletException(e); + + } catch (InvocationTargetException e) { + if (log.isDebugEnabled()) log.debug(e); + Throwable originalThrowable = e.getTargetException(); + if (originalThrowable == null) { + originalThrowable = e.getCause(); + if (originalThrowable == null) { + throw new ServletException(e); + } + } + if (originalThrowable instanceof Error) throw (Error) originalThrowable; + if (originalThrowable instanceof RuntimeException) throw (RuntimeException) originalThrowable; + if (originalThrowable instanceof ServletException) throw (ServletException) originalThrowable; + if (originalThrowable instanceof IOException) throw (IOException) originalThrowable; + throw new ServletException(originalThrowable); + } + + if ( returnedObj != null && returnedObj instanceof RewriteMatch) { + return new RewrittenUrlClass((RewriteMatch) returnedObj); + } + return null; + } + + + + + + + public boolean initialise(ServletContext context) { + // check all the conditions + initialised = true; + + Class ruleClass; + try { + ruleClass = Class.forName(classStr); + } catch (ClassNotFoundException e) { + addError("could not find " + classStr + " got a " + e.toString(), e); + return false; + } catch (NoClassDefFoundError e) { + addError("could not find " + classStr + " got a " + e.toString(), e); + return false; + } + + Constructor constructor; + try { + constructor = ruleClass.getConstructor((Class[]) null); + } catch (NoSuchMethodException e) { + addError("could not get constructor for " + classStr, e); + return false; + } + + if (log.isDebugEnabled()) { + log.debug("looking for " + methodStr + " will try with several arguments"); + } + try { + matchesMethod = ruleClass.getMethod(methodStr, methodParameterTypes); + } catch (NoSuchMethodException e) { + try { + matchesMethod = ruleClass.getMethod(methodStr, methodParameterTypesHttp); + } catch (NoSuchMethodException e2) { + addError("could not find " + methodStr + "(ServletRequest, ServletResponse) on " + classStr, e); + addError("also tried " + methodStr + "(HttpServletRequest, HttpServletResponse)", e2); + } + } + + Method[] methods = ruleClass.getMethods(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if ("destroy".equals(method.getName()) && method.getParameterTypes().length == 0) { + log.debug("found destroy methodStr"); + destroyMethod = method; + } + if ("init".equals(method.getName()) && method.getParameterTypes().length == 1 && + ServletContext.class.getName().equals(method.getParameterTypes()[0].getName())) { + log.debug("found init methodStr"); + initMethod = method; + } + if (initMethod != null && destroyMethod != null) break; + } + + Object instance; + log.debug("getting new instance of " + classStr); + try { + instance = constructor.newInstance((Object[]) null); + } catch (InstantiationException e) { + logInvokeException("constructor", e); + return false; + } catch (IllegalAccessException e) { + logInvokeException("constructor", e); + return false; + } catch (InvocationTargetException e) { + logInvokeException("constructor", e); + return false; + } + if (initMethod != null) { + log.debug("about to run init(ServletContext) on " + classStr); + Object[] args = new Object[1]; + args[0] = context; + try { + initMethod.invoke(instance, args); + } catch (IllegalAccessException e) { + logInvokeException("init(ServletContext)", e); + return false; + } catch (InvocationTargetException e) { + logInvokeException("init(ServletContext)", e); + return false; + } + } + + localRule = (RewriteRule) instance; + + valid = true; + return true; + } + + private void logInvokeException(String methodStr, Exception e) { + Throwable cause = e.getCause(); + if (cause == null) { + addError("when invoking " + methodStr + " on " + classStr + + " got an " + e.toString(), e); + } else { + addError("when invoking " + methodStr + " on " + classStr + + " got an " + e.toString() + " caused by " + cause.toString(), cause); + } + } + + public void destroy() { + if (localRule == null) return; + localRule.destroy(); + } + + public String getName() { + return classStr; + } + + public String getDisplayName() { + return "Class Rule " + classStr; + } + + public boolean isLast() { + return last; + } + + public void setLast(boolean last) { + this.last = last; + } + + public void setClassStr(String classStr) { + this.classStr = classStr; + } + + public String getClassStr() { + return classStr; + } + + public void setMethodStr(String methodStr) { + this.methodStr = StringUtils.trimToNull(methodStr); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setId(int i) { + this.id = i; + } + + public int getId() { + return id; + } + + public boolean isValid() { + return valid; + } + + public boolean isFilter() { + return false; + } + + public List getErrors() { + return errors; + } + + private void addError(String s, Throwable t) { + log.error(getDisplayName() + " had error: " + s, t); + errors.add(s); + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Condition.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Condition.java index 4a425cb3..27a64256 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Condition.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Condition.java @@ -1,787 +1,787 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.NumberUtils; -import org.tuckey.web.filters.urlrewrite.utils.RegexPattern; -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingPattern; -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingPatternSyntaxException; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; -import org.tuckey.web.filters.urlrewrite.utils.WildcardPattern; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpSession; -import java.io.File; -import java.util.Calendar; -import java.net.URI; -import java.net.URISyntaxException; - -/** - * Conditions must be met when the filter is processing a url. - * - * @author Paul Tuckey - * @version $Revision: 48 $ $Date: 2006-11-27 16:53:31 +1300 (Mon, 27 Nov 2006) $ - */ -public class Condition extends TypeConverter { - - private static Log log = Log.getLog(Condition.class); - - /** - * Should this expression be matched case sensitively. - */ - private boolean caseSensitive = false; - - /** - * Used to identify the condition. - */ - private int id = 0; - - /** - * Used to cache the pattern for faster execution. - */ - private StringMatchingPattern pattern; - - /** - * The name of the header etc. - */ - private String name; - - /** - * The operator that should be used to evaluate the condition. - */ - private short operator; - - /** - * Value of this condition if the type is header. - */ - private String strValue; - - /** - * Value of this condition if the type is port. - */ - private long numericValue = 0; - - /** - * What to do with the next rule, this will indicate "or" otherwise do "and". - */ - private boolean processNextOr = false; - - private boolean valid = false; - private boolean initialised = false; - - // Operators - private static final short OPERATOR_EQUAL = 1; - private static final short OPERATOR_NOT_EQUAL = 2; - private static final short OPERATOR_GREATER_THAN = 3; - private static final short OPERATOR_LESS_THAN = 4; - private static final short OPERATOR_GREATER_THAN_OR_EQUAL = 5; - private static final short OPERATOR_LESS_THAN_OR_EQUAL = 6; - private static final short OPERATOR_INSTANCEOF = 7; - private static final short OPERATOR_IS_DIR = 8; - private static final short OPERATOR_IS_FILE = 9; - private static final short OPERATOR_IS_FILE_WITH_SIZE = 10; - private static final short OPERATOR_NOT_DIR = 11; - private static final short OPERATOR_NOT_FILE = 12; - private static final short OPERATOR_NOT_FILE_WITH_SIZE = 13; - - // if we are doing an instanceof test the class we want to test against - Class instanceOfClass = null; - - // the rule that "owns" this condition. - private RuleBase rule; - - - /** - * Will check and see if the condition matches the request. - * - * @param hsRequest - * @return true on match - * @deprecated use getConditionMatch(HttpServletRequest hsRequest) - */ - public boolean matches(final HttpServletRequest hsRequest) { - return getConditionMatch(hsRequest) != null; - } - - /** - * Will check and see if the condition matches the request. - * - * @param hsRequest - * @return true on match - */ - public ConditionMatch getConditionMatch(final HttpServletRequest hsRequest) { - if (!initialised) { - log.debug("condition not initialised skipping"); - // error initialising do not process - return null; - } - if (!valid) { - log.debug("condition not valid skipping"); - return null; - } - - switch (type) { - case TYPE_TIME: - return evaluateNumericCondition(System.currentTimeMillis()); - case TYPE_TIME_YEAR: - return evaluateCalendarCondition(Calendar.YEAR); - case TYPE_TIME_MONTH: - return evaluateCalendarCondition(Calendar.MONTH); - case TYPE_TIME_DAY_OF_MONTH: - return evaluateCalendarCondition(Calendar.DAY_OF_MONTH); - case TYPE_TIME_DAY_OF_WEEK: - return evaluateCalendarCondition(Calendar.DAY_OF_WEEK); - case TYPE_TIME_AMPM: - return evaluateCalendarCondition(Calendar.AM_PM); - case TYPE_TIME_HOUR_OF_DAY: - return evaluateCalendarCondition(Calendar.HOUR_OF_DAY); - case TYPE_TIME_MINUTE: - return evaluateCalendarCondition(Calendar.MINUTE); - case TYPE_TIME_SECOND: - return evaluateCalendarCondition(Calendar.SECOND); - case TYPE_TIME_MILLISECOND: - return evaluateCalendarCondition(Calendar.MILLISECOND); - - case TYPE_ATTRIBUTE: - return evaluateAttributeCondition(name == null ? null : hsRequest.getAttribute(name)); - case TYPE_AUTH_TYPE: - return evaluateStringCondition(hsRequest.getAuthType()); - case TYPE_CHARACTER_ENCODING: - return evaluateStringCondition(hsRequest.getCharacterEncoding()); - case TYPE_CONTENT_LENGTH: - return evaluateNumericCondition(hsRequest.getContentLength()); - case TYPE_CONTENT_TYPE: - return evaluateStringCondition(hsRequest.getContentType()); - case TYPE_CONTEXT_PATH: - return evaluateStringCondition(hsRequest.getContextPath()); - case TYPE_COOKIE: - return evaluateCookieCondition(hsRequest.getCookies(), name); - case TYPE_LOCAL_PORT: - return evaluateNumericCondition(hsRequest.getLocalPort()); - case TYPE_METHOD: - return evaluateStringCondition(hsRequest.getMethod()); - case TYPE_PARAMETER: - return evaluateStringCondition(name == null ? null : hsRequest.getParameter(name)); - case TYPE_PATH_INFO: - return evaluateStringCondition(hsRequest.getPathInfo()); - case TYPE_PATH_TRANSLATED: - return evaluateStringCondition(hsRequest.getPathTranslated()); - case TYPE_PROTOCOL: - return evaluateStringCondition(hsRequest.getProtocol()); - case TYPE_QUERY_STRING: - return evaluateStringCondition(hsRequest.getQueryString()); - case TYPE_REMOTE_ADDR: - return evaluateStringCondition(hsRequest.getRemoteAddr()); - case TYPE_REMOTE_HOST: - return evaluateStringCondition(hsRequest.getRemoteHost()); - case TYPE_REMOTE_USER: - return evaluateStringCondition(hsRequest.getRemoteUser()); - case TYPE_REQUESTED_SESSION_ID: - return evaluateStringCondition(hsRequest.getRequestedSessionId()); - case TYPE_REQUESTED_SESSION_ID_FROM_COOKIE: - return evaluateBoolCondition(hsRequest.isRequestedSessionIdFromCookie()); - case TYPE_REQUESTED_SESSION_ID_FROM_URL: - return evaluateBoolCondition(hsRequest.isRequestedSessionIdFromURL()); - case TYPE_REQUESTED_SESSION_ID_VALID: - return evaluateBoolCondition(hsRequest.isRequestedSessionIdValid()); - case TYPE_REQUEST_URI: - return evaluateStringCondition(hsRequest.getRequestURI()); - case TYPE_REQUEST_URL: - StringBuffer requestUrlBuff = hsRequest.getRequestURL(); - String requestUrlStr = null; - if (requestUrlBuff != null) { - requestUrlStr = requestUrlBuff.toString(); - } - return evaluateStringCondition(requestUrlStr); - case TYPE_SESSION_ATTRIBUTE: - Object sessionAttributeValue = null; - final HttpSession session = hsRequest.getSession(false); - if (session != null && name != null) { - sessionAttributeValue = session.getAttribute(name); - } - return evaluateAttributeCondition(sessionAttributeValue); - - case TYPE_SESSION_IS_NEW: - boolean sessionNew = false; - final HttpSession sessionIsNew = hsRequest.getSession(false); - if (sessionIsNew != null) { - sessionNew = sessionIsNew.isNew(); - } - return evaluateBoolCondition(sessionNew); - case TYPE_SERVER_PORT: - return evaluateNumericCondition(hsRequest.getServerPort()); - case TYPE_SERVER_NAME: - return evaluateStringCondition(hsRequest.getServerName()); - case TYPE_SCHEME: - return evaluateStringCondition(hsRequest.getScheme()); - case TYPE_USER_IN_ROLE: - log.debug("is user in role " + name + " op " + operator); - return evaluateBoolCondition(hsRequest.isUserInRole(name)); - - case TYPE_EXCEPTION: - String eName = null; - Exception e = (Exception) hsRequest.getAttribute("javax.servlet.error.exception"); - - if (OPERATOR_INSTANCEOF == operator) { - return evaluateInstanceOfCondition(e); - } else { - if (e != null && e.getClass() != null) eName = e.getClass().getName(); - return evaluateStringCondition(eName); - } - - case TYPE_REQUEST_FILENAME: - if ( rule.getServletContext() != null ) { - String requestURI = hsRequest.getRequestURI(); - if (requestURI.startsWith(hsRequest.getContextPath() + "/")){ - requestURI = requestURI.substring(hsRequest.getContextPath().length()); - } - // Decode any encoded URI chars - try { - requestURI = new URI( requestURI ).getPath(); - } catch( URISyntaxException URIe ) {} - String fileName = rule.getServletContext().getRealPath( requestURI ); - if ( log.isDebugEnabled() ) log.debug("fileName found is " + fileName); - return evaluateStringCondition(fileName); - } else { - log.error("unable to get servlet context for filename lookup, skipping"); - return null; - } - - default: - return evaluateHeaderCondition(hsRequest); - } - } - - private ConditionMatch evaluateAttributeCondition(Object attribObject) { - String attribValue = null; - if (attribObject == null) { - if (log.isDebugEnabled()) { - log.debug(name + " doesn't exist"); - } - } else { - attribValue = attribObject.toString(); - } - if (OPERATOR_INSTANCEOF == operator) { - return evaluateInstanceOfCondition(attribObject); - } else { - return evaluateStringCondition(attribValue); - } - } - - private ConditionMatch evaluateInstanceOfCondition(Object obj) { - // only test for instanceof if object is not null - if (obj == null) return null; - - if (log.isDebugEnabled()) { - log.debug("is " + obj.getClass() + " an instanceof " + instanceOfClass); - } - if (instanceOfClass == null) { - log.error("this condition may have failed to initialise correctly, instanceof class is null"); - return null; - } - if (instanceOfClass.isInstance(obj)) { - log.debug("yes"); - return new ConditionMatch(); - } - log.debug("no"); - return null; - } - - - private ConditionMatch evaluateCookieCondition(Cookie[] cookies, String name) { - if (cookies == null) { - // we will have to do an exists check - return evaluateBoolCondition(false); - } - if (name == null) { - return evaluateBoolCondition(false); - } - for (int i = 0; i < cookies.length; i++) { - Cookie cookie = cookies[i]; - if (cookie == null) { - continue; - } - if (name.equals(cookie.getName())) { - return evaluateStringCondition(cookie.getValue()); - } - } - return evaluateBoolCondition(false); - } - - - private ConditionMatch evaluateStringCondition(String value) { - if ( operator == OPERATOR_IS_DIR ) { - if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is a directory"); - if (value == null){ - return evaluateBoolCondition(false); - } - File fileToCheck = new File(value); - return evaluateBoolCondition(fileToCheck.isDirectory()); - } else if ( operator == OPERATOR_IS_FILE ) { - if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is a file"); - if (value == null){ - return evaluateBoolCondition(false); - } - File fileToCheck = new File(value); - return evaluateBoolCondition(fileToCheck.isFile()); - } else if ( operator == OPERATOR_IS_FILE_WITH_SIZE ) { - if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is a file with size"); - if (value == null){ - return evaluateBoolCondition(false); - } - File fileToCheck = new File(value); - return evaluateBoolCondition(fileToCheck.isFile() && fileToCheck.length() > 0); - } else if ( operator == OPERATOR_NOT_DIR ) { - if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is not a directory"); - if (value == null){ - return evaluateBoolCondition(true); - } - File fileToCheck = new File(value); - return evaluateBoolCondition(!fileToCheck.isDirectory()); - } else if ( operator == OPERATOR_NOT_FILE ) { - if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is not a file"); - if (value == null){ - return evaluateBoolCondition(true); - } - File fileToCheck = new File(value); - return evaluateBoolCondition(!fileToCheck.isFile()); - } else if ( operator == OPERATOR_NOT_FILE_WITH_SIZE ) { - if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is not a file with size"); - if (value == null){ - return evaluateBoolCondition(true); - } - File fileToCheck = new File(value); - return evaluateBoolCondition(!(fileToCheck.isFile() && fileToCheck.length() > 0)); - } - if (pattern == null && value == null) { - log.debug("value is empty and pattern is also, condition false"); - return evaluateBoolCondition(false); - } - if (pattern == null) { - log.debug("value isn't empty but pattern is, assuming checking for existence, condition true"); - return evaluateBoolCondition(true); - } - if (value == null) { - // value is null make value "" - value = ""; - } - if (log.isDebugEnabled()) { - log.debug("evaluating \"" + value + "\" against " + strValue); - } - StringMatchingMatcher matcher = pattern.matcher(value); - return evaluateBoolCondition(matcher, matcher.find()); - } - - /** - * Evaluate taking into account the operator, not only boolean operators considered. - */ - private ConditionMatch evaluateBoolCondition(boolean outcome) { - if (log.isTraceEnabled()) { - log.trace("outcome " + outcome); - } - if (operator == OPERATOR_NOT_EQUAL) { - log.debug("not equal operator in use"); - return !outcome ? new ConditionMatch() : null; - } - return outcome ? new ConditionMatch() : null; - } - - private ConditionMatch evaluateBoolCondition(StringMatchingMatcher matcher, boolean outcome) { - ConditionMatch conditionMatch = evaluateBoolCondition(outcome); - if (conditionMatch != null) { - conditionMatch.setMatcher(matcher); - } - return conditionMatch; - } - - private ConditionMatch evaluateHeaderCondition(final HttpServletRequest hsRequest) { - String headerValue = null; - if (name != null) { - headerValue = hsRequest.getHeader(name); - } - return evaluateStringCondition(headerValue); - } - - /** - * Will evaluate a calendar condition. - * - * @param calField the calendar field from Calendar - */ - private ConditionMatch evaluateCalendarCondition(final int calField) { - return evaluateNumericCondition((Calendar.getInstance()).get(calField)); - } - - /** - * Will evaluate usign operator. - * - * @param compareWith what to compare with - * @return true or false - */ - private ConditionMatch evaluateNumericCondition(final long compareWith) { - if (log.isDebugEnabled()) { - log.debug("evaluating with operator, is " + compareWith + " " + getOperator() + " " + numericValue); - } - switch (operator) { - case OPERATOR_NOT_EQUAL: - return compareWith != numericValue ? new ConditionMatch() : null; - case OPERATOR_GREATER_THAN: - return compareWith > numericValue ? new ConditionMatch() : null; - case OPERATOR_LESS_THAN: - return compareWith < numericValue ? new ConditionMatch() : null; - case OPERATOR_GREATER_THAN_OR_EQUAL: - return compareWith >= numericValue ? new ConditionMatch() : null; - case OPERATOR_LESS_THAN_OR_EQUAL: - return compareWith <= numericValue ? new ConditionMatch() : null; - default: - return compareWith == numericValue ? new ConditionMatch() : null; - } - } - - - /** - * Returns false on failure. Use getError to get the description of the error. - * - * @return weather or not the condition was successful in initialisation. - */ - public boolean initialise() { - initialised = true; - if (error != null) { - return false; - } - // make sure we default to header if not set - if (type == 0) { - type = TYPE_HEADER; - } - switch (type) { - // note, only numeric specified others handled by default: - case TYPE_SERVER_PORT: - initNumericValue(); - break; - case TYPE_TIME: - initNumericValue(); - break; - case TYPE_TIME_YEAR: - initNumericValue(); - break; - case TYPE_TIME_MONTH: - initNumericValue(); - break; - case TYPE_TIME_DAY_OF_MONTH: - initNumericValue(); - break; - case TYPE_TIME_DAY_OF_WEEK: - initNumericValue(); - break; - case TYPE_TIME_AMPM: - initNumericValue(); - break; - case TYPE_TIME_HOUR_OF_DAY: - initNumericValue(); - break; - case TYPE_TIME_MINUTE: - initNumericValue(); - break; - case TYPE_TIME_SECOND: - initNumericValue(); - break; - case TYPE_TIME_MILLISECOND: - initNumericValue(); - break; - case TYPE_CONTENT_LENGTH: - initNumericValue(); - break; - case TYPE_LOCAL_PORT: - initNumericValue(); - break; - case TYPE_USER_IN_ROLE: - // we only care to make sure the user has entered a name (if no name use value) - // note regexs cannot be entered against this due to limitations in servlet spec - if (StringUtils.isBlank(name)) { - name = strValue; - } - break; - case TYPE_SESSION_ATTRIBUTE: - if (StringUtils.isBlank(name)) { - setError("you must set a name for session attributes"); - } - initStringValue(); - break; - case TYPE_ATTRIBUTE: - if (StringUtils.isBlank(name)) { - setError("you must set a name for attributes"); - } - initStringValue(); - break; - case TYPE_HEADER: - if (StringUtils.isBlank(name)) { - setError("you must set a name for a header"); - } - initStringValue(); - break; - default: - // other generic types - initStringValue(); - } - if (log.isDebugEnabled()) { - log.debug("loaded condition " + getType() + " " + name + " " + strValue); - } - valid = error == null; - return valid; - } - - private void initStringValue() { - if (StringUtils.isBlank(strValue)) { - log.debug("value is blank initing pattern to null"); - pattern = null; - return; - } - if (OPERATOR_INSTANCEOF == operator) { - // want to be able to do instance of that means value is not a regexp - log.debug("initialising instanceof condition"); - strValue = StringUtils.trim(strValue); - try { - instanceOfClass = Class.forName(strValue); - } catch (ClassNotFoundException e) { - setError("could not find " + strValue + " got a " + e.toString()); - } catch (NoClassDefFoundError e) { - setError("could not find " + strValue + " got a " + e.toString()); - } - - } else { - try { - if (rule != null && rule.isMatchTypeWildcard()) { - log.debug("rule match type is wildcard"); - pattern = new WildcardPattern(strValue); - - } else { - // default is regex - pattern = new RegexPattern(strValue, caseSensitive); - } - - } catch (StringMatchingPatternSyntaxException e) { - setError("Problem compiling regular expression " + strValue + " (" + e.getMessage() + ")"); - } - } - } - - /** - * Will init a numeric value type ie port. - */ - private void initNumericValue() { - if (numericValue == 0) { - numericValue = NumberUtils.stringToLong(StringUtils.trim(strValue)); - if (numericValue == 0 && !"0".equals(strValue)) { - setError("Value " + strValue + " is not a valid number (tried to cast to java type long)"); - } - } - } - - protected void setError(String s) { - super.setError(s); - log.error("Condition " + id + " had error: " + s); - } - - - /** - * Will get the operator type. - * - * @return notequal, greater etc. - */ - public String getOperator() { - switch (operator) { - case OPERATOR_NOT_EQUAL: - return "notequal"; - case OPERATOR_GREATER_THAN: - return "greater"; - case OPERATOR_LESS_THAN: - return "less"; - case OPERATOR_GREATER_THAN_OR_EQUAL: - return "greaterorequal"; - case OPERATOR_LESS_THAN_OR_EQUAL: - return "lessorequal"; - case OPERATOR_INSTANCEOF: - return "instanceof"; - case OPERATOR_EQUAL: - return "equal"; - case OPERATOR_IS_DIR: - return "isdir"; - case OPERATOR_IS_FILE: - return "isfile"; - case OPERATOR_IS_FILE_WITH_SIZE: - return "isfilewithsize"; - case OPERATOR_NOT_DIR: - return "notdir"; - case OPERATOR_NOT_FILE: - return "notfile"; - case OPERATOR_NOT_FILE_WITH_SIZE: - return "notfilewithsize"; - default: - return ""; - } - } - - /** - * Will ste the operator. - * - * @param operator type - */ - public void setOperator(final String operator) { - if ("notequal".equals(operator)) { - this.operator = OPERATOR_NOT_EQUAL; - } else if ("greater".equals(operator)) { - this.operator = OPERATOR_GREATER_THAN; - } else if ("less".equals(operator)) { - this.operator = OPERATOR_LESS_THAN; - } else if ("greaterorequal".equals(operator)) { - this.operator = OPERATOR_GREATER_THAN_OR_EQUAL; - } else if ("lessorequal".equals(operator)) { - this.operator = OPERATOR_LESS_THAN_OR_EQUAL; - } else if ("instanceof".equals(operator)) { - this.operator = OPERATOR_INSTANCEOF; - } else if ("equal".equals(operator) || StringUtils.isBlank(operator)) { - this.operator = OPERATOR_EQUAL; - } else if ("isdir".equals(operator)) { - this.operator = OPERATOR_IS_DIR; - } else if ("isfile".equals(operator)) { - this.operator = OPERATOR_IS_FILE; - } else if ("isfilewithsize".equals(operator)) { - this.operator = OPERATOR_IS_FILE_WITH_SIZE; - } else if ("notdir".equals(operator)) { - this.operator = OPERATOR_NOT_DIR; - } else if ("notfile".equals(operator)) { - this.operator = OPERATOR_NOT_FILE; - } else if ("notfilewithsize".equals(operator)) { - this.operator = OPERATOR_NOT_FILE_WITH_SIZE; - } else { - setError("Operator " + operator + " is not valid"); - } - } - - /** - * Will get the name. - * - * @return String - */ - public String getName() { - return name; - } - - /** - * Will set the name. - * - * @param name the name - */ - public void setName(final String name) { - this.name = name; - } - - /** - * Will return "add" or "or". - * - * @return "add" or "or" - */ - public String getNext() { - if (processNextOr) return "or"; - return "and"; - } - - /** - * Will set next. - * - * @param next "or" or "and" - */ - public void setNext(final String next) { - if ("or".equals(next)) { - this.processNextOr = true; - } else if ("and".equals(next) || StringUtils.isBlank(next)) { - this.processNextOr = false; - } else { - setError("Next " + next + " is not valid (can be 'and', 'or')"); - } - } - - /** - * Will get the value. - * - * @return String - */ - public String getValue() { - return strValue; - } - - /** - * Will set the value. - * - * @param value the value - */ - public void setValue(final String value) { - this.strValue = value; - } - - /** - * True if process next is or. - * - * @return boolean - */ - public boolean isProcessNextOr() { - return processNextOr; - } - - public void setId(int id) { - this.id = id; - } - - public int getId() { - return id; - } - - public boolean isCaseSensitive() { - return caseSensitive; - } - - public void setCaseSensitive(boolean caseSensitive) { - this.caseSensitive = caseSensitive; - } - - public String getDisplayName() { - return "Condtition " + id; - } - - public void setRule(RuleBase rule) { - this.rule = rule; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.NumberUtils; +import org.tuckey.web.filters.urlrewrite.utils.RegexPattern; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingPattern; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingPatternSyntaxException; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; +import org.tuckey.web.filters.urlrewrite.utils.WildcardPattern; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpSession; +import java.io.File; +import java.util.Calendar; +import java.net.URI; +import java.net.URISyntaxException; + +/** + * Conditions must be met when the filter is processing a url. + * + * @author Paul Tuckey + * @version $Revision: 48 $ $Date: 2006-11-27 16:53:31 +1300 (Mon, 27 Nov 2006) $ + */ +public class Condition extends TypeConverter { + + private static Log log = Log.getLog(Condition.class); + + /** + * Should this expression be matched case sensitively. + */ + private boolean caseSensitive = false; + + /** + * Used to identify the condition. + */ + private int id = 0; + + /** + * Used to cache the pattern for faster execution. + */ + private StringMatchingPattern pattern; + + /** + * The name of the header etc. + */ + private String name; + + /** + * The operator that should be used to evaluate the condition. + */ + private short operator; + + /** + * Value of this condition if the type is header. + */ + private String strValue; + + /** + * Value of this condition if the type is port. + */ + private long numericValue = 0; + + /** + * What to do with the next rule, this will indicate "or" otherwise do "and". + */ + private boolean processNextOr = false; + + private boolean valid = false; + private boolean initialised = false; + + // Operators + private static final short OPERATOR_EQUAL = 1; + private static final short OPERATOR_NOT_EQUAL = 2; + private static final short OPERATOR_GREATER_THAN = 3; + private static final short OPERATOR_LESS_THAN = 4; + private static final short OPERATOR_GREATER_THAN_OR_EQUAL = 5; + private static final short OPERATOR_LESS_THAN_OR_EQUAL = 6; + private static final short OPERATOR_INSTANCEOF = 7; + private static final short OPERATOR_IS_DIR = 8; + private static final short OPERATOR_IS_FILE = 9; + private static final short OPERATOR_IS_FILE_WITH_SIZE = 10; + private static final short OPERATOR_NOT_DIR = 11; + private static final short OPERATOR_NOT_FILE = 12; + private static final short OPERATOR_NOT_FILE_WITH_SIZE = 13; + + // if we are doing an instanceof test the class we want to test against + Class instanceOfClass = null; + + // the rule that "owns" this condition. + private RuleBase rule; + + + /** + * Will check and see if the condition matches the request. + * + * @param hsRequest + * @return true on match + * @deprecated use getConditionMatch(HttpServletRequest hsRequest) + */ + public boolean matches(final HttpServletRequest hsRequest) { + return getConditionMatch(hsRequest) != null; + } + + /** + * Will check and see if the condition matches the request. + * + * @param hsRequest + * @return true on match + */ + public ConditionMatch getConditionMatch(final HttpServletRequest hsRequest) { + if (!initialised) { + log.debug("condition not initialised skipping"); + // error initialising do not process + return null; + } + if (!valid) { + log.debug("condition not valid skipping"); + return null; + } + + switch (type) { + case TYPE_TIME: + return evaluateNumericCondition(System.currentTimeMillis()); + case TYPE_TIME_YEAR: + return evaluateCalendarCondition(Calendar.YEAR); + case TYPE_TIME_MONTH: + return evaluateCalendarCondition(Calendar.MONTH); + case TYPE_TIME_DAY_OF_MONTH: + return evaluateCalendarCondition(Calendar.DAY_OF_MONTH); + case TYPE_TIME_DAY_OF_WEEK: + return evaluateCalendarCondition(Calendar.DAY_OF_WEEK); + case TYPE_TIME_AMPM: + return evaluateCalendarCondition(Calendar.AM_PM); + case TYPE_TIME_HOUR_OF_DAY: + return evaluateCalendarCondition(Calendar.HOUR_OF_DAY); + case TYPE_TIME_MINUTE: + return evaluateCalendarCondition(Calendar.MINUTE); + case TYPE_TIME_SECOND: + return evaluateCalendarCondition(Calendar.SECOND); + case TYPE_TIME_MILLISECOND: + return evaluateCalendarCondition(Calendar.MILLISECOND); + + case TYPE_ATTRIBUTE: + return evaluateAttributeCondition(name == null ? null : hsRequest.getAttribute(name)); + case TYPE_AUTH_TYPE: + return evaluateStringCondition(hsRequest.getAuthType()); + case TYPE_CHARACTER_ENCODING: + return evaluateStringCondition(hsRequest.getCharacterEncoding()); + case TYPE_CONTENT_LENGTH: + return evaluateNumericCondition(hsRequest.getContentLength()); + case TYPE_CONTENT_TYPE: + return evaluateStringCondition(hsRequest.getContentType()); + case TYPE_CONTEXT_PATH: + return evaluateStringCondition(hsRequest.getContextPath()); + case TYPE_COOKIE: + return evaluateCookieCondition(hsRequest.getCookies(), name); + case TYPE_LOCAL_PORT: + return evaluateNumericCondition(hsRequest.getLocalPort()); + case TYPE_METHOD: + return evaluateStringCondition(hsRequest.getMethod()); + case TYPE_PARAMETER: + return evaluateStringCondition(name == null ? null : hsRequest.getParameter(name)); + case TYPE_PATH_INFO: + return evaluateStringCondition(hsRequest.getPathInfo()); + case TYPE_PATH_TRANSLATED: + return evaluateStringCondition(hsRequest.getPathTranslated()); + case TYPE_PROTOCOL: + return evaluateStringCondition(hsRequest.getProtocol()); + case TYPE_QUERY_STRING: + return evaluateStringCondition(hsRequest.getQueryString()); + case TYPE_REMOTE_ADDR: + return evaluateStringCondition(hsRequest.getRemoteAddr()); + case TYPE_REMOTE_HOST: + return evaluateStringCondition(hsRequest.getRemoteHost()); + case TYPE_REMOTE_USER: + return evaluateStringCondition(hsRequest.getRemoteUser()); + case TYPE_REQUESTED_SESSION_ID: + return evaluateStringCondition(hsRequest.getRequestedSessionId()); + case TYPE_REQUESTED_SESSION_ID_FROM_COOKIE: + return evaluateBoolCondition(hsRequest.isRequestedSessionIdFromCookie()); + case TYPE_REQUESTED_SESSION_ID_FROM_URL: + return evaluateBoolCondition(hsRequest.isRequestedSessionIdFromURL()); + case TYPE_REQUESTED_SESSION_ID_VALID: + return evaluateBoolCondition(hsRequest.isRequestedSessionIdValid()); + case TYPE_REQUEST_URI: + return evaluateStringCondition(hsRequest.getRequestURI()); + case TYPE_REQUEST_URL: + StringBuffer requestUrlBuff = hsRequest.getRequestURL(); + String requestUrlStr = null; + if (requestUrlBuff != null) { + requestUrlStr = requestUrlBuff.toString(); + } + return evaluateStringCondition(requestUrlStr); + case TYPE_SESSION_ATTRIBUTE: + Object sessionAttributeValue = null; + final HttpSession session = hsRequest.getSession(false); + if (session != null && name != null) { + sessionAttributeValue = session.getAttribute(name); + } + return evaluateAttributeCondition(sessionAttributeValue); + + case TYPE_SESSION_IS_NEW: + boolean sessionNew = false; + final HttpSession sessionIsNew = hsRequest.getSession(false); + if (sessionIsNew != null) { + sessionNew = sessionIsNew.isNew(); + } + return evaluateBoolCondition(sessionNew); + case TYPE_SERVER_PORT: + return evaluateNumericCondition(hsRequest.getServerPort()); + case TYPE_SERVER_NAME: + return evaluateStringCondition(hsRequest.getServerName()); + case TYPE_SCHEME: + return evaluateStringCondition(hsRequest.getScheme()); + case TYPE_USER_IN_ROLE: + log.debug("is user in role " + name + " op " + operator); + return evaluateBoolCondition(hsRequest.isUserInRole(name)); + + case TYPE_EXCEPTION: + String eName = null; + Exception e = (Exception) hsRequest.getAttribute("javax.servlet.error.exception"); + + if (OPERATOR_INSTANCEOF == operator) { + return evaluateInstanceOfCondition(e); + } else { + if (e != null && e.getClass() != null) eName = e.getClass().getName(); + return evaluateStringCondition(eName); + } + + case TYPE_REQUEST_FILENAME: + if ( rule.getServletContext() != null ) { + String requestURI = hsRequest.getRequestURI(); + if (requestURI.startsWith(hsRequest.getContextPath() + "/")){ + requestURI = requestURI.substring(hsRequest.getContextPath().length()); + } + // Decode any encoded URI chars + try { + requestURI = new URI( requestURI ).getPath(); + } catch( URISyntaxException URIe ) {} + String fileName = rule.getServletContext().getRealPath( requestURI ); + if ( log.isDebugEnabled() ) log.debug("fileName found is " + fileName); + return evaluateStringCondition(fileName); + } else { + log.error("unable to get servlet context for filename lookup, skipping"); + return null; + } + + default: + return evaluateHeaderCondition(hsRequest); + } + } + + private ConditionMatch evaluateAttributeCondition(Object attribObject) { + String attribValue = null; + if (attribObject == null) { + if (log.isDebugEnabled()) { + log.debug(name + " doesn't exist"); + } + } else { + attribValue = attribObject.toString(); + } + if (OPERATOR_INSTANCEOF == operator) { + return evaluateInstanceOfCondition(attribObject); + } else { + return evaluateStringCondition(attribValue); + } + } + + private ConditionMatch evaluateInstanceOfCondition(Object obj) { + // only test for instanceof if object is not null + if (obj == null) return null; + + if (log.isDebugEnabled()) { + log.debug("is " + obj.getClass() + " an instanceof " + instanceOfClass); + } + if (instanceOfClass == null) { + log.error("this condition may have failed to initialise correctly, instanceof class is null"); + return null; + } + if (instanceOfClass.isInstance(obj)) { + log.debug("yes"); + return new ConditionMatch(); + } + log.debug("no"); + return null; + } + + + private ConditionMatch evaluateCookieCondition(Cookie[] cookies, String name) { + if (cookies == null) { + // we will have to do an exists check + return evaluateBoolCondition(false); + } + if (name == null) { + return evaluateBoolCondition(false); + } + for (int i = 0; i < cookies.length; i++) { + Cookie cookie = cookies[i]; + if (cookie == null) { + continue; + } + if (name.equals(cookie.getName())) { + return evaluateStringCondition(cookie.getValue()); + } + } + return evaluateBoolCondition(false); + } + + + private ConditionMatch evaluateStringCondition(String value) { + if ( operator == OPERATOR_IS_DIR ) { + if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is a directory"); + if (value == null){ + return evaluateBoolCondition(false); + } + File fileToCheck = new File(value); + return evaluateBoolCondition(fileToCheck.isDirectory()); + } else if ( operator == OPERATOR_IS_FILE ) { + if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is a file"); + if (value == null){ + return evaluateBoolCondition(false); + } + File fileToCheck = new File(value); + return evaluateBoolCondition(fileToCheck.isFile()); + } else if ( operator == OPERATOR_IS_FILE_WITH_SIZE ) { + if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is a file with size"); + if (value == null){ + return evaluateBoolCondition(false); + } + File fileToCheck = new File(value); + return evaluateBoolCondition(fileToCheck.isFile() && fileToCheck.length() > 0); + } else if ( operator == OPERATOR_NOT_DIR ) { + if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is not a directory"); + if (value == null){ + return evaluateBoolCondition(true); + } + File fileToCheck = new File(value); + return evaluateBoolCondition(!fileToCheck.isDirectory()); + } else if ( operator == OPERATOR_NOT_FILE ) { + if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is not a file"); + if (value == null){ + return evaluateBoolCondition(true); + } + File fileToCheck = new File(value); + return evaluateBoolCondition(!fileToCheck.isFile()); + } else if ( operator == OPERATOR_NOT_FILE_WITH_SIZE ) { + if ( log.isDebugEnabled() ) log.debug("checking to see if " + value + " is not a file with size"); + if (value == null){ + return evaluateBoolCondition(true); + } + File fileToCheck = new File(value); + return evaluateBoolCondition(!(fileToCheck.isFile() && fileToCheck.length() > 0)); + } + if (pattern == null && value == null) { + log.debug("value is empty and pattern is also, condition false"); + return evaluateBoolCondition(false); + } + if (pattern == null) { + log.debug("value isn't empty but pattern is, assuming checking for existence, condition true"); + return evaluateBoolCondition(true); + } + if (value == null) { + // value is null make value "" + value = ""; + } + if (log.isDebugEnabled()) { + log.debug("evaluating \"" + value + "\" against " + strValue); + } + StringMatchingMatcher matcher = pattern.matcher(value); + return evaluateBoolCondition(matcher, matcher.find()); + } + + /** + * Evaluate taking into account the operator, not only boolean operators considered. + */ + private ConditionMatch evaluateBoolCondition(boolean outcome) { + if (log.isTraceEnabled()) { + log.trace("outcome " + outcome); + } + if (operator == OPERATOR_NOT_EQUAL) { + log.debug("not equal operator in use"); + return !outcome ? new ConditionMatch() : null; + } + return outcome ? new ConditionMatch() : null; + } + + private ConditionMatch evaluateBoolCondition(StringMatchingMatcher matcher, boolean outcome) { + ConditionMatch conditionMatch = evaluateBoolCondition(outcome); + if (conditionMatch != null) { + conditionMatch.setMatcher(matcher); + } + return conditionMatch; + } + + private ConditionMatch evaluateHeaderCondition(final HttpServletRequest hsRequest) { + String headerValue = null; + if (name != null) { + headerValue = hsRequest.getHeader(name); + } + return evaluateStringCondition(headerValue); + } + + /** + * Will evaluate a calendar condition. + * + * @param calField the calendar field from Calendar + */ + private ConditionMatch evaluateCalendarCondition(final int calField) { + return evaluateNumericCondition((Calendar.getInstance()).get(calField)); + } + + /** + * Will evaluate usign operator. + * + * @param compareWith what to compare with + * @return true or false + */ + private ConditionMatch evaluateNumericCondition(final long compareWith) { + if (log.isDebugEnabled()) { + log.debug("evaluating with operator, is " + compareWith + " " + getOperator() + " " + numericValue); + } + switch (operator) { + case OPERATOR_NOT_EQUAL: + return compareWith != numericValue ? new ConditionMatch() : null; + case OPERATOR_GREATER_THAN: + return compareWith > numericValue ? new ConditionMatch() : null; + case OPERATOR_LESS_THAN: + return compareWith < numericValue ? new ConditionMatch() : null; + case OPERATOR_GREATER_THAN_OR_EQUAL: + return compareWith >= numericValue ? new ConditionMatch() : null; + case OPERATOR_LESS_THAN_OR_EQUAL: + return compareWith <= numericValue ? new ConditionMatch() : null; + default: + return compareWith == numericValue ? new ConditionMatch() : null; + } + } + + + /** + * Returns false on failure. Use getError to get the description of the error. + * + * @return weather or not the condition was successful in initialisation. + */ + public boolean initialise() { + initialised = true; + if (error != null) { + return false; + } + // make sure we default to header if not set + if (type == 0) { + type = TYPE_HEADER; + } + switch (type) { + // note, only numeric specified others handled by default: + case TYPE_SERVER_PORT: + initNumericValue(); + break; + case TYPE_TIME: + initNumericValue(); + break; + case TYPE_TIME_YEAR: + initNumericValue(); + break; + case TYPE_TIME_MONTH: + initNumericValue(); + break; + case TYPE_TIME_DAY_OF_MONTH: + initNumericValue(); + break; + case TYPE_TIME_DAY_OF_WEEK: + initNumericValue(); + break; + case TYPE_TIME_AMPM: + initNumericValue(); + break; + case TYPE_TIME_HOUR_OF_DAY: + initNumericValue(); + break; + case TYPE_TIME_MINUTE: + initNumericValue(); + break; + case TYPE_TIME_SECOND: + initNumericValue(); + break; + case TYPE_TIME_MILLISECOND: + initNumericValue(); + break; + case TYPE_CONTENT_LENGTH: + initNumericValue(); + break; + case TYPE_LOCAL_PORT: + initNumericValue(); + break; + case TYPE_USER_IN_ROLE: + // we only care to make sure the user has entered a name (if no name use value) + // note regexs cannot be entered against this due to limitations in servlet spec + if (StringUtils.isBlank(name)) { + name = strValue; + } + break; + case TYPE_SESSION_ATTRIBUTE: + if (StringUtils.isBlank(name)) { + setError("you must set a name for session attributes"); + } + initStringValue(); + break; + case TYPE_ATTRIBUTE: + if (StringUtils.isBlank(name)) { + setError("you must set a name for attributes"); + } + initStringValue(); + break; + case TYPE_HEADER: + if (StringUtils.isBlank(name)) { + setError("you must set a name for a header"); + } + initStringValue(); + break; + default: + // other generic types + initStringValue(); + } + if (log.isDebugEnabled()) { + log.debug("loaded condition " + getType() + " " + name + " " + strValue); + } + valid = error == null; + return valid; + } + + private void initStringValue() { + if (StringUtils.isBlank(strValue)) { + log.debug("value is blank initing pattern to null"); + pattern = null; + return; + } + if (OPERATOR_INSTANCEOF == operator) { + // want to be able to do instance of that means value is not a regexp + log.debug("initialising instanceof condition"); + strValue = StringUtils.trim(strValue); + try { + instanceOfClass = Class.forName(strValue); + } catch (ClassNotFoundException e) { + setError("could not find " + strValue + " got a " + e.toString()); + } catch (NoClassDefFoundError e) { + setError("could not find " + strValue + " got a " + e.toString()); + } + + } else { + try { + if (rule != null && rule.isMatchTypeWildcard()) { + log.debug("rule match type is wildcard"); + pattern = new WildcardPattern(strValue); + + } else { + // default is regex + pattern = new RegexPattern(strValue, caseSensitive); + } + + } catch (StringMatchingPatternSyntaxException e) { + setError("Problem compiling regular expression " + strValue + " (" + e.getMessage() + ")"); + } + } + } + + /** + * Will init a numeric value type ie port. + */ + private void initNumericValue() { + if (numericValue == 0) { + numericValue = NumberUtils.stringToLong(StringUtils.trim(strValue)); + if (numericValue == 0 && !"0".equals(strValue)) { + setError("Value " + strValue + " is not a valid number (tried to cast to java type long)"); + } + } + } + + protected void setError(String s) { + super.setError(s); + log.error("Condition " + id + " had error: " + s); + } + + + /** + * Will get the operator type. + * + * @return notequal, greater etc. + */ + public String getOperator() { + switch (operator) { + case OPERATOR_NOT_EQUAL: + return "notequal"; + case OPERATOR_GREATER_THAN: + return "greater"; + case OPERATOR_LESS_THAN: + return "less"; + case OPERATOR_GREATER_THAN_OR_EQUAL: + return "greaterorequal"; + case OPERATOR_LESS_THAN_OR_EQUAL: + return "lessorequal"; + case OPERATOR_INSTANCEOF: + return "instanceof"; + case OPERATOR_EQUAL: + return "equal"; + case OPERATOR_IS_DIR: + return "isdir"; + case OPERATOR_IS_FILE: + return "isfile"; + case OPERATOR_IS_FILE_WITH_SIZE: + return "isfilewithsize"; + case OPERATOR_NOT_DIR: + return "notdir"; + case OPERATOR_NOT_FILE: + return "notfile"; + case OPERATOR_NOT_FILE_WITH_SIZE: + return "notfilewithsize"; + default: + return ""; + } + } + + /** + * Will ste the operator. + * + * @param operator type + */ + public void setOperator(final String operator) { + if ("notequal".equals(operator)) { + this.operator = OPERATOR_NOT_EQUAL; + } else if ("greater".equals(operator)) { + this.operator = OPERATOR_GREATER_THAN; + } else if ("less".equals(operator)) { + this.operator = OPERATOR_LESS_THAN; + } else if ("greaterorequal".equals(operator)) { + this.operator = OPERATOR_GREATER_THAN_OR_EQUAL; + } else if ("lessorequal".equals(operator)) { + this.operator = OPERATOR_LESS_THAN_OR_EQUAL; + } else if ("instanceof".equals(operator)) { + this.operator = OPERATOR_INSTANCEOF; + } else if ("equal".equals(operator) || StringUtils.isBlank(operator)) { + this.operator = OPERATOR_EQUAL; + } else if ("isdir".equals(operator)) { + this.operator = OPERATOR_IS_DIR; + } else if ("isfile".equals(operator)) { + this.operator = OPERATOR_IS_FILE; + } else if ("isfilewithsize".equals(operator)) { + this.operator = OPERATOR_IS_FILE_WITH_SIZE; + } else if ("notdir".equals(operator)) { + this.operator = OPERATOR_NOT_DIR; + } else if ("notfile".equals(operator)) { + this.operator = OPERATOR_NOT_FILE; + } else if ("notfilewithsize".equals(operator)) { + this.operator = OPERATOR_NOT_FILE_WITH_SIZE; + } else { + setError("Operator " + operator + " is not valid"); + } + } + + /** + * Will get the name. + * + * @return String + */ + public String getName() { + return name; + } + + /** + * Will set the name. + * + * @param name the name + */ + public void setName(final String name) { + this.name = name; + } + + /** + * Will return "add" or "or". + * + * @return "add" or "or" + */ + public String getNext() { + if (processNextOr) return "or"; + return "and"; + } + + /** + * Will set next. + * + * @param next "or" or "and" + */ + public void setNext(final String next) { + if ("or".equals(next)) { + this.processNextOr = true; + } else if ("and".equals(next) || StringUtils.isBlank(next)) { + this.processNextOr = false; + } else { + setError("Next " + next + " is not valid (can be 'and', 'or')"); + } + } + + /** + * Will get the value. + * + * @return String + */ + public String getValue() { + return strValue; + } + + /** + * Will set the value. + * + * @param value the value + */ + public void setValue(final String value) { + this.strValue = value; + } + + /** + * True if process next is or. + * + * @return boolean + */ + public boolean isProcessNextOr() { + return processNextOr; + } + + public void setId(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public boolean isCaseSensitive() { + return caseSensitive; + } + + public void setCaseSensitive(boolean caseSensitive) { + this.caseSensitive = caseSensitive; + } + + public String getDisplayName() { + return "Condtition " + id; + } + + public void setRule(RuleBase rule) { + this.rule = rule; + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/ConditionMatch.java b/src/main/java/org/tuckey/web/filters/urlrewrite/ConditionMatch.java index d5719cce..e2b79c82 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/ConditionMatch.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/ConditionMatch.java @@ -1,56 +1,56 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; - - -/** - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class ConditionMatch { - - private StringMatchingMatcher matcher; - - public StringMatchingMatcher getMatcher() { - return matcher; - } - - public void setMatcher(StringMatchingMatcher matcher) { - this.matcher = matcher; - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; + + +/** + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class ConditionMatch { + + private StringMatchingMatcher matcher; + + public StringMatchingMatcher getMatcher() { + return matcher; + } + + public void setMatcher(StringMatchingMatcher matcher) { + this.matcher = matcher; + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Conf.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Conf.java index 0b8a4ba2..7b8068b3 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Conf.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Conf.java @@ -1,639 +1,639 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.gzip.GzipFilter; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.ModRewriteConfLoader; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; -import org.xml.sax.SAXParseException; - -import jakarta.servlet.ServletContext; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLDecoder; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * Configuration object for urlrewrite filter. - * - * @author Paul Tuckey - * @version $Revision: 43 $ $Date: 2006-10-31 17:29:59 +1300 (Tue, 31 Oct 2006) $ - */ -public class Conf { - - private static Log log = Log.getLog(Conf.class); - - private final List errors = new ArrayList(); - private final List rules = new ArrayList(50); - private final List catchElems = new ArrayList(10); - private List outboundRules = new ArrayList(50); - private boolean ok = false; - private Date loadedDate = null; - private int ruleIdCounter = 0; - private int outboundRuleIdCounter = 0; - private String fileName; - private String confSystemId; - - protected boolean useQueryString; - protected boolean useContext; - - private static final String NONE_DECODE_USING = "null"; - private static final String HEADER_DECODE_USING = "header"; - private static final String DEFAULT_DECODE_USING = "header,utf-8"; - - protected String decodeUsing = DEFAULT_DECODE_USING; - private boolean decodeUsingEncodingHeader; - - protected String defaultMatchType = null; - - private ServletContext context; - private boolean docProcessed = false; - private boolean engineEnabled = true; - - /** - * Empty const for testing etc. - */ - public Conf() { - loadedDate = new Date(); - } - - /** - * Constructor for use only when loading XML style configuration. - * - * @param fileName to display on status screen - */ - public Conf(ServletContext context, final InputStream inputStream, String fileName, String systemId) { - this(context, inputStream, fileName, systemId, false); - } - - /** - * Normal constructor. - * - * @param fileName to display on status screen - * @param modRewriteStyleConf true if loading mod_rewrite style conf - */ - public Conf(ServletContext context, final InputStream inputStream, String fileName, String systemId, - boolean modRewriteStyleConf) { - // make sure context is setup before calling initialise() - this.context = context; - this.fileName = fileName; - this.confSystemId = systemId; - if (modRewriteStyleConf) { - loadModRewriteStyle(inputStream); - } else { - loadDom(inputStream); - } - if (docProcessed) initialise(); - loadedDate = new Date(); - } - - protected void loadModRewriteStyle(InputStream inputStream) { - ModRewriteConfLoader loader = new ModRewriteConfLoader(); - try { - loader.process(inputStream, this); - docProcessed = true; // fixed - } catch (IOException e) { - addError("Exception loading conf " + " " + e.getMessage(), e); - } - } - - /** - * Constructor when run elements don't need to be initialised correctly, for docuementation etc. - */ - public Conf(URL confUrl) { - // make sure context is setup before calling initialise() - this.context = null; - this.fileName = confUrl.getFile(); - this.confSystemId = confUrl.toString(); - try { - loadDom(confUrl.openStream()); - } catch (IOException e) { - addError("Exception loading conf " + " " + e.getMessage(), e); - } - if (docProcessed) initialise(); - loadedDate = new Date(); - } - - /** - * Constructor when run elements don't need to be initialised correctly, for docuementation etc. - */ - public Conf(InputStream inputStream, String conffile) { - this(null, inputStream, conffile, conffile); - } - - /** - * Load the dom document from the inputstream - *

- * Note, protected so that is can be extended. - * - * @param inputStream stream of the conf file to load - */ - protected synchronized void loadDom(final InputStream inputStream) { - if (inputStream == null) { - log.error("inputstream is null"); - return; - } - DocumentBuilder parser; - - /** - * the thing that resolves dtd's and other xml entities. - */ - ConfHandler handler = new ConfHandler(confSystemId); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - log.debug("XML builder factory is: " + factory.getClass().getName()); - factory.setValidating(true); - factory.setNamespaceAware(true); - factory.setIgnoringComments(true); - factory.setIgnoringElementContentWhitespace(true); - try { - parser = factory.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - log.error("Unable to setup XML parser for reading conf", e); - return; - } - log.debug("XML Parser: " + parser.getClass().getName()); - - parser.setErrorHandler(handler); - parser.setEntityResolver(handler); - - try { - log.debug("about to parse conf"); - Document doc = parser.parse(inputStream, confSystemId); - processConfDoc(doc); - - } catch (SAXParseException e) { - addError("Parse error on line " + e.getLineNumber() + " " + e.getMessage(), e); - - } catch (Exception e) { - addError("Exception loading conf " + " " + e.getMessage(), e); - } - } - - /** - * Process dom document and populate Conf object. - *

- * Note, protected so that is can be extended. - */ - protected void processConfDoc(Document doc) { - Element rootElement = doc.getDocumentElement(); - - if ("true".equalsIgnoreCase(getAttrValue(rootElement, "use-query-string"))) setUseQueryString(true); - if ("true".equalsIgnoreCase(getAttrValue(rootElement, "use-context"))) { - log.debug("use-context set to true"); - setUseContext(true); - } - setDecodeUsing(getAttrValue(rootElement, "decode-using")); - setDefaultMatchType(getAttrValue(rootElement, "default-match-type")); - - NodeList rootElementList = rootElement.getChildNodes(); - for (int i = 0; i < rootElementList.getLength(); i++) { - Node node = rootElementList.item(i); - - if (node.getNodeType() == Node.ELEMENT_NODE && - ((Element) node).getTagName().equals("rule")) { - Element ruleElement = (Element) node; - // we have a rule node - NormalRule rule = new NormalRule(); - - processRuleBasics(ruleElement, rule); - procesConditions(ruleElement, rule); - processRuns(ruleElement, rule); - - Node toNode = ruleElement.getElementsByTagName("to").item(0); - rule.setTo(getNodeValue(toNode)); - rule.setToType(getAttrValue(toNode, "type")); - rule.setToContextStr(getAttrValue(toNode, "context")); - rule.setToLast(getAttrValue(toNode, "last")); - rule.setQueryStringAppend(getAttrValue(toNode, "qsappend")); - rule.setDropCookies(getAttrValue(toNode, "drop-cookies")); - if ("true".equalsIgnoreCase(getAttrValue(toNode, "encode"))) rule.setEncodeToUrl(true); - - processSetAttributes(ruleElement, rule); - - addRule(rule); - - } else if (node.getNodeType() == Node.ELEMENT_NODE && - ((Element) node).getTagName().equals("class-rule")) { - Element ruleElement = (Element) node; - - ClassRule classRule = new ClassRule(); - if ("false".equalsIgnoreCase(getAttrValue(ruleElement, "enabled"))) classRule.setEnabled(false); - if ("false".equalsIgnoreCase(getAttrValue(ruleElement, "last"))) classRule.setLast(false); - classRule.setClassStr(getAttrValue(ruleElement, "class")); - classRule.setMethodStr(getAttrValue(ruleElement, "method")); - - addRule(classRule); - - } else if (node.getNodeType() == Node.ELEMENT_NODE && - ((Element) node).getTagName().equals("outbound-rule")) { - - Element ruleElement = (Element) node; - // we have a rule node - OutboundRule rule = new OutboundRule(); - - processRuleBasics(ruleElement, rule); - if ("true".equalsIgnoreCase(getAttrValue(ruleElement, "encodefirst"))) rule.setEncodeFirst(true); - - procesConditions(ruleElement, rule); - processRuns(ruleElement, rule); - - Node toNode = ruleElement.getElementsByTagName("to").item(0); - rule.setTo(getNodeValue(toNode)); - rule.setToLast(getAttrValue(toNode, "last")); - if ("false".equalsIgnoreCase(getAttrValue(toNode, "encode"))) rule.setEncodeToUrl(false); - - processSetAttributes(ruleElement, rule); - - addOutboundRule(rule); - - } else if (node.getNodeType() == Node.ELEMENT_NODE && - ((Element) node).getTagName().equals("catch")) { - - Element catchXMLElement = (Element) node; - // we have a rule node - CatchElem catchElem = new CatchElem(); - - catchElem.setClassStr(getAttrValue(catchXMLElement, "class")); - - processRuns(catchXMLElement, catchElem); - - catchElems.add(catchElem); - - } - } - docProcessed = true; - } - - private void processRuleBasics(Element ruleElement, RuleBase rule) { - if ("false".equalsIgnoreCase(getAttrValue(ruleElement, "enabled"))) rule.setEnabled(false); - - String ruleMatchType = getAttrValue(ruleElement, "match-type"); - if (StringUtils.isBlank(ruleMatchType)) ruleMatchType = defaultMatchType; - rule.setMatchType(ruleMatchType); - - Node nameNode = ruleElement.getElementsByTagName("name").item(0); - rule.setName(getNodeValue(nameNode)); - - Node noteNode = ruleElement.getElementsByTagName("note").item(0); - rule.setNote(getNodeValue(noteNode)); - - Node fromNode = ruleElement.getElementsByTagName("from").item(0); - rule.setFrom(getNodeValue(fromNode)); - if ("true".equalsIgnoreCase(getAttrValue(fromNode, "casesensitive"))) rule.setFromCaseSensitive(true); - } - - private static void processSetAttributes(Element ruleElement, RuleBase rule) { - NodeList setNodes = ruleElement.getElementsByTagName("set"); - for (int j = 0; j < setNodes.getLength(); j++) { - Node setNode = setNodes.item(j); - if (setNode == null) continue; - SetAttribute setAttribute = new SetAttribute(); - setAttribute.setValue(getNodeValue(setNode)); - setAttribute.setType(getAttrValue(setNode, "type")); - setAttribute.setName(getAttrValue(setNode, "name")); - rule.addSetAttribute(setAttribute); - } - } - - private static void processRuns(Element ruleElement, Runnable runnable) { - NodeList runNodes = ruleElement.getElementsByTagName("run"); - for (int j = 0; j < runNodes.getLength(); j++) { - Node runNode = runNodes.item(j); - if (runNode == null) continue; - Run run = new Run(); - processInitParams(runNode, run); - run.setClassStr(getAttrValue(runNode, "class")); - run.setMethodStr(getAttrValue(runNode, "method")); - run.setJsonHandler("true".equalsIgnoreCase(getAttrValue(runNode, "jsonhandler"))); - run.setNewEachTime("true".equalsIgnoreCase(getAttrValue(runNode, "neweachtime"))); - runnable.addRun(run); - } - - // gzip element is just a shortcut to run: org.tuckey.web.filters.urlrewrite.gzip.GzipFilter - NodeList gzipNodes = ruleElement.getElementsByTagName("gzip"); - for (int j = 0; j < gzipNodes.getLength(); j++) { - Node runNode = gzipNodes.item(j); - if (runNode == null) continue; - Run run = new Run(); - run.setClassStr(GzipFilter.class.getName()); - run.setMethodStr("doFilter(ServletRequest, ServletResponse, FilterChain)"); - processInitParams(runNode, run); - runnable.addRun(run); - } - } - - private static void processInitParams(Node runNode, Run run) { - if (runNode.getNodeType() == Node.ELEMENT_NODE) { - Element runElement = (Element) runNode; - NodeList initParamsNodeList = runElement.getElementsByTagName("init-param"); - for (int k = 0; k < initParamsNodeList.getLength(); k++) { - Node initParamNode = initParamsNodeList.item(k); - if (initParamNode == null) continue; - if (initParamNode.getNodeType() != Node.ELEMENT_NODE) continue; - Element initParamElement = (Element) initParamNode; - Node paramNameNode = initParamElement.getElementsByTagName("param-name").item(0); - Node paramValueNode = initParamElement.getElementsByTagName("param-value").item(0); - run.addInitParam(getNodeValue(paramNameNode), getNodeValue(paramValueNode)); - } - } - } - - private static void procesConditions(Element ruleElement, RuleBase rule) { - NodeList conditionNodes = ruleElement.getElementsByTagName("condition"); - for (int j = 0; j < conditionNodes.getLength(); j++) { - Node conditionNode = conditionNodes.item(j); - if (conditionNode == null) continue; - Condition condition = new Condition(); - condition.setValue(getNodeValue(conditionNode)); - condition.setType(getAttrValue(conditionNode, "type")); - condition.setName(getAttrValue(conditionNode, "name")); - condition.setNext(getAttrValue(conditionNode, "next")); - condition.setCaseSensitive("true".equalsIgnoreCase(getAttrValue(conditionNode, "casesensitive"))); - condition.setOperator(getAttrValue(conditionNode, "operator")); - rule.addCondition(condition); - } - } - - private static String getNodeValue(Node node) { - if (node == null) return null; - NodeList nodeList = node.getChildNodes(); - if (nodeList == null) return null; - Node child = nodeList.item(0); - if (child == null) return null; - if ((child.getNodeType() == Node.TEXT_NODE)) { - String value = ((Text) child).getData(); - return value.trim(); - } - return null; - } - - private static String getAttrValue(Node n, String attrName) { - if (n == null) return null; - NamedNodeMap attrs = n.getAttributes(); - if (attrs == null) return null; - Node attr = attrs.getNamedItem(attrName); - if (attr == null) return null; - String val = attr.getNodeValue(); - if (val == null) return null; - return val.trim(); - } - - /** - * Initialise the conf file. This will run initialise on each rule and condition in the conf file. - */ - public void initialise() { - if (log.isDebugEnabled()) { - log.debug("now initialising conf"); - } - - initDecodeUsing(decodeUsing); - - boolean rulesOk = true; - for (int i = 0; i < rules.size(); i++) { - final Rule rule = (Rule) rules.get(i); - if (!rule.initialise(context)) { - // if we failed to initialise anything set the status to bad - rulesOk = false; - } - } - for (int i = 0; i < outboundRules.size(); i++) { - final OutboundRule outboundRule = (OutboundRule) outboundRules.get(i); - if (!outboundRule.initialise(context)) { - // if we failed to initialise anything set the status to bad - rulesOk = false; - } - } - for (int i = 0; i < catchElems.size(); i++) { - final CatchElem catchElem = (CatchElem) catchElems.get(i); - if (!catchElem.initialise(context)) { - // if we failed to initialise anything set the status to bad - rulesOk = false; - } - } - if (rulesOk) { - ok = true; - } - if (log.isDebugEnabled()) { - log.debug("conf status " + ok); - } - } - - private void initDecodeUsing(String decodeUsingSetting) { - decodeUsingSetting = StringUtils.trimToNull(decodeUsingSetting); - if (decodeUsingSetting == null) decodeUsingSetting = DEFAULT_DECODE_USING; - - if ( decodeUsingSetting.equalsIgnoreCase(HEADER_DECODE_USING)) { // is 'header' - decodeUsingEncodingHeader = true; - decodeUsingSetting = null; - - } else if ( decodeUsingSetting.startsWith(HEADER_DECODE_USING + ",")) { // is 'header,xxx' - decodeUsingEncodingHeader = true; - decodeUsingSetting = decodeUsingSetting.substring((HEADER_DECODE_USING + ",").length()); - - } - if (NONE_DECODE_USING.equalsIgnoreCase(decodeUsingSetting)) { - decodeUsingSetting = null; - } - if ( decodeUsingSetting != null ) { - try { - URLDecoder.decode("testUrl", decodeUsingSetting); - this.decodeUsing = decodeUsingSetting; - } catch (UnsupportedEncodingException e) { - addError("unsupported 'decodeusing' " + decodeUsingSetting + " see Java SDK docs for supported encodings"); - } - } else { - this.decodeUsing = null; - } - } - - /** - * Destory the conf gracefully. - */ - public void destroy() { - for (int i = 0; i < rules.size(); i++) { - final Rule rule = (Rule) rules.get(i); - rule.destroy(); - } - } - - /** - * Will add the rule to the rules list. - * - * @param rule The Rule to add - */ - public void addRule(final Rule rule) { - rule.setId(ruleIdCounter++); - rules.add(rule); - } - - /** - * Will add the rule to the rules list. - * - * @param outboundRule The outbound rule to add - */ - public void addOutboundRule(final OutboundRule outboundRule) { - outboundRule.setId(outboundRuleIdCounter++); - outboundRules.add(outboundRule); - } - - /** - * Will get the List of errors. - * - * @return the List of errors - */ - public List getErrors() { - return errors; - } - - /** - * Will get the List of rules. - * - * @return the List of rules - */ - public List getRules() { - return rules; - } - - /** - * Will get the List of outbound rules. - * - * @return the List of outbound rules - */ - public List getOutboundRules() { - return outboundRules; - } - - /** - * true if the conf has been loaded ok. - * - * @return boolean - */ - public boolean isOk() { - return ok; - } - - private void addError(final String errorMsg, final Exception e) { - errors.add(errorMsg); - log.error(errorMsg, e); - } - - private void addError(final String errorMsg) { - errors.add(errorMsg); - } - - public Date getLoadedDate() { - return (Date) loadedDate.clone(); - } - - public String getFileName() { - return fileName; - } - - - public boolean isUseQueryString() { - return useQueryString; - } - - public void setUseQueryString(boolean useQueryString) { - this.useQueryString = useQueryString; - } - - public boolean isUseContext() { - return useContext; - } - - public void setUseContext(boolean useContext) { - this.useContext = useContext; - } - - public String getDecodeUsing() { - return decodeUsing; - } - - public void setDecodeUsing(String decodeUsing) { - this.decodeUsing = decodeUsing; - } - - public void setDefaultMatchType(String defaultMatchType) { - if (RuleBase.MATCH_TYPE_WILDCARD.equalsIgnoreCase(defaultMatchType)) { - this.defaultMatchType = RuleBase.MATCH_TYPE_WILDCARD; - } else { - this.defaultMatchType = RuleBase.DEFAULT_MATCH_TYPE; - } - } - - public String getDefaultMatchType() { - return defaultMatchType; - } - - public List getCatchElems() { - return catchElems; - } - - public boolean isDecodeUsingCustomCharsetRequired() { - return decodeUsing != null; - } - - public boolean isEngineEnabled() { - return engineEnabled; - } - - public void setEngineEnabled(boolean engineEnabled) { - this.engineEnabled = engineEnabled; - } - - public boolean isLoadedFromFile() { - return fileName != null; - } - - public boolean isDecodeUsingEncodingHeader() { - return decodeUsingEncodingHeader; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.gzip.GzipFilter; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.ModRewriteConfLoader; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.xml.sax.SAXParseException; + +import jakarta.servlet.ServletContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Configuration object for urlrewrite filter. + * + * @author Paul Tuckey + * @version $Revision: 43 $ $Date: 2006-10-31 17:29:59 +1300 (Tue, 31 Oct 2006) $ + */ +public class Conf { + + private static Log log = Log.getLog(Conf.class); + + private final List errors = new ArrayList(); + private final List rules = new ArrayList(50); + private final List catchElems = new ArrayList(10); + private List outboundRules = new ArrayList(50); + private boolean ok = false; + private Date loadedDate = null; + private int ruleIdCounter = 0; + private int outboundRuleIdCounter = 0; + private String fileName; + private String confSystemId; + + protected boolean useQueryString; + protected boolean useContext; + + private static final String NONE_DECODE_USING = "null"; + private static final String HEADER_DECODE_USING = "header"; + private static final String DEFAULT_DECODE_USING = "header,utf-8"; + + protected String decodeUsing = DEFAULT_DECODE_USING; + private boolean decodeUsingEncodingHeader; + + protected String defaultMatchType = null; + + private ServletContext context; + private boolean docProcessed = false; + private boolean engineEnabled = true; + + /** + * Empty const for testing etc. + */ + public Conf() { + loadedDate = new Date(); + } + + /** + * Constructor for use only when loading XML style configuration. + * + * @param fileName to display on status screen + */ + public Conf(ServletContext context, final InputStream inputStream, String fileName, String systemId) { + this(context, inputStream, fileName, systemId, false); + } + + /** + * Normal constructor. + * + * @param fileName to display on status screen + * @param modRewriteStyleConf true if loading mod_rewrite style conf + */ + public Conf(ServletContext context, final InputStream inputStream, String fileName, String systemId, + boolean modRewriteStyleConf) { + // make sure context is setup before calling initialise() + this.context = context; + this.fileName = fileName; + this.confSystemId = systemId; + if (modRewriteStyleConf) { + loadModRewriteStyle(inputStream); + } else { + loadDom(inputStream); + } + if (docProcessed) initialise(); + loadedDate = new Date(); + } + + protected void loadModRewriteStyle(InputStream inputStream) { + ModRewriteConfLoader loader = new ModRewriteConfLoader(); + try { + loader.process(inputStream, this); + docProcessed = true; // fixed + } catch (IOException e) { + addError("Exception loading conf " + " " + e.getMessage(), e); + } + } + + /** + * Constructor when run elements don't need to be initialised correctly, for docuementation etc. + */ + public Conf(URL confUrl) { + // make sure context is setup before calling initialise() + this.context = null; + this.fileName = confUrl.getFile(); + this.confSystemId = confUrl.toString(); + try { + loadDom(confUrl.openStream()); + } catch (IOException e) { + addError("Exception loading conf " + " " + e.getMessage(), e); + } + if (docProcessed) initialise(); + loadedDate = new Date(); + } + + /** + * Constructor when run elements don't need to be initialised correctly, for docuementation etc. + */ + public Conf(InputStream inputStream, String conffile) { + this(null, inputStream, conffile, conffile); + } + + /** + * Load the dom document from the inputstream + *

+ * Note, protected so that is can be extended. + * + * @param inputStream stream of the conf file to load + */ + protected synchronized void loadDom(final InputStream inputStream) { + if (inputStream == null) { + log.error("inputstream is null"); + return; + } + DocumentBuilder parser; + + /** + * the thing that resolves dtd's and other xml entities. + */ + ConfHandler handler = new ConfHandler(confSystemId); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + log.debug("XML builder factory is: " + factory.getClass().getName()); + factory.setValidating(true); + factory.setNamespaceAware(true); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + try { + parser = factory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + log.error("Unable to setup XML parser for reading conf", e); + return; + } + log.debug("XML Parser: " + parser.getClass().getName()); + + parser.setErrorHandler(handler); + parser.setEntityResolver(handler); + + try { + log.debug("about to parse conf"); + Document doc = parser.parse(inputStream, confSystemId); + processConfDoc(doc); + + } catch (SAXParseException e) { + addError("Parse error on line " + e.getLineNumber() + " " + e.getMessage(), e); + + } catch (Exception e) { + addError("Exception loading conf " + " " + e.getMessage(), e); + } + } + + /** + * Process dom document and populate Conf object. + *

+ * Note, protected so that is can be extended. + */ + protected void processConfDoc(Document doc) { + Element rootElement = doc.getDocumentElement(); + + if ("true".equalsIgnoreCase(getAttrValue(rootElement, "use-query-string"))) setUseQueryString(true); + if ("true".equalsIgnoreCase(getAttrValue(rootElement, "use-context"))) { + log.debug("use-context set to true"); + setUseContext(true); + } + setDecodeUsing(getAttrValue(rootElement, "decode-using")); + setDefaultMatchType(getAttrValue(rootElement, "default-match-type")); + + NodeList rootElementList = rootElement.getChildNodes(); + for (int i = 0; i < rootElementList.getLength(); i++) { + Node node = rootElementList.item(i); + + if (node.getNodeType() == Node.ELEMENT_NODE && + ((Element) node).getTagName().equals("rule")) { + Element ruleElement = (Element) node; + // we have a rule node + NormalRule rule = new NormalRule(); + + processRuleBasics(ruleElement, rule); + procesConditions(ruleElement, rule); + processRuns(ruleElement, rule); + + Node toNode = ruleElement.getElementsByTagName("to").item(0); + rule.setTo(getNodeValue(toNode)); + rule.setToType(getAttrValue(toNode, "type")); + rule.setToContextStr(getAttrValue(toNode, "context")); + rule.setToLast(getAttrValue(toNode, "last")); + rule.setQueryStringAppend(getAttrValue(toNode, "qsappend")); + rule.setDropCookies(getAttrValue(toNode, "drop-cookies")); + if ("true".equalsIgnoreCase(getAttrValue(toNode, "encode"))) rule.setEncodeToUrl(true); + + processSetAttributes(ruleElement, rule); + + addRule(rule); + + } else if (node.getNodeType() == Node.ELEMENT_NODE && + ((Element) node).getTagName().equals("class-rule")) { + Element ruleElement = (Element) node; + + ClassRule classRule = new ClassRule(); + if ("false".equalsIgnoreCase(getAttrValue(ruleElement, "enabled"))) classRule.setEnabled(false); + if ("false".equalsIgnoreCase(getAttrValue(ruleElement, "last"))) classRule.setLast(false); + classRule.setClassStr(getAttrValue(ruleElement, "class")); + classRule.setMethodStr(getAttrValue(ruleElement, "method")); + + addRule(classRule); + + } else if (node.getNodeType() == Node.ELEMENT_NODE && + ((Element) node).getTagName().equals("outbound-rule")) { + + Element ruleElement = (Element) node; + // we have a rule node + OutboundRule rule = new OutboundRule(); + + processRuleBasics(ruleElement, rule); + if ("true".equalsIgnoreCase(getAttrValue(ruleElement, "encodefirst"))) rule.setEncodeFirst(true); + + procesConditions(ruleElement, rule); + processRuns(ruleElement, rule); + + Node toNode = ruleElement.getElementsByTagName("to").item(0); + rule.setTo(getNodeValue(toNode)); + rule.setToLast(getAttrValue(toNode, "last")); + if ("false".equalsIgnoreCase(getAttrValue(toNode, "encode"))) rule.setEncodeToUrl(false); + + processSetAttributes(ruleElement, rule); + + addOutboundRule(rule); + + } else if (node.getNodeType() == Node.ELEMENT_NODE && + ((Element) node).getTagName().equals("catch")) { + + Element catchXMLElement = (Element) node; + // we have a rule node + CatchElem catchElem = new CatchElem(); + + catchElem.setClassStr(getAttrValue(catchXMLElement, "class")); + + processRuns(catchXMLElement, catchElem); + + catchElems.add(catchElem); + + } + } + docProcessed = true; + } + + private void processRuleBasics(Element ruleElement, RuleBase rule) { + if ("false".equalsIgnoreCase(getAttrValue(ruleElement, "enabled"))) rule.setEnabled(false); + + String ruleMatchType = getAttrValue(ruleElement, "match-type"); + if (StringUtils.isBlank(ruleMatchType)) ruleMatchType = defaultMatchType; + rule.setMatchType(ruleMatchType); + + Node nameNode = ruleElement.getElementsByTagName("name").item(0); + rule.setName(getNodeValue(nameNode)); + + Node noteNode = ruleElement.getElementsByTagName("note").item(0); + rule.setNote(getNodeValue(noteNode)); + + Node fromNode = ruleElement.getElementsByTagName("from").item(0); + rule.setFrom(getNodeValue(fromNode)); + if ("true".equalsIgnoreCase(getAttrValue(fromNode, "casesensitive"))) rule.setFromCaseSensitive(true); + } + + private static void processSetAttributes(Element ruleElement, RuleBase rule) { + NodeList setNodes = ruleElement.getElementsByTagName("set"); + for (int j = 0; j < setNodes.getLength(); j++) { + Node setNode = setNodes.item(j); + if (setNode == null) continue; + SetAttribute setAttribute = new SetAttribute(); + setAttribute.setValue(getNodeValue(setNode)); + setAttribute.setType(getAttrValue(setNode, "type")); + setAttribute.setName(getAttrValue(setNode, "name")); + rule.addSetAttribute(setAttribute); + } + } + + private static void processRuns(Element ruleElement, Runnable runnable) { + NodeList runNodes = ruleElement.getElementsByTagName("run"); + for (int j = 0; j < runNodes.getLength(); j++) { + Node runNode = runNodes.item(j); + if (runNode == null) continue; + Run run = new Run(); + processInitParams(runNode, run); + run.setClassStr(getAttrValue(runNode, "class")); + run.setMethodStr(getAttrValue(runNode, "method")); + run.setJsonHandler("true".equalsIgnoreCase(getAttrValue(runNode, "jsonhandler"))); + run.setNewEachTime("true".equalsIgnoreCase(getAttrValue(runNode, "neweachtime"))); + runnable.addRun(run); + } + + // gzip element is just a shortcut to run: org.tuckey.web.filters.urlrewrite.gzip.GzipFilter + NodeList gzipNodes = ruleElement.getElementsByTagName("gzip"); + for (int j = 0; j < gzipNodes.getLength(); j++) { + Node runNode = gzipNodes.item(j); + if (runNode == null) continue; + Run run = new Run(); + run.setClassStr(GzipFilter.class.getName()); + run.setMethodStr("doFilter(ServletRequest, ServletResponse, FilterChain)"); + processInitParams(runNode, run); + runnable.addRun(run); + } + } + + private static void processInitParams(Node runNode, Run run) { + if (runNode.getNodeType() == Node.ELEMENT_NODE) { + Element runElement = (Element) runNode; + NodeList initParamsNodeList = runElement.getElementsByTagName("init-param"); + for (int k = 0; k < initParamsNodeList.getLength(); k++) { + Node initParamNode = initParamsNodeList.item(k); + if (initParamNode == null) continue; + if (initParamNode.getNodeType() != Node.ELEMENT_NODE) continue; + Element initParamElement = (Element) initParamNode; + Node paramNameNode = initParamElement.getElementsByTagName("param-name").item(0); + Node paramValueNode = initParamElement.getElementsByTagName("param-value").item(0); + run.addInitParam(getNodeValue(paramNameNode), getNodeValue(paramValueNode)); + } + } + } + + private static void procesConditions(Element ruleElement, RuleBase rule) { + NodeList conditionNodes = ruleElement.getElementsByTagName("condition"); + for (int j = 0; j < conditionNodes.getLength(); j++) { + Node conditionNode = conditionNodes.item(j); + if (conditionNode == null) continue; + Condition condition = new Condition(); + condition.setValue(getNodeValue(conditionNode)); + condition.setType(getAttrValue(conditionNode, "type")); + condition.setName(getAttrValue(conditionNode, "name")); + condition.setNext(getAttrValue(conditionNode, "next")); + condition.setCaseSensitive("true".equalsIgnoreCase(getAttrValue(conditionNode, "casesensitive"))); + condition.setOperator(getAttrValue(conditionNode, "operator")); + rule.addCondition(condition); + } + } + + private static String getNodeValue(Node node) { + if (node == null) return null; + NodeList nodeList = node.getChildNodes(); + if (nodeList == null) return null; + Node child = nodeList.item(0); + if (child == null) return null; + if ((child.getNodeType() == Node.TEXT_NODE)) { + String value = ((Text) child).getData(); + return value.trim(); + } + return null; + } + + private static String getAttrValue(Node n, String attrName) { + if (n == null) return null; + NamedNodeMap attrs = n.getAttributes(); + if (attrs == null) return null; + Node attr = attrs.getNamedItem(attrName); + if (attr == null) return null; + String val = attr.getNodeValue(); + if (val == null) return null; + return val.trim(); + } + + /** + * Initialise the conf file. This will run initialise on each rule and condition in the conf file. + */ + public void initialise() { + if (log.isDebugEnabled()) { + log.debug("now initialising conf"); + } + + initDecodeUsing(decodeUsing); + + boolean rulesOk = true; + for (int i = 0; i < rules.size(); i++) { + final Rule rule = (Rule) rules.get(i); + if (!rule.initialise(context)) { + // if we failed to initialise anything set the status to bad + rulesOk = false; + } + } + for (int i = 0; i < outboundRules.size(); i++) { + final OutboundRule outboundRule = (OutboundRule) outboundRules.get(i); + if (!outboundRule.initialise(context)) { + // if we failed to initialise anything set the status to bad + rulesOk = false; + } + } + for (int i = 0; i < catchElems.size(); i++) { + final CatchElem catchElem = (CatchElem) catchElems.get(i); + if (!catchElem.initialise(context)) { + // if we failed to initialise anything set the status to bad + rulesOk = false; + } + } + if (rulesOk) { + ok = true; + } + if (log.isDebugEnabled()) { + log.debug("conf status " + ok); + } + } + + private void initDecodeUsing(String decodeUsingSetting) { + decodeUsingSetting = StringUtils.trimToNull(decodeUsingSetting); + if (decodeUsingSetting == null) decodeUsingSetting = DEFAULT_DECODE_USING; + + if ( decodeUsingSetting.equalsIgnoreCase(HEADER_DECODE_USING)) { // is 'header' + decodeUsingEncodingHeader = true; + decodeUsingSetting = null; + + } else if ( decodeUsingSetting.startsWith(HEADER_DECODE_USING + ",")) { // is 'header,xxx' + decodeUsingEncodingHeader = true; + decodeUsingSetting = decodeUsingSetting.substring((HEADER_DECODE_USING + ",").length()); + + } + if (NONE_DECODE_USING.equalsIgnoreCase(decodeUsingSetting)) { + decodeUsingSetting = null; + } + if ( decodeUsingSetting != null ) { + try { + URLDecoder.decode("testUrl", decodeUsingSetting); + this.decodeUsing = decodeUsingSetting; + } catch (UnsupportedEncodingException e) { + addError("unsupported 'decodeusing' " + decodeUsingSetting + " see Java SDK docs for supported encodings"); + } + } else { + this.decodeUsing = null; + } + } + + /** + * Destory the conf gracefully. + */ + public void destroy() { + for (int i = 0; i < rules.size(); i++) { + final Rule rule = (Rule) rules.get(i); + rule.destroy(); + } + } + + /** + * Will add the rule to the rules list. + * + * @param rule The Rule to add + */ + public void addRule(final Rule rule) { + rule.setId(ruleIdCounter++); + rules.add(rule); + } + + /** + * Will add the rule to the rules list. + * + * @param outboundRule The outbound rule to add + */ + public void addOutboundRule(final OutboundRule outboundRule) { + outboundRule.setId(outboundRuleIdCounter++); + outboundRules.add(outboundRule); + } + + /** + * Will get the List of errors. + * + * @return the List of errors + */ + public List getErrors() { + return errors; + } + + /** + * Will get the List of rules. + * + * @return the List of rules + */ + public List getRules() { + return rules; + } + + /** + * Will get the List of outbound rules. + * + * @return the List of outbound rules + */ + public List getOutboundRules() { + return outboundRules; + } + + /** + * true if the conf has been loaded ok. + * + * @return boolean + */ + public boolean isOk() { + return ok; + } + + private void addError(final String errorMsg, final Exception e) { + errors.add(errorMsg); + log.error(errorMsg, e); + } + + private void addError(final String errorMsg) { + errors.add(errorMsg); + } + + public Date getLoadedDate() { + return (Date) loadedDate.clone(); + } + + public String getFileName() { + return fileName; + } + + + public boolean isUseQueryString() { + return useQueryString; + } + + public void setUseQueryString(boolean useQueryString) { + this.useQueryString = useQueryString; + } + + public boolean isUseContext() { + return useContext; + } + + public void setUseContext(boolean useContext) { + this.useContext = useContext; + } + + public String getDecodeUsing() { + return decodeUsing; + } + + public void setDecodeUsing(String decodeUsing) { + this.decodeUsing = decodeUsing; + } + + public void setDefaultMatchType(String defaultMatchType) { + if (RuleBase.MATCH_TYPE_WILDCARD.equalsIgnoreCase(defaultMatchType)) { + this.defaultMatchType = RuleBase.MATCH_TYPE_WILDCARD; + } else { + this.defaultMatchType = RuleBase.DEFAULT_MATCH_TYPE; + } + } + + public String getDefaultMatchType() { + return defaultMatchType; + } + + public List getCatchElems() { + return catchElems; + } + + public boolean isDecodeUsingCustomCharsetRequired() { + return decodeUsing != null; + } + + public boolean isEngineEnabled() { + return engineEnabled; + } + + public void setEngineEnabled(boolean engineEnabled) { + this.engineEnabled = engineEnabled; + } + + public boolean isLoadedFromFile() { + return fileName != null; + } + + public boolean isDecodeUsingEncodingHeader() { + return decodeUsingEncodingHeader; + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/ConfHandler.java b/src/main/java/org/tuckey/web/filters/urlrewrite/ConfHandler.java index 69dac7d2..81a3e29c 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/ConfHandler.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/ConfHandler.java @@ -1,144 +1,144 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.DefaultHandler; - -import java.util.Hashtable; -import java.util.regex.Pattern; - -/** - * Handles DTD lookup and error handling for XML Conf parsing. - * - * @author Paul Tuckey - * @version $Revision: 35 $ $Date: 2006-09-18 19:15:17 +1200 (Mon, 18 Sep 2006) $ - */ -public class ConfHandler extends DefaultHandler { - - private static Log log = Log.getLog(ConfHandler.class); - - // pattern to match file://, http://, jndi:// - private static final Pattern HAS_PROTOCOL = Pattern.compile("^\\w+:"); - - private String confSystemId; - - private static Hashtable dtdPaths = new Hashtable(); - - static { - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 1.0//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite1.0.dtd"); - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 2.0//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.0.dtd"); - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 2.3//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.3.dtd"); - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 2.4//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.4.dtd"); - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 2.5//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.5.dtd"); - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 2.6//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.6.dtd"); - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 3.0//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.0.dtd"); - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 3.1//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.1.dtd"); - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 3.2//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.2.dtd"); - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 3.3//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.3.dtd"); - dtdPaths.put("-//tuckey.org//DTD UrlRewrite 4.0//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite4.0.dtd"); - } - - public ConfHandler(String confSystemId) { - this.confSystemId = confSystemId; - } - - /** - * Resolve the requested external entity. - * - * @param publicId The public identifier of the entity being referenced - * @param systemId The system identifier of the entity being referenced - * @throws org.xml.sax.SAXException if a parsing exception occurs - */ - public InputSource resolveEntity(String publicId, String systemId) - throws SAXException { - if (publicId == null) { - if (log.isDebugEnabled()) { - log.debug("Couldn't resolve entity with no publicId, system id is " + systemId); - } - if (confSystemId != null && !hasProtocol(systemId)) { - return new InputSource(confSystemId.substring(0, confSystemId.lastIndexOf('/')) + "/" + systemId); - } - return new InputSource(systemId); - } - String entity = (String) dtdPaths.get(publicId); - - if (entity == null) { - if (log.isDebugEnabled()) { - log.debug("Couldn't resolve DTD: " + publicId + ", " + systemId); - } - return null; - } - - if (log.isDebugEnabled()) { - log.debug("Resolving to DTD " + entity); - } - return new InputSource(ConfHandler.class.getResourceAsStream(entity)); - } - - /** - * Check for protocol on a systemId. - * eg, file://blah, http://blah, jndi://blah have protocols - * /blah does not - * - * @param systemId the full systemId - * @return true if systemId has protocol - */ - private static boolean hasProtocol(String systemId) { - return systemId != null && HAS_PROTOCOL.matcher(systemId).find(); - } - - // - // ErrorHandler methods - // - - public void warning(SAXParseException ex) { - log.debug("error: " + ex.getMessage()); - } - - public void error(SAXParseException ex) { - - log.debug("error: " + ex.getMessage()); - } - - public void fatalError(SAXParseException ex) throws SAXException { - log.debug("error: " + ex.getMessage()); - } - - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + +import java.util.Hashtable; +import java.util.regex.Pattern; + +/** + * Handles DTD lookup and error handling for XML Conf parsing. + * + * @author Paul Tuckey + * @version $Revision: 35 $ $Date: 2006-09-18 19:15:17 +1200 (Mon, 18 Sep 2006) $ + */ +public class ConfHandler extends DefaultHandler { + + private static Log log = Log.getLog(ConfHandler.class); + + // pattern to match file://, http://, jndi:// + private static final Pattern HAS_PROTOCOL = Pattern.compile("^\\w+:"); + + private String confSystemId; + + private static Hashtable dtdPaths = new Hashtable(); + + static { + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 1.0//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite1.0.dtd"); + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 2.0//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.0.dtd"); + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 2.3//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.3.dtd"); + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 2.4//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.4.dtd"); + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 2.5//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.5.dtd"); + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 2.6//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.6.dtd"); + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 3.0//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.0.dtd"); + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 3.1//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.1.dtd"); + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 3.2//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.2.dtd"); + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 3.3//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.3.dtd"); + dtdPaths.put("-//tuckey.org//DTD UrlRewrite 4.0//EN", "/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite4.0.dtd"); + } + + public ConfHandler(String confSystemId) { + this.confSystemId = confSystemId; + } + + /** + * Resolve the requested external entity. + * + * @param publicId The public identifier of the entity being referenced + * @param systemId The system identifier of the entity being referenced + * @throws org.xml.sax.SAXException if a parsing exception occurs + */ + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException { + if (publicId == null) { + if (log.isDebugEnabled()) { + log.debug("Couldn't resolve entity with no publicId, system id is " + systemId); + } + if (confSystemId != null && !hasProtocol(systemId)) { + return new InputSource(confSystemId.substring(0, confSystemId.lastIndexOf('/')) + "/" + systemId); + } + return new InputSource(systemId); + } + String entity = (String) dtdPaths.get(publicId); + + if (entity == null) { + if (log.isDebugEnabled()) { + log.debug("Couldn't resolve DTD: " + publicId + ", " + systemId); + } + return null; + } + + if (log.isDebugEnabled()) { + log.debug("Resolving to DTD " + entity); + } + return new InputSource(ConfHandler.class.getResourceAsStream(entity)); + } + + /** + * Check for protocol on a systemId. + * eg, file://blah, http://blah, jndi://blah have protocols + * /blah does not + * + * @param systemId the full systemId + * @return true if systemId has protocol + */ + private static boolean hasProtocol(String systemId) { + return systemId != null && HAS_PROTOCOL.matcher(systemId).find(); + } + + // + // ErrorHandler methods + // + + public void warning(SAXParseException ex) { + log.debug("error: " + ex.getMessage()); + } + + public void error(SAXParseException ex) { + + log.debug("error: " + ex.getMessage()); + } + + public void fatalError(SAXParseException ex) throws SAXException { + log.debug("error: " + ex.getMessage()); + } + + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRewrittenUrl.java b/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRewrittenUrl.java index 65fe2c7b..b47492f4 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRewrittenUrl.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRewrittenUrl.java @@ -1,368 +1,368 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; -import org.tuckey.web.filters.urlrewrite.utils.Log; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.RequestDispatcher; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; - - -/** - * Holds information about the rewirtten url. - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class NormalRewrittenUrl implements RewrittenUrl { - - private static Log log = Log.getLog(RewrittenUrl.class); - - private boolean forward = false; - private boolean redirect = false; - private boolean permanentRedirect = false; - private boolean temporaryRedirect = false; - private boolean permanentRedirect308 = false; - private boolean temporaryRedirect307 = false; - private boolean preInclude = false; - private boolean postInclude = false; - private boolean proxy = false; - private String target; - private boolean encode; - private boolean stopFilterChain = false; - private boolean noSubstitution = false; - private boolean dropCookies = true; - private RewriteMatch rewriteMatch; - private ServletContext targetContext = null; - - /** - * Holds information about the rewritten url. - * - * @param ruleExecutionOutput the url to rewrite to - */ - public NormalRewrittenUrl(RuleExecutionOutput ruleExecutionOutput) { - this.target = ruleExecutionOutput.getReplacedUrl(); - this.targetContext = ruleExecutionOutput.getReplacedUrlContext(); - this.stopFilterChain = ruleExecutionOutput.isStopFilterMatch(); - this.rewriteMatch = ruleExecutionOutput.getRewriteMatch(); - this.noSubstitution = ruleExecutionOutput.isNoSubstitution(); - this.dropCookies = ruleExecutionOutput.shouldDropCookies(); - } - - /** - * Holds information about the rewirtten url. - * - * @param target the url to rewrite to - */ - protected NormalRewrittenUrl(String target) { - this.target = target; - } - - /** - * Gets the target url - * - * @return the target - */ - public String getTarget() { - return target; - } - - public boolean isForward() { - return forward; - } - - public void setRedirect(boolean redirect) { - this.redirect = redirect; - } - - public boolean isRedirect() { - return redirect; - } - - public void setForward(boolean forward) { - this.forward = forward; - } - - public void setPermanentRedirect(boolean permanentRedirect) { - this.permanentRedirect = permanentRedirect; - } - - public boolean isPermanentRedirect() { - return permanentRedirect; - } - - public void setTemporaryRedirect(boolean temporaryRedirect) { - this.temporaryRedirect = temporaryRedirect; - } - - public boolean isTemporaryRedirect() { - return temporaryRedirect; - } - - public void set308PermanentRedirect(boolean permanentRedirect308) { - this.permanentRedirect308 = permanentRedirect308; - } - - public boolean is308PermanentRedirect() { - return permanentRedirect308; - } - - public void set307TemporaryRedirect(boolean temporaryRedirect307) { - this.temporaryRedirect307 = temporaryRedirect307; - } - - public boolean is307TemporaryRedirect() { - return temporaryRedirect307; - } - - public void setEncode(boolean b) { - encode = b; - } - - public boolean isEncode() { - return encode; - } - - public boolean isPreInclude() { - return preInclude; - } - - public void setPreInclude(boolean preInclude) { - this.preInclude = preInclude; - } - - public boolean isPostInclude() { - return postInclude; - } - - public void setPostInclude(boolean postInclude) { - this.postInclude = postInclude; - } - - public boolean isStopFilterChain() { - return stopFilterChain; - } - - public void setStopFilterChain(boolean stopFilterChain) { - this.stopFilterChain = stopFilterChain; - } - - public boolean isProxy() { - return proxy; - } - - public void setProxy(boolean proxy) { - this.proxy = proxy; - } - - /** - * The method that actually handles the outcome and rewrites. - * - * @param hsRequest - * @param hsResponse - * @param chain - * @return True if the request was rewritten otherwise false. - * @throws javax.servlet.ServletException - * @throws java.io.IOException - */ - public boolean doRewrite(final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse, final FilterChain chain) - throws IOException, ServletException { - boolean requestRewritten = false; - String target = getTarget(); - if (log.isTraceEnabled()) { - log.trace("doRewrite called"); - } - if (rewriteMatch != null) { - // todo: exception handling? - rewriteMatch.execute(hsRequest, hsResponse); - } - if (stopFilterChain) { - // if we need to stop the filter chain don't do anything - log.trace("stopping filter chain"); - requestRewritten = true; - - } else if (isNoSubstitution()) { - log.trace("no substitution"); - requestRewritten = false; - - } else if (isForward()) { - if (hsResponse.isCommitted()) { - log.error("response is comitted cannot forward to " + target + - " (check you haven't done anything to the response (ie, written to it) before here)"); - } else { - final RequestDispatcher rq = getRequestDispatcher(hsRequest, target, targetContext); - rq.forward(hsRequest, hsResponse); - if (log.isTraceEnabled()) log.trace("forwarded to " + target); - } - requestRewritten = true; - - } else if (isPreInclude()) { - final RequestDispatcher rq = getRequestDispatcher(hsRequest, target, targetContext); - rq.include(hsRequest, hsResponse); - chain.doFilter(hsRequest, hsResponse); - requestRewritten = true; - if (log.isTraceEnabled()) log.trace("preinclded " + target); - - } else if (isPostInclude()) { - final RequestDispatcher rq = getRequestDispatcher(hsRequest, target, targetContext); - chain.doFilter(hsRequest, hsResponse); - rq.include(hsRequest, hsResponse); - requestRewritten = true; - if (log.isTraceEnabled()) log.trace("postinclded " + target); - - } else if (isRedirect()) { - if (hsResponse.isCommitted()) { - log.error("response is comitted cannot redirect to " + target + - " (check you haven't done anything to the response (ie, written to it) before here)"); - } else { - if (isEncode()) { - target = hsResponse.encodeRedirectURL(target); - } - hsResponse.sendRedirect(target); - if (log.isTraceEnabled()) log.trace("redirected to " + target); - } - requestRewritten = true; - - } else if (isTemporaryRedirect()) { - if (hsResponse.isCommitted()) { - log.error("response is comitted cannot temporary redirect to " + target + - " (check you haven't done anything to the response (ie, written to it) before here)"); - } else { - if (isEncode()) { - target = hsResponse.encodeRedirectURL(target); - } - hsResponse.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); - hsResponse.setHeader("Location", target); - if (log.isTraceEnabled()) log.trace("temporarily redirected to " + target); - } - requestRewritten = true; - - } else if (isPermanentRedirect()) { - if (hsResponse.isCommitted()) { - log.error("response is comitted cannot permanent redirect " + target + - " (check you haven't done anything to the response (ie, written to it) before here)"); - } else { - if (isEncode()) { - target = hsResponse.encodeRedirectURL(target); - } - hsResponse.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); - hsResponse.setHeader("Location", target); - if (log.isTraceEnabled()) log.trace("permanently redirected to " + target); - } - requestRewritten = true; - - } else if (is307TemporaryRedirect()) { - if (hsResponse.isCommitted()) { - log.error("response is committed cannot temporary redirect (307) to " + target + - " (check you haven't done anything to the response (ie, written to it) before here)"); - } else { - if (isEncode()) { - target = hsResponse.encodeRedirectURL(target); - } - hsResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); - hsResponse.setHeader("Location", target); - if (log.isDebugEnabled()) log.debug("temporarily redirected (with response 307) to " + target); - } - requestRewritten = true; - - } else if (is308PermanentRedirect()) { - if (hsResponse.isCommitted()) { - log.error("response is committed cannot permanent redirect (308) to " + target + - " (check you haven't done anything to the response (ie, written to it) before here)"); - } else { - if (isEncode()) { - target = hsResponse.encodeRedirectURL(target); - } - hsResponse.setStatus(308); - hsResponse.setHeader("Location", target); - if (log.isDebugEnabled()) log.debug("permanently redirected (with response 308) to " + target); - } - requestRewritten = true; - - } else if (isProxy()) { - if (hsResponse.isCommitted()) { - log.error("response is committed. cannot proxy " + target + ". Check that you havn't written to the response before."); - } else { - RequestProxy.execute(target, hsRequest, hsResponse, dropCookies); - if (log.isTraceEnabled()) { - log.trace("Proxied request to " + target); - } - } - requestRewritten = true; - } - return requestRewritten; - } - - private RequestDispatcher getRequestDispatcher(final HttpServletRequest hsRequest, String toUrl, - ServletContext targetContext) throws ServletException { - final RequestDispatcher rq = (targetContext != null) ? targetContext.getRequestDispatcher(target) : hsRequest.getRequestDispatcher(toUrl); - if (rq == null) { - // this might be a 404 possibly something else, could re-throw a 404 but is best to throw servlet exception - throw new ServletException("unable to get request dispatcher for " + toUrl); - } - return rq; - } - - /** - * @return the targetContext - */ - public ServletContext getTargetContext() { - return targetContext; - } - - /** - * @param targetContext the targetContext to set - */ - public void setTargetContext(ServletContext targetContext) { - this.targetContext = targetContext; - } - - public boolean isNoSubstitution() { - return noSubstitution; - } - - public void setNoSubstitution(boolean noSubstitution) { - this.noSubstitution = noSubstitution; - } - - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; +import org.tuckey.web.filters.urlrewrite.utils.Log; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + + +/** + * Holds information about the rewirtten url. + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class NormalRewrittenUrl implements RewrittenUrl { + + private static Log log = Log.getLog(RewrittenUrl.class); + + private boolean forward = false; + private boolean redirect = false; + private boolean permanentRedirect = false; + private boolean temporaryRedirect = false; + private boolean permanentRedirect308 = false; + private boolean temporaryRedirect307 = false; + private boolean preInclude = false; + private boolean postInclude = false; + private boolean proxy = false; + private String target; + private boolean encode; + private boolean stopFilterChain = false; + private boolean noSubstitution = false; + private boolean dropCookies = true; + private RewriteMatch rewriteMatch; + private ServletContext targetContext = null; + + /** + * Holds information about the rewritten url. + * + * @param ruleExecutionOutput the url to rewrite to + */ + public NormalRewrittenUrl(RuleExecutionOutput ruleExecutionOutput) { + this.target = ruleExecutionOutput.getReplacedUrl(); + this.targetContext = ruleExecutionOutput.getReplacedUrlContext(); + this.stopFilterChain = ruleExecutionOutput.isStopFilterMatch(); + this.rewriteMatch = ruleExecutionOutput.getRewriteMatch(); + this.noSubstitution = ruleExecutionOutput.isNoSubstitution(); + this.dropCookies = ruleExecutionOutput.shouldDropCookies(); + } + + /** + * Holds information about the rewirtten url. + * + * @param target the url to rewrite to + */ + protected NormalRewrittenUrl(String target) { + this.target = target; + } + + /** + * Gets the target url + * + * @return the target + */ + public String getTarget() { + return target; + } + + public boolean isForward() { + return forward; + } + + public void setRedirect(boolean redirect) { + this.redirect = redirect; + } + + public boolean isRedirect() { + return redirect; + } + + public void setForward(boolean forward) { + this.forward = forward; + } + + public void setPermanentRedirect(boolean permanentRedirect) { + this.permanentRedirect = permanentRedirect; + } + + public boolean isPermanentRedirect() { + return permanentRedirect; + } + + public void setTemporaryRedirect(boolean temporaryRedirect) { + this.temporaryRedirect = temporaryRedirect; + } + + public boolean isTemporaryRedirect() { + return temporaryRedirect; + } + + public void set308PermanentRedirect(boolean permanentRedirect308) { + this.permanentRedirect308 = permanentRedirect308; + } + + public boolean is308PermanentRedirect() { + return permanentRedirect308; + } + + public void set307TemporaryRedirect(boolean temporaryRedirect307) { + this.temporaryRedirect307 = temporaryRedirect307; + } + + public boolean is307TemporaryRedirect() { + return temporaryRedirect307; + } + + public void setEncode(boolean b) { + encode = b; + } + + public boolean isEncode() { + return encode; + } + + public boolean isPreInclude() { + return preInclude; + } + + public void setPreInclude(boolean preInclude) { + this.preInclude = preInclude; + } + + public boolean isPostInclude() { + return postInclude; + } + + public void setPostInclude(boolean postInclude) { + this.postInclude = postInclude; + } + + public boolean isStopFilterChain() { + return stopFilterChain; + } + + public void setStopFilterChain(boolean stopFilterChain) { + this.stopFilterChain = stopFilterChain; + } + + public boolean isProxy() { + return proxy; + } + + public void setProxy(boolean proxy) { + this.proxy = proxy; + } + + /** + * The method that actually handles the outcome and rewrites. + * + * @param hsRequest + * @param hsResponse + * @param chain + * @return True if the request was rewritten otherwise false. + * @throws javax.servlet.ServletException + * @throws java.io.IOException + */ + public boolean doRewrite(final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse, final FilterChain chain) + throws IOException, ServletException { + boolean requestRewritten = false; + String target = getTarget(); + if (log.isTraceEnabled()) { + log.trace("doRewrite called"); + } + if (rewriteMatch != null) { + // todo: exception handling? + rewriteMatch.execute(hsRequest, hsResponse); + } + if (stopFilterChain) { + // if we need to stop the filter chain don't do anything + log.trace("stopping filter chain"); + requestRewritten = true; + + } else if (isNoSubstitution()) { + log.trace("no substitution"); + requestRewritten = false; + + } else if (isForward()) { + if (hsResponse.isCommitted()) { + log.error("response is comitted cannot forward to " + target + + " (check you haven't done anything to the response (ie, written to it) before here)"); + } else { + final RequestDispatcher rq = getRequestDispatcher(hsRequest, target, targetContext); + rq.forward(hsRequest, hsResponse); + if (log.isTraceEnabled()) log.trace("forwarded to " + target); + } + requestRewritten = true; + + } else if (isPreInclude()) { + final RequestDispatcher rq = getRequestDispatcher(hsRequest, target, targetContext); + rq.include(hsRequest, hsResponse); + chain.doFilter(hsRequest, hsResponse); + requestRewritten = true; + if (log.isTraceEnabled()) log.trace("preinclded " + target); + + } else if (isPostInclude()) { + final RequestDispatcher rq = getRequestDispatcher(hsRequest, target, targetContext); + chain.doFilter(hsRequest, hsResponse); + rq.include(hsRequest, hsResponse); + requestRewritten = true; + if (log.isTraceEnabled()) log.trace("postinclded " + target); + + } else if (isRedirect()) { + if (hsResponse.isCommitted()) { + log.error("response is comitted cannot redirect to " + target + + " (check you haven't done anything to the response (ie, written to it) before here)"); + } else { + if (isEncode()) { + target = hsResponse.encodeRedirectURL(target); + } + hsResponse.sendRedirect(target); + if (log.isTraceEnabled()) log.trace("redirected to " + target); + } + requestRewritten = true; + + } else if (isTemporaryRedirect()) { + if (hsResponse.isCommitted()) { + log.error("response is comitted cannot temporary redirect to " + target + + " (check you haven't done anything to the response (ie, written to it) before here)"); + } else { + if (isEncode()) { + target = hsResponse.encodeRedirectURL(target); + } + hsResponse.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); + hsResponse.setHeader("Location", target); + if (log.isTraceEnabled()) log.trace("temporarily redirected to " + target); + } + requestRewritten = true; + + } else if (isPermanentRedirect()) { + if (hsResponse.isCommitted()) { + log.error("response is comitted cannot permanent redirect " + target + + " (check you haven't done anything to the response (ie, written to it) before here)"); + } else { + if (isEncode()) { + target = hsResponse.encodeRedirectURL(target); + } + hsResponse.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); + hsResponse.setHeader("Location", target); + if (log.isTraceEnabled()) log.trace("permanently redirected to " + target); + } + requestRewritten = true; + + } else if (is307TemporaryRedirect()) { + if (hsResponse.isCommitted()) { + log.error("response is committed cannot temporary redirect (307) to " + target + + " (check you haven't done anything to the response (ie, written to it) before here)"); + } else { + if (isEncode()) { + target = hsResponse.encodeRedirectURL(target); + } + hsResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); + hsResponse.setHeader("Location", target); + if (log.isDebugEnabled()) log.debug("temporarily redirected (with response 307) to " + target); + } + requestRewritten = true; + + } else if (is308PermanentRedirect()) { + if (hsResponse.isCommitted()) { + log.error("response is committed cannot permanent redirect (308) to " + target + + " (check you haven't done anything to the response (ie, written to it) before here)"); + } else { + if (isEncode()) { + target = hsResponse.encodeRedirectURL(target); + } + hsResponse.setStatus(308); + hsResponse.setHeader("Location", target); + if (log.isDebugEnabled()) log.debug("permanently redirected (with response 308) to " + target); + } + requestRewritten = true; + + } else if (isProxy()) { + if (hsResponse.isCommitted()) { + log.error("response is committed. cannot proxy " + target + ". Check that you havn't written to the response before."); + } else { + RequestProxy.execute(target, hsRequest, hsResponse, dropCookies); + if (log.isTraceEnabled()) { + log.trace("Proxied request to " + target); + } + } + requestRewritten = true; + } + return requestRewritten; + } + + private RequestDispatcher getRequestDispatcher(final HttpServletRequest hsRequest, String toUrl, + ServletContext targetContext) throws ServletException { + final RequestDispatcher rq = (targetContext != null) ? targetContext.getRequestDispatcher(target) : hsRequest.getRequestDispatcher(toUrl); + if (rq == null) { + // this might be a 404 possibly something else, could re-throw a 404 but is best to throw servlet exception + throw new ServletException("unable to get request dispatcher for " + toUrl); + } + return rq; + } + + /** + * @return the targetContext + */ + public ServletContext getTargetContext() { + return targetContext; + } + + /** + * @param targetContext the targetContext to set + */ + public void setTargetContext(ServletContext targetContext) { + this.targetContext = targetContext; + } + + public boolean isNoSubstitution() { + return noSubstitution; + } + + public void setNoSubstitution(boolean noSubstitution) { + this.noSubstitution = noSubstitution; + } + + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRule.java index 188dd568..ff8891d4 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRule.java @@ -1,251 +1,251 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; - - -/** - * Defines a rule that can be run against an incoming request. - * 20040304 - Thanks to Scott Askew for help with concurrency issue with Perl5Compiler and Perl5Matcher. - * - * @author Paul Tuckey - * @version $Revision: 36 $ $Date: 2006-09-19 18:32:39 +1200 (Tue, 19 Sep 2006) $ - */ -public class NormalRule extends RuleBase implements Rule { - - private static Log log = Log.getLog(NormalRule.class); - - public short toType = TO_TYPE_FORWARD; // default to passthrough/forward - - public static final short TO_TYPE_REDIRECT = 0; - public static final short TO_TYPE_FORWARD = 1; - public static final short TO_TYPE_PERMANENT_REDIRECT = 2; - public static final short TO_TYPE_TEMPORARY_REDIRECT = 3; - public static final short TO_TYPE_PRE_INCLUDE = 4; - public static final short TO_TYPE_POST_INCLUDE = 5; - public static final short TO_TYPE_PROXY = 6; - public static final short TO_TYPE_307_TEMPORARY_REDIRECT = 7; - public static final short TO_TYPE_308_PERMANENT_REDIRECT = 8; - - private boolean dropCookies = true; - private boolean encodeToUrl = false; - private boolean queryStringAppend = false; - private String toContextStr = null; - private ServletContext toServletContext = null; - - /** - * Constructor. - */ - public NormalRule() { - // empty - } - - /** - * Will run the rule against the uri and perform action required will return false is not matched - * otherwise true. - * - * @param url - * @param hsRequest - * @return String of the rewritten url or the same as the url passed in if no match was made - */ - public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse, RuleChain chain) - throws IOException, ServletException, InvocationTargetException { - RuleExecutionOutput ruleExecutionOutput = super.matchesBase(url, hsRequest, hsResponse, chain); - if (ruleExecutionOutput == null || !ruleExecutionOutput.isRuleMatched()) { - // no match, or run/set only match - return null; - } - ruleExecutionOutput.setDropCookies(dropCookies); - if ( queryStringAppend && hsRequest.getQueryString() != null && hsRequest.getQueryString().length() > 0) { - String target = ruleExecutionOutput.getReplacedUrl(); - if (target.contains("?")) { - ruleExecutionOutput.setReplacedUrl(target + "&" + hsRequest.getQueryString()); - } else { - ruleExecutionOutput.setReplacedUrl(target + "?" + hsRequest.getQueryString()); - } - } - if ( toServletContext != null ) ruleExecutionOutput.setReplacedUrlContext(toServletContext); - return RuleExecutionOutput.getRewritenUrl(toType, encodeToUrl, ruleExecutionOutput); - } - - public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse) - throws IOException, ServletException, InvocationTargetException { - return matches(url, hsRequest, hsResponse, null); - } - - - /** - * Will initialise the rule. - * - * @return true on success - */ - public boolean initialise(ServletContext context) { - boolean ok = super.initialise(context); - // check all the conditions - initialised = true; - if (!ok) { - log.debug("failed to load rule"); - } else { - log.debug("loaded rule " + getDisplayName() + " (" + from + ", " + to + " " + toType + ")"); - } - - if ( !StringUtils.isBlank(toContextStr)) { - log.debug("looking for context " + toContextStr); - if ( context == null) { - addError("unable to look for context as current context null"); - } else { - toServletContext = context.getContext("/" + toContextStr); - if ( toServletContext == null ) { - addError("could not get servlet context " + toContextStr); - } else { - log.debug("got context ok"); - } - } - } - - if (errors.size() > 0) { - ok = false; - } - valid = ok; - return ok; - } - - - /** - * Redirect or passthrough, passthrough is the default. - * - * @param toTypeStr to type string - */ - public void setToType(final String toTypeStr) { - if ("redirect".equals(toTypeStr)) { - toType = TO_TYPE_REDIRECT; - } else if ("permanent-redirect".equals(toTypeStr)) { - toType = TO_TYPE_PERMANENT_REDIRECT; - } else if ("temporary-redirect".equals(toTypeStr)) { - toType = TO_TYPE_TEMPORARY_REDIRECT; - } else if ("308-permanent-redirect".equals(toTypeStr)) { - toType = TO_TYPE_308_PERMANENT_REDIRECT; - } else if ("307-temporary-redirect".equals(toTypeStr)) { - toType = TO_TYPE_307_TEMPORARY_REDIRECT; - } else if ("pre-include".equals(toTypeStr)) { - toType = TO_TYPE_PRE_INCLUDE; - } else if ("post-include".equals(toTypeStr)) { - toType = TO_TYPE_POST_INCLUDE; - } else if ("forward".equals(toTypeStr) || "passthrough".equals(toTypeStr) || - StringUtils.isBlank(toTypeStr)) { - toType = TO_TYPE_FORWARD; - } else if ("proxy".equals(toTypeStr)) { - toType = TO_TYPE_PROXY; - } else { - addError("type (" + toTypeStr + ") is not valid"); - } - } - - /** - * Will get to type ie redirect or passthrough. - * - * @return String - */ - public String getToType() { - if (toType == TO_TYPE_REDIRECT) return "redirect"; - if (toType == TO_TYPE_PERMANENT_REDIRECT) return "permanent-redirect"; - if (toType == TO_TYPE_TEMPORARY_REDIRECT) return "temporary-redirect"; - if (toType == TO_TYPE_308_PERMANENT_REDIRECT) return "permanent-redirect-308"; - if (toType == TO_TYPE_307_TEMPORARY_REDIRECT) return "temporary-redirect-307"; - if (toType == TO_TYPE_PRE_INCLUDE) return "pre-include"; - if (toType == TO_TYPE_POST_INCLUDE) return "post-include"; - if (toType == TO_TYPE_PROXY) return "proxy"; - return "forward"; - } - - protected void addError(String s) { - log.error("Rule " + getDisplayName() + " had error: " + s); - super.addError(s); - } - - public String getDisplayName() { - if (name != null) { - return name + " (rule " + id + ")"; - } - return "Rule " + id; - } - - public String getName() { - return name; - } - - public String getFullDisplayName() { - return getDisplayName() + " (" + from + ", " + to + " " + toType + ")"; - } - - public boolean isEncodeToUrl() { - return encodeToUrl; - } - - public void setEncodeToUrl(boolean encodeToUrl) { - this.encodeToUrl = encodeToUrl; - } - - public String getToContextStr() { - return toContextStr; - } - - public void setToContextStr(String toContextStr) { - this.toContextStr = toContextStr; - } - - public ServletContext getToServletContext() { - return toServletContext; - } - - public void setQueryStringAppend(String value) { - queryStringAppend = "true".equalsIgnoreCase(value); - } - - public void setDropCookies(String value) { - dropCookies = "true".equalsIgnoreCase(value); - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + + +/** + * Defines a rule that can be run against an incoming request. + * 20040304 - Thanks to Scott Askew for help with concurrency issue with Perl5Compiler and Perl5Matcher. + * + * @author Paul Tuckey + * @version $Revision: 36 $ $Date: 2006-09-19 18:32:39 +1200 (Tue, 19 Sep 2006) $ + */ +public class NormalRule extends RuleBase implements Rule { + + private static Log log = Log.getLog(NormalRule.class); + + public short toType = TO_TYPE_FORWARD; // default to passthrough/forward + + public static final short TO_TYPE_REDIRECT = 0; + public static final short TO_TYPE_FORWARD = 1; + public static final short TO_TYPE_PERMANENT_REDIRECT = 2; + public static final short TO_TYPE_TEMPORARY_REDIRECT = 3; + public static final short TO_TYPE_PRE_INCLUDE = 4; + public static final short TO_TYPE_POST_INCLUDE = 5; + public static final short TO_TYPE_PROXY = 6; + public static final short TO_TYPE_307_TEMPORARY_REDIRECT = 7; + public static final short TO_TYPE_308_PERMANENT_REDIRECT = 8; + + private boolean dropCookies = true; + private boolean encodeToUrl = false; + private boolean queryStringAppend = false; + private String toContextStr = null; + private ServletContext toServletContext = null; + + /** + * Constructor. + */ + public NormalRule() { + // empty + } + + /** + * Will run the rule against the uri and perform action required will return false is not matched + * otherwise true. + * + * @param url + * @param hsRequest + * @return String of the rewritten url or the same as the url passed in if no match was made + */ + public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse, RuleChain chain) + throws IOException, ServletException, InvocationTargetException { + RuleExecutionOutput ruleExecutionOutput = super.matchesBase(url, hsRequest, hsResponse, chain); + if (ruleExecutionOutput == null || !ruleExecutionOutput.isRuleMatched()) { + // no match, or run/set only match + return null; + } + ruleExecutionOutput.setDropCookies(dropCookies); + if ( queryStringAppend && hsRequest.getQueryString() != null && hsRequest.getQueryString().length() > 0) { + String target = ruleExecutionOutput.getReplacedUrl(); + if (target.contains("?")) { + ruleExecutionOutput.setReplacedUrl(target + "&" + hsRequest.getQueryString()); + } else { + ruleExecutionOutput.setReplacedUrl(target + "?" + hsRequest.getQueryString()); + } + } + if ( toServletContext != null ) ruleExecutionOutput.setReplacedUrlContext(toServletContext); + return RuleExecutionOutput.getRewritenUrl(toType, encodeToUrl, ruleExecutionOutput); + } + + public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse) + throws IOException, ServletException, InvocationTargetException { + return matches(url, hsRequest, hsResponse, null); + } + + + /** + * Will initialise the rule. + * + * @return true on success + */ + public boolean initialise(ServletContext context) { + boolean ok = super.initialise(context); + // check all the conditions + initialised = true; + if (!ok) { + log.debug("failed to load rule"); + } else { + log.debug("loaded rule " + getDisplayName() + " (" + from + ", " + to + " " + toType + ")"); + } + + if ( !StringUtils.isBlank(toContextStr)) { + log.debug("looking for context " + toContextStr); + if ( context == null) { + addError("unable to look for context as current context null"); + } else { + toServletContext = context.getContext("/" + toContextStr); + if ( toServletContext == null ) { + addError("could not get servlet context " + toContextStr); + } else { + log.debug("got context ok"); + } + } + } + + if (errors.size() > 0) { + ok = false; + } + valid = ok; + return ok; + } + + + /** + * Redirect or passthrough, passthrough is the default. + * + * @param toTypeStr to type string + */ + public void setToType(final String toTypeStr) { + if ("redirect".equals(toTypeStr)) { + toType = TO_TYPE_REDIRECT; + } else if ("permanent-redirect".equals(toTypeStr)) { + toType = TO_TYPE_PERMANENT_REDIRECT; + } else if ("temporary-redirect".equals(toTypeStr)) { + toType = TO_TYPE_TEMPORARY_REDIRECT; + } else if ("308-permanent-redirect".equals(toTypeStr)) { + toType = TO_TYPE_308_PERMANENT_REDIRECT; + } else if ("307-temporary-redirect".equals(toTypeStr)) { + toType = TO_TYPE_307_TEMPORARY_REDIRECT; + } else if ("pre-include".equals(toTypeStr)) { + toType = TO_TYPE_PRE_INCLUDE; + } else if ("post-include".equals(toTypeStr)) { + toType = TO_TYPE_POST_INCLUDE; + } else if ("forward".equals(toTypeStr) || "passthrough".equals(toTypeStr) || + StringUtils.isBlank(toTypeStr)) { + toType = TO_TYPE_FORWARD; + } else if ("proxy".equals(toTypeStr)) { + toType = TO_TYPE_PROXY; + } else { + addError("type (" + toTypeStr + ") is not valid"); + } + } + + /** + * Will get to type ie redirect or passthrough. + * + * @return String + */ + public String getToType() { + if (toType == TO_TYPE_REDIRECT) return "redirect"; + if (toType == TO_TYPE_PERMANENT_REDIRECT) return "permanent-redirect"; + if (toType == TO_TYPE_TEMPORARY_REDIRECT) return "temporary-redirect"; + if (toType == TO_TYPE_308_PERMANENT_REDIRECT) return "permanent-redirect-308"; + if (toType == TO_TYPE_307_TEMPORARY_REDIRECT) return "temporary-redirect-307"; + if (toType == TO_TYPE_PRE_INCLUDE) return "pre-include"; + if (toType == TO_TYPE_POST_INCLUDE) return "post-include"; + if (toType == TO_TYPE_PROXY) return "proxy"; + return "forward"; + } + + protected void addError(String s) { + log.error("Rule " + getDisplayName() + " had error: " + s); + super.addError(s); + } + + public String getDisplayName() { + if (name != null) { + return name + " (rule " + id + ")"; + } + return "Rule " + id; + } + + public String getName() { + return name; + } + + public String getFullDisplayName() { + return getDisplayName() + " (" + from + ", " + to + " " + toType + ")"; + } + + public boolean isEncodeToUrl() { + return encodeToUrl; + } + + public void setEncodeToUrl(boolean encodeToUrl) { + this.encodeToUrl = encodeToUrl; + } + + public String getToContextStr() { + return toContextStr; + } + + public void setToContextStr(String toContextStr) { + this.toContextStr = toContextStr; + } + + public ServletContext getToServletContext() { + return toServletContext; + } + + public void setQueryStringAppend(String value) { + queryStringAppend = "true".equalsIgnoreCase(value); + } + + public void setDropCookies(String value) { + dropCookies = "true".equalsIgnoreCase(value); + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/OutboundRule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/OutboundRule.java index d2c257ea..98da38d7 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/OutboundRule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/OutboundRule.java @@ -1,143 +1,143 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.Log; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; - -/** - * Defines an outbound rule that can be run against a link in a page. - * - * @author Paul Tuckey - * @version $Revision: 36 $ $Date: 2006-09-19 18:32:39 +1200 (Tue, 19 Sep 2006) $ - */ -public class OutboundRule extends RuleBase { - - private static final Log log = Log.getLog(OutboundRule.class); - - private boolean encodeFirst; - private boolean encodeToUrl = true; - - /** - * Constructor. - */ - public OutboundRule() { - super(); - // empty - } - - /** - * Execute this outbound rule. - */ - public RewrittenOutboundUrl execute(String url, HttpServletRequest hsRequest, HttpServletResponse hsResponse) - throws InvocationTargetException { - RuleExecutionOutput ruleRuleExecutionOutput; - - // if we are running a "run" it might result in an exception and we have to handle it - // unfortunately the servlet spec dow no allow throwing exceptions from encodeURL - // so we have to throw a runtimeException - try { - ruleRuleExecutionOutput = super.matchesBase(url, hsRequest, hsResponse, null); - } catch (IOException e) { - throw new RuntimeException(e); - } catch (ServletException e) { - throw new RuntimeException(e); - } - - if (ruleRuleExecutionOutput == null || !ruleRuleExecutionOutput.isRuleMatched()) { - return null; // no match - } - return new RewrittenOutboundUrl(ruleRuleExecutionOutput.getReplacedUrl(), this.encodeToUrl); - } - - /** - * Will initialise the outbound rule. - * - * @return true on success - */ - public boolean initialise(ServletContext servletContext) { - boolean ok = super.initialise(servletContext); - // check all the conditions - - if (ok) { - String displayName = getDisplayName(); - log.debug("loaded outbound rule " + displayName + " (" + from + ", " + to + ')'); - } else { - log.debug("failed to load outbound rule"); - } - if (errors.size() > 0) { - ok = false; - } - valid = ok; - return ok; - } - - protected void addError(String s) { - String displayName = getDisplayName(); - log.error("Outbound Rule " + displayName + " had error: " + s); - super.addError(s); - } - - public String getDisplayName() { - if (name != null) { - return name + " (outbound rule " + id + ')'; - } - return "Outbound Rule " + id; - } - - public boolean isEncodeFirst() { - return encodeFirst; - } - - public boolean isEncodeToUrl() { - return encodeToUrl; - } - - public void setEncodeFirst(boolean encodeFirst) { - this.encodeFirst = encodeFirst; - } - - public void setEncodeToUrl(boolean encodeToUrl) { - this.encodeToUrl = encodeToUrl; - } -} - - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.Log; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +/** + * Defines an outbound rule that can be run against a link in a page. + * + * @author Paul Tuckey + * @version $Revision: 36 $ $Date: 2006-09-19 18:32:39 +1200 (Tue, 19 Sep 2006) $ + */ +public class OutboundRule extends RuleBase { + + private static final Log log = Log.getLog(OutboundRule.class); + + private boolean encodeFirst; + private boolean encodeToUrl = true; + + /** + * Constructor. + */ + public OutboundRule() { + super(); + // empty + } + + /** + * Execute this outbound rule. + */ + public RewrittenOutboundUrl execute(String url, HttpServletRequest hsRequest, HttpServletResponse hsResponse) + throws InvocationTargetException { + RuleExecutionOutput ruleRuleExecutionOutput; + + // if we are running a "run" it might result in an exception and we have to handle it + // unfortunately the servlet spec dow no allow throwing exceptions from encodeURL + // so we have to throw a runtimeException + try { + ruleRuleExecutionOutput = super.matchesBase(url, hsRequest, hsResponse, null); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (ServletException e) { + throw new RuntimeException(e); + } + + if (ruleRuleExecutionOutput == null || !ruleRuleExecutionOutput.isRuleMatched()) { + return null; // no match + } + return new RewrittenOutboundUrl(ruleRuleExecutionOutput.getReplacedUrl(), this.encodeToUrl); + } + + /** + * Will initialise the outbound rule. + * + * @return true on success + */ + public boolean initialise(ServletContext servletContext) { + boolean ok = super.initialise(servletContext); + // check all the conditions + + if (ok) { + String displayName = getDisplayName(); + log.debug("loaded outbound rule " + displayName + " (" + from + ", " + to + ')'); + } else { + log.debug("failed to load outbound rule"); + } + if (errors.size() > 0) { + ok = false; + } + valid = ok; + return ok; + } + + protected void addError(String s) { + String displayName = getDisplayName(); + log.error("Outbound Rule " + displayName + " had error: " + s); + super.addError(s); + } + + public String getDisplayName() { + if (name != null) { + return name + " (outbound rule " + id + ')'; + } + return "Outbound Rule " + id; + } + + public boolean isEncodeFirst() { + return encodeFirst; + } + + public boolean isEncodeToUrl() { + return encodeToUrl; + } + + public void setEncodeFirst(boolean encodeFirst) { + this.encodeFirst = encodeFirst; + } + + public void setEncodeToUrl(boolean encodeToUrl) { + this.encodeToUrl = encodeToUrl; + } +} + + diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenOutboundUrl.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenOutboundUrl.java index fa0d1e2f..1f68de05 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenOutboundUrl.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenOutboundUrl.java @@ -1,78 +1,78 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -/** - * Holds information about the rewritten outbound url. - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class RewrittenOutboundUrl { - - private String target; - private boolean encode; - - /** - * Holds information about the rewritten outbound url. - * - * @param target the url to rewrite to - */ - public RewrittenOutboundUrl(String target, boolean encode) { - this.target = target; - this.encode = encode; - } - - /** - * Gets the target url - * - * @return the target - */ - public String getTarget() { - return target; - } - - public void setEncode(boolean b) { - encode = b; - } - - public boolean isEncode() { - return encode; - } - - public void setTarget(String s) { - target = s; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +/** + * Holds information about the rewritten outbound url. + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class RewrittenOutboundUrl { + + private String target; + private boolean encode; + + /** + * Holds information about the rewritten outbound url. + * + * @param target the url to rewrite to + */ + public RewrittenOutboundUrl(String target, boolean encode) { + this.target = target; + this.encode = encode; + } + + /** + * Gets the target url + * + * @return the target + */ + public String getTarget() { + return target; + } + + public void setEncode(boolean b) { + encode = b; + } + + public boolean isEncode() { + return encode; + } + + public void setTarget(String s) { + target = s; + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrl.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrl.java index b0de9b0f..f58d7b98 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrl.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrl.java @@ -1,56 +1,56 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Holds information about the rewirtten url. - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public interface RewrittenUrl { - - public String getTarget(); - - public boolean doRewrite(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, - FilterChain filterChain) throws ServletException, IOException; - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * Holds information about the rewirtten url. + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public interface RewrittenUrl { + + public String getTarget(); + + public boolean doRewrite(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + FilterChain filterChain) throws ServletException, IOException; + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlClass.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlClass.java index 4a65366f..06d589ec 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlClass.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlClass.java @@ -1,68 +1,68 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import java.io.IOException; - -/** - * A rewrite target that is acually rewriting the url to a class a user has specified. - */ -class RewrittenUrlClass implements RewrittenUrl { - RewriteMatch rewriteMatch; - private String matchingUrl; - - protected RewrittenUrlClass(RewriteMatch rewriteMatch) { - this.matchingUrl = rewriteMatch.getMatchingUrl(); - this.rewriteMatch = rewriteMatch; - } - - public boolean doRewrite(final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse, final FilterChain chain) - throws IOException, ServletException { - - return rewriteMatch.execute(hsRequest, hsResponse); - } - - public String getTarget() { - return matchingUrl; - } - - } +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import java.io.IOException; + +/** + * A rewrite target that is acually rewriting the url to a class a user has specified. + */ +class RewrittenUrlClass implements RewrittenUrl { + RewriteMatch rewriteMatch; + private String matchingUrl; + + protected RewrittenUrlClass(RewriteMatch rewriteMatch) { + this.matchingUrl = rewriteMatch.getMatchingUrl(); + this.rewriteMatch = rewriteMatch; + } + + public boolean doRewrite(final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse, final FilterChain chain) + throws IOException, ServletException { + + return rewriteMatch.execute(hsRequest, hsResponse); + } + + public String getTarget() { + return matchingUrl; + } + + } diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Rule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Rule.java index b52709f5..ed086b44 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Rule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Rule.java @@ -1,92 +1,92 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.lang.reflect.InvocationTargetException; - - -public interface Rule { - - /** - * Will run the rule against the uri and perform action required will return false is not matched - * otherwise true. - * - * @param url - * @param hsRequest - * @return String of the rewritten url or the same as the url passed in if no match was made - */ - public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse, final RuleChain chain) - throws IOException, ServletException, InvocationTargetException; - - public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse) - throws IOException, ServletException, InvocationTargetException; - - /** - * Will initialise the rule. - * - * @return true on success - */ - public boolean initialise(ServletContext context); - - public void destroy(); - - public String getName(); - - public String getDisplayName(); - - public boolean isLast(); - - public void setId(int i); - - public int getId(); - - public boolean isValid(); - - public boolean isFilter(); - - /** - * List of strings for all errors. - */ - public List getErrors(); - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.lang.reflect.InvocationTargetException; + + +public interface Rule { + + /** + * Will run the rule against the uri and perform action required will return false is not matched + * otherwise true. + * + * @param url + * @param hsRequest + * @return String of the rewritten url or the same as the url passed in if no match was made + */ + public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse, final RuleChain chain) + throws IOException, ServletException, InvocationTargetException; + + public RewrittenUrl matches(final String url, final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse) + throws IOException, ServletException, InvocationTargetException; + + /** + * Will initialise the rule. + * + * @return true on success + */ + public boolean initialise(ServletContext context); + + public void destroy(); + + public String getName(); + + public String getDisplayName(); + + public boolean isLast(); + + public void setId(int i); + + public int getId(); + + public boolean isValid(); + + public boolean isFilter(); + + /** + * List of strings for all errors. + */ + public List getErrors(); + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleBase.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleBase.java index 7bfb42d1..2cc1f0f7 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleBase.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleBase.java @@ -1,579 +1,579 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; -import org.tuckey.web.filters.urlrewrite.substitution.BackReferenceReplacer; -import org.tuckey.web.filters.urlrewrite.substitution.ChainedSubstitutionFilters; -import org.tuckey.web.filters.urlrewrite.substitution.FunctionReplacer; -import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionContext; -import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionFilterChain; -import org.tuckey.web.filters.urlrewrite.substitution.VariableReplacer; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.RegexPattern; -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingPattern; -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingPatternSyntaxException; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; -import org.tuckey.web.filters.urlrewrite.utils.WildcardPattern; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.List; - -/** - * Defines a rule that can be run against an incoming request. - * - * @author Paul Tuckey - * @version $Revision: 36 $ $Date: 2006-09-19 18:32:39 +1200 (Tue, 19 Sep 2006) $ - */ -public class RuleBase implements Runnable { - - private static Log log = Log.getLog(RuleBase.class); - - private static String DEFAULT_RULE_FROM = "^(.*)$"; - - protected int id; - - private boolean enabled = true; - - private boolean fromCaseSensitive; - protected boolean initialised; - protected boolean valid; - - protected String name; - private String note; - protected String from; - protected String to; - private boolean toEmpty; - private String matchType; - private boolean last = false; - - private int conditionIdCounter; - private int runIdCounter; - - private StringMatchingPattern pattern; - protected final List errors = new ArrayList(5); - private final List conditions = new ArrayList(5); - private final List runs = new ArrayList(2); - protected final List setAttributes = new ArrayList(2); - private boolean stopFilterChainOnMatch = false; - private boolean noSubstitution = false; - - private boolean toContainsVariable = false; - private boolean toContainsBackReference = false; - private boolean toContainsFunction = false; - - public static final String MATCH_TYPE_WILDCARD = "wildcard"; - public static final String DEFAULT_MATCH_TYPE = "regex"; - - private boolean filter = false; - private ServletContext servletContext; - - /** - * Constructor. - */ - public RuleBase() { - super(); - // empty - } - - /** - * Will run the rule against the uri and perform action required will return false is not matched - * otherwise true. - * - * @param url - * @param hsRequest - * @return String of the rewritten url or the same as the url passed in if no match was made - */ - protected RuleExecutionOutput matchesBase(String url, final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse, RuleChain chain) - throws IOException, ServletException, InvocationTargetException { - // make sure all the conditions match - if (log.isDebugEnabled()) { - String displayName = getDisplayName(); - log.debug(displayName + " run called with " + url); - } - if (!initialised) { - log.debug("not initialised, skipping"); - return null; - } - if (!valid) { - log.debug("not valid, skipping"); - return null; - } - if (!enabled) { - log.debug("not enabled, skipping"); - return null; - } - if (url == null) { - log.debug("url is null (maybe because of a previous match), skipping"); - return null; - } - - StringMatchingMatcher matcher = pattern.matcher(url); - boolean performToReplacement = false; - if (toEmpty || stopFilterChainOnMatch) { - // to is empty this must be an attempt to "set" and/or "run" - if (!matcher.find()) { - if (log.isTraceEnabled()) { - log.trace("no match on \"from\" (to is empty)"); - } - return null; - } - } else { - if (!matcher.find()) { - if (log.isTraceEnabled()) { - log.trace("no match on \"from\" for " + from + " and " + url); - } - return null; - } - if (!toEmpty && !noSubstitution) { - performToReplacement = true; - } - } - if (log.isDebugEnabled()) { - log.debug("matched \"from\""); - } - - int conditionsSize = conditions.size(); - ConditionMatch lastConditionMatch = null; - if (conditionsSize > 0) { - boolean processNextOr = false; - boolean currentResult = true; - for (int i = 0; i < conditionsSize; i++) { - final Condition condition = (Condition) conditions.get(i); - ConditionMatch conditionMatch = condition.getConditionMatch(hsRequest); - if (conditionMatch != null) { - lastConditionMatch = conditionMatch; - } - boolean conditionMatches = conditionMatch != null; - if (processNextOr) { - currentResult |= conditionMatches; - } else { - // must be and - currentResult &= conditionMatches; - } - processNextOr = condition.isProcessNextOr(); - } - if (!currentResult) { - log.debug("conditions do not match"); - return null; - } else { - log.debug("conditions match"); - } - } - - // set a req attrib in case people want to use it - hsRequest.setAttribute("org.tuckey.web.filters.urlrewrite.RuleMatched", Boolean.TRUE); - - // make sure the setAttributes are handled - int setAttributesSize = setAttributes.size(); - if (setAttributesSize > 0) { - log.trace("setting attributes"); - for (int i = 0; i < setAttributesSize; i++) { - SetAttribute setAttribute = (SetAttribute) setAttributes.get(i); - setAttribute.execute(lastConditionMatch, matcher, hsRequest, hsResponse); - } - } - - // make sure the runs are handled - int runsSize = runs.size(); - RewriteMatch lastRunMatch = null; - if (runsSize > 0) { - log.trace("performing runs"); - for (int i = 0; i < runsSize; i++) { - Run run = (Run) runs.get(i); - lastRunMatch = run.execute(hsRequest, hsResponse, matcher, lastConditionMatch, chain); - } - } - - String replacedTo = null; - if (performToReplacement && to != null) { - SubstitutionContext substitutionContext = new SubstitutionContext(hsRequest, matcher, lastConditionMatch, to); - SubstitutionFilterChain substitutionFilter = ChainedSubstitutionFilters.getDefaultSubstitutionChain(true, toContainsFunction, toContainsVariable, toContainsBackReference, servletContext); - replacedTo = substitutionFilter.substitute(url, substitutionContext); - } - - RuleExecutionOutput ruleExecutionOutput = new RuleExecutionOutput(replacedTo, true, lastRunMatch); - - // check for empty to element (valid when only set's) - if (toEmpty) { - log.debug("'to' is empty, no rewrite, only 'set' and or 'run'"); - return null; - } - - // Check for "no substitution" (-) - if (noSubstitution) { - log.debug("'to' is '-', no substitution, passing through URL"); - ruleExecutionOutput.setNoSubstitution(true); - ruleExecutionOutput.setReplacedUrl(url); - } - - // when match found but need to stop filter chain - if (stopFilterChainOnMatch) { - ruleExecutionOutput.setStopFilterMatch(true); - ruleExecutionOutput.setReplacedUrl(null); - } - // note, the rewritten URL is unchanged if there was no element. - return ruleExecutionOutput; - } - - - public String getDisplayName() { - return null; - } - - - /** - * Will initialise the rule. - * - * @return true on success - */ - public boolean initialise(ServletContext context) { - this.servletContext = context; - // check all the conditions - initialised = true; - boolean ok = true; - for (int i = 0; i < conditions.size(); i++) { - final Condition condition = (Condition) conditions.get(i); - condition.setRule(this); - if (!condition.initialise()) { - ok = false; - } - } - for (int i = 0; i < runs.size(); i++) { - final Run run = (Run) runs.get(i); - if (!run.initialise(context)) { - ok = false; - } - if (run.isFilter()) { - log.debug("rule is a filtering rule"); - filter = true; - } - } - for (int i = 0; i < setAttributes.size(); i++) { - final SetAttribute setAttribute = (SetAttribute) setAttributes.get(i); - if (!setAttribute.initialise()) { - ok = false; - } - } - // make sure default set for matchType - if (!isMatchTypeWildcard()) { - matchType = DEFAULT_MATCH_TYPE; - } - - // compile the from regexp - if (StringUtils.isBlank(from)) { - log.debug("rule's from is blank, setting to " + DEFAULT_RULE_FROM); - from = DEFAULT_RULE_FROM; - } - - try { - if (isMatchTypeWildcard()) { - log.debug("rule match type is wildcard"); - pattern = new WildcardPattern(from); - - } else { - // default is regexp - pattern = new RegexPattern(from, fromCaseSensitive); - } - - } catch (StringMatchingPatternSyntaxException e) { - addError("from (" + from + ") is an invalid expression - " + e.getMessage()); - } - - // set the substitution - if (StringUtils.isBlank(to) && setAttributes.size() == 0 && runs.size() == 0) { - addError("to is not valid because it is blank (it is allowed to be blank when there is a 'set' specified)"); - } else if ("null".equalsIgnoreCase(to)) { - stopFilterChainOnMatch = true; - } else if ("-".equals(to)) { - noSubstitution = true; - } else if (StringUtils.isBlank(to)) { - toEmpty = true; - } else if (!StringUtils.isBlank(to)) { - // check for back refs - if (BackReferenceReplacer.containsBackRef(to)) { - toContainsBackReference = true; - } - // look for vars - if (VariableReplacer.containsVariable(to)) { - toContainsVariable = true; - } - // look for functions - if (FunctionReplacer.containsFunction(to)) { - toContainsFunction = true; - } - } - - if (ok) { - log.debug("loaded rule " + getFullDisplayName()); - } else { - log.debug("failed to load rule"); - } - if (errors.size() > 0) { - ok = false; - } - valid = ok; - return ok; - } - - public boolean isMatchTypeWildcard() { - return MATCH_TYPE_WILDCARD.equalsIgnoreCase(matchType); - } - - public boolean isToContainsBackReference() { - return toContainsBackReference; - } - - public boolean isToContainsVariable() { - return toContainsVariable; - } - - public boolean isToContainsFunction() { - return toContainsFunction; - } - - public String getFullDisplayName() { - return null; - } - - protected void addError(String s) { - errors.add(s); - log.error(s); - } - - /** - * Destroy the rule gracefully. - */ - public void destroy() { - for (int i = 0; i < runs.size(); i++) { - final Run run = (Run) runs.get(i); - run.destroy(); - } - } - - /** - * Will get the contents of the from element. - * - * @return the contents of the from element - */ - public String getFrom() { - return from; - } - - /** - * Will set from, usually called by Digester. - * - * @param from the url to match from - */ - public void setFrom(final String from) { - this.from = from; - } - - /** - * Will set the to, usually called by Digester. - * - * @param to url for redirecting/passing through to - */ - public void setTo(final String to) { - if (!StringUtils.isBlank(to)) { - this.to = to; - } - } - - /** - * Set to type. note, it will default to false. - * - * @param lastStr true or false - */ - public void setToLast(final String lastStr) { - last = "true".equalsIgnoreCase(lastStr); - } - - /** - * Is this rule last?. - * - * @return boolean - */ - public boolean isLast() { - return last; - } - - /** - * Get to. - * - * @return String - */ - public String getTo() { - return to; - } - - /** - * Will get the rule's id. - * - * @return int - */ - public int getId() { - return id; - } - - - /** - * Will get the list of errors. - * - * @return the list of errors - */ - public List getErrors() { - return errors; - } - - /** - * Will add the condition to the List. - * - * @param condition The Condition object to add - */ - public void addCondition(final Condition condition) { - conditions.add(condition); - condition.setId(conditionIdCounter++); - } - - /** - * Will add the run to the List. - * - * @param run The Run object to add - */ - public void addRun(final Run run) { - runs.add(run); - run.setId(runIdCounter++); - } - - /** - * Will add the SetAttribute to the List. - * - * @param setAttribute The SetAttribute object to add - */ - public void addSetAttribute(final SetAttribute setAttribute) { - setAttributes.add(setAttribute); - } - - public List getSetAttributes() { - return setAttributes; - } - - /** - * Will get the List of conditions. - * - * @return the List of Condition objects - */ - public List getConditions() { - return conditions; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getNote() { - return note; - } - - public void setNote(String note) { - this.note = note; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public void setId(int id) { - this.id = id; - } - - public boolean isFromCaseSensitive() { - return fromCaseSensitive; - } - - public void setFromCaseSensitive(boolean fromCaseSensitive) { - this.fromCaseSensitive = fromCaseSensitive; - } - - public List getRuns() { - return runs; - } - - public boolean isValid() { - return valid; - } - - public String getMatchType() { - return matchType; - } - - public void setMatchType(String matchType) { - matchType = StringUtils.trimToNull(matchType); - if (MATCH_TYPE_WILDCARD.equalsIgnoreCase(matchType)) { - this.matchType = MATCH_TYPE_WILDCARD; - } else { - this.matchType = DEFAULT_MATCH_TYPE; - } - } - - public boolean isFilter() { - return filter; - } - - public boolean isNoSubstitution() { - return noSubstitution; - } - - public ServletContext getServletContext() { - return servletContext; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; +import org.tuckey.web.filters.urlrewrite.substitution.BackReferenceReplacer; +import org.tuckey.web.filters.urlrewrite.substitution.ChainedSubstitutionFilters; +import org.tuckey.web.filters.urlrewrite.substitution.FunctionReplacer; +import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionContext; +import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionFilterChain; +import org.tuckey.web.filters.urlrewrite.substitution.VariableReplacer; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.RegexPattern; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingPattern; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingPatternSyntaxException; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; +import org.tuckey.web.filters.urlrewrite.utils.WildcardPattern; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +/** + * Defines a rule that can be run against an incoming request. + * + * @author Paul Tuckey + * @version $Revision: 36 $ $Date: 2006-09-19 18:32:39 +1200 (Tue, 19 Sep 2006) $ + */ +public class RuleBase implements Runnable { + + private static Log log = Log.getLog(RuleBase.class); + + private static String DEFAULT_RULE_FROM = "^(.*)$"; + + protected int id; + + private boolean enabled = true; + + private boolean fromCaseSensitive; + protected boolean initialised; + protected boolean valid; + + protected String name; + private String note; + protected String from; + protected String to; + private boolean toEmpty; + private String matchType; + private boolean last = false; + + private int conditionIdCounter; + private int runIdCounter; + + private StringMatchingPattern pattern; + protected final List errors = new ArrayList(5); + private final List conditions = new ArrayList(5); + private final List runs = new ArrayList(2); + protected final List setAttributes = new ArrayList(2); + private boolean stopFilterChainOnMatch = false; + private boolean noSubstitution = false; + + private boolean toContainsVariable = false; + private boolean toContainsBackReference = false; + private boolean toContainsFunction = false; + + public static final String MATCH_TYPE_WILDCARD = "wildcard"; + public static final String DEFAULT_MATCH_TYPE = "regex"; + + private boolean filter = false; + private ServletContext servletContext; + + /** + * Constructor. + */ + public RuleBase() { + super(); + // empty + } + + /** + * Will run the rule against the uri and perform action required will return false is not matched + * otherwise true. + * + * @param url + * @param hsRequest + * @return String of the rewritten url or the same as the url passed in if no match was made + */ + protected RuleExecutionOutput matchesBase(String url, final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse, RuleChain chain) + throws IOException, ServletException, InvocationTargetException { + // make sure all the conditions match + if (log.isDebugEnabled()) { + String displayName = getDisplayName(); + log.debug(displayName + " run called with " + url); + } + if (!initialised) { + log.debug("not initialised, skipping"); + return null; + } + if (!valid) { + log.debug("not valid, skipping"); + return null; + } + if (!enabled) { + log.debug("not enabled, skipping"); + return null; + } + if (url == null) { + log.debug("url is null (maybe because of a previous match), skipping"); + return null; + } + + StringMatchingMatcher matcher = pattern.matcher(url); + boolean performToReplacement = false; + if (toEmpty || stopFilterChainOnMatch) { + // to is empty this must be an attempt to "set" and/or "run" + if (!matcher.find()) { + if (log.isTraceEnabled()) { + log.trace("no match on \"from\" (to is empty)"); + } + return null; + } + } else { + if (!matcher.find()) { + if (log.isTraceEnabled()) { + log.trace("no match on \"from\" for " + from + " and " + url); + } + return null; + } + if (!toEmpty && !noSubstitution) { + performToReplacement = true; + } + } + if (log.isDebugEnabled()) { + log.debug("matched \"from\""); + } + + int conditionsSize = conditions.size(); + ConditionMatch lastConditionMatch = null; + if (conditionsSize > 0) { + boolean processNextOr = false; + boolean currentResult = true; + for (int i = 0; i < conditionsSize; i++) { + final Condition condition = (Condition) conditions.get(i); + ConditionMatch conditionMatch = condition.getConditionMatch(hsRequest); + if (conditionMatch != null) { + lastConditionMatch = conditionMatch; + } + boolean conditionMatches = conditionMatch != null; + if (processNextOr) { + currentResult |= conditionMatches; + } else { + // must be and + currentResult &= conditionMatches; + } + processNextOr = condition.isProcessNextOr(); + } + if (!currentResult) { + log.debug("conditions do not match"); + return null; + } else { + log.debug("conditions match"); + } + } + + // set a req attrib in case people want to use it + hsRequest.setAttribute("org.tuckey.web.filters.urlrewrite.RuleMatched", Boolean.TRUE); + + // make sure the setAttributes are handled + int setAttributesSize = setAttributes.size(); + if (setAttributesSize > 0) { + log.trace("setting attributes"); + for (int i = 0; i < setAttributesSize; i++) { + SetAttribute setAttribute = (SetAttribute) setAttributes.get(i); + setAttribute.execute(lastConditionMatch, matcher, hsRequest, hsResponse); + } + } + + // make sure the runs are handled + int runsSize = runs.size(); + RewriteMatch lastRunMatch = null; + if (runsSize > 0) { + log.trace("performing runs"); + for (int i = 0; i < runsSize; i++) { + Run run = (Run) runs.get(i); + lastRunMatch = run.execute(hsRequest, hsResponse, matcher, lastConditionMatch, chain); + } + } + + String replacedTo = null; + if (performToReplacement && to != null) { + SubstitutionContext substitutionContext = new SubstitutionContext(hsRequest, matcher, lastConditionMatch, to); + SubstitutionFilterChain substitutionFilter = ChainedSubstitutionFilters.getDefaultSubstitutionChain(true, toContainsFunction, toContainsVariable, toContainsBackReference, servletContext); + replacedTo = substitutionFilter.substitute(url, substitutionContext); + } + + RuleExecutionOutput ruleExecutionOutput = new RuleExecutionOutput(replacedTo, true, lastRunMatch); + + // check for empty to element (valid when only set's) + if (toEmpty) { + log.debug("'to' is empty, no rewrite, only 'set' and or 'run'"); + return null; + } + + // Check for "no substitution" (-) + if (noSubstitution) { + log.debug("'to' is '-', no substitution, passing through URL"); + ruleExecutionOutput.setNoSubstitution(true); + ruleExecutionOutput.setReplacedUrl(url); + } + + // when match found but need to stop filter chain + if (stopFilterChainOnMatch) { + ruleExecutionOutput.setStopFilterMatch(true); + ruleExecutionOutput.setReplacedUrl(null); + } + // note, the rewritten URL is unchanged if there was no element. + return ruleExecutionOutput; + } + + + public String getDisplayName() { + return null; + } + + + /** + * Will initialise the rule. + * + * @return true on success + */ + public boolean initialise(ServletContext context) { + this.servletContext = context; + // check all the conditions + initialised = true; + boolean ok = true; + for (int i = 0; i < conditions.size(); i++) { + final Condition condition = (Condition) conditions.get(i); + condition.setRule(this); + if (!condition.initialise()) { + ok = false; + } + } + for (int i = 0; i < runs.size(); i++) { + final Run run = (Run) runs.get(i); + if (!run.initialise(context)) { + ok = false; + } + if (run.isFilter()) { + log.debug("rule is a filtering rule"); + filter = true; + } + } + for (int i = 0; i < setAttributes.size(); i++) { + final SetAttribute setAttribute = (SetAttribute) setAttributes.get(i); + if (!setAttribute.initialise()) { + ok = false; + } + } + // make sure default set for matchType + if (!isMatchTypeWildcard()) { + matchType = DEFAULT_MATCH_TYPE; + } + + // compile the from regexp + if (StringUtils.isBlank(from)) { + log.debug("rule's from is blank, setting to " + DEFAULT_RULE_FROM); + from = DEFAULT_RULE_FROM; + } + + try { + if (isMatchTypeWildcard()) { + log.debug("rule match type is wildcard"); + pattern = new WildcardPattern(from); + + } else { + // default is regexp + pattern = new RegexPattern(from, fromCaseSensitive); + } + + } catch (StringMatchingPatternSyntaxException e) { + addError("from (" + from + ") is an invalid expression - " + e.getMessage()); + } + + // set the substitution + if (StringUtils.isBlank(to) && setAttributes.size() == 0 && runs.size() == 0) { + addError("to is not valid because it is blank (it is allowed to be blank when there is a 'set' specified)"); + } else if ("null".equalsIgnoreCase(to)) { + stopFilterChainOnMatch = true; + } else if ("-".equals(to)) { + noSubstitution = true; + } else if (StringUtils.isBlank(to)) { + toEmpty = true; + } else if (!StringUtils.isBlank(to)) { + // check for back refs + if (BackReferenceReplacer.containsBackRef(to)) { + toContainsBackReference = true; + } + // look for vars + if (VariableReplacer.containsVariable(to)) { + toContainsVariable = true; + } + // look for functions + if (FunctionReplacer.containsFunction(to)) { + toContainsFunction = true; + } + } + + if (ok) { + log.debug("loaded rule " + getFullDisplayName()); + } else { + log.debug("failed to load rule"); + } + if (errors.size() > 0) { + ok = false; + } + valid = ok; + return ok; + } + + public boolean isMatchTypeWildcard() { + return MATCH_TYPE_WILDCARD.equalsIgnoreCase(matchType); + } + + public boolean isToContainsBackReference() { + return toContainsBackReference; + } + + public boolean isToContainsVariable() { + return toContainsVariable; + } + + public boolean isToContainsFunction() { + return toContainsFunction; + } + + public String getFullDisplayName() { + return null; + } + + protected void addError(String s) { + errors.add(s); + log.error(s); + } + + /** + * Destroy the rule gracefully. + */ + public void destroy() { + for (int i = 0; i < runs.size(); i++) { + final Run run = (Run) runs.get(i); + run.destroy(); + } + } + + /** + * Will get the contents of the from element. + * + * @return the contents of the from element + */ + public String getFrom() { + return from; + } + + /** + * Will set from, usually called by Digester. + * + * @param from the url to match from + */ + public void setFrom(final String from) { + this.from = from; + } + + /** + * Will set the to, usually called by Digester. + * + * @param to url for redirecting/passing through to + */ + public void setTo(final String to) { + if (!StringUtils.isBlank(to)) { + this.to = to; + } + } + + /** + * Set to type. note, it will default to false. + * + * @param lastStr true or false + */ + public void setToLast(final String lastStr) { + last = "true".equalsIgnoreCase(lastStr); + } + + /** + * Is this rule last?. + * + * @return boolean + */ + public boolean isLast() { + return last; + } + + /** + * Get to. + * + * @return String + */ + public String getTo() { + return to; + } + + /** + * Will get the rule's id. + * + * @return int + */ + public int getId() { + return id; + } + + + /** + * Will get the list of errors. + * + * @return the list of errors + */ + public List getErrors() { + return errors; + } + + /** + * Will add the condition to the List. + * + * @param condition The Condition object to add + */ + public void addCondition(final Condition condition) { + conditions.add(condition); + condition.setId(conditionIdCounter++); + } + + /** + * Will add the run to the List. + * + * @param run The Run object to add + */ + public void addRun(final Run run) { + runs.add(run); + run.setId(runIdCounter++); + } + + /** + * Will add the SetAttribute to the List. + * + * @param setAttribute The SetAttribute object to add + */ + public void addSetAttribute(final SetAttribute setAttribute) { + setAttributes.add(setAttribute); + } + + public List getSetAttributes() { + return setAttributes; + } + + /** + * Will get the List of conditions. + * + * @return the List of Condition objects + */ + public List getConditions() { + return conditions; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNote() { + return note; + } + + public void setNote(String note) { + this.note = note; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setId(int id) { + this.id = id; + } + + public boolean isFromCaseSensitive() { + return fromCaseSensitive; + } + + public void setFromCaseSensitive(boolean fromCaseSensitive) { + this.fromCaseSensitive = fromCaseSensitive; + } + + public List getRuns() { + return runs; + } + + public boolean isValid() { + return valid; + } + + public String getMatchType() { + return matchType; + } + + public void setMatchType(String matchType) { + matchType = StringUtils.trimToNull(matchType); + if (MATCH_TYPE_WILDCARD.equalsIgnoreCase(matchType)) { + this.matchType = MATCH_TYPE_WILDCARD; + } else { + this.matchType = DEFAULT_MATCH_TYPE; + } + } + + public boolean isFilter() { + return filter; + } + + public boolean isNoSubstitution() { + return noSubstitution; + } + + public ServletContext getServletContext() { + return servletContext; + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleChain.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleChain.java index ee8be776..0010cd8c 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleChain.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleChain.java @@ -1,180 +1,180 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.Log; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.List; -import java.util.HashMap; - -/** - * Chain of rules. Implemented as a chain so that java rules can filter the request, resposne. - * - * @author Paul Tuckey - * @version $Revision: 33 $ $Date: 2006-09-12 16:41:56 +1200 (Tue, 12 Sep 2006) $ - */ -public class RuleChain implements FilterChain { - - private static Log log = Log.getLog(UrlRewriter.class); - - // if called then call continue to process rules and call chain as if nothing happened - private int ruleIdxToRun = 0; - private RewrittenUrl finalRewrittenRequest = null; - private String finalToUrl; - private List rules; - private boolean requestRewritten; - private boolean rewriteHandled = false; - private boolean responseHandled; - private FilterChain parentChain; - private UrlRewriter urlRewriter; - - public RuleChain(UrlRewriter urlRewriter, String originalUrl, FilterChain parentChain) { - this.finalToUrl = originalUrl; - this.urlRewriter = urlRewriter; - this.rules = urlRewriter.getConf().getRules(); - this.parentChain = parentChain; - } - - private void doRuleProcessing(HttpServletRequest hsRequest, HttpServletResponse hsResponse) - throws IOException, ServletException, InvocationTargetException { - // return to next level up and contniue to process rules - int currentIdx = ruleIdxToRun++; - final Rule rule = (Rule) rules.get(currentIdx); - final RewrittenUrl rewrittenUrl = rule.matches(finalToUrl, hsRequest, hsResponse, this); - - // if this is a filter don't process any more rules, only process them via doFilter - if (rule.isFilter()) { - dontProcessAnyMoreRules(); - } - if (rewrittenUrl != null) { - log.trace("got a rewritten url"); - // if doFilter was used and final rewritten url is null - finalRewrittenRequest = rewrittenUrl; - finalToUrl = rewrittenUrl.getTarget(); - if (rule.isLast()) { - log.debug("rule is last"); - // there can be no more matches on this request - dontProcessAnyMoreRules(); - } - } - // rule terminated and doFilter wasn't called - // if doFilter wasn't called then either execute the returning object or assume run has handled it - } - - private void dontProcessAnyMoreRules() { - ruleIdxToRun = rules.size(); - } - - public RewrittenUrl getFinalRewrittenRequest() { - return finalRewrittenRequest; - } - - public boolean isResponseHandled() { - return responseHandled; - } - - public void doFilter(ServletRequest request, ServletResponse response) - throws IOException, ServletException { - try { - process(request, response); - handleRewrite(request, response); - } catch (InvocationTargetException e) { - handleExcep(request, response, e); - } - } - - private void handleExcep(ServletRequest request, ServletResponse response, InvocationTargetException e) - throws IOException, ServletException { - dontProcessAnyMoreRules(); - finalRewrittenRequest = urlRewriter.handleInvocationTargetException((HttpServletRequest) request, - (HttpServletResponse) response, e); - handleRewrite(request, response); - } - - public void process(ServletRequest request, ServletResponse response) - throws IOException, ServletException, InvocationTargetException { - while (ruleIdxToRun < rules.size()) { - doRuleProcessing((HttpServletRequest) request, (HttpServletResponse) response); - } - } - - public void doRules(ServletRequest request, ServletResponse response) - throws IOException, ServletException { - try { - process(request, response); - handleRewrite(request, response); - } catch (InvocationTargetException e) { - handleExcep(request, response, e); - - } catch (ServletException e) { - if ( e.getCause() instanceof InvocationTargetException ) { - handleExcep(request, response, (InvocationTargetException) e.getCause()); - } else { - throw e; - } - } - } - - private void handleRewrite(ServletRequest request, ServletResponse response) throws ServletException, IOException { - if (rewriteHandled) return; - rewriteHandled = true; - // wrap the request if necessary to allow overriding of request parameters and method - if ( response instanceof UrlRewriteWrappedResponse && request instanceof HttpServletRequest) { - HashMap overiddenRequestParameters = ((UrlRewriteWrappedResponse) response).getOverridenRequestParameters(); - String overiddenMethod = ((UrlRewriteWrappedResponse) response).getOverridenMethod(); - if ( overiddenRequestParameters != null || overiddenMethod != null) { - request = new UrlRewriteWrappedRequest((HttpServletRequest) request, overiddenRequestParameters, overiddenMethod); - } - } - if (finalRewrittenRequest != null) { - responseHandled = true; - requestRewritten = finalRewrittenRequest.doRewrite((HttpServletRequest) request, - (HttpServletResponse) response, parentChain); - } - if (! requestRewritten) { - responseHandled = true; - parentChain.doFilter(request, response); - } - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.Log; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.HashMap; + +/** + * Chain of rules. Implemented as a chain so that java rules can filter the request, resposne. + * + * @author Paul Tuckey + * @version $Revision: 33 $ $Date: 2006-09-12 16:41:56 +1200 (Tue, 12 Sep 2006) $ + */ +public class RuleChain implements FilterChain { + + private static Log log = Log.getLog(UrlRewriter.class); + + // if called then call continue to process rules and call chain as if nothing happened + private int ruleIdxToRun = 0; + private RewrittenUrl finalRewrittenRequest = null; + private String finalToUrl; + private List rules; + private boolean requestRewritten; + private boolean rewriteHandled = false; + private boolean responseHandled; + private FilterChain parentChain; + private UrlRewriter urlRewriter; + + public RuleChain(UrlRewriter urlRewriter, String originalUrl, FilterChain parentChain) { + this.finalToUrl = originalUrl; + this.urlRewriter = urlRewriter; + this.rules = urlRewriter.getConf().getRules(); + this.parentChain = parentChain; + } + + private void doRuleProcessing(HttpServletRequest hsRequest, HttpServletResponse hsResponse) + throws IOException, ServletException, InvocationTargetException { + // return to next level up and contniue to process rules + int currentIdx = ruleIdxToRun++; + final Rule rule = (Rule) rules.get(currentIdx); + final RewrittenUrl rewrittenUrl = rule.matches(finalToUrl, hsRequest, hsResponse, this); + + // if this is a filter don't process any more rules, only process them via doFilter + if (rule.isFilter()) { + dontProcessAnyMoreRules(); + } + if (rewrittenUrl != null) { + log.trace("got a rewritten url"); + // if doFilter was used and final rewritten url is null + finalRewrittenRequest = rewrittenUrl; + finalToUrl = rewrittenUrl.getTarget(); + if (rule.isLast()) { + log.debug("rule is last"); + // there can be no more matches on this request + dontProcessAnyMoreRules(); + } + } + // rule terminated and doFilter wasn't called + // if doFilter wasn't called then either execute the returning object or assume run has handled it + } + + private void dontProcessAnyMoreRules() { + ruleIdxToRun = rules.size(); + } + + public RewrittenUrl getFinalRewrittenRequest() { + return finalRewrittenRequest; + } + + public boolean isResponseHandled() { + return responseHandled; + } + + public void doFilter(ServletRequest request, ServletResponse response) + throws IOException, ServletException { + try { + process(request, response); + handleRewrite(request, response); + } catch (InvocationTargetException e) { + handleExcep(request, response, e); + } + } + + private void handleExcep(ServletRequest request, ServletResponse response, InvocationTargetException e) + throws IOException, ServletException { + dontProcessAnyMoreRules(); + finalRewrittenRequest = urlRewriter.handleInvocationTargetException((HttpServletRequest) request, + (HttpServletResponse) response, e); + handleRewrite(request, response); + } + + public void process(ServletRequest request, ServletResponse response) + throws IOException, ServletException, InvocationTargetException { + while (ruleIdxToRun < rules.size()) { + doRuleProcessing((HttpServletRequest) request, (HttpServletResponse) response); + } + } + + public void doRules(ServletRequest request, ServletResponse response) + throws IOException, ServletException { + try { + process(request, response); + handleRewrite(request, response); + } catch (InvocationTargetException e) { + handleExcep(request, response, e); + + } catch (ServletException e) { + if ( e.getCause() instanceof InvocationTargetException ) { + handleExcep(request, response, (InvocationTargetException) e.getCause()); + } else { + throw e; + } + } + } + + private void handleRewrite(ServletRequest request, ServletResponse response) throws ServletException, IOException { + if (rewriteHandled) return; + rewriteHandled = true; + // wrap the request if necessary to allow overriding of request parameters and method + if ( response instanceof UrlRewriteWrappedResponse && request instanceof HttpServletRequest) { + HashMap overiddenRequestParameters = ((UrlRewriteWrappedResponse) response).getOverridenRequestParameters(); + String overiddenMethod = ((UrlRewriteWrappedResponse) response).getOverridenMethod(); + if ( overiddenRequestParameters != null || overiddenMethod != null) { + request = new UrlRewriteWrappedRequest((HttpServletRequest) request, overiddenRequestParameters, overiddenMethod); + } + } + if (finalRewrittenRequest != null) { + responseHandled = true; + requestRewritten = finalRewrittenRequest.doRewrite((HttpServletRequest) request, + (HttpServletResponse) response, parentChain); + } + if (! requestRewritten) { + responseHandled = true; + parentChain.doFilter(request, response); + } + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleExecutionOutput.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleExecutionOutput.java index a5f9b7d4..9e2e5f7c 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleExecutionOutput.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleExecutionOutput.java @@ -1,195 +1,195 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import jakarta.servlet.ServletContext; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; -import org.tuckey.web.filters.urlrewrite.utils.Log; - - -public class RuleExecutionOutput { - - private static Log log = Log.getLog(RuleExecutionOutput.class); - - private String replacedUrl; - private ServletContext replacedUrlContext = null; - private boolean ruleMatched = false; - private boolean stopFilterMatch = false; - private boolean noSubstitution = false; - private boolean dropCookies = true; - private RewriteMatch rewriteMatch; - - /** - * Will perform the action defined by the rule ie, redirect or passthrough. - * - * @param ruleExecutionOutput - */ - public static RewrittenUrl getRewritenUrl(short toType, boolean encodeToUrl, RuleExecutionOutput ruleExecutionOutput) { - - NormalRewrittenUrl rewrittenRequest = new NormalRewrittenUrl(ruleExecutionOutput); - String toUrl = ruleExecutionOutput.getReplacedUrl(); - - if (ruleExecutionOutput.isNoSubstitution()) { - if (log.isDebugEnabled()) { - log.debug("needs no substitution"); - } - } else if (toType == NormalRule.TO_TYPE_REDIRECT) { - if (log.isDebugEnabled()) { - log.debug("needs to be redirected to " + toUrl); - } - rewrittenRequest.setRedirect(true); - - } else if (toType == NormalRule.TO_TYPE_PERMANENT_REDIRECT) { - if (log.isDebugEnabled()) { - log.debug("needs to be permanentely redirected to " + toUrl); - } - rewrittenRequest.setPermanentRedirect(true); - - } else if (toType == NormalRule.TO_TYPE_TEMPORARY_REDIRECT) { - if (log.isDebugEnabled()) { - log.debug("needs to be temporarily redirected to " + toUrl); - } - rewrittenRequest.setTemporaryRedirect(true); - - } else if (toType == NormalRule.TO_TYPE_308_PERMANENT_REDIRECT) { - if (log.isDebugEnabled()) { - log.debug("needs to be permanently redirected (with response code 308) to " + toUrl); - } - rewrittenRequest.set308PermanentRedirect(true); - - } else if (toType == NormalRule.TO_TYPE_307_TEMPORARY_REDIRECT) { - if (log.isDebugEnabled()) { - log.debug("needs to be temporarily redirected (with response code 307) to " + toUrl); - } - rewrittenRequest.set307TemporaryRedirect(true); - - } else if (toType == NormalRule.TO_TYPE_PRE_INCLUDE) { - if (log.isDebugEnabled()) { - log.debug(toUrl + " needs to be pre included"); - } - rewrittenRequest.setPreInclude(true); - - } else if (toType == NormalRule.TO_TYPE_POST_INCLUDE) { - if (log.isDebugEnabled()) { - log.debug(toUrl + " needs to be post included"); - } - rewrittenRequest.setPostInclude(true); - - } else if (toType == NormalRule.TO_TYPE_FORWARD) { - - // pass the request to the "to" url - if (log.isDebugEnabled()) { - log.debug("needs to be forwarded to " + toUrl); - } - rewrittenRequest.setForward(true); - } else if (toType == NormalRule.TO_TYPE_PROXY) { - // pass the request to the "to" url - if (log.isDebugEnabled()) { - log.debug("needs to be proxied from " + toUrl); - } - rewrittenRequest.setProxy(true); - } - - if (encodeToUrl) { - rewrittenRequest.setEncode(true); - } else { - rewrittenRequest.setEncode(false); - } - - return rewrittenRequest; - } - - public RuleExecutionOutput(String replacedUrl, boolean ruleMatched, RewriteMatch lastRunMatch) { - this.replacedUrl = replacedUrl; - this.ruleMatched = ruleMatched; - this.rewriteMatch = lastRunMatch; - } - - public String getReplacedUrl() { - return replacedUrl; - } - - public boolean isRuleMatched() { - return ruleMatched; - } - - public boolean isStopFilterMatch() { - return stopFilterMatch; - } - - public void setStopFilterMatch(boolean stopFilterMatch) { - this.stopFilterMatch = stopFilterMatch; - } - - public void setReplacedUrl(String replacedUrl) { - this.replacedUrl = replacedUrl; - } - - public RewriteMatch getRewriteMatch() { - return rewriteMatch; - } - - /** - * @return the replacedUrlContext - */ - public ServletContext getReplacedUrlContext() { - return replacedUrlContext; - } - - /** - * @param replacedUrlContext the replacedUrlContext to set - */ - public void setReplacedUrlContext(ServletContext replacedUrlContext) { - this.replacedUrlContext = replacedUrlContext; - } - - public boolean isNoSubstitution() { - return noSubstitution; - } - - public void setNoSubstitution(boolean noSubstitution) { - this.noSubstitution = noSubstitution; - } - - public void setDropCookies(boolean forwardCookies) { - this.dropCookies = forwardCookies; - } - - public boolean shouldDropCookies() { - return dropCookies; - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import jakarta.servlet.ServletContext; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; +import org.tuckey.web.filters.urlrewrite.utils.Log; + + +public class RuleExecutionOutput { + + private static Log log = Log.getLog(RuleExecutionOutput.class); + + private String replacedUrl; + private ServletContext replacedUrlContext = null; + private boolean ruleMatched = false; + private boolean stopFilterMatch = false; + private boolean noSubstitution = false; + private boolean dropCookies = true; + private RewriteMatch rewriteMatch; + + /** + * Will perform the action defined by the rule ie, redirect or passthrough. + * + * @param ruleExecutionOutput + */ + public static RewrittenUrl getRewritenUrl(short toType, boolean encodeToUrl, RuleExecutionOutput ruleExecutionOutput) { + + NormalRewrittenUrl rewrittenRequest = new NormalRewrittenUrl(ruleExecutionOutput); + String toUrl = ruleExecutionOutput.getReplacedUrl(); + + if (ruleExecutionOutput.isNoSubstitution()) { + if (log.isDebugEnabled()) { + log.debug("needs no substitution"); + } + } else if (toType == NormalRule.TO_TYPE_REDIRECT) { + if (log.isDebugEnabled()) { + log.debug("needs to be redirected to " + toUrl); + } + rewrittenRequest.setRedirect(true); + + } else if (toType == NormalRule.TO_TYPE_PERMANENT_REDIRECT) { + if (log.isDebugEnabled()) { + log.debug("needs to be permanentely redirected to " + toUrl); + } + rewrittenRequest.setPermanentRedirect(true); + + } else if (toType == NormalRule.TO_TYPE_TEMPORARY_REDIRECT) { + if (log.isDebugEnabled()) { + log.debug("needs to be temporarily redirected to " + toUrl); + } + rewrittenRequest.setTemporaryRedirect(true); + + } else if (toType == NormalRule.TO_TYPE_308_PERMANENT_REDIRECT) { + if (log.isDebugEnabled()) { + log.debug("needs to be permanently redirected (with response code 308) to " + toUrl); + } + rewrittenRequest.set308PermanentRedirect(true); + + } else if (toType == NormalRule.TO_TYPE_307_TEMPORARY_REDIRECT) { + if (log.isDebugEnabled()) { + log.debug("needs to be temporarily redirected (with response code 307) to " + toUrl); + } + rewrittenRequest.set307TemporaryRedirect(true); + + } else if (toType == NormalRule.TO_TYPE_PRE_INCLUDE) { + if (log.isDebugEnabled()) { + log.debug(toUrl + " needs to be pre included"); + } + rewrittenRequest.setPreInclude(true); + + } else if (toType == NormalRule.TO_TYPE_POST_INCLUDE) { + if (log.isDebugEnabled()) { + log.debug(toUrl + " needs to be post included"); + } + rewrittenRequest.setPostInclude(true); + + } else if (toType == NormalRule.TO_TYPE_FORWARD) { + + // pass the request to the "to" url + if (log.isDebugEnabled()) { + log.debug("needs to be forwarded to " + toUrl); + } + rewrittenRequest.setForward(true); + } else if (toType == NormalRule.TO_TYPE_PROXY) { + // pass the request to the "to" url + if (log.isDebugEnabled()) { + log.debug("needs to be proxied from " + toUrl); + } + rewrittenRequest.setProxy(true); + } + + if (encodeToUrl) { + rewrittenRequest.setEncode(true); + } else { + rewrittenRequest.setEncode(false); + } + + return rewrittenRequest; + } + + public RuleExecutionOutput(String replacedUrl, boolean ruleMatched, RewriteMatch lastRunMatch) { + this.replacedUrl = replacedUrl; + this.ruleMatched = ruleMatched; + this.rewriteMatch = lastRunMatch; + } + + public String getReplacedUrl() { + return replacedUrl; + } + + public boolean isRuleMatched() { + return ruleMatched; + } + + public boolean isStopFilterMatch() { + return stopFilterMatch; + } + + public void setStopFilterMatch(boolean stopFilterMatch) { + this.stopFilterMatch = stopFilterMatch; + } + + public void setReplacedUrl(String replacedUrl) { + this.replacedUrl = replacedUrl; + } + + public RewriteMatch getRewriteMatch() { + return rewriteMatch; + } + + /** + * @return the replacedUrlContext + */ + public ServletContext getReplacedUrlContext() { + return replacedUrlContext; + } + + /** + * @param replacedUrlContext the replacedUrlContext to set + */ + public void setReplacedUrlContext(ServletContext replacedUrlContext) { + this.replacedUrlContext = replacedUrlContext; + } + + public boolean isNoSubstitution() { + return noSubstitution; + } + + public void setNoSubstitution(boolean noSubstitution) { + this.noSubstitution = noSubstitution; + } + + public void setDropCookies(boolean forwardCookies) { + this.dropCookies = forwardCookies; + } + + public boolean shouldDropCookies() { + return dropCookies; + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Run.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Run.java index b8b020db..1c74647f 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Run.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Run.java @@ -1,716 +1,716 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; -import org.tuckey.web.filters.urlrewrite.utils.TypeUtils; -import org.tuckey.web.filters.urlrewrite.json.JsonRewriteMatch; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Hashtable; - - -/** - * Defines a run element, the ability to run a methodStr - * (eg, xx(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)) - * - * @author Paul Tuckey - * @version $Revision: 43 $ $Date: 2006-10-31 17:29:59 +1300 (Tue, 31 Oct 2006) $ - */ -public class Run { - - private static Log log = Log.getLog(Run.class); - - /** - * Weather or not the user wants the classStr created for each run. - */ - private boolean newEachTime = false; - - private boolean jsonHandler = false; - - private String classStr; - - private static final String DEAULT_METHOD_STR = "run"; - private String methodStr = DEAULT_METHOD_STR; - - /** - * Used to identify the condition. - */ - private int id = 0; - - private String error = null; - - private boolean valid = false; - private boolean initialised = false; - - /** - * The instance of the classStr to run. Note, will be null if newEachTime is true. - */ - private Object runClassInstance; - - /** - * handles to the methods we are going to run. - */ - private Constructor runConstructor; - private Method initMethod; - private Method filterInitMethod; - private Method runMethod; - private Class[] runMethodParams; - private String[] runMethodParamNames; - private boolean runMethodUseDefaultParams = true; - private Method destroyMethod; - - /** - * The config that we pass to the objectwe are trying to run. - */ - private RunConfig runServletConfig; - - private Hashtable initParams = new Hashtable(); - - private static boolean loadClass = true; - - private static Class[][] runMethodPossibleSignatures = { - {ServletRequest.class, ServletResponse.class}, - {ServletRequest.class}, - {ServletResponse.class}, - {HttpServletRequest.class, HttpServletResponse.class}, - {HttpServletRequest.class}, - {HttpServletResponse.class} - }; - private boolean filter = false; - - /** - * @see #initialise(ServletContext,Class) initialise - */ - public boolean initialise(ServletContext context) { - return initialise(context, null); - } - - /** - * Initialise the Run, this will check specified classStr, constructor and methodStr exist. - */ - public boolean initialise(ServletContext context, Class extraParam) { - log.debug("initialising run"); - runServletConfig = new RunConfig(context, initParams); - initialised = true; - valid = false; - if (StringUtils.isBlank(classStr)) { - setError("cannot initialise run " + id + " value is empty"); - return valid; - } - if (methodStr == null) { - methodStr = DEAULT_METHOD_STR; - } - log.debug("methodStr: " + methodStr); - - String rawMethodStr = methodStr; - int bkStart = rawMethodStr.indexOf('('); - int bkEnd = rawMethodStr.indexOf(')'); - if (bkStart != -1 && bkEnd != -1 && (bkEnd - bkStart) > 0) { - runMethodUseDefaultParams = false; - // set method str back to just method name - methodStr = rawMethodStr.substring(0, bkStart); - // get the list of params ie, "String name, int id" - String paramsList = rawMethodStr.substring(bkStart + 1, bkEnd); - paramsList = StringUtils.trimToNull(paramsList); - if (paramsList != null) { - String[] params = paramsList.split(","); - // validate and clean the incoming params list - Class[] paramClasses = new Class[params.length]; - String[] paramNames = new String[params.length]; - for (int i = 0; i < params.length; i++) { - String param = StringUtils.trimToNull(params[i]); - if (param == null) continue; - if (param.contains(" ")) { - String paramName = StringUtils.trimToNull(param.substring(param.indexOf(" "))); - if (paramName != null) { - log.debug("param name: " + paramName); - paramNames[i] = paramName; - } - param = param.substring(0, param.indexOf(' ')); - } - Class clazz = parseClass(param); - if (clazz == null) return valid; - paramClasses[i] = clazz; - } - runMethodParams = paramClasses; - runMethodParamNames = paramNames; - } - } - if (loadClass) { - prepareRunObject(extraParam); - } else { - valid = true; - } - return valid; - } - - /** - * Turns a class or language keyword name into the Class object, works with short names, ie, L - Long. - *

- * boolean Z - * byte B - * char C - * class or interface Lclassname; - * double D - * float F - * int I - * long J - * short S - * - * @see Class - */ - private Class parseClass(String param) { - // do shortcuts - Class paramClass = TypeUtils.findClass(param); - - if ("javax.servlet.FilterChain".equalsIgnoreCase(param) || "FilterChain".equalsIgnoreCase(param) - || "chain".equalsIgnoreCase(param)) { - filter = true; - paramClass = FilterChain.class; - } - - if (loadClass) { - if (paramClass == null) { - try { - paramClass = Class.forName(param); - } catch (ClassNotFoundException e) { - setError("could not find " + param + " got a " + e.toString(), e); - return null; - } catch (NoClassDefFoundError e) { - setError("could not find " + param + " got a " + e.toString(), e); - return null; - } - } - if (paramClass == null) { - setError("could not find class of type " + param); - return null; - } - } - if (log.isDebugEnabled()) { - log.debug("parseClass found class " + paramClass + " for " + param); - } - return paramClass; - } - - /** - * Prepare the object for running by constructing and setting up method handles. - */ - private void prepareRunObject(Class extraParam) { - if (log.isDebugEnabled()) { - log.debug("looking for class " + classStr); - } - Class runClass; - try { - runClass = Class.forName(classStr); - } catch (ClassNotFoundException e) { - setError("could not find " + classStr + " got a " + e.toString(), e); - return; - } catch (NoClassDefFoundError e) { - setError("could not find " + classStr + " got a " + e.toString(), e); - return; - } - try { - runConstructor = runClass.getConstructor((Class[]) null); - } catch (NoSuchMethodException e) { - setError("could not get constructor for " + classStr, e); - return; - } - - if (!runMethodUseDefaultParams) { - if (log.isDebugEnabled()) { - log.debug("looking for " + methodStr + " with specific params"); - } - try { - runMethod = runClass.getMethod(methodStr, runMethodParams); - } catch (NoSuchMethodException e) { - // do nothing - if (log.isDebugEnabled()) { - log.debug(methodStr + " not found"); - } - } - } else { - if (log.isDebugEnabled()) { - log.debug("looking for " + methodStr + "(ServletRequest, ServletResponse)"); - } - for (int i = 0; i < runMethodPossibleSignatures.length; i++) { - Class[] runMethodPossibleSignature = runMethodPossibleSignatures[i]; - if (extraParam != null) { - if (runMethodPossibleSignature.length == 2) { - runMethodPossibleSignature = new Class[]{runMethodPossibleSignature[0], - runMethodPossibleSignature[1], extraParam}; - } - if (runMethodPossibleSignature.length == 1) { - runMethodPossibleSignature = new Class[]{runMethodPossibleSignature[0], extraParam}; - } - } - if (log.isDebugEnabled()) { - StringBuffer possible = new StringBuffer(); - for (int j = 0; j < runMethodPossibleSignature.length; j++) { - if (j > 0) possible.append(","); - possible.append(runMethodPossibleSignature[j].getName()); - } - log.debug("looking for " + methodStr + "(" + possible + ")"); - } - try { - runMethod = runClass.getMethod(methodStr, runMethodPossibleSignature); - runMethodParams = runMethodPossibleSignature; - break; - - } catch (NoSuchMethodException e) { - // do nothing except be paranoid about resetting runMethodParams - runMethodParams = null; - } - } - if (runMethod == null) { - setError("could not find method with the name " + methodStr + " on " + classStr); - return; - } - } - - Method[] methods = runClass.getMethods(); - for (int i = 0; i < methods.length; i++) { - Method method = methods[i]; - if ("destroy".equals(method.getName()) && method.getParameterTypes().length == 0) { - log.debug("found destroy methodStr"); - destroyMethod = method; - } - if ("init".equals(method.getName()) && method.getParameterTypes().length == 1 && - ServletConfig.class.getName().equals(method.getParameterTypes()[0].getName())) { - log.debug("found init methodStr"); - initMethod = method; - } - if ("init".equals(method.getName()) && method.getParameterTypes().length == 1 && - FilterConfig.class.getName().equals(method.getParameterTypes()[0].getName())) { - log.debug("found filter init methodStr"); - filterInitMethod = method; - } - if (initMethod != null && destroyMethod != null) break; - } - if (!newEachTime) { - runClassInstance = fetchNewInstance(); - } - valid = true; - - } - - private void invokeDestroy(Object runClassInstanceToDestroy) { - if (runClassInstanceToDestroy != null && destroyMethod != null) { - if (log.isDebugEnabled()) { - log.debug("running " + classStr + ".destroy()"); - } - try { - destroyMethod.invoke(runClassInstanceToDestroy, (Object[]) null); - } catch (IllegalAccessException e) { - logInvokeException("destroy()", e); - } catch (InvocationTargetException e) { - logInvokeException("destroy()", e); - } - } - } - - /** - * Invokes the run method. - *

- * Exceptions at invocation time are either rethrown as a ServletException or as thr original exception if we can - * manage to do it. - *

- * We don't log exceptions here, the container can do that. - */ - private RewriteMatch invokeRunMethod(Object classInstanceToRun, HttpServletRequest httpServletRequest, - HttpServletResponse httpServletResponse, FilterChain chain, Object[] matchObjs) - throws ServletException, InvocationTargetException { - if (log.isDebugEnabled()) { - log.debug("running " + classStr + "." + getMethodSignature() + " "); - } - if (classInstanceToRun == null || runMethod == null) return null; - RewriteMatch returned = null; - Object[] params = null; - - if (runMethodParams != null && runMethodParams.length > 0) { - params = new Object[runMethodParams.length]; - int paramMatchCounter = 0; - for (int i = 0; i < runMethodParams.length; i++) { - Class runMethodParam = runMethodParams[i]; - String runMethodParamName = null; - if (runMethodParamNames != null && runMethodParamNames.length > i) { - runMethodParamName = runMethodParamNames[i]; - } - Object param; - - if (runMethodParamName != null) { - log.debug("need parameter from request called " + runMethodParamName); - Object matchObj = httpServletRequest.getParameter(runMethodParamName); - param = TypeUtils.getConvertedParam(runMethodParam, matchObj); - - } else if (runMethodParam.isAssignableFrom(HttpServletRequest.class)) { - param = httpServletRequest; - - } else if (runMethodParam.isAssignableFrom(HttpServletResponse.class)) { - param = httpServletResponse; - - } else if (runMethodParam.isAssignableFrom(FilterChain.class)) { - param = chain; - - } else { - Object matchObj = null; - if (matchObjs != null && matchObjs.length > paramMatchCounter) { - matchObj = matchObjs[paramMatchCounter]; - } - param = TypeUtils.getConvertedParam(runMethodParam, matchObj); - paramMatchCounter++; - } - - params[i] = param; - if (log.isDebugEnabled()) { - log.debug("argument " + i + " (" + runMethodParam.getName() + "): " + param); - } - } - } - - try { - Object objReturned = runMethod.invoke(classInstanceToRun, (Object[]) params); - if ( jsonHandler ) { - returned = new JsonRewriteMatch(objReturned); - } else if (objReturned != null && objReturned instanceof RewriteMatch) { - // if we get a rewriteMatch object then return it for execution later - returned = (RewriteMatch) objReturned; - } - - } catch (IllegalAccessException e) { - if (log.isDebugEnabled()) log.debug(e); - throw new ServletException(e); - - } - return returned; - } - - - /** - * Run the underlying destroy methodStr on the run classStr. - */ - public void destroy() { - initialised = false; - valid = false; - - invokeDestroy(runClassInstance); - - // be paranoid and clean up all hooks to users classStr - destroyMethod = null; - runMethod = null; - initMethod = null; - filterInitMethod = null; - runServletConfig = null; - runConstructor = null; - runClassInstance = null; - - methodStr = null; - classStr = null; - error = null; - } - - /** - * @deprecated see #execute(HttpServletRequest,HttpServletResponse,Object[],FilterChain) - */ - public RewriteMatch execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws IOException, ServletException, InvocationTargetException { - return execute(httpServletRequest, httpServletResponse, null, null); - } - - public RewriteMatch execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, - StringMatchingMatcher matcher, ConditionMatch conditionMatch, FilterChain chain) - throws IOException, ServletException, InvocationTargetException { - int matches = 0; - int condMatches = 0; - if (matcher != null && matcher.isFound()) { - matches = matcher.groupCount(); - } - if (conditionMatch != null) { - StringMatchingMatcher condMatcher = conditionMatch.getMatcher(); - if (condMatcher != null && condMatcher.isFound()) { - condMatches = condMatcher.groupCount(); - } - } - String[] allMatches = null; - if ((matches + condMatches) > 0) { - allMatches = new String[matches + condMatches]; - if (matcher != null && matches > 0) { - for (int i = 0; i < matches; i++) { - allMatches[i] = matcher.group(i + 1); // note, good groups start from 1 - } - } - if (conditionMatch != null && condMatches > 0) { - for (int i = 0; i < condMatches; i++) { - allMatches[i] = conditionMatch.getMatcher().group(i); - } - } - } - return execute(httpServletRequest, httpServletResponse, allMatches, chain); - } - - /** - * Will invoke the instance created in initialise. - * - * @param httpServletRequest - * @param httpServletResponse - */ - public RewriteMatch execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, - Throwable throwable) - throws IOException, ServletException, InvocationTargetException { - Object[] params = new Object[]{throwable}; - return execute(httpServletRequest, httpServletResponse, params, null); - } - - /** - * @deprecated use execute(HttpServletRequest, HttpServletResponse, Object[], FilterChain) - */ - public RewriteMatch execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, - Object[] params) throws IOException, ServletException, InvocationTargetException { - return execute(httpServletRequest, httpServletResponse, params, null); - } - - public RewriteMatch execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, - Object[] params, FilterChain chain) - throws IOException, ServletException, InvocationTargetException { - if (!initialised) { - log.debug("not initialised skipping"); - return null; - } - if (!valid) { - log.debug("not valid skipping"); - return null; - } - RewriteMatch returned; - try { - if (newEachTime) { - Object newRunClassInstance = fetchNewInstance(); - returned = invokeRunMethod(newRunClassInstance, httpServletRequest, httpServletResponse, chain, params); - invokeDestroy(newRunClassInstance); - } else { - returned = invokeRunMethod(runClassInstance, httpServletRequest, httpServletResponse, chain, params); - } - } catch (ServletException e) { - httpServletRequest.setAttribute("javax.servlet.error.exception", e); - throw e; - } - return returned; - } - - private void logInvokeException(String methodStr, Exception e) { - Throwable cause = e.getCause(); - if (cause == null) { - setError("when invoking " + methodStr + " on " + classStr - + " got an " + e.toString(), e); - } else { - setError("when invoking " + methodStr + " on " + classStr - + " got an " + e.toString() + " caused by " + cause.toString(), cause); - } - } - - /** - * Get a new instance of the classStr we want to run and init if required. - * - * @return the new instance - */ - private Object fetchNewInstance() { - Object obj; - log.debug("getting new instance of " + classStr); - try { - obj = runConstructor.newInstance((Object[]) null); - } catch (InstantiationException e) { - logInvokeException("constructor", e); - return null; - } catch (IllegalAccessException e) { - logInvokeException("constructor", e); - return null; - } catch (InvocationTargetException e) { - logInvokeException("constructor", e); - return null; - } - if (initMethod != null) { - log.debug("about to run init(ServletConfig) on " + classStr); - Object[] args = new Object[1]; - args[0] = runServletConfig; - try { - initMethod.invoke(obj, args); - } catch (IllegalAccessException e) { - logInvokeException("init(ServletConfig)", e); - return null; - } catch (InvocationTargetException e) { - logInvokeException("init(ServletConfig)", e); - return null; - } - } - if (filterInitMethod != null) { - log.debug("about to run init(FilterConfig) on " + classStr); - Object[] args = new Object[1]; - args[0] = runServletConfig; - try { - filterInitMethod.invoke(obj, args); - } catch (IllegalAccessException e) { - logInvokeException("init(FilterConfig)", e); - return null; - } catch (InvocationTargetException e) { - logInvokeException("init(FilterConfig)", e); - return null; - } - } - return obj; - } - - public String getError() { - return error; - } - - public void setId(int id) { - this.id = id; - } - - public int getId() { - return id; - } - - public boolean isValid() { - return valid; - } - - public boolean isInitialised() { - return initialised; - } - - /** - * The name of the classStr that will be run for each rule match. - * - * @return String eg, org.tuckey.YellowObject - */ - public String getClassStr() { - return classStr; - } - - /** - * The name of the methodStr that will be run for each rule match. - * - * @return String eg, setDate - */ - public String getMethodStr() { - return methodStr; - } - - /** - * The name of the method signature ie, setDate(java.util.Date, int). Includes fully qualified object names - * for paramters. - */ - public String getMethodSignature() { - return TypeUtils.getMethodSignature(methodStr, runMethodParams); - } - - - public boolean isNewEachTime() { - return newEachTime; - } - - public void setNewEachTime(boolean newEachTime) { - this.newEachTime = newEachTime; - } - - /** - * Gets a handle on the instance of the class run is running. - *

- * If newEachTime is set to true this will always return null. - */ - public Object getRunClassInstance() { - return runClassInstance; - } - - public void addInitParam(String name, String value) { - if (name != null) { - initParams.put(name, value); - } - } - - public String getInitParam(String paramName) { - return (String) initParams.get(paramName); - } - - public void setClassStr(String classStr) { - this.classStr = classStr; - } - - public void setMethodStr(String methodStr) { - this.methodStr = methodStr; - } - - public static void setLoadClass(boolean loadClass) { - Run.loadClass = loadClass; - } - - public void setError(String error, Throwable t) { - this.error = error; - log.error(error, t); - } - - public void setError(String error) { - this.error = error; - log.error(error); - } - - public String getDisplayName() { - return "Run " + id; - } - - public boolean isFilter() { - return filter; - } - - public void setJsonHandler(boolean jsonHandler) { - this.jsonHandler = jsonHandler; - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; +import org.tuckey.web.filters.urlrewrite.utils.TypeUtils; +import org.tuckey.web.filters.urlrewrite.json.JsonRewriteMatch; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Hashtable; + + +/** + * Defines a run element, the ability to run a methodStr + * (eg, xx(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)) + * + * @author Paul Tuckey + * @version $Revision: 43 $ $Date: 2006-10-31 17:29:59 +1300 (Tue, 31 Oct 2006) $ + */ +public class Run { + + private static Log log = Log.getLog(Run.class); + + /** + * Weather or not the user wants the classStr created for each run. + */ + private boolean newEachTime = false; + + private boolean jsonHandler = false; + + private String classStr; + + private static final String DEAULT_METHOD_STR = "run"; + private String methodStr = DEAULT_METHOD_STR; + + /** + * Used to identify the condition. + */ + private int id = 0; + + private String error = null; + + private boolean valid = false; + private boolean initialised = false; + + /** + * The instance of the classStr to run. Note, will be null if newEachTime is true. + */ + private Object runClassInstance; + + /** + * handles to the methods we are going to run. + */ + private Constructor runConstructor; + private Method initMethod; + private Method filterInitMethod; + private Method runMethod; + private Class[] runMethodParams; + private String[] runMethodParamNames; + private boolean runMethodUseDefaultParams = true; + private Method destroyMethod; + + /** + * The config that we pass to the objectwe are trying to run. + */ + private RunConfig runServletConfig; + + private Hashtable initParams = new Hashtable(); + + private static boolean loadClass = true; + + private static Class[][] runMethodPossibleSignatures = { + {ServletRequest.class, ServletResponse.class}, + {ServletRequest.class}, + {ServletResponse.class}, + {HttpServletRequest.class, HttpServletResponse.class}, + {HttpServletRequest.class}, + {HttpServletResponse.class} + }; + private boolean filter = false; + + /** + * @see #initialise(ServletContext,Class) initialise + */ + public boolean initialise(ServletContext context) { + return initialise(context, null); + } + + /** + * Initialise the Run, this will check specified classStr, constructor and methodStr exist. + */ + public boolean initialise(ServletContext context, Class extraParam) { + log.debug("initialising run"); + runServletConfig = new RunConfig(context, initParams); + initialised = true; + valid = false; + if (StringUtils.isBlank(classStr)) { + setError("cannot initialise run " + id + " value is empty"); + return valid; + } + if (methodStr == null) { + methodStr = DEAULT_METHOD_STR; + } + log.debug("methodStr: " + methodStr); + + String rawMethodStr = methodStr; + int bkStart = rawMethodStr.indexOf('('); + int bkEnd = rawMethodStr.indexOf(')'); + if (bkStart != -1 && bkEnd != -1 && (bkEnd - bkStart) > 0) { + runMethodUseDefaultParams = false; + // set method str back to just method name + methodStr = rawMethodStr.substring(0, bkStart); + // get the list of params ie, "String name, int id" + String paramsList = rawMethodStr.substring(bkStart + 1, bkEnd); + paramsList = StringUtils.trimToNull(paramsList); + if (paramsList != null) { + String[] params = paramsList.split(","); + // validate and clean the incoming params list + Class[] paramClasses = new Class[params.length]; + String[] paramNames = new String[params.length]; + for (int i = 0; i < params.length; i++) { + String param = StringUtils.trimToNull(params[i]); + if (param == null) continue; + if (param.contains(" ")) { + String paramName = StringUtils.trimToNull(param.substring(param.indexOf(" "))); + if (paramName != null) { + log.debug("param name: " + paramName); + paramNames[i] = paramName; + } + param = param.substring(0, param.indexOf(' ')); + } + Class clazz = parseClass(param); + if (clazz == null) return valid; + paramClasses[i] = clazz; + } + runMethodParams = paramClasses; + runMethodParamNames = paramNames; + } + } + if (loadClass) { + prepareRunObject(extraParam); + } else { + valid = true; + } + return valid; + } + + /** + * Turns a class or language keyword name into the Class object, works with short names, ie, L - Long. + *

+ * boolean Z + * byte B + * char C + * class or interface Lclassname; + * double D + * float F + * int I + * long J + * short S + * + * @see Class + */ + private Class parseClass(String param) { + // do shortcuts + Class paramClass = TypeUtils.findClass(param); + + if ("javax.servlet.FilterChain".equalsIgnoreCase(param) || "FilterChain".equalsIgnoreCase(param) + || "chain".equalsIgnoreCase(param)) { + filter = true; + paramClass = FilterChain.class; + } + + if (loadClass) { + if (paramClass == null) { + try { + paramClass = Class.forName(param); + } catch (ClassNotFoundException e) { + setError("could not find " + param + " got a " + e.toString(), e); + return null; + } catch (NoClassDefFoundError e) { + setError("could not find " + param + " got a " + e.toString(), e); + return null; + } + } + if (paramClass == null) { + setError("could not find class of type " + param); + return null; + } + } + if (log.isDebugEnabled()) { + log.debug("parseClass found class " + paramClass + " for " + param); + } + return paramClass; + } + + /** + * Prepare the object for running by constructing and setting up method handles. + */ + private void prepareRunObject(Class extraParam) { + if (log.isDebugEnabled()) { + log.debug("looking for class " + classStr); + } + Class runClass; + try { + runClass = Class.forName(classStr); + } catch (ClassNotFoundException e) { + setError("could not find " + classStr + " got a " + e.toString(), e); + return; + } catch (NoClassDefFoundError e) { + setError("could not find " + classStr + " got a " + e.toString(), e); + return; + } + try { + runConstructor = runClass.getConstructor((Class[]) null); + } catch (NoSuchMethodException e) { + setError("could not get constructor for " + classStr, e); + return; + } + + if (!runMethodUseDefaultParams) { + if (log.isDebugEnabled()) { + log.debug("looking for " + methodStr + " with specific params"); + } + try { + runMethod = runClass.getMethod(methodStr, runMethodParams); + } catch (NoSuchMethodException e) { + // do nothing + if (log.isDebugEnabled()) { + log.debug(methodStr + " not found"); + } + } + } else { + if (log.isDebugEnabled()) { + log.debug("looking for " + methodStr + "(ServletRequest, ServletResponse)"); + } + for (int i = 0; i < runMethodPossibleSignatures.length; i++) { + Class[] runMethodPossibleSignature = runMethodPossibleSignatures[i]; + if (extraParam != null) { + if (runMethodPossibleSignature.length == 2) { + runMethodPossibleSignature = new Class[]{runMethodPossibleSignature[0], + runMethodPossibleSignature[1], extraParam}; + } + if (runMethodPossibleSignature.length == 1) { + runMethodPossibleSignature = new Class[]{runMethodPossibleSignature[0], extraParam}; + } + } + if (log.isDebugEnabled()) { + StringBuffer possible = new StringBuffer(); + for (int j = 0; j < runMethodPossibleSignature.length; j++) { + if (j > 0) possible.append(","); + possible.append(runMethodPossibleSignature[j].getName()); + } + log.debug("looking for " + methodStr + "(" + possible + ")"); + } + try { + runMethod = runClass.getMethod(methodStr, runMethodPossibleSignature); + runMethodParams = runMethodPossibleSignature; + break; + + } catch (NoSuchMethodException e) { + // do nothing except be paranoid about resetting runMethodParams + runMethodParams = null; + } + } + if (runMethod == null) { + setError("could not find method with the name " + methodStr + " on " + classStr); + return; + } + } + + Method[] methods = runClass.getMethods(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if ("destroy".equals(method.getName()) && method.getParameterTypes().length == 0) { + log.debug("found destroy methodStr"); + destroyMethod = method; + } + if ("init".equals(method.getName()) && method.getParameterTypes().length == 1 && + ServletConfig.class.getName().equals(method.getParameterTypes()[0].getName())) { + log.debug("found init methodStr"); + initMethod = method; + } + if ("init".equals(method.getName()) && method.getParameterTypes().length == 1 && + FilterConfig.class.getName().equals(method.getParameterTypes()[0].getName())) { + log.debug("found filter init methodStr"); + filterInitMethod = method; + } + if (initMethod != null && destroyMethod != null) break; + } + if (!newEachTime) { + runClassInstance = fetchNewInstance(); + } + valid = true; + + } + + private void invokeDestroy(Object runClassInstanceToDestroy) { + if (runClassInstanceToDestroy != null && destroyMethod != null) { + if (log.isDebugEnabled()) { + log.debug("running " + classStr + ".destroy()"); + } + try { + destroyMethod.invoke(runClassInstanceToDestroy, (Object[]) null); + } catch (IllegalAccessException e) { + logInvokeException("destroy()", e); + } catch (InvocationTargetException e) { + logInvokeException("destroy()", e); + } + } + } + + /** + * Invokes the run method. + *

+ * Exceptions at invocation time are either rethrown as a ServletException or as thr original exception if we can + * manage to do it. + *

+ * We don't log exceptions here, the container can do that. + */ + private RewriteMatch invokeRunMethod(Object classInstanceToRun, HttpServletRequest httpServletRequest, + HttpServletResponse httpServletResponse, FilterChain chain, Object[] matchObjs) + throws ServletException, InvocationTargetException { + if (log.isDebugEnabled()) { + log.debug("running " + classStr + "." + getMethodSignature() + " "); + } + if (classInstanceToRun == null || runMethod == null) return null; + RewriteMatch returned = null; + Object[] params = null; + + if (runMethodParams != null && runMethodParams.length > 0) { + params = new Object[runMethodParams.length]; + int paramMatchCounter = 0; + for (int i = 0; i < runMethodParams.length; i++) { + Class runMethodParam = runMethodParams[i]; + String runMethodParamName = null; + if (runMethodParamNames != null && runMethodParamNames.length > i) { + runMethodParamName = runMethodParamNames[i]; + } + Object param; + + if (runMethodParamName != null) { + log.debug("need parameter from request called " + runMethodParamName); + Object matchObj = httpServletRequest.getParameter(runMethodParamName); + param = TypeUtils.getConvertedParam(runMethodParam, matchObj); + + } else if (runMethodParam.isAssignableFrom(HttpServletRequest.class)) { + param = httpServletRequest; + + } else if (runMethodParam.isAssignableFrom(HttpServletResponse.class)) { + param = httpServletResponse; + + } else if (runMethodParam.isAssignableFrom(FilterChain.class)) { + param = chain; + + } else { + Object matchObj = null; + if (matchObjs != null && matchObjs.length > paramMatchCounter) { + matchObj = matchObjs[paramMatchCounter]; + } + param = TypeUtils.getConvertedParam(runMethodParam, matchObj); + paramMatchCounter++; + } + + params[i] = param; + if (log.isDebugEnabled()) { + log.debug("argument " + i + " (" + runMethodParam.getName() + "): " + param); + } + } + } + + try { + Object objReturned = runMethod.invoke(classInstanceToRun, (Object[]) params); + if ( jsonHandler ) { + returned = new JsonRewriteMatch(objReturned); + } else if (objReturned != null && objReturned instanceof RewriteMatch) { + // if we get a rewriteMatch object then return it for execution later + returned = (RewriteMatch) objReturned; + } + + } catch (IllegalAccessException e) { + if (log.isDebugEnabled()) log.debug(e); + throw new ServletException(e); + + } + return returned; + } + + + /** + * Run the underlying destroy methodStr on the run classStr. + */ + public void destroy() { + initialised = false; + valid = false; + + invokeDestroy(runClassInstance); + + // be paranoid and clean up all hooks to users classStr + destroyMethod = null; + runMethod = null; + initMethod = null; + filterInitMethod = null; + runServletConfig = null; + runConstructor = null; + runClassInstance = null; + + methodStr = null; + classStr = null; + error = null; + } + + /** + * @deprecated see #execute(HttpServletRequest,HttpServletResponse,Object[],FilterChain) + */ + public RewriteMatch execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws IOException, ServletException, InvocationTargetException { + return execute(httpServletRequest, httpServletResponse, null, null); + } + + public RewriteMatch execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + StringMatchingMatcher matcher, ConditionMatch conditionMatch, FilterChain chain) + throws IOException, ServletException, InvocationTargetException { + int matches = 0; + int condMatches = 0; + if (matcher != null && matcher.isFound()) { + matches = matcher.groupCount(); + } + if (conditionMatch != null) { + StringMatchingMatcher condMatcher = conditionMatch.getMatcher(); + if (condMatcher != null && condMatcher.isFound()) { + condMatches = condMatcher.groupCount(); + } + } + String[] allMatches = null; + if ((matches + condMatches) > 0) { + allMatches = new String[matches + condMatches]; + if (matcher != null && matches > 0) { + for (int i = 0; i < matches; i++) { + allMatches[i] = matcher.group(i + 1); // note, good groups start from 1 + } + } + if (conditionMatch != null && condMatches > 0) { + for (int i = 0; i < condMatches; i++) { + allMatches[i] = conditionMatch.getMatcher().group(i); + } + } + } + return execute(httpServletRequest, httpServletResponse, allMatches, chain); + } + + /** + * Will invoke the instance created in initialise. + * + * @param httpServletRequest + * @param httpServletResponse + */ + public RewriteMatch execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + Throwable throwable) + throws IOException, ServletException, InvocationTargetException { + Object[] params = new Object[]{throwable}; + return execute(httpServletRequest, httpServletResponse, params, null); + } + + /** + * @deprecated use execute(HttpServletRequest, HttpServletResponse, Object[], FilterChain) + */ + public RewriteMatch execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + Object[] params) throws IOException, ServletException, InvocationTargetException { + return execute(httpServletRequest, httpServletResponse, params, null); + } + + public RewriteMatch execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + Object[] params, FilterChain chain) + throws IOException, ServletException, InvocationTargetException { + if (!initialised) { + log.debug("not initialised skipping"); + return null; + } + if (!valid) { + log.debug("not valid skipping"); + return null; + } + RewriteMatch returned; + try { + if (newEachTime) { + Object newRunClassInstance = fetchNewInstance(); + returned = invokeRunMethod(newRunClassInstance, httpServletRequest, httpServletResponse, chain, params); + invokeDestroy(newRunClassInstance); + } else { + returned = invokeRunMethod(runClassInstance, httpServletRequest, httpServletResponse, chain, params); + } + } catch (ServletException e) { + httpServletRequest.setAttribute("javax.servlet.error.exception", e); + throw e; + } + return returned; + } + + private void logInvokeException(String methodStr, Exception e) { + Throwable cause = e.getCause(); + if (cause == null) { + setError("when invoking " + methodStr + " on " + classStr + + " got an " + e.toString(), e); + } else { + setError("when invoking " + methodStr + " on " + classStr + + " got an " + e.toString() + " caused by " + cause.toString(), cause); + } + } + + /** + * Get a new instance of the classStr we want to run and init if required. + * + * @return the new instance + */ + private Object fetchNewInstance() { + Object obj; + log.debug("getting new instance of " + classStr); + try { + obj = runConstructor.newInstance((Object[]) null); + } catch (InstantiationException e) { + logInvokeException("constructor", e); + return null; + } catch (IllegalAccessException e) { + logInvokeException("constructor", e); + return null; + } catch (InvocationTargetException e) { + logInvokeException("constructor", e); + return null; + } + if (initMethod != null) { + log.debug("about to run init(ServletConfig) on " + classStr); + Object[] args = new Object[1]; + args[0] = runServletConfig; + try { + initMethod.invoke(obj, args); + } catch (IllegalAccessException e) { + logInvokeException("init(ServletConfig)", e); + return null; + } catch (InvocationTargetException e) { + logInvokeException("init(ServletConfig)", e); + return null; + } + } + if (filterInitMethod != null) { + log.debug("about to run init(FilterConfig) on " + classStr); + Object[] args = new Object[1]; + args[0] = runServletConfig; + try { + filterInitMethod.invoke(obj, args); + } catch (IllegalAccessException e) { + logInvokeException("init(FilterConfig)", e); + return null; + } catch (InvocationTargetException e) { + logInvokeException("init(FilterConfig)", e); + return null; + } + } + return obj; + } + + public String getError() { + return error; + } + + public void setId(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public boolean isValid() { + return valid; + } + + public boolean isInitialised() { + return initialised; + } + + /** + * The name of the classStr that will be run for each rule match. + * + * @return String eg, org.tuckey.YellowObject + */ + public String getClassStr() { + return classStr; + } + + /** + * The name of the methodStr that will be run for each rule match. + * + * @return String eg, setDate + */ + public String getMethodStr() { + return methodStr; + } + + /** + * The name of the method signature ie, setDate(java.util.Date, int). Includes fully qualified object names + * for paramters. + */ + public String getMethodSignature() { + return TypeUtils.getMethodSignature(methodStr, runMethodParams); + } + + + public boolean isNewEachTime() { + return newEachTime; + } + + public void setNewEachTime(boolean newEachTime) { + this.newEachTime = newEachTime; + } + + /** + * Gets a handle on the instance of the class run is running. + *

+ * If newEachTime is set to true this will always return null. + */ + public Object getRunClassInstance() { + return runClassInstance; + } + + public void addInitParam(String name, String value) { + if (name != null) { + initParams.put(name, value); + } + } + + public String getInitParam(String paramName) { + return (String) initParams.get(paramName); + } + + public void setClassStr(String classStr) { + this.classStr = classStr; + } + + public void setMethodStr(String methodStr) { + this.methodStr = methodStr; + } + + public static void setLoadClass(boolean loadClass) { + Run.loadClass = loadClass; + } + + public void setError(String error, Throwable t) { + this.error = error; + log.error(error, t); + } + + public void setError(String error) { + this.error = error; + log.error(error); + } + + public String getDisplayName() { + return "Run " + id; + } + + public boolean isFilter() { + return filter; + } + + public void setJsonHandler(boolean jsonHandler) { + this.jsonHandler = jsonHandler; + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RunConfig.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RunConfig.java index ccb6a93f..5b070185 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RunConfig.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RunConfig.java @@ -1,79 +1,79 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; -import jakarta.servlet.FilterConfig; -import java.util.Enumeration; -import java.util.Hashtable; - - -/** - * Defines a the config that will be passed to the run object on startup. - * - * @author Paul Tuckey - * @version $Revision: 26 $ $Date: 2006-09-05 22:21:17 +1200 (Tue, 05 Sep 2006) $ - */ -public class RunConfig implements ServletConfig, FilterConfig { - - private ServletContext servletContext; - private Hashtable initParameters; - - public RunConfig(ServletContext servletContext, Hashtable initParameters) { - this.servletContext = servletContext; - this.initParameters = new Hashtable(initParameters); - } - - public String getServletName() { - return null; - } - - public String getFilterName() { - return null; - } - - public ServletContext getServletContext() { - return servletContext; - } - - public String getInitParameter(String s) { - return (String) initParameters.get(s); - } - - public Enumeration getInitParameterNames() { - return initParameters.keys(); - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.FilterConfig; +import java.util.Enumeration; +import java.util.Hashtable; + + +/** + * Defines a the config that will be passed to the run object on startup. + * + * @author Paul Tuckey + * @version $Revision: 26 $ $Date: 2006-09-05 22:21:17 +1200 (Tue, 05 Sep 2006) $ + */ +public class RunConfig implements ServletConfig, FilterConfig { + + private ServletContext servletContext; + private Hashtable initParameters; + + public RunConfig(ServletContext servletContext, Hashtable initParameters) { + this.servletContext = servletContext; + this.initParameters = new Hashtable(initParameters); + } + + public String getServletName() { + return null; + } + + public String getFilterName() { + return null; + } + + public ServletContext getServletContext() { + return servletContext; + } + + public String getInitParameter(String s) { + return (String) initParameters.get(s); + } + + public Enumeration getInitParameterNames() { + return initParameters.keys(); + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Runnable.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Runnable.java index ec8dd6bd..c8bdf9b8 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Runnable.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Runnable.java @@ -1,44 +1,44 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -/** - * Inteface for something that contains Run's, so we can initialise cleanly. - */ -public interface Runnable { - - public void addRun(final Run run); - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +/** + * Inteface for something that contains Run's, so we can initialise cleanly. + */ +public interface Runnable { + + public void addRun(final Run run); + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/SetAttribute.java b/src/main/java/org/tuckey/web/filters/urlrewrite/SetAttribute.java index ba447c73..c0676353 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/SetAttribute.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/SetAttribute.java @@ -1,390 +1,390 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.substitution.BackReferenceReplacer; -import org.tuckey.web.filters.urlrewrite.substitution.ChainedSubstitutionFilters; -import org.tuckey.web.filters.urlrewrite.substitution.FunctionReplacer; -import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionContext; -import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionFilterChain; -import org.tuckey.web.filters.urlrewrite.substitution.VariableReplacer; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.NumberUtils; -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpSession; - -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @author Paul Tuckey - * @version $Revision: 12 $ $Date: 2006-08-20 20:53:09 +1200 (Sun, 20 Aug 2006) $ - */ -public class SetAttribute { - - private static Log log = Log.getLog(SetAttribute.class); - - private boolean initialised = false; - private boolean valid = false; - - /** - * Error message from the regular expression compilation. - */ - private String error = null; - - private short type; - private String name; - private String value; - private int numericValue; - private Locale locale; - - private static final short SET_TYPE_REQUEST = 0; - private static final short SET_TYPE_SESSION = 1; - private static final short SET_TYPE_RESPONSE_HEADER = 2; - private static final short SET_TYPE_COOKIE = 3; - private static final short SET_TYPE_CONTENT_TYPE = 4; - private static final short SET_TYPE_CHARSET = 5; - private static final short SET_TYPE_LOCALE = 6; - private static final short SET_TYPE_STAUS = 7; - private static final short SET_TYPE_PARAM = 8; - private static final short SET_TYPE_EXPIRES = 9; - private static final short SET_TYPE_METHOD = 10; - - private long expiresValueAdd = 0; - private boolean valueContainsVariable = false; - private boolean valueContainsBackRef = false; - private boolean valueContainsFunction = false; - - public String getType() { - if (type == SET_TYPE_RESPONSE_HEADER) return "response-header"; - if (type == SET_TYPE_SESSION) return "session"; - if (type == SET_TYPE_COOKIE) return "cookie"; - if (type == SET_TYPE_CONTENT_TYPE) return "content-type"; - if (type == SET_TYPE_CHARSET) return "charset"; - if (type == SET_TYPE_LOCALE) return "locale"; - if (type == SET_TYPE_STAUS) return "status"; - if (type == SET_TYPE_PARAM) return "parameter"; - if (type == SET_TYPE_EXPIRES) return "expires"; - if (type == SET_TYPE_METHOD) return "method"; - return "request"; - } - - public void setType(String typeStr) { - if ("response-header".equals(typeStr)) { - type = SET_TYPE_RESPONSE_HEADER; - } else if ("session".equals(typeStr)) { - type = SET_TYPE_SESSION; - } else if ("cookie".equals(typeStr)) { - type = SET_TYPE_COOKIE; - } else if ("content-type".equals(typeStr)) { - type = SET_TYPE_CONTENT_TYPE; - } else if ("charset".equals(typeStr)) { - type = SET_TYPE_CHARSET; - } else if ("locale".equals(typeStr)) { - type = SET_TYPE_LOCALE; - } else if ("status".equals(typeStr)) { - type = SET_TYPE_STAUS; - } else if ("parameter".equals(typeStr) || "param".equals(typeStr)) { - type = SET_TYPE_PARAM; - } else if ("expires".equals(typeStr)) { - type = SET_TYPE_EXPIRES; - } else if ("request".equals(typeStr) || StringUtils.isBlank(typeStr)) { - type = SET_TYPE_REQUEST; - } else if ("method".equals(typeStr)) { - type = SET_TYPE_METHOD; - } else { - setError("type (" + typeStr + ") is not valid"); - } - } - - private void setError(String s) { - log.error("set " + getDisplayName() + " had error: " + s); - error = s; - } - - public String getError() { - return error; - } - - public String getDisplayName() { - return "Set " + getType() + " " + name + " " + value; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public void execute(ConditionMatch lastConditionMatch, StringMatchingMatcher toMatcher, - HttpServletRequest hsRequest, HttpServletResponse hsResponse) { - - if (log.isDebugEnabled()) { - log.debug("set " + getDisplayName() + " called"); - } - if (!valid) { - log.debug("not valid, skipping"); - return; - } - if (!initialised) { - log.debug("not initialised, skipping"); - return; - } - - String value = this.value; - - SubstitutionContext substitutionContext = new SubstitutionContext(hsRequest, toMatcher, lastConditionMatch, null); - SubstitutionFilterChain substitutionFilter = ChainedSubstitutionFilters.getDefaultSubstitutionChain(false, valueContainsFunction, valueContainsVariable, valueContainsBackRef); - value = substitutionFilter.substitute(value, substitutionContext); - - if (type == SET_TYPE_REQUEST) { - log.debug("setting request attrib"); - hsRequest.setAttribute(name, value); - - } else if (type == SET_TYPE_METHOD) { - log.debug("setting request method"); - if ( hsResponse instanceof UrlRewriteWrappedResponse ) { - ((UrlRewriteWrappedResponse) hsResponse).setOverridenMethod(value); - } else { - log.warn("unable to set request method as request not a UrlRewriteWrappedResponse"); - } - - } else if (type == SET_TYPE_PARAM) { - log.debug("setting request parameter"); - if ( hsResponse instanceof UrlRewriteWrappedResponse ) { - ((UrlRewriteWrappedResponse) hsResponse).addOverridenRequestParameter(name, value); - } else { - log.warn("unable to set request parameter as request not a UrlRewriteWrappedResponse"); - } - - } else if (type == SET_TYPE_SESSION) { - log.debug("setting session attrib"); - HttpSession session = hsRequest.getSession(true); - if (session == null) { - log.warn("could not create a new session for a request"); - } else { - session.setAttribute(name, value); - } - - } else if (type == SET_TYPE_RESPONSE_HEADER) { - log.debug("setting response header"); - hsResponse.addHeader(name, value); - - } else if (type == SET_TYPE_STAUS) { - log.debug("setting status"); - hsResponse.setStatus(numericValue); - - } else if (type == SET_TYPE_COOKIE) { - Cookie cookieToAdd = getCookie(name, value); - if ( cookieToAdd != null ) { - log.debug("adding cookie"); - hsResponse.addCookie(cookieToAdd); - } - - } else if (type == SET_TYPE_CONTENT_TYPE) { - log.debug("setting content type"); - hsResponse.setContentType(value); - - } else if (type == SET_TYPE_CHARSET) { - log.debug("setting charset"); - hsResponse.setCharacterEncoding(value); - - } else if (type == SET_TYPE_LOCALE) { - log.debug("setting charset"); - hsResponse.setLocale(locale); - - } else if (type == SET_TYPE_EXPIRES) { - log.debug("setting expires"); - hsResponse.setDateHeader("Expires", System.currentTimeMillis() + expiresValueAdd); - - } else { - log.warn("unknown type" + type); - } - - } - - public boolean initialise() { - initialised = true; - - if (value != null) { - if (BackReferenceReplacer.containsBackRef(value)) { - valueContainsBackRef = true; - } - if (VariableReplacer.containsVariable(value)) { - valueContainsVariable = true; - } - if (FunctionReplacer.containsFunction(value)) { - valueContainsFunction = true; - } - } - - if (type == SET_TYPE_STAUS) { - initNumericValue(); - } else if (type == SET_TYPE_LOCALE) { - // value might be zh-CN-abcdef or zh-CN or zh - locale = null; - if (value == null) { - setError("Locale is not valid because value is null"); - } else if (value.matches("[a-zA-Z][a-zA-Z]")) { - locale = new Locale(value); - } else if (value.matches("[a-zA-Z][a-zA-Z]-[a-zA-Z][a-zA-Z]")) { - locale = new Locale(value.substring(1, 2), value.substring(2, 4)); - } else if (value.matches("[a-zA-Z][a-zA-Z]-[a-zA-Z][a-zA-Z]-.*")) { - locale = new Locale(value.substring(1, 2), value.substring(4, 5), value.substring(6, value.length())); - } else { - setError("Locale " + value + " is not valid (valid locales are, zh, zh-CN, zh-CN-rural)"); - } - - } else if (type == SET_TYPE_COOKIE) { - // VAL[:domain[:lifetime[:path]]] - if (value != null && name != null) { - getCookie(name, value); - } else { - setError("cookie must have a name and a value"); - } - - } else if (type == SET_TYPE_EXPIRES) { - // "access plus 1 month" - if (value != null ) { - expiresValueAdd = parseTimeValue(value); - } else { - setError("expires must have a value"); - } - } - - if (error == null) { - valid = true; - } - return valid; - } - - /** - * takes a string a number expression and converts it to a long. - * syntax: number type - * - * Valid examples: "1 day", "2 days", "1 hour", "1 hour 2 minutes", "34 months" - * - * Any positive number is valid - * - * Valid types are: years, months, weeks, days, hours, minutes, seconds - * - * note, this syntax is a direct copy of mod_expires syntax - * http://httpd.apache.org/docs/2.0/mod/mod_expires.html - * - * note, a year is calculated as 365.25 days and a month as 365.25 days divided by 12. - */ - protected long parseTimeValue(String parsingValue) { - long calculatedMillis = 0; - if ( parsingValue.startsWith("access")) parsingValue = parsingValue.substring("access".length()).trim(); - if ( parsingValue.startsWith("plus")) parsingValue = parsingValue.substring("plus".length()).trim(); - log.debug("calculating expires ms based on '" + parsingValue + "'"); - Matcher matcher = Pattern.compile("([0-9]+)\\s+(\\w+)").matcher(parsingValue); - while ( matcher.find()) { - long num = NumberUtils.stringToInt(matcher.group(1), -1); - if ( num < 0 ) setError("could not calculate numeric value of " + matcher.group(1)); - String part = matcher.group(2); - log.debug("adding '"+num+"' '" + part + "'"); - long addThisRound = 0; - if ( part.matches("year[s]?") ) addThisRound = num * Math.round(1000 * 60 * 60 * 24 * 365.25); - if ( part.matches("month[s]?") ) addThisRound = num * Math.round( 1000 * 60 * 60 * 24 * (365.25/12) ); - if ( part.matches("week[s]?") ) addThisRound = num * ( 1000 * 60 * 60 * 24 * 7 ); - if ( part.matches("day[s]?") ) addThisRound = num * ( 1000 * 60 * 60 * 24 ); - if ( part.matches("hour[s]?") ) addThisRound = num * ( 1000 * 60 * 60 ); - if ( part.matches("minute[s]?") ) addThisRound = num * ( 1000 * 60 ); - if ( part.matches("second[s]?") ) addThisRound = num * ( 1000 ); - if ( addThisRound == 0 ) { - setError("unkown time unit '" + part + "'"); - } - calculatedMillis += addThisRound; - } - if ( calculatedMillis == 0 ) { - setError("could not calculate expires time from '"+parsingValue+"'"); - } - return calculatedMillis; - } - - private Cookie getCookie(String name, String value) { - if ( log.isDebugEnabled() ) { - log.debug("making cookie for " + name + ", " + value); - } - if ( name == null ) { - log.info("getCookie called with null name"); - return null; - } - Cookie cookie; - if (value != null && value.indexOf(":") != -1) { - // we must have extra items - String items[] = value.split(":"); - cookie = new Cookie(name, items[0]); - if (items.length > 1) cookie.setDomain(items[1]); - if (items.length > 2) cookie.setMaxAge(NumberUtils.stringToInt(items[2])); - if (items.length > 3) cookie.setPath(items[3]); - - } else { - cookie = new Cookie(name, value); - } - return cookie; - } - - /** - * Will init a numeric value type ie port. - */ - private void initNumericValue() { - if (numericValue == 0) { - numericValue = NumberUtils.stringToInt(StringUtils.trim(value)); - if (numericValue == 0 && !"0".equals(value)) { - setError("Value " + value + " is not a valid number (tried to cast to java type long)"); - } - } - } - - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.substitution.BackReferenceReplacer; +import org.tuckey.web.filters.urlrewrite.substitution.ChainedSubstitutionFilters; +import org.tuckey.web.filters.urlrewrite.substitution.FunctionReplacer; +import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionContext; +import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionFilterChain; +import org.tuckey.web.filters.urlrewrite.substitution.VariableReplacer; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.NumberUtils; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Paul Tuckey + * @version $Revision: 12 $ $Date: 2006-08-20 20:53:09 +1200 (Sun, 20 Aug 2006) $ + */ +public class SetAttribute { + + private static Log log = Log.getLog(SetAttribute.class); + + private boolean initialised = false; + private boolean valid = false; + + /** + * Error message from the regular expression compilation. + */ + private String error = null; + + private short type; + private String name; + private String value; + private int numericValue; + private Locale locale; + + private static final short SET_TYPE_REQUEST = 0; + private static final short SET_TYPE_SESSION = 1; + private static final short SET_TYPE_RESPONSE_HEADER = 2; + private static final short SET_TYPE_COOKIE = 3; + private static final short SET_TYPE_CONTENT_TYPE = 4; + private static final short SET_TYPE_CHARSET = 5; + private static final short SET_TYPE_LOCALE = 6; + private static final short SET_TYPE_STAUS = 7; + private static final short SET_TYPE_PARAM = 8; + private static final short SET_TYPE_EXPIRES = 9; + private static final short SET_TYPE_METHOD = 10; + + private long expiresValueAdd = 0; + private boolean valueContainsVariable = false; + private boolean valueContainsBackRef = false; + private boolean valueContainsFunction = false; + + public String getType() { + if (type == SET_TYPE_RESPONSE_HEADER) return "response-header"; + if (type == SET_TYPE_SESSION) return "session"; + if (type == SET_TYPE_COOKIE) return "cookie"; + if (type == SET_TYPE_CONTENT_TYPE) return "content-type"; + if (type == SET_TYPE_CHARSET) return "charset"; + if (type == SET_TYPE_LOCALE) return "locale"; + if (type == SET_TYPE_STAUS) return "status"; + if (type == SET_TYPE_PARAM) return "parameter"; + if (type == SET_TYPE_EXPIRES) return "expires"; + if (type == SET_TYPE_METHOD) return "method"; + return "request"; + } + + public void setType(String typeStr) { + if ("response-header".equals(typeStr)) { + type = SET_TYPE_RESPONSE_HEADER; + } else if ("session".equals(typeStr)) { + type = SET_TYPE_SESSION; + } else if ("cookie".equals(typeStr)) { + type = SET_TYPE_COOKIE; + } else if ("content-type".equals(typeStr)) { + type = SET_TYPE_CONTENT_TYPE; + } else if ("charset".equals(typeStr)) { + type = SET_TYPE_CHARSET; + } else if ("locale".equals(typeStr)) { + type = SET_TYPE_LOCALE; + } else if ("status".equals(typeStr)) { + type = SET_TYPE_STAUS; + } else if ("parameter".equals(typeStr) || "param".equals(typeStr)) { + type = SET_TYPE_PARAM; + } else if ("expires".equals(typeStr)) { + type = SET_TYPE_EXPIRES; + } else if ("request".equals(typeStr) || StringUtils.isBlank(typeStr)) { + type = SET_TYPE_REQUEST; + } else if ("method".equals(typeStr)) { + type = SET_TYPE_METHOD; + } else { + setError("type (" + typeStr + ") is not valid"); + } + } + + private void setError(String s) { + log.error("set " + getDisplayName() + " had error: " + s); + error = s; + } + + public String getError() { + return error; + } + + public String getDisplayName() { + return "Set " + getType() + " " + name + " " + value; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public void execute(ConditionMatch lastConditionMatch, StringMatchingMatcher toMatcher, + HttpServletRequest hsRequest, HttpServletResponse hsResponse) { + + if (log.isDebugEnabled()) { + log.debug("set " + getDisplayName() + " called"); + } + if (!valid) { + log.debug("not valid, skipping"); + return; + } + if (!initialised) { + log.debug("not initialised, skipping"); + return; + } + + String value = this.value; + + SubstitutionContext substitutionContext = new SubstitutionContext(hsRequest, toMatcher, lastConditionMatch, null); + SubstitutionFilterChain substitutionFilter = ChainedSubstitutionFilters.getDefaultSubstitutionChain(false, valueContainsFunction, valueContainsVariable, valueContainsBackRef); + value = substitutionFilter.substitute(value, substitutionContext); + + if (type == SET_TYPE_REQUEST) { + log.debug("setting request attrib"); + hsRequest.setAttribute(name, value); + + } else if (type == SET_TYPE_METHOD) { + log.debug("setting request method"); + if ( hsResponse instanceof UrlRewriteWrappedResponse ) { + ((UrlRewriteWrappedResponse) hsResponse).setOverridenMethod(value); + } else { + log.warn("unable to set request method as request not a UrlRewriteWrappedResponse"); + } + + } else if (type == SET_TYPE_PARAM) { + log.debug("setting request parameter"); + if ( hsResponse instanceof UrlRewriteWrappedResponse ) { + ((UrlRewriteWrappedResponse) hsResponse).addOverridenRequestParameter(name, value); + } else { + log.warn("unable to set request parameter as request not a UrlRewriteWrappedResponse"); + } + + } else if (type == SET_TYPE_SESSION) { + log.debug("setting session attrib"); + HttpSession session = hsRequest.getSession(true); + if (session == null) { + log.warn("could not create a new session for a request"); + } else { + session.setAttribute(name, value); + } + + } else if (type == SET_TYPE_RESPONSE_HEADER) { + log.debug("setting response header"); + hsResponse.addHeader(name, value); + + } else if (type == SET_TYPE_STAUS) { + log.debug("setting status"); + hsResponse.setStatus(numericValue); + + } else if (type == SET_TYPE_COOKIE) { + Cookie cookieToAdd = getCookie(name, value); + if ( cookieToAdd != null ) { + log.debug("adding cookie"); + hsResponse.addCookie(cookieToAdd); + } + + } else if (type == SET_TYPE_CONTENT_TYPE) { + log.debug("setting content type"); + hsResponse.setContentType(value); + + } else if (type == SET_TYPE_CHARSET) { + log.debug("setting charset"); + hsResponse.setCharacterEncoding(value); + + } else if (type == SET_TYPE_LOCALE) { + log.debug("setting charset"); + hsResponse.setLocale(locale); + + } else if (type == SET_TYPE_EXPIRES) { + log.debug("setting expires"); + hsResponse.setDateHeader("Expires", System.currentTimeMillis() + expiresValueAdd); + + } else { + log.warn("unknown type" + type); + } + + } + + public boolean initialise() { + initialised = true; + + if (value != null) { + if (BackReferenceReplacer.containsBackRef(value)) { + valueContainsBackRef = true; + } + if (VariableReplacer.containsVariable(value)) { + valueContainsVariable = true; + } + if (FunctionReplacer.containsFunction(value)) { + valueContainsFunction = true; + } + } + + if (type == SET_TYPE_STAUS) { + initNumericValue(); + } else if (type == SET_TYPE_LOCALE) { + // value might be zh-CN-abcdef or zh-CN or zh + locale = null; + if (value == null) { + setError("Locale is not valid because value is null"); + } else if (value.matches("[a-zA-Z][a-zA-Z]")) { + locale = new Locale(value); + } else if (value.matches("[a-zA-Z][a-zA-Z]-[a-zA-Z][a-zA-Z]")) { + locale = new Locale(value.substring(1, 2), value.substring(2, 4)); + } else if (value.matches("[a-zA-Z][a-zA-Z]-[a-zA-Z][a-zA-Z]-.*")) { + locale = new Locale(value.substring(1, 2), value.substring(4, 5), value.substring(6, value.length())); + } else { + setError("Locale " + value + " is not valid (valid locales are, zh, zh-CN, zh-CN-rural)"); + } + + } else if (type == SET_TYPE_COOKIE) { + // VAL[:domain[:lifetime[:path]]] + if (value != null && name != null) { + getCookie(name, value); + } else { + setError("cookie must have a name and a value"); + } + + } else if (type == SET_TYPE_EXPIRES) { + // "access plus 1 month" + if (value != null ) { + expiresValueAdd = parseTimeValue(value); + } else { + setError("expires must have a value"); + } + } + + if (error == null) { + valid = true; + } + return valid; + } + + /** + * takes a string a number expression and converts it to a long. + * syntax: number type + * + * Valid examples: "1 day", "2 days", "1 hour", "1 hour 2 minutes", "34 months" + * + * Any positive number is valid + * + * Valid types are: years, months, weeks, days, hours, minutes, seconds + * + * note, this syntax is a direct copy of mod_expires syntax + * http://httpd.apache.org/docs/2.0/mod/mod_expires.html + * + * note, a year is calculated as 365.25 days and a month as 365.25 days divided by 12. + */ + protected long parseTimeValue(String parsingValue) { + long calculatedMillis = 0; + if ( parsingValue.startsWith("access")) parsingValue = parsingValue.substring("access".length()).trim(); + if ( parsingValue.startsWith("plus")) parsingValue = parsingValue.substring("plus".length()).trim(); + log.debug("calculating expires ms based on '" + parsingValue + "'"); + Matcher matcher = Pattern.compile("([0-9]+)\\s+(\\w+)").matcher(parsingValue); + while ( matcher.find()) { + long num = NumberUtils.stringToInt(matcher.group(1), -1); + if ( num < 0 ) setError("could not calculate numeric value of " + matcher.group(1)); + String part = matcher.group(2); + log.debug("adding '"+num+"' '" + part + "'"); + long addThisRound = 0; + if ( part.matches("year[s]?") ) addThisRound = num * Math.round(1000 * 60 * 60 * 24 * 365.25); + if ( part.matches("month[s]?") ) addThisRound = num * Math.round( 1000 * 60 * 60 * 24 * (365.25/12) ); + if ( part.matches("week[s]?") ) addThisRound = num * ( 1000 * 60 * 60 * 24 * 7 ); + if ( part.matches("day[s]?") ) addThisRound = num * ( 1000 * 60 * 60 * 24 ); + if ( part.matches("hour[s]?") ) addThisRound = num * ( 1000 * 60 * 60 ); + if ( part.matches("minute[s]?") ) addThisRound = num * ( 1000 * 60 ); + if ( part.matches("second[s]?") ) addThisRound = num * ( 1000 ); + if ( addThisRound == 0 ) { + setError("unkown time unit '" + part + "'"); + } + calculatedMillis += addThisRound; + } + if ( calculatedMillis == 0 ) { + setError("could not calculate expires time from '"+parsingValue+"'"); + } + return calculatedMillis; + } + + private Cookie getCookie(String name, String value) { + if ( log.isDebugEnabled() ) { + log.debug("making cookie for " + name + ", " + value); + } + if ( name == null ) { + log.info("getCookie called with null name"); + return null; + } + Cookie cookie; + if (value != null && value.indexOf(":") != -1) { + // we must have extra items + String items[] = value.split(":"); + cookie = new Cookie(name, items[0]); + if (items.length > 1) cookie.setDomain(items[1]); + if (items.length > 2) cookie.setMaxAge(NumberUtils.stringToInt(items[2])); + if (items.length > 3) cookie.setPath(items[3]); + + } else { + cookie = new Cookie(name, value); + } + return cookie; + } + + /** + * Will init a numeric value type ie port. + */ + private void initNumericValue() { + if (numericValue == 0) { + numericValue = NumberUtils.stringToInt(StringUtils.trim(value)); + if (numericValue == 0 && !"0".equals(value)) { + setError("Value " + value + " is not a valid number (tried to cast to java type long)"); + } + } + } + + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Status.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Status.java index 522649cf..83478566 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Status.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Status.java @@ -1,566 +1,566 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpSession; -import java.io.IOException; -import java.io.InputStream; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.Enumeration; -import java.util.List; - -/** - * Outputs information about urlrewritefilter. - *

- * todo: add ability to trigger reload conf - * - * @author Paul Tuckey - * @version $Revision: 43 $ $Date: 2006-10-31 17:29:59 +1300 (Tue, 31 Oct 2006) $ - */ -public class Status { - - private static Log log = Log.getLog(Status.class); - - private StringBuffer buffer = new StringBuffer(); - - private Conf conf; - private UrlRewriteFilter urlRewriteFilter; - - public Status(Conf conf) { - this.conf = conf; - } - - public Status(Conf conf, UrlRewriteFilter urlRewriteFilter) { - this.conf = conf; - this.urlRewriteFilter = urlRewriteFilter; - } - - public void displayStatusInContainer(final HttpServletRequest hsRequest) { - showHeader(); - showRunningInfo(); - showConf(); - showRequestInfo(hsRequest); - showFooter(); - } - - public void displayStatusOffline() { - showHeader(); - showConf(); - showFooter(); - } - - - private void showRequestInfo(final HttpServletRequest hsRequest) { - // other info - println("

Request Debug Info

"); - - println("

General

"); - println("
");
-
-        println("method: " + hsRequest.getMethod());
-        if (hsRequest.getAuthType() != null) println("auth-type: " + hsRequest.getAuthType());
-        if (hsRequest.getCharacterEncoding() != null)
-            println("character-encoding: " + hsRequest.getCharacterEncoding());
-        println("context-path: " + hsRequest.getContextPath());
-        if (hsRequest.getPathInfo() != null) println("path-info: " + hsRequest.getPathInfo());
-        if (hsRequest.getPathTranslated() != null) println("path-translated: " + hsRequest.getPathTranslated());
-        println("port: " + hsRequest.getServerPort());
-        println("protocol: " + hsRequest.getProtocol());
-        if (hsRequest.getQueryString() != null) println("query-string: " + hsRequest.getQueryString());
-        println("remote-addr: " + hsRequest.getRemoteAddr());
-        println("remote-host: " + hsRequest.getRemoteHost());
-        if (hsRequest.getRemoteUser() != null) println("remote-user: " + hsRequest.getRemoteUser());
-        if (hsRequest.getRequestedSessionId() != null)
-            println("requested-session-id: " + hsRequest.getRequestedSessionId());
-        println("request-uri: " + hsRequest.getRequestURI());
-        println("request-url: " + hsRequest.getRequestURL());
-        println("server-name: " + hsRequest.getServerName());
-        println("scheme: " + hsRequest.getScheme());
-
-        println("
"); - - HttpSession session = hsRequest.getSession(false); - if (session != null) { - println("

Session

"); - println("
session-isnew: " + session.isNew()); - Enumeration enumer = session.getAttributeNames(); - while (enumer.hasMoreElements()) { - String name = (String) enumer.nextElement(); - println("
session-attribute " + name + ": " + session.getAttribute(name)); - } - } - - // show headers from request - println("

Request Headers

"); - println("
");
-        final Enumeration headers = hsRequest.getHeaderNames();
-        while (headers.hasMoreElements()) {
-            final String headerName = (String) headers.nextElement();
-            // ignore cookies as they are handled later
-            if ("cookie".equals(headerName)) continue;
-            println(headerName + ": " + hsRequest.getHeader(headerName));
-        }
-        println("
"); - - final Cookie[] cookies = hsRequest.getCookies(); - if (cookies != null && cookies.length > 0) { - println("

Cookies

"); - for (int i = 0; i < cookies.length; i++) { - println("
Cookie " + i + "
"); - final Cookie cookie = cookies[i]; - if (cookie == null) continue; - println("
");
-                println("    name     : " + cookie.getName());
-                println("    value    : " + cookie.getValue());
-                println("    path     : " + cookie.getPath());
-                println("    domain   : " + cookie.getDomain());
-                println("    max age  : " + cookie.getMaxAge());
-                println("    is secure: " + cookie.getSecure());
-                println("    version  : " + cookie.getVersion());
-                println("    comment  : " + cookie.getComment());
-                println("
"); - } - } - - // show headers from request - println("

Time info

"); - println("
");
-        Calendar nowCal = Calendar.getInstance();
-        println("time: " + nowCal.getTime().getTime());
-        println("year: " + nowCal.get(Calendar.YEAR));
-        println("month: " + nowCal.get(Calendar.MONTH));
-        println("dayofmonth: " + nowCal.get(Calendar.DAY_OF_MONTH));
-        println("dayofweek: " + nowCal.get(Calendar.DAY_OF_WEEK));
-        println("ampm: " + nowCal.get(Calendar.AM_PM));
-        println("hourofday: " + nowCal.get(Calendar.HOUR_OF_DAY));
-        println("minute: " + nowCal.get(Calendar.MINUTE));
-        println("second: " + nowCal.get(Calendar.SECOND));
-        println("millisecond: " + nowCal.get(Calendar.MILLISECOND));
-        println("
"); - - } - - private void showConf() { - if (conf == null) return; - - println("

Summary"); - if (conf.isLoadedFromFile()) println(" of " + conf.getFileName()); - println("

"); - - if (!conf.isOk()) { - final List errors = conf.getErrors(); - println("

Errors During Load of " + conf.getFileName() + "

"); - println(""); - } - - int conditionsCount = 0; - final List rules = conf.getRules(); - for (int i = 0; i < rules.size(); i++) { - final Rule rule = (Rule) rules.get(i); - if (rule instanceof NormalRule) { - conditionsCount += ((NormalRule) rule).getConditions().size(); - } - } - final List outboundRules = conf.getOutboundRules(); - for (int i = 0; i < outboundRules.size(); i++) { - final OutboundRule rule = (OutboundRule) outboundRules.get(i); - conditionsCount += rule.getConditions().size(); - } - println("

In total there " + - (rules.size() == 1 ? "is 1 rule" : "are " + rules.size() + " rules") + ", " + - (outboundRules.size() == 1 ? "1 outbound rule" : outboundRules.size() + " outbound rules") + - (conditionsCount > 0 ? " and " : "") + - (conditionsCount == 1 ? conditionsCount + " condition" : "") + - (conditionsCount > 1 ? conditionsCount + " conditions" : "") + - " in the configuration file.

"); - - showRules(rules); - showOutboundRules(outboundRules); - println("
"); - } - - private void showRules(List rules) { - for (int i = 0; i < rules.size(); i++) { - final Rule rule = (Rule) rules.get(i); - if (rule instanceof NormalRule) { - NormalRule normalRule = (NormalRule) rule; - println("

" + normalRule.getDisplayName() + - (normalRule.isEnabled() ? "" : " **DISABLED**") + "

"); - if (!StringUtils.isBlank(normalRule.getNote())) { - println("

" + StringUtils.nl2br(normalRule.getNote()) + "

"); - } - - print("

URL's matching " + normalRule.getFrom() + ""); - if (normalRule.isFilter()) { - print(" (filter)"); - } - if (!StringUtils.isBlank(normalRule.getTo())) { - print(" will "); - if ("forward".equals(normalRule.getToType())) - print("be forwarded to"); - else if ("include".equals(normalRule.getToType())) - print("include"); - else if ("redirect".equals(normalRule.getToType())) - print("be redirected to"); - else - print("" + normalRule.getToType() + " to"); - print(" " + normalRule.getTo() + ""); - } - println(".

"); - print("

This rule and it's conditions will use the " + normalRule.getMatchType() + " matching engine.

"); - showConditions(normalRule); - showSets(normalRule); - showRuns(normalRule); - - if (!rule.isLast()) { - println("

Note, other rules will be processed after this rule.

"); - } - } - if (rule instanceof ClassRule) { - ClassRule classRule = (ClassRule) rule; - println("

" + classRule.getDisplayName() + - (classRule.isEnabled() ? "" : " **DISABLED**") + "

"); - } - println(); - println(); - } - } - - private void showOutboundRules(List outboundRules) { - for (int i = 0; i < outboundRules.size(); i++) { - final OutboundRule rule = (OutboundRule) outboundRules.get(i); - println("

" + rule.getDisplayName() + - (rule.isEnabled() ? "" : " **DISABLED**") + "

"); - if (!StringUtils.isBlank(rule.getNote())) { - println("

" + StringUtils.nl2br(rule.getNote()) + "

"); - } - print("

Outbound URL's matching " + rule.getFrom() + ""); - if (!StringUtils.isBlank(rule.getTo())) { - print(" will be rewritten to " + rule.getTo() + ""); - } - if (!rule.isEncodeFirst()) { - print(", after response.encodeURL() has been called"); - } - if (!rule.isEncodeToUrl()) { - print(", response.encodeURL() will not be called"); - } - println(".

"); - - showConditions(rule); - showSets(rule); - showRuns(rule); - - if (!rule.isLast()) { - println("

Note, other outbound rules will be processed after this rule.

"); - } - println(); - println(); - } - } - - private void showHeader() { - SimpleDateFormat s = new SimpleDateFormat(); - println(""); - println(""); - println(""); - if ( conf == null ) { - println("UrlRewriteFilter configuration overview"); - } else { - println("UrlRewriteFilter configuration overview for " + conf.getFileName() + ""); - } - println(""); - println(""); - println("

UrlRewriteFilter " + - UrlRewriteFilter.getFullVersionString() + " configuration overview " + - "(generated " + s.format(new Date()) + ")

"); - println("
"); - } - - private void showRunningInfo() { - println("

Running Status

"); - if (conf == null) { - println("

ERROR: UrlRewriteFilter failed to load config, check server log

"); - } else if (!conf.isOk()) { - println("

ERROR: UrlRewriteFilter NOT ACTIVE

"); - } - println("

Conf"); - if (conf == null ) println(" empty.

"); - if (conf != null && conf.isLoadedFromFile()) println("file " + conf.getFileName() + ""); - if (conf != null ) println("loaded " + conf.getLoadedDate() + ".

"); - if (urlRewriteFilter != null) { - if (urlRewriteFilter.isConfReloadCheckEnabled()) { - Date nextReloadCheckDate = new Date(urlRewriteFilter.getConfReloadLastCheck().getTime() + - (urlRewriteFilter.getConfReloadCheckInterval() * 1000L)); - println("

Conf file reload check enabled, last modified will be checked every " + - urlRewriteFilter.getConfReloadCheckInterval() + "s, last checked " + - urlRewriteFilter.getConfReloadLastCheck() + ", next check at " + - nextReloadCheckDate + " in " + - Math.round((nextReloadCheckDate.getTime() - System.currentTimeMillis()) / 1000d) + "s."); - } else { - println("Conf file reload check disabled"); - } - println("

Status path " + urlRewriteFilter.getStatusPath() + ".

"); - } - } - - private void displayRuleErrors(final List rules) { - for (int i = 0; i < rules.size(); i++) { - Object ruleObj = rules.get(i); - if (ruleObj instanceof Rule) { - final Rule rule = (Rule) rules.get(i); - if (rule.isValid()) continue; - println("
  • Error in " + rule.getDisplayName()); - println("
  • "); - } - if (ruleObj instanceof OutboundRule) { - final OutboundRule outboundRule = (OutboundRule) rules.get(i); - if (outboundRule.isValid()) continue; - println("
  • Error in " + outboundRule.getDisplayName()); - println("
  • "); - } - } - } - - private void displayRuleCondSetRun(List conditions, List sets, List runs) { - for (int j = 0; j < conditions.size(); j++) { - Condition condition = (Condition) conditions.get(j); - if (condition.getError() == null) continue; - println("
  • " + condition.getDisplayName() + " " + condition.getError() + "
  • "); - } - for (int j = 0; j < sets.size(); j++) { - SetAttribute setAttribute = (SetAttribute) sets.get(j); - if (setAttribute.getError() == null) continue; - println("
  • " + setAttribute.getDisplayName() + " " + setAttribute.getError() + "
  • "); - } - for (int j = 0; j < runs.size(); j++) { - Run run = (Run) runs.get(j); - if (run.getError() == null) continue; - println("
  • " + run.getDisplayName() + " " + run.getError() + "
  • "); - } - } - - private void displayCatchErrors(final List catchElems) { - for (int i = 0; i < catchElems.size(); i++) { - final CatchElem catchElem = (CatchElem) catchElems.get(i); - if (catchElem.isValid()) continue; - println("
  • Error in catch for " + catchElem.getClass() + "
  • "); - println(""); - } - } - - private void showSets(final RuleBase rule) { - if (rule.getSetAttributes().size() == 0) return; - List setAttributes = rule.getSetAttributes(); - println("

    This rule will set:

    " + - "
      "); - for (int j = 0; j < setAttributes.size(); j++) { - SetAttribute setAttribute = (SetAttribute) setAttributes.get(j); - println("
    1. "); - if ("response-header".equals(setAttribute.getType())) { - println("The " + setAttribute.getName() + " HTTP response header " + - "to " + setAttribute.getValue() + ""); - - } else if ("request".equals(setAttribute.getType()) || - "session".equals(setAttribute.getType())) { - println("An attribute on the " + setAttribute.getType() + " object " + - "called " + setAttribute.getName() + " " + - "to the value " + - "" + setAttribute.getValue() + ""); - } else if ("cookie".equals(setAttribute.getType())) { - println("A cookie " + - "called " + setAttribute.getName() + " " + - " to the value " + - "" + setAttribute.getValue() + ""); - } else if ("locale".equals(setAttribute.getType())) { - println("locale to " + - "" + setAttribute.getValue() + ""); - } else if ("status".equals(setAttribute.getType())) { - println("status to " + - "" + setAttribute.getValue() + ""); - } else if ("content-type".equals(setAttribute.getType())) { - println("content-type to " + - "" + setAttribute.getValue() + ""); - } else if ("charset".equals(setAttribute.getType())) { - println("charset to " + - "" + setAttribute.getValue() + ""); - } - println("
    2. "); - - } - println("
    "); - } - - private void showRuns(RuleBase rule) { - List runs = rule.getRuns(); - if (runs.size() == 0) return; - - println("

    This rule will run:

    " + - "
      "); - for (int j = 0; j < runs.size(); j++) { - Run run = (Run) runs.get(j); - println("
    1. "); - println(" " + run.getMethodSignature() + " on an instance " + - "of " + "" + run.getClassStr() + ""); - if (run.isNewEachTime()) { - println(" (a new instance will be created for each rule match)"); - } - println("
    2. "); - } - println("
    "); - println("Note, if init(ServletConfig) or destroy() is found on the above " + - "object" + (runs.size() > 1 ? "s" : "") + " they will be run at when creating or destroying an instance."); - } - - private void showConditions(RuleBase rule) { - List conditions = rule.getConditions(); - if (conditions.size() == 0) return; - - println("

    Given that the following condition" + - (conditions.size() == 1 ? " is" : "s are") + " met.

    " + - "
      "); - for (int j = 0; j < conditions.size(); j++) { - Condition condition = (Condition) conditions.get(j); - println("
    1. "); - if ("header".equals(condition.getType())) { - println("The " + condition.getName() + " HTTP header " + - ("notequal".equals(condition.getOperator()) ? "does NOT match" : "matches") + " the value " + - "" + condition.getValue() + ""); - } else { - println("" + condition.getType() + " " + - (condition.getName() == null ? "" : "" + condition.getName() + " ") + - "is " + - ("greater".equals(condition.getOperator()) ? "greater than" : "") + - ("less".equals(condition.getOperator()) ? "less than" : "") + - ("equal".equals(condition.getOperator()) ? "equal to" : "") + - ("notequal".equals(condition.getOperator()) ? "NOT equal to" : "") + - ("greaterorequal".equals(condition.getOperator()) ? "is greater than or equal to" : "") + - ("lessorequal".equals(condition.getOperator()) ? "is less than or equal to" : "") + - " the value " + - (StringUtils.isBlank(condition.getValue()) ? condition.getName() : condition.getValue()) + ""); - } - if (j < conditions.size() - 1) { - println("" + condition.getNext() + ""); - } - println("
    2. "); - - } - println("
    "); - } - - private void showFooter() { - println("


    "); - println(""); - println(""); - } - - private void println() { - buffer.append("\n"); - } - - private void print(String s) { - buffer.append(s); - } - - private void println(String s) { - buffer.append(s); - println(); - } - - public StringBuffer getBuffer() { - return buffer; - } - -} - - - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpSession; +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Enumeration; +import java.util.List; + +/** + * Outputs information about urlrewritefilter. + *

    + * todo: add ability to trigger reload conf + * + * @author Paul Tuckey + * @version $Revision: 43 $ $Date: 2006-10-31 17:29:59 +1300 (Tue, 31 Oct 2006) $ + */ +public class Status { + + private static Log log = Log.getLog(Status.class); + + private StringBuffer buffer = new StringBuffer(); + + private Conf conf; + private UrlRewriteFilter urlRewriteFilter; + + public Status(Conf conf) { + this.conf = conf; + } + + public Status(Conf conf, UrlRewriteFilter urlRewriteFilter) { + this.conf = conf; + this.urlRewriteFilter = urlRewriteFilter; + } + + public void displayStatusInContainer(final HttpServletRequest hsRequest) { + showHeader(); + showRunningInfo(); + showConf(); + showRequestInfo(hsRequest); + showFooter(); + } + + public void displayStatusOffline() { + showHeader(); + showConf(); + showFooter(); + } + + + private void showRequestInfo(final HttpServletRequest hsRequest) { + // other info + println("

    Request Debug Info

    "); + + println("

    General

    "); + println("
    ");
    +
    +        println("method: " + hsRequest.getMethod());
    +        if (hsRequest.getAuthType() != null) println("auth-type: " + hsRequest.getAuthType());
    +        if (hsRequest.getCharacterEncoding() != null)
    +            println("character-encoding: " + hsRequest.getCharacterEncoding());
    +        println("context-path: " + hsRequest.getContextPath());
    +        if (hsRequest.getPathInfo() != null) println("path-info: " + hsRequest.getPathInfo());
    +        if (hsRequest.getPathTranslated() != null) println("path-translated: " + hsRequest.getPathTranslated());
    +        println("port: " + hsRequest.getServerPort());
    +        println("protocol: " + hsRequest.getProtocol());
    +        if (hsRequest.getQueryString() != null) println("query-string: " + hsRequest.getQueryString());
    +        println("remote-addr: " + hsRequest.getRemoteAddr());
    +        println("remote-host: " + hsRequest.getRemoteHost());
    +        if (hsRequest.getRemoteUser() != null) println("remote-user: " + hsRequest.getRemoteUser());
    +        if (hsRequest.getRequestedSessionId() != null)
    +            println("requested-session-id: " + hsRequest.getRequestedSessionId());
    +        println("request-uri: " + hsRequest.getRequestURI());
    +        println("request-url: " + hsRequest.getRequestURL());
    +        println("server-name: " + hsRequest.getServerName());
    +        println("scheme: " + hsRequest.getScheme());
    +
    +        println("
    "); + + HttpSession session = hsRequest.getSession(false); + if (session != null) { + println("

    Session

    "); + println("
    session-isnew: " + session.isNew()); + Enumeration enumer = session.getAttributeNames(); + while (enumer.hasMoreElements()) { + String name = (String) enumer.nextElement(); + println("
    session-attribute " + name + ": " + session.getAttribute(name)); + } + } + + // show headers from request + println("

    Request Headers

    "); + println("
    ");
    +        final Enumeration headers = hsRequest.getHeaderNames();
    +        while (headers.hasMoreElements()) {
    +            final String headerName = (String) headers.nextElement();
    +            // ignore cookies as they are handled later
    +            if ("cookie".equals(headerName)) continue;
    +            println(headerName + ": " + hsRequest.getHeader(headerName));
    +        }
    +        println("
    "); + + final Cookie[] cookies = hsRequest.getCookies(); + if (cookies != null && cookies.length > 0) { + println("

    Cookies

    "); + for (int i = 0; i < cookies.length; i++) { + println("
    Cookie " + i + "
    "); + final Cookie cookie = cookies[i]; + if (cookie == null) continue; + println("
    ");
    +                println("    name     : " + cookie.getName());
    +                println("    value    : " + cookie.getValue());
    +                println("    path     : " + cookie.getPath());
    +                println("    domain   : " + cookie.getDomain());
    +                println("    max age  : " + cookie.getMaxAge());
    +                println("    is secure: " + cookie.getSecure());
    +                println("    version  : " + cookie.getVersion());
    +                println("    comment  : " + cookie.getComment());
    +                println("
    "); + } + } + + // show headers from request + println("

    Time info

    "); + println("
    ");
    +        Calendar nowCal = Calendar.getInstance();
    +        println("time: " + nowCal.getTime().getTime());
    +        println("year: " + nowCal.get(Calendar.YEAR));
    +        println("month: " + nowCal.get(Calendar.MONTH));
    +        println("dayofmonth: " + nowCal.get(Calendar.DAY_OF_MONTH));
    +        println("dayofweek: " + nowCal.get(Calendar.DAY_OF_WEEK));
    +        println("ampm: " + nowCal.get(Calendar.AM_PM));
    +        println("hourofday: " + nowCal.get(Calendar.HOUR_OF_DAY));
    +        println("minute: " + nowCal.get(Calendar.MINUTE));
    +        println("second: " + nowCal.get(Calendar.SECOND));
    +        println("millisecond: " + nowCal.get(Calendar.MILLISECOND));
    +        println("
    "); + + } + + private void showConf() { + if (conf == null) return; + + println("

    Summary"); + if (conf.isLoadedFromFile()) println(" of " + conf.getFileName()); + println("

    "); + + if (!conf.isOk()) { + final List errors = conf.getErrors(); + println("

    Errors During Load of " + conf.getFileName() + "

    "); + println(""); + } + + int conditionsCount = 0; + final List rules = conf.getRules(); + for (int i = 0; i < rules.size(); i++) { + final Rule rule = (Rule) rules.get(i); + if (rule instanceof NormalRule) { + conditionsCount += ((NormalRule) rule).getConditions().size(); + } + } + final List outboundRules = conf.getOutboundRules(); + for (int i = 0; i < outboundRules.size(); i++) { + final OutboundRule rule = (OutboundRule) outboundRules.get(i); + conditionsCount += rule.getConditions().size(); + } + println("

    In total there " + + (rules.size() == 1 ? "is 1 rule" : "are " + rules.size() + " rules") + ", " + + (outboundRules.size() == 1 ? "1 outbound rule" : outboundRules.size() + " outbound rules") + + (conditionsCount > 0 ? " and " : "") + + (conditionsCount == 1 ? conditionsCount + " condition" : "") + + (conditionsCount > 1 ? conditionsCount + " conditions" : "") + + " in the configuration file.

    "); + + showRules(rules); + showOutboundRules(outboundRules); + println("
    "); + } + + private void showRules(List rules) { + for (int i = 0; i < rules.size(); i++) { + final Rule rule = (Rule) rules.get(i); + if (rule instanceof NormalRule) { + NormalRule normalRule = (NormalRule) rule; + println("

    " + normalRule.getDisplayName() + + (normalRule.isEnabled() ? "" : " **DISABLED**") + "

    "); + if (!StringUtils.isBlank(normalRule.getNote())) { + println("

    " + StringUtils.nl2br(normalRule.getNote()) + "

    "); + } + + print("

    URL's matching " + normalRule.getFrom() + ""); + if (normalRule.isFilter()) { + print(" (filter)"); + } + if (!StringUtils.isBlank(normalRule.getTo())) { + print(" will "); + if ("forward".equals(normalRule.getToType())) + print("be forwarded to"); + else if ("include".equals(normalRule.getToType())) + print("include"); + else if ("redirect".equals(normalRule.getToType())) + print("be redirected to"); + else + print("" + normalRule.getToType() + " to"); + print(" " + normalRule.getTo() + ""); + } + println(".

    "); + print("

    This rule and it's conditions will use the " + normalRule.getMatchType() + " matching engine.

    "); + showConditions(normalRule); + showSets(normalRule); + showRuns(normalRule); + + if (!rule.isLast()) { + println("

    Note, other rules will be processed after this rule.

    "); + } + } + if (rule instanceof ClassRule) { + ClassRule classRule = (ClassRule) rule; + println("

    " + classRule.getDisplayName() + + (classRule.isEnabled() ? "" : " **DISABLED**") + "

    "); + } + println(); + println(); + } + } + + private void showOutboundRules(List outboundRules) { + for (int i = 0; i < outboundRules.size(); i++) { + final OutboundRule rule = (OutboundRule) outboundRules.get(i); + println("

    " + rule.getDisplayName() + + (rule.isEnabled() ? "" : " **DISABLED**") + "

    "); + if (!StringUtils.isBlank(rule.getNote())) { + println("

    " + StringUtils.nl2br(rule.getNote()) + "

    "); + } + print("

    Outbound URL's matching " + rule.getFrom() + ""); + if (!StringUtils.isBlank(rule.getTo())) { + print(" will be rewritten to " + rule.getTo() + ""); + } + if (!rule.isEncodeFirst()) { + print(", after response.encodeURL() has been called"); + } + if (!rule.isEncodeToUrl()) { + print(", response.encodeURL() will not be called"); + } + println(".

    "); + + showConditions(rule); + showSets(rule); + showRuns(rule); + + if (!rule.isLast()) { + println("

    Note, other outbound rules will be processed after this rule.

    "); + } + println(); + println(); + } + } + + private void showHeader() { + SimpleDateFormat s = new SimpleDateFormat(); + println(""); + println(""); + println(""); + if ( conf == null ) { + println("UrlRewriteFilter configuration overview"); + } else { + println("UrlRewriteFilter configuration overview for " + conf.getFileName() + ""); + } + println(""); + println(""); + println("

    UrlRewriteFilter " + + UrlRewriteFilter.getFullVersionString() + " configuration overview " + + "(generated " + s.format(new Date()) + ")

    "); + println("
    "); + } + + private void showRunningInfo() { + println("

    Running Status

    "); + if (conf == null) { + println("

    ERROR: UrlRewriteFilter failed to load config, check server log

    "); + } else if (!conf.isOk()) { + println("

    ERROR: UrlRewriteFilter NOT ACTIVE

    "); + } + println("

    Conf"); + if (conf == null ) println(" empty.

    "); + if (conf != null && conf.isLoadedFromFile()) println("file " + conf.getFileName() + ""); + if (conf != null ) println("loaded " + conf.getLoadedDate() + ".

    "); + if (urlRewriteFilter != null) { + if (urlRewriteFilter.isConfReloadCheckEnabled()) { + Date nextReloadCheckDate = new Date(urlRewriteFilter.getConfReloadLastCheck().getTime() + + (urlRewriteFilter.getConfReloadCheckInterval() * 1000L)); + println("

    Conf file reload check enabled, last modified will be checked every " + + urlRewriteFilter.getConfReloadCheckInterval() + "s, last checked " + + urlRewriteFilter.getConfReloadLastCheck() + ", next check at " + + nextReloadCheckDate + " in " + + Math.round((nextReloadCheckDate.getTime() - System.currentTimeMillis()) / 1000d) + "s."); + } else { + println("Conf file reload check disabled"); + } + println("

    Status path " + urlRewriteFilter.getStatusPath() + ".

    "); + } + } + + private void displayRuleErrors(final List rules) { + for (int i = 0; i < rules.size(); i++) { + Object ruleObj = rules.get(i); + if (ruleObj instanceof Rule) { + final Rule rule = (Rule) rules.get(i); + if (rule.isValid()) continue; + println("
  • Error in " + rule.getDisplayName()); + println("
  • "); + } + if (ruleObj instanceof OutboundRule) { + final OutboundRule outboundRule = (OutboundRule) rules.get(i); + if (outboundRule.isValid()) continue; + println("
  • Error in " + outboundRule.getDisplayName()); + println("
  • "); + } + } + } + + private void displayRuleCondSetRun(List conditions, List sets, List runs) { + for (int j = 0; j < conditions.size(); j++) { + Condition condition = (Condition) conditions.get(j); + if (condition.getError() == null) continue; + println("
  • " + condition.getDisplayName() + " " + condition.getError() + "
  • "); + } + for (int j = 0; j < sets.size(); j++) { + SetAttribute setAttribute = (SetAttribute) sets.get(j); + if (setAttribute.getError() == null) continue; + println("
  • " + setAttribute.getDisplayName() + " " + setAttribute.getError() + "
  • "); + } + for (int j = 0; j < runs.size(); j++) { + Run run = (Run) runs.get(j); + if (run.getError() == null) continue; + println("
  • " + run.getDisplayName() + " " + run.getError() + "
  • "); + } + } + + private void displayCatchErrors(final List catchElems) { + for (int i = 0; i < catchElems.size(); i++) { + final CatchElem catchElem = (CatchElem) catchElems.get(i); + if (catchElem.isValid()) continue; + println("
  • Error in catch for " + catchElem.getClass() + "
  • "); + println(""); + } + } + + private void showSets(final RuleBase rule) { + if (rule.getSetAttributes().size() == 0) return; + List setAttributes = rule.getSetAttributes(); + println("

    This rule will set:

    " + + "
      "); + for (int j = 0; j < setAttributes.size(); j++) { + SetAttribute setAttribute = (SetAttribute) setAttributes.get(j); + println("
    1. "); + if ("response-header".equals(setAttribute.getType())) { + println("The " + setAttribute.getName() + " HTTP response header " + + "to " + setAttribute.getValue() + ""); + + } else if ("request".equals(setAttribute.getType()) || + "session".equals(setAttribute.getType())) { + println("An attribute on the " + setAttribute.getType() + " object " + + "called " + setAttribute.getName() + " " + + "to the value " + + "" + setAttribute.getValue() + ""); + } else if ("cookie".equals(setAttribute.getType())) { + println("A cookie " + + "called " + setAttribute.getName() + " " + + " to the value " + + "" + setAttribute.getValue() + ""); + } else if ("locale".equals(setAttribute.getType())) { + println("locale to " + + "" + setAttribute.getValue() + ""); + } else if ("status".equals(setAttribute.getType())) { + println("status to " + + "" + setAttribute.getValue() + ""); + } else if ("content-type".equals(setAttribute.getType())) { + println("content-type to " + + "" + setAttribute.getValue() + ""); + } else if ("charset".equals(setAttribute.getType())) { + println("charset to " + + "" + setAttribute.getValue() + ""); + } + println("
    2. "); + + } + println("
    "); + } + + private void showRuns(RuleBase rule) { + List runs = rule.getRuns(); + if (runs.size() == 0) return; + + println("

    This rule will run:

    " + + "
      "); + for (int j = 0; j < runs.size(); j++) { + Run run = (Run) runs.get(j); + println("
    1. "); + println(" " + run.getMethodSignature() + " on an instance " + + "of " + "" + run.getClassStr() + ""); + if (run.isNewEachTime()) { + println(" (a new instance will be created for each rule match)"); + } + println("
    2. "); + } + println("
    "); + println("Note, if init(ServletConfig) or destroy() is found on the above " + + "object" + (runs.size() > 1 ? "s" : "") + " they will be run at when creating or destroying an instance."); + } + + private void showConditions(RuleBase rule) { + List conditions = rule.getConditions(); + if (conditions.size() == 0) return; + + println("

    Given that the following condition" + + (conditions.size() == 1 ? " is" : "s are") + " met.

    " + + "
      "); + for (int j = 0; j < conditions.size(); j++) { + Condition condition = (Condition) conditions.get(j); + println("
    1. "); + if ("header".equals(condition.getType())) { + println("The " + condition.getName() + " HTTP header " + + ("notequal".equals(condition.getOperator()) ? "does NOT match" : "matches") + " the value " + + "" + condition.getValue() + ""); + } else { + println("" + condition.getType() + " " + + (condition.getName() == null ? "" : "" + condition.getName() + " ") + + "is " + + ("greater".equals(condition.getOperator()) ? "greater than" : "") + + ("less".equals(condition.getOperator()) ? "less than" : "") + + ("equal".equals(condition.getOperator()) ? "equal to" : "") + + ("notequal".equals(condition.getOperator()) ? "NOT equal to" : "") + + ("greaterorequal".equals(condition.getOperator()) ? "is greater than or equal to" : "") + + ("lessorequal".equals(condition.getOperator()) ? "is less than or equal to" : "") + + " the value " + + (StringUtils.isBlank(condition.getValue()) ? condition.getName() : condition.getValue()) + ""); + } + if (j < conditions.size() - 1) { + println("" + condition.getNext() + ""); + } + println("
    2. "); + + } + println("
    "); + } + + private void showFooter() { + println("


    "); + println(""); + println(""); + } + + private void println() { + buffer.append("\n"); + } + + private void print(String s) { + buffer.append(s); + } + + private void println(String s) { + buffer.append(s); + println(); + } + + public StringBuffer getBuffer() { + return buffer; + } + +} + + + diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/TypeConverter.java b/src/main/java/org/tuckey/web/filters/urlrewrite/TypeConverter.java index a5e5ec17..9502064e 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/TypeConverter.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/TypeConverter.java @@ -1,332 +1,332 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; - -/** - * Assists with the setting of variable type names for condition types and rule to variables. - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class TypeConverter { - - /** - * Type of condition ie, header, port etc. - */ - protected short type; - - /** - * Error message from the regular expression compilation. - */ - protected String error = null; - - // Type statics - public static final short TYPE_TIME = 4; - public static final short TYPE_TIME_YEAR = 5; - public static final short TYPE_TIME_MONTH = 6; - public static final short TYPE_TIME_DAY_OF_MONTH = 7; - public static final short TYPE_TIME_DAY_OF_WEEK = 8; - public static final short TYPE_TIME_AMPM = 9; - public static final short TYPE_TIME_HOUR_OF_DAY = 10; - public static final short TYPE_TIME_MINUTE = 11; - public static final short TYPE_TIME_SECOND = 12; - public static final short TYPE_TIME_MILLISECOND = 13; - public static final short TYPE_ATTRIBUTE = 14; - public static final short TYPE_AUTH_TYPE = 15; - public static final short TYPE_CHARACTER_ENCODING = 16; - public static final short TYPE_CONTENT_LENGTH = 17; - public static final short TYPE_CONTENT_TYPE = 18; - public static final short TYPE_CONTEXT_PATH = 19; - public static final short TYPE_COOKIE = 20; - public static final short TYPE_HEADER = 1; - public static final short TYPE_LOCAL_PORT = 39; - public static final short TYPE_METHOD = 21; - public static final short TYPE_PARAMETER = 22; - public static final short TYPE_PATH_INFO = 23; - public static final short TYPE_PATH_TRANSLATED = 24; - public static final short TYPE_PROTOCOL = 25; - public static final short TYPE_QUERY_STRING = 26; - public static final short TYPE_REMOTE_ADDR = 27; - public static final short TYPE_REMOTE_HOST = 28; - public static final short TYPE_REMOTE_USER = 29; - public static final short TYPE_REQUESTED_SESSION_ID = 30; - public static final short TYPE_REQUEST_URI = 31; - public static final short TYPE_REQUEST_URL = 32; - public static final short TYPE_SESSION_ATTRIBUTE = 33; - public static final short TYPE_SESSION_IS_NEW = 34; - public static final short TYPE_SERVER_PORT = 35; - public static final short TYPE_SERVER_NAME = 36; - public static final short TYPE_SCHEME = 37; - public static final short TYPE_USER_IN_ROLE = 38; - public static final short TYPE_EXCEPTION = 40; - public static final short TYPE_REQUESTED_SESSION_ID_FROM_COOKIE = 41; - public static final short TYPE_REQUESTED_SESSION_ID_FROM_URL = 42; - public static final short TYPE_REQUESTED_SESSION_ID_VALID = 43; - public static final short TYPE_REQUEST_FILENAME = 44; - public static final short TYPE_SERVLET_CONTEXT = 45; - - /** - * Will get the type code ie, method, port, header etc. - * - * @return String - */ - public String getType() { - switch (type) { - - case TYPE_TIME: - return "time"; - case TYPE_TIME_YEAR: - return "year"; - case TYPE_TIME_MONTH: - return "month"; - case TYPE_TIME_DAY_OF_MONTH: - return "dayofmonth"; - case TYPE_TIME_DAY_OF_WEEK: - return "dayofweek"; - - case TYPE_TIME_AMPM: - return "ampm"; - case TYPE_TIME_HOUR_OF_DAY: - return "hourofday"; - case TYPE_TIME_MINUTE: - return "minute"; - case TYPE_TIME_SECOND: - return "second"; - case TYPE_TIME_MILLISECOND: - return "millisecond"; - - case TYPE_ATTRIBUTE: - return "attribute"; - case TYPE_AUTH_TYPE: - return "auth-type"; - case TYPE_CHARACTER_ENCODING: - return "character-encoding"; - case TYPE_CONTENT_LENGTH: - return "content-length"; - case TYPE_CONTENT_TYPE: - return "content-type"; - - case TYPE_CONTEXT_PATH: - return "context-path"; - case TYPE_COOKIE: - return "cookie"; - case TYPE_HEADER: - return "header"; - case TYPE_LOCAL_PORT: - return "local-port"; - case TYPE_METHOD: - return "method"; - case TYPE_PARAMETER: - return "parameter"; - - case TYPE_PATH_INFO: - return "path-info"; - case TYPE_PATH_TRANSLATED: - return "path-translated"; - case TYPE_PROTOCOL: - return "protocol"; - case TYPE_QUERY_STRING: - return "query-string"; - case TYPE_REMOTE_ADDR: - return "remote-addr"; - - case TYPE_REMOTE_HOST: - return "remote-host"; - case TYPE_REMOTE_USER: - return "remote-user"; - case TYPE_REQUESTED_SESSION_ID: - return "requested-session-id"; - case TYPE_REQUESTED_SESSION_ID_FROM_COOKIE: - return "requested-session-id-from-cookie"; - case TYPE_REQUESTED_SESSION_ID_FROM_URL: - return "requested-session-id-from-url"; - case TYPE_REQUESTED_SESSION_ID_VALID: - return "requested-session-id-valid"; - case TYPE_REQUEST_URI: - return "request-uri"; - case TYPE_REQUEST_URL: - return "request-url"; - case TYPE_SESSION_ATTRIBUTE: - return "session-attribute"; - case TYPE_SESSION_IS_NEW: - return "session-isnew"; - case TYPE_SERVER_PORT: - return "port"; - case TYPE_SERVER_NAME: - return "server-name"; - case TYPE_SCHEME: - return "scheme"; - - case TYPE_USER_IN_ROLE: - return "user-in-role"; - case TYPE_EXCEPTION: - return "exception"; - case TYPE_REQUEST_FILENAME: - return "request-filename"; - case TYPE_SERVLET_CONTEXT: - return "context"; - default: - return ""; - } - } - - /** - * Will set the type. - * - * @param strType the type - */ - public void setType(final String strType) { - if ("time".equals(strType)) { - this.type = TYPE_TIME; - } else if ("year".equals(strType)) { - this.type = TYPE_TIME_YEAR; - } else if ("month".equals(strType)) { - this.type = TYPE_TIME_MONTH; - } else if ("dayofmonth".equals(strType)) { - this.type = TYPE_TIME_DAY_OF_MONTH; - } else if ("dayofweek".equals(strType)) { - this.type = TYPE_TIME_DAY_OF_WEEK; - - } else if ("ampm".equals(strType)) { - this.type = TYPE_TIME_AMPM; - } else if ("hourofday".equals(strType)) { - this.type = TYPE_TIME_HOUR_OF_DAY; - } else if ("minute".equals(strType)) { - this.type = TYPE_TIME_MINUTE; - } else if ("second".equals(strType)) { - this.type = TYPE_TIME_SECOND; - } else if ("millisecond".equals(strType)) { - this.type = TYPE_TIME_MILLISECOND; - - } else if ("attribute".equals(strType)) { - this.type = TYPE_ATTRIBUTE; - } else if ("auth-type".equals(strType)) { - this.type = TYPE_AUTH_TYPE; - } else if ("character-encoding".equals(strType)) { - this.type = TYPE_CHARACTER_ENCODING; - } else if ("content-length".equals(strType)) { - this.type = TYPE_CONTENT_LENGTH; - } else if ("content-type".equals(strType)) { - this.type = TYPE_CONTENT_TYPE; - - } else if ("context-path".equals(strType)) { - this.type = TYPE_CONTEXT_PATH; - } else if ("cookie".equals(strType)) { - this.type = TYPE_COOKIE; - } else if ("header".equals(strType) || StringUtils.isBlank(strType)) { - this.type = TYPE_HEADER; - } else if ("local-port".equals(strType)) { - this.type = TYPE_LOCAL_PORT; - } else if ("method".equals(strType)) { - this.type = TYPE_METHOD; - } else if ("parameter".equals(strType) || "param".equals(strType)) { - this.type = TYPE_PARAMETER; - - } else if ("path-info".equals(strType)) { - this.type = TYPE_PATH_INFO; - } else if ("path-translated".equals(strType)) { - this.type = TYPE_PATH_TRANSLATED; - } else if ("protocol".equals(strType)) { - this.type = TYPE_PROTOCOL; - } else if ("query-string".equals(strType)) { - this.type = TYPE_QUERY_STRING; - } else if ("remote-addr".equals(strType)) { - this.type = TYPE_REMOTE_ADDR; - - } else if ("remote-host".equals(strType)) { - this.type = TYPE_REMOTE_HOST; - } else if ("remote-user".equals(strType)) { - this.type = TYPE_REMOTE_USER; - } else if ("requested-session-id".equals(strType)) { - this.type = TYPE_REQUESTED_SESSION_ID; - } else if ("requested-session-id-from-cookie".equals(strType)) { - this.type = TYPE_REQUESTED_SESSION_ID_FROM_COOKIE; - } else if ("requested-session-id-from-url".equals(strType)) { - this.type = TYPE_REQUESTED_SESSION_ID_FROM_URL; - } else if ("requested-session-id-valid".equals(strType)) { - this.type = TYPE_REQUESTED_SESSION_ID_VALID; - } else if ("request-uri".equals(strType)) { - this.type = TYPE_REQUEST_URI; - } else if ("request-url".equals(strType)) { - this.type = TYPE_REQUEST_URL; - - } else if ("session-attribute".equals(strType)) { - this.type = TYPE_SESSION_ATTRIBUTE; - } else if ("session-isnew".equals(strType)) { - this.type = TYPE_SESSION_IS_NEW; - } else if ("port".equals(strType)) { - this.type = TYPE_SERVER_PORT; - } else if ("server-name".equals(strType)) { - this.type = TYPE_SERVER_NAME; - } else if ("scheme".equals(strType)) { - this.type = TYPE_SCHEME; - - } else if ("user-in-role".equals(strType)) { - this.type = TYPE_USER_IN_ROLE; - - } else if ("exception".equals(strType)) { - this.type = TYPE_EXCEPTION; - - } else if ("request-filename".equals(strType)) { - this.type = TYPE_REQUEST_FILENAME; - - } else if ("context".equals(strType)) { - this.type = TYPE_SERVLET_CONTEXT; - - }else { - setError("Type " + strType + " is not valid"); - } - } - - - /** - * Will get the description of the error. - * - * @return String - */ - public final String getError() { - return error; - } - - protected void setError(String error) { - this.error = error; - } - - public int getTypeShort() { - return type; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; + +/** + * Assists with the setting of variable type names for condition types and rule to variables. + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class TypeConverter { + + /** + * Type of condition ie, header, port etc. + */ + protected short type; + + /** + * Error message from the regular expression compilation. + */ + protected String error = null; + + // Type statics + public static final short TYPE_TIME = 4; + public static final short TYPE_TIME_YEAR = 5; + public static final short TYPE_TIME_MONTH = 6; + public static final short TYPE_TIME_DAY_OF_MONTH = 7; + public static final short TYPE_TIME_DAY_OF_WEEK = 8; + public static final short TYPE_TIME_AMPM = 9; + public static final short TYPE_TIME_HOUR_OF_DAY = 10; + public static final short TYPE_TIME_MINUTE = 11; + public static final short TYPE_TIME_SECOND = 12; + public static final short TYPE_TIME_MILLISECOND = 13; + public static final short TYPE_ATTRIBUTE = 14; + public static final short TYPE_AUTH_TYPE = 15; + public static final short TYPE_CHARACTER_ENCODING = 16; + public static final short TYPE_CONTENT_LENGTH = 17; + public static final short TYPE_CONTENT_TYPE = 18; + public static final short TYPE_CONTEXT_PATH = 19; + public static final short TYPE_COOKIE = 20; + public static final short TYPE_HEADER = 1; + public static final short TYPE_LOCAL_PORT = 39; + public static final short TYPE_METHOD = 21; + public static final short TYPE_PARAMETER = 22; + public static final short TYPE_PATH_INFO = 23; + public static final short TYPE_PATH_TRANSLATED = 24; + public static final short TYPE_PROTOCOL = 25; + public static final short TYPE_QUERY_STRING = 26; + public static final short TYPE_REMOTE_ADDR = 27; + public static final short TYPE_REMOTE_HOST = 28; + public static final short TYPE_REMOTE_USER = 29; + public static final short TYPE_REQUESTED_SESSION_ID = 30; + public static final short TYPE_REQUEST_URI = 31; + public static final short TYPE_REQUEST_URL = 32; + public static final short TYPE_SESSION_ATTRIBUTE = 33; + public static final short TYPE_SESSION_IS_NEW = 34; + public static final short TYPE_SERVER_PORT = 35; + public static final short TYPE_SERVER_NAME = 36; + public static final short TYPE_SCHEME = 37; + public static final short TYPE_USER_IN_ROLE = 38; + public static final short TYPE_EXCEPTION = 40; + public static final short TYPE_REQUESTED_SESSION_ID_FROM_COOKIE = 41; + public static final short TYPE_REQUESTED_SESSION_ID_FROM_URL = 42; + public static final short TYPE_REQUESTED_SESSION_ID_VALID = 43; + public static final short TYPE_REQUEST_FILENAME = 44; + public static final short TYPE_SERVLET_CONTEXT = 45; + + /** + * Will get the type code ie, method, port, header etc. + * + * @return String + */ + public String getType() { + switch (type) { + + case TYPE_TIME: + return "time"; + case TYPE_TIME_YEAR: + return "year"; + case TYPE_TIME_MONTH: + return "month"; + case TYPE_TIME_DAY_OF_MONTH: + return "dayofmonth"; + case TYPE_TIME_DAY_OF_WEEK: + return "dayofweek"; + + case TYPE_TIME_AMPM: + return "ampm"; + case TYPE_TIME_HOUR_OF_DAY: + return "hourofday"; + case TYPE_TIME_MINUTE: + return "minute"; + case TYPE_TIME_SECOND: + return "second"; + case TYPE_TIME_MILLISECOND: + return "millisecond"; + + case TYPE_ATTRIBUTE: + return "attribute"; + case TYPE_AUTH_TYPE: + return "auth-type"; + case TYPE_CHARACTER_ENCODING: + return "character-encoding"; + case TYPE_CONTENT_LENGTH: + return "content-length"; + case TYPE_CONTENT_TYPE: + return "content-type"; + + case TYPE_CONTEXT_PATH: + return "context-path"; + case TYPE_COOKIE: + return "cookie"; + case TYPE_HEADER: + return "header"; + case TYPE_LOCAL_PORT: + return "local-port"; + case TYPE_METHOD: + return "method"; + case TYPE_PARAMETER: + return "parameter"; + + case TYPE_PATH_INFO: + return "path-info"; + case TYPE_PATH_TRANSLATED: + return "path-translated"; + case TYPE_PROTOCOL: + return "protocol"; + case TYPE_QUERY_STRING: + return "query-string"; + case TYPE_REMOTE_ADDR: + return "remote-addr"; + + case TYPE_REMOTE_HOST: + return "remote-host"; + case TYPE_REMOTE_USER: + return "remote-user"; + case TYPE_REQUESTED_SESSION_ID: + return "requested-session-id"; + case TYPE_REQUESTED_SESSION_ID_FROM_COOKIE: + return "requested-session-id-from-cookie"; + case TYPE_REQUESTED_SESSION_ID_FROM_URL: + return "requested-session-id-from-url"; + case TYPE_REQUESTED_SESSION_ID_VALID: + return "requested-session-id-valid"; + case TYPE_REQUEST_URI: + return "request-uri"; + case TYPE_REQUEST_URL: + return "request-url"; + case TYPE_SESSION_ATTRIBUTE: + return "session-attribute"; + case TYPE_SESSION_IS_NEW: + return "session-isnew"; + case TYPE_SERVER_PORT: + return "port"; + case TYPE_SERVER_NAME: + return "server-name"; + case TYPE_SCHEME: + return "scheme"; + + case TYPE_USER_IN_ROLE: + return "user-in-role"; + case TYPE_EXCEPTION: + return "exception"; + case TYPE_REQUEST_FILENAME: + return "request-filename"; + case TYPE_SERVLET_CONTEXT: + return "context"; + default: + return ""; + } + } + + /** + * Will set the type. + * + * @param strType the type + */ + public void setType(final String strType) { + if ("time".equals(strType)) { + this.type = TYPE_TIME; + } else if ("year".equals(strType)) { + this.type = TYPE_TIME_YEAR; + } else if ("month".equals(strType)) { + this.type = TYPE_TIME_MONTH; + } else if ("dayofmonth".equals(strType)) { + this.type = TYPE_TIME_DAY_OF_MONTH; + } else if ("dayofweek".equals(strType)) { + this.type = TYPE_TIME_DAY_OF_WEEK; + + } else if ("ampm".equals(strType)) { + this.type = TYPE_TIME_AMPM; + } else if ("hourofday".equals(strType)) { + this.type = TYPE_TIME_HOUR_OF_DAY; + } else if ("minute".equals(strType)) { + this.type = TYPE_TIME_MINUTE; + } else if ("second".equals(strType)) { + this.type = TYPE_TIME_SECOND; + } else if ("millisecond".equals(strType)) { + this.type = TYPE_TIME_MILLISECOND; + + } else if ("attribute".equals(strType)) { + this.type = TYPE_ATTRIBUTE; + } else if ("auth-type".equals(strType)) { + this.type = TYPE_AUTH_TYPE; + } else if ("character-encoding".equals(strType)) { + this.type = TYPE_CHARACTER_ENCODING; + } else if ("content-length".equals(strType)) { + this.type = TYPE_CONTENT_LENGTH; + } else if ("content-type".equals(strType)) { + this.type = TYPE_CONTENT_TYPE; + + } else if ("context-path".equals(strType)) { + this.type = TYPE_CONTEXT_PATH; + } else if ("cookie".equals(strType)) { + this.type = TYPE_COOKIE; + } else if ("header".equals(strType) || StringUtils.isBlank(strType)) { + this.type = TYPE_HEADER; + } else if ("local-port".equals(strType)) { + this.type = TYPE_LOCAL_PORT; + } else if ("method".equals(strType)) { + this.type = TYPE_METHOD; + } else if ("parameter".equals(strType) || "param".equals(strType)) { + this.type = TYPE_PARAMETER; + + } else if ("path-info".equals(strType)) { + this.type = TYPE_PATH_INFO; + } else if ("path-translated".equals(strType)) { + this.type = TYPE_PATH_TRANSLATED; + } else if ("protocol".equals(strType)) { + this.type = TYPE_PROTOCOL; + } else if ("query-string".equals(strType)) { + this.type = TYPE_QUERY_STRING; + } else if ("remote-addr".equals(strType)) { + this.type = TYPE_REMOTE_ADDR; + + } else if ("remote-host".equals(strType)) { + this.type = TYPE_REMOTE_HOST; + } else if ("remote-user".equals(strType)) { + this.type = TYPE_REMOTE_USER; + } else if ("requested-session-id".equals(strType)) { + this.type = TYPE_REQUESTED_SESSION_ID; + } else if ("requested-session-id-from-cookie".equals(strType)) { + this.type = TYPE_REQUESTED_SESSION_ID_FROM_COOKIE; + } else if ("requested-session-id-from-url".equals(strType)) { + this.type = TYPE_REQUESTED_SESSION_ID_FROM_URL; + } else if ("requested-session-id-valid".equals(strType)) { + this.type = TYPE_REQUESTED_SESSION_ID_VALID; + } else if ("request-uri".equals(strType)) { + this.type = TYPE_REQUEST_URI; + } else if ("request-url".equals(strType)) { + this.type = TYPE_REQUEST_URL; + + } else if ("session-attribute".equals(strType)) { + this.type = TYPE_SESSION_ATTRIBUTE; + } else if ("session-isnew".equals(strType)) { + this.type = TYPE_SESSION_IS_NEW; + } else if ("port".equals(strType)) { + this.type = TYPE_SERVER_PORT; + } else if ("server-name".equals(strType)) { + this.type = TYPE_SERVER_NAME; + } else if ("scheme".equals(strType)) { + this.type = TYPE_SCHEME; + + } else if ("user-in-role".equals(strType)) { + this.type = TYPE_USER_IN_ROLE; + + } else if ("exception".equals(strType)) { + this.type = TYPE_EXCEPTION; + + } else if ("request-filename".equals(strType)) { + this.type = TYPE_REQUEST_FILENAME; + + } else if ("context".equals(strType)) { + this.type = TYPE_SERVLET_CONTEXT; + + }else { + setError("Type " + strType + " is not valid"); + } + } + + + /** + * Will get the description of the error. + * + * @return String + */ + public final String getError() { + return error; + } + + protected void setError(String error) { + this.error = error; + } + + public int getTypeShort() { + return type; + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteDocTask.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteDocTask.java index d6930c6f..5394e4a3 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteDocTask.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteDocTask.java @@ -1,111 +1,111 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Task; -import org.tuckey.web.filters.urlrewrite.utils.Log; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.IOException; - - -/** - * Used for javadoc style output of conf file. - * todo: doc for urlrewrite links to javadocs for actions - * - * @author Paul Tuckey - * @version $Revision: 49 $ $Date: 2006-12-08 10:09:07 +1300 (Fri, 08 Dec 2006) $ - */ -public class UrlRewriteDocTask extends Task { - - private File conf = new File(UrlRewriteFilter.DEFAULT_WEB_CONF_PATH); - private File dest = new File("urlrewrite-conf-overview.html"); - private String logLevel = "INFO"; - - public void execute() throws BuildException { - try { - Log.setLevel("SYSOUT:" + logLevel); - show(); - - } catch (FileNotFoundException e) { - throw new BuildException(e); - } catch (IOException e) { - throw new BuildException(e); - } - } - - private void show() throws IOException { - // make sure we don't have claspath issues when we load runs - Run.setLoadClass(false); - CatchElem.setLoadClass(false); - - Conf confObj = new Conf(new FileInputStream(conf), conf.getName()); - confObj.initialise(); - - if (!confObj.isOk()) { - throw new BuildException("conf is not ok"); - } - log("loaded fine with " + confObj.getRules().size() + " rules"); - - File reportFile = dest; - if (reportFile.exists()) { - reportFile.delete(); - } - FileWriter writer; - writer = new FileWriter(reportFile); - - Status status = new Status(confObj); - status.displayStatusOffline(); - - writer.write(status.getBuffer().toString()); - writer.close(); - } - - public void setConf(File conf) { - this.conf = conf; - } - - public void setDest(File dest) { - this.dest = dest; - } - - public void setLogLevel(String logLevel) { - this.logLevel = logLevel; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.tuckey.web.filters.urlrewrite.utils.Log; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; + + +/** + * Used for javadoc style output of conf file. + * todo: doc for urlrewrite links to javadocs for actions + * + * @author Paul Tuckey + * @version $Revision: 49 $ $Date: 2006-12-08 10:09:07 +1300 (Fri, 08 Dec 2006) $ + */ +public class UrlRewriteDocTask extends Task { + + private File conf = new File(UrlRewriteFilter.DEFAULT_WEB_CONF_PATH); + private File dest = new File("urlrewrite-conf-overview.html"); + private String logLevel = "INFO"; + + public void execute() throws BuildException { + try { + Log.setLevel("SYSOUT:" + logLevel); + show(); + + } catch (FileNotFoundException e) { + throw new BuildException(e); + } catch (IOException e) { + throw new BuildException(e); + } + } + + private void show() throws IOException { + // make sure we don't have claspath issues when we load runs + Run.setLoadClass(false); + CatchElem.setLoadClass(false); + + Conf confObj = new Conf(new FileInputStream(conf), conf.getName()); + confObj.initialise(); + + if (!confObj.isOk()) { + throw new BuildException("conf is not ok"); + } + log("loaded fine with " + confObj.getRules().size() + " rules"); + + File reportFile = dest; + if (reportFile.exists()) { + reportFile.delete(); + } + FileWriter writer; + writer = new FileWriter(reportFile); + + Status status = new Status(confObj); + status.displayStatusOffline(); + + writer.write(status.getBuffer().toString()); + writer.close(); + } + + public void setConf(File conf) { + this.conf = conf; + } + + public void setDest(File dest) { + this.dest = dest; + } + + public void setLogLevel(String logLevel) { + this.logLevel = logLevel; + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilter.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilter.java index f78afc71..cb90909b 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilter.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilter.java @@ -1,569 +1,569 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.ModRewriteConfLoader; -import org.tuckey.web.filters.urlrewrite.utils.NumberUtils; -import org.tuckey.web.filters.urlrewrite.utils.ServerNameMatcher; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Date; -import java.util.Properties; - -/** - * Based on the popular and very useful mod_rewrite for apache, UrlRewriteFilter is a Java Web Filter for any J2EE - * compliant web application server (such as Resin or Tomcat), which allows you to rewrite URLs before they get to your - * code. It is a very powerful tool just like Apache's mod_rewrite. - *

    - * The main things it is used for are: - *

    - *

    - * UrlRewriteFilter uses an xml file, called urlrewrite.xml (lives in the WEB-INF directory), for configuration. Most - * parameters can be Perl5 style Regular Expressions or Wildcards (i.e. *). This makes it very powerful indeed. - *

    - * Special thanks to all those who gave patches/feedback especially Vineet Kumar. - *

    - * Thanks also to Ralf S. Engelschall (www.engelschall.com) the inventor of mod_rewrite. - *

    - * - * @author Paul Tuckey - * @version $Revision: 51 $ $Date: 2006-12-08 11:37:07 +1300 (Fri, 08 Dec 2006) $ - */ -public class UrlRewriteFilter implements Filter { - - private static Log log = Log.getLog(UrlRewriteFilter.class); - - public static final String DEFAULT_WEB_CONF_PATH = "/WEB-INF/urlrewrite.xml"; - - /** - * The conf for this filter. - */ - private UrlRewriter urlRewriter = null; - - /** - * A user defined setting that can enable conf reloading. - */ - private boolean confReloadCheckEnabled = false; - - /** - * A user defined setting that says how often to check the conf has changed. - */ - private int confReloadCheckInterval = 0; - - /** - * A user defined setting that will allow configuration to be swapped via an HTTP to rewrite-status. - */ - private boolean allowConfSwapViaHttp = false; - - /** - * The last time that the conf file was loaded. - */ - private long confLastLoad = 0; - private Conf confLastLoaded = null; - private long confReloadLastCheck = 30; - private boolean confLoadedFromFile = true; - - /** - * path to conf file. - */ - private String confPath; - - /** - * Flag to make sure we don't bog the filter down during heavy load. - */ - private boolean confReloadInProgress = false; - - private boolean statusEnabled = true; - private String statusPath = "/rewrite-status"; - - private boolean modRewriteStyleConf = false; - public static final String DEFAULT_MOD_REWRITE_STYLE_CONF_PATH = "/WEB-INF/.htaccess"; - - private ServerNameMatcher statusServerNameMatcher; - private static final String DEFAULT_STATUS_ENABLED_ON_HOSTS = "localhost, local, 127.0.0.1"; - - - /** - * - */ - private ServletContext context = null; - - /** - * Init is called automatically by the application server when it creates this filter. - * - * @param filterConfig The config of the filter - */ - public void init(final FilterConfig filterConfig) throws ServletException { - - log.debug("filter init called"); - if (filterConfig == null) { - log.error("unable to init filter as filter config is null"); - return; - } - - log.debug("init: calling destroy just in case we are being re-inited uncleanly"); - destroyActual(); - - context = filterConfig.getServletContext(); - if (context == null) { - log.error("unable to init as servlet context is null"); - return; - } - - // set the conf of the logger to make sure we get the messages in context log - Log.setConfiguration(filterConfig); - - // get init paramerers from context web.xml file - String confReloadCheckIntervalStr = filterConfig.getInitParameter("confReloadCheckInterval"); - String confPathStr = filterConfig.getInitParameter("confPath"); - String statusPathConf = filterConfig.getInitParameter("statusPath"); - String statusEnabledConf = filterConfig.getInitParameter("statusEnabled"); - String statusEnabledOnHosts = filterConfig.getInitParameter("statusEnabledOnHosts"); - - String allowConfSwapViaHttpStr = filterConfig.getInitParameter("allowConfSwapViaHttp"); - if (!StringUtils.isBlank(allowConfSwapViaHttpStr)) { - allowConfSwapViaHttp = "true".equalsIgnoreCase(allowConfSwapViaHttpStr); - } - - // confReloadCheckInterval (default to null) - if (!StringUtils.isBlank(confReloadCheckIntervalStr)) { - // convert to millis - confReloadCheckInterval = 1000 * NumberUtils.stringToInt(confReloadCheckIntervalStr); - - if (confReloadCheckInterval < 0) { - confReloadCheckEnabled = false; - log.info("conf reload check disabled"); - - } else if (confReloadCheckInterval == 0) { - confReloadCheckEnabled = true; - log.info("conf reload check performed each request"); - - } else { - confReloadCheckEnabled = true; - log.info("conf reload check set to " + confReloadCheckInterval / 1000 + "s"); - } - - } else { - confReloadCheckEnabled = false; - } - - String modRewriteConf = filterConfig.getInitParameter("modRewriteConf"); - if (!StringUtils.isBlank(modRewriteConf)) { - modRewriteStyleConf = "true".equals(StringUtils.trim(modRewriteConf).toLowerCase()); - } - - if (!StringUtils.isBlank(confPathStr)) { - confPath = StringUtils.trim(confPathStr); - } else { - confPath = modRewriteStyleConf ? DEFAULT_MOD_REWRITE_STYLE_CONF_PATH : DEFAULT_WEB_CONF_PATH; - } - log.debug("confPath set to " + confPath); - - // status enabled (default true) - if (statusEnabledConf != null && !"".equals(statusEnabledConf)) { - log.debug("statusEnabledConf set to " + statusEnabledConf); - statusEnabled = "true".equals(statusEnabledConf.toLowerCase()); - } - if (statusEnabled) { - // status path (default /rewrite-status) - if (statusPathConf != null && !"".equals(statusPathConf)) { - statusPath = statusPathConf.trim(); - log.info("status display enabled, path set to " + statusPath); - } - } else { - log.info("status display disabled"); - } - - if (StringUtils.isBlank(statusEnabledOnHosts)) { - statusEnabledOnHosts = DEFAULT_STATUS_ENABLED_ON_HOSTS; - } else { - log.debug("statusEnabledOnHosts set to " + statusEnabledOnHosts); - } - statusServerNameMatcher = new ServerNameMatcher(statusEnabledOnHosts); - - // now load conf from snippet in web.xml if modRewriteStyleConf is set - String modRewriteConfText = filterConfig.getInitParameter("modRewriteConfText"); - if (!StringUtils.isBlank(modRewriteConfText)) { - ModRewriteConfLoader loader = new ModRewriteConfLoader(); - Conf conf = new Conf(); - loader.process(modRewriteConfText, conf); - conf.initialise(); - checkConf(conf); - confLoadedFromFile = false; - - } else { - - loadUrlRewriter(filterConfig); - } - } - - /** - * Separate from init so that it can be overidden. - */ - protected void loadUrlRewriter(FilterConfig filterConfig) throws ServletException { - try { - loadUrlRewriterLocal(); - } catch(Throwable e) { - log.error(e); - throw new ServletException(e); - } - } - - private void loadUrlRewriterLocal() { - URL confUrl = null; - InputStream inputStream = null; - try { - File confFile = new File(confPath); - if (confFile.exists()) { - inputStream = new FileInputStream(confFile); - confUrl = confFile.toURI().toURL(); - } - } catch (FileNotFoundException e) { - log.debug(e); - } catch (MalformedURLException ex) { - log.debug(ex); - } - if (inputStream == null) { - inputStream = context.getResourceAsStream(confPath); - // attempt to retrieve from location other than local WEB-INF - if (inputStream == null) { - inputStream = ClassLoader.getSystemResourceAsStream(confPath); - } - try { - confUrl = context.getResource(confPath); - } catch (MalformedURLException e) { - log.debug(e); - } - } - String confUrlStr = null; - if (confUrl != null) { - confUrlStr = confUrl.toString(); - } - if (inputStream == null) { - log.error("unable to find urlrewrite conf file at " + confPath); - // set the writer back to null - if (urlRewriter != null) { - log.error("unloading existing conf"); - urlRewriter = null; - } - - } else { - Conf conf = new Conf(context, inputStream, confPath, confUrlStr, modRewriteStyleConf); - checkConf(conf); - } - } - - /** - * Separate from checkConfLocal so that it can be overidden. - */ - protected void checkConf(Conf conf) { - checkConfLocal(conf); - } - - private void checkConfLocal(Conf conf) { - if (log.isDebugEnabled()) { - if (conf.getRules() != null) { - log.debug("inited with " + conf.getRules().size() + " rules"); - } - log.debug("conf is " + (conf.isOk() ? "ok" : "NOT ok")); - } - confLastLoaded = conf; - if (conf.isOk() && conf.isEngineEnabled()) { - urlRewriter = new UrlRewriter(conf); - log.info("loaded (conf ok)"); - - } else { - if (!conf.isOk()) { - log.error("Conf failed to load"); - } - if (!conf.isEngineEnabled()) { - log.error("Engine explicitly disabled in conf"); // not really an error but we want ot to show in logs - } - if (urlRewriter != null) { - log.error("unloading existing conf"); - urlRewriter = null; - } - } - } - - /** - * Destroy is called by the application server when it unloads this filter. - */ - public void destroy() { - log.info("destroy called"); - destroyActual(); - Log.resetAll(); - } - - public void destroyActual() { - destroyUrlRewriter(); - context = null; - confLastLoad = 0; - confPath = DEFAULT_WEB_CONF_PATH; - confReloadCheckEnabled = false; - confReloadCheckInterval = 0; - confReloadInProgress = false; - } - - protected void destroyUrlRewriter() { - if (urlRewriter != null) { - urlRewriter.destroy(); - urlRewriter = null; - } - } - - /** - * The main method called for each request that this filter is mapped for. - * - * @param request the request to filter - * @param response the response to filter - * @param chain the chain for the filtering - * @throws IOException - * @throws ServletException - */ - public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) - throws IOException, ServletException { - - UrlRewriter urlRewriter = getUrlRewriter(request, response, chain); - - final HttpServletRequest hsRequest = (HttpServletRequest) request; - final HttpServletResponse hsResponse = (HttpServletResponse) response; - UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(hsResponse, hsRequest, - urlRewriter); - - // check for status request - if (statusEnabled && statusServerNameMatcher.isMatch(request.getServerName())) { - String uri = hsRequest.getRequestURI(); - if (log.isDebugEnabled()) { - log.debug("checking for status path on " + uri); - } - String contextPath = hsRequest.getContextPath(); - if (uri != null && uri.startsWith(contextPath + statusPath)) { - showStatus(hsRequest, urlRewriteWrappedResponse); - return; - } - } - - boolean requestRewritten = false; - if (urlRewriter != null) { - - // process the request - requestRewritten = urlRewriter.processRequest(hsRequest, urlRewriteWrappedResponse, chain); - - } else { - if (log.isDebugEnabled()) { - log.debug("urlRewriter engine not loaded ignoring request (could be a conf file problem)"); - } - } - - // if no rewrite has taken place continue as normal - if (!requestRewritten) { - chain.doFilter(hsRequest, urlRewriteWrappedResponse); - } - } - - - /** - * Called for every request. - *

    - * Split from doFilter so that it can be overriden. - */ - protected UrlRewriter getUrlRewriter(ServletRequest request, ServletResponse response, FilterChain chain) { - // check to see if the conf needs reloading - if (isTimeToReloadConf()) { - reloadConf(); - } - return urlRewriter; - } - - /** - * Is it time to reload the configuration now. Depends on is conf reloading is enabled. - */ - public boolean isTimeToReloadConf() { - if (!confLoadedFromFile) return false; - long now = System.currentTimeMillis(); - return confReloadCheckEnabled && !confReloadInProgress && (now - confReloadCheckInterval) > confReloadLastCheck; - } - - /** - * Forcibly reload the configuration now. - */ - public void reloadConf() { - long now = System.currentTimeMillis(); - confReloadInProgress = true; - confReloadLastCheck = now; - - log.debug("starting conf reload check"); - long confFileCurrentTime = getConfFileLastModified(); - if (confLastLoad < confFileCurrentTime) { - // reload conf - confLastLoad = System.currentTimeMillis(); - log.info("conf file modified since last load, reloading"); - try{ - loadUrlRewriterLocal(); - } catch(Exception ex){ - log.error("Error in reloading the conf file. No rules to be applied for subsequent requests.", ex); - } - } else { - log.debug("conf is not modified"); - } - confReloadInProgress = false; - } - - /** - * Gets the last modified date of the conf file. - * - * @return time as a long - */ - private long getConfFileLastModified() { - if (context != null) { - File confFile = new File(confPath); - if (confFile.exists()) { - return confFile.lastModified(); - } else if (context.getRealPath(confPath) != null) { - confFile = new File(context.getRealPath(confPath)); - return confFile.lastModified(); - } - } - return INITIALISED_TIME; - } - private static long INITIALISED_TIME = System.currentTimeMillis(); - - - /** - * Show the status of the conf and the filter to the user. - * - * @param request to get status info from - * @param response response to show the status on. - * @throws java.io.IOException if the output cannot be written - */ - private void showStatus(final HttpServletRequest request, final ServletResponse response) - throws IOException { - - log.debug("showing status"); - - if ( allowConfSwapViaHttp ) { - String newConfPath = request.getParameter("conf"); - if ( !StringUtils.isBlank(newConfPath)) { - confPath = newConfPath; - loadUrlRewriterLocal(); - } - } - - Status status = new Status(confLastLoaded, this); - status.displayStatusInContainer(request); - - response.setContentType("text/html; charset=UTF-8"); - response.setContentLength(status.getBuffer().length()); - - final PrintWriter out = response.getWriter(); - out.write(status.getBuffer().toString()); - out.close(); - - } - - public boolean isConfReloadCheckEnabled() { - return confReloadCheckEnabled; - } - - /** - * The amount of seconds between reload checks. - * - * @return int number of millis - */ - public int getConfReloadCheckInterval() { - return confReloadCheckInterval / 1000; - } - - public Date getConfReloadLastCheck() { - return new Date(confReloadLastCheck); - } - - public boolean isStatusEnabled() { - return statusEnabled; - } - - public String getStatusPath() { - return statusPath; - } - - public boolean isLoaded() { - return urlRewriter != null; - } - - public static String getFullVersionString() { - Properties props = new Properties(); - String buildNumberStr = ""; - try { - InputStream is = UrlRewriteFilter.class.getResourceAsStream("build.number.properties"); - if ( is != null ) { - try { - props.load(is); - String buildNumber = (String) props.get("build.number"); - if (!StringUtils.isBlank(buildNumber)){ - buildNumberStr = props.get("project.version") + " build " + props.get("build.number"); - } - } finally { - is.close(); - } - } - } catch (IOException e) { - log.error(e); - } - return buildNumberStr; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.ModRewriteConfLoader; +import org.tuckey.web.filters.urlrewrite.utils.NumberUtils; +import org.tuckey.web.filters.urlrewrite.utils.ServerNameMatcher; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Date; +import java.util.Properties; + +/** + * Based on the popular and very useful mod_rewrite for apache, UrlRewriteFilter is a Java Web Filter for any J2EE + * compliant web application server (such as Resin or Tomcat), which allows you to rewrite URLs before they get to your + * code. It is a very powerful tool just like Apache's mod_rewrite. + *

    + * The main things it is used for are: + *

    + *

    + * UrlRewriteFilter uses an xml file, called urlrewrite.xml (lives in the WEB-INF directory), for configuration. Most + * parameters can be Perl5 style Regular Expressions or Wildcards (i.e. *). This makes it very powerful indeed. + *

    + * Special thanks to all those who gave patches/feedback especially Vineet Kumar. + *

    + * Thanks also to Ralf S. Engelschall (www.engelschall.com) the inventor of mod_rewrite. + *

    + * + * @author Paul Tuckey + * @version $Revision: 51 $ $Date: 2006-12-08 11:37:07 +1300 (Fri, 08 Dec 2006) $ + */ +public class UrlRewriteFilter implements Filter { + + private static Log log = Log.getLog(UrlRewriteFilter.class); + + public static final String DEFAULT_WEB_CONF_PATH = "/WEB-INF/urlrewrite.xml"; + + /** + * The conf for this filter. + */ + private UrlRewriter urlRewriter = null; + + /** + * A user defined setting that can enable conf reloading. + */ + private boolean confReloadCheckEnabled = false; + + /** + * A user defined setting that says how often to check the conf has changed. + */ + private int confReloadCheckInterval = 0; + + /** + * A user defined setting that will allow configuration to be swapped via an HTTP to rewrite-status. + */ + private boolean allowConfSwapViaHttp = false; + + /** + * The last time that the conf file was loaded. + */ + private long confLastLoad = 0; + private Conf confLastLoaded = null; + private long confReloadLastCheck = 30; + private boolean confLoadedFromFile = true; + + /** + * path to conf file. + */ + private String confPath; + + /** + * Flag to make sure we don't bog the filter down during heavy load. + */ + private boolean confReloadInProgress = false; + + private boolean statusEnabled = true; + private String statusPath = "/rewrite-status"; + + private boolean modRewriteStyleConf = false; + public static final String DEFAULT_MOD_REWRITE_STYLE_CONF_PATH = "/WEB-INF/.htaccess"; + + private ServerNameMatcher statusServerNameMatcher; + private static final String DEFAULT_STATUS_ENABLED_ON_HOSTS = "localhost, local, 127.0.0.1"; + + + /** + * + */ + private ServletContext context = null; + + /** + * Init is called automatically by the application server when it creates this filter. + * + * @param filterConfig The config of the filter + */ + public void init(final FilterConfig filterConfig) throws ServletException { + + log.debug("filter init called"); + if (filterConfig == null) { + log.error("unable to init filter as filter config is null"); + return; + } + + log.debug("init: calling destroy just in case we are being re-inited uncleanly"); + destroyActual(); + + context = filterConfig.getServletContext(); + if (context == null) { + log.error("unable to init as servlet context is null"); + return; + } + + // set the conf of the logger to make sure we get the messages in context log + Log.setConfiguration(filterConfig); + + // get init paramerers from context web.xml file + String confReloadCheckIntervalStr = filterConfig.getInitParameter("confReloadCheckInterval"); + String confPathStr = filterConfig.getInitParameter("confPath"); + String statusPathConf = filterConfig.getInitParameter("statusPath"); + String statusEnabledConf = filterConfig.getInitParameter("statusEnabled"); + String statusEnabledOnHosts = filterConfig.getInitParameter("statusEnabledOnHosts"); + + String allowConfSwapViaHttpStr = filterConfig.getInitParameter("allowConfSwapViaHttp"); + if (!StringUtils.isBlank(allowConfSwapViaHttpStr)) { + allowConfSwapViaHttp = "true".equalsIgnoreCase(allowConfSwapViaHttpStr); + } + + // confReloadCheckInterval (default to null) + if (!StringUtils.isBlank(confReloadCheckIntervalStr)) { + // convert to millis + confReloadCheckInterval = 1000 * NumberUtils.stringToInt(confReloadCheckIntervalStr); + + if (confReloadCheckInterval < 0) { + confReloadCheckEnabled = false; + log.info("conf reload check disabled"); + + } else if (confReloadCheckInterval == 0) { + confReloadCheckEnabled = true; + log.info("conf reload check performed each request"); + + } else { + confReloadCheckEnabled = true; + log.info("conf reload check set to " + confReloadCheckInterval / 1000 + "s"); + } + + } else { + confReloadCheckEnabled = false; + } + + String modRewriteConf = filterConfig.getInitParameter("modRewriteConf"); + if (!StringUtils.isBlank(modRewriteConf)) { + modRewriteStyleConf = "true".equals(StringUtils.trim(modRewriteConf).toLowerCase()); + } + + if (!StringUtils.isBlank(confPathStr)) { + confPath = StringUtils.trim(confPathStr); + } else { + confPath = modRewriteStyleConf ? DEFAULT_MOD_REWRITE_STYLE_CONF_PATH : DEFAULT_WEB_CONF_PATH; + } + log.debug("confPath set to " + confPath); + + // status enabled (default true) + if (statusEnabledConf != null && !"".equals(statusEnabledConf)) { + log.debug("statusEnabledConf set to " + statusEnabledConf); + statusEnabled = "true".equals(statusEnabledConf.toLowerCase()); + } + if (statusEnabled) { + // status path (default /rewrite-status) + if (statusPathConf != null && !"".equals(statusPathConf)) { + statusPath = statusPathConf.trim(); + log.info("status display enabled, path set to " + statusPath); + } + } else { + log.info("status display disabled"); + } + + if (StringUtils.isBlank(statusEnabledOnHosts)) { + statusEnabledOnHosts = DEFAULT_STATUS_ENABLED_ON_HOSTS; + } else { + log.debug("statusEnabledOnHosts set to " + statusEnabledOnHosts); + } + statusServerNameMatcher = new ServerNameMatcher(statusEnabledOnHosts); + + // now load conf from snippet in web.xml if modRewriteStyleConf is set + String modRewriteConfText = filterConfig.getInitParameter("modRewriteConfText"); + if (!StringUtils.isBlank(modRewriteConfText)) { + ModRewriteConfLoader loader = new ModRewriteConfLoader(); + Conf conf = new Conf(); + loader.process(modRewriteConfText, conf); + conf.initialise(); + checkConf(conf); + confLoadedFromFile = false; + + } else { + + loadUrlRewriter(filterConfig); + } + } + + /** + * Separate from init so that it can be overidden. + */ + protected void loadUrlRewriter(FilterConfig filterConfig) throws ServletException { + try { + loadUrlRewriterLocal(); + } catch(Throwable e) { + log.error(e); + throw new ServletException(e); + } + } + + private void loadUrlRewriterLocal() { + URL confUrl = null; + InputStream inputStream = null; + try { + File confFile = new File(confPath); + if (confFile.exists()) { + inputStream = new FileInputStream(confFile); + confUrl = confFile.toURI().toURL(); + } + } catch (FileNotFoundException e) { + log.debug(e); + } catch (MalformedURLException ex) { + log.debug(ex); + } + if (inputStream == null) { + inputStream = context.getResourceAsStream(confPath); + // attempt to retrieve from location other than local WEB-INF + if (inputStream == null) { + inputStream = ClassLoader.getSystemResourceAsStream(confPath); + } + try { + confUrl = context.getResource(confPath); + } catch (MalformedURLException e) { + log.debug(e); + } + } + String confUrlStr = null; + if (confUrl != null) { + confUrlStr = confUrl.toString(); + } + if (inputStream == null) { + log.error("unable to find urlrewrite conf file at " + confPath); + // set the writer back to null + if (urlRewriter != null) { + log.error("unloading existing conf"); + urlRewriter = null; + } + + } else { + Conf conf = new Conf(context, inputStream, confPath, confUrlStr, modRewriteStyleConf); + checkConf(conf); + } + } + + /** + * Separate from checkConfLocal so that it can be overidden. + */ + protected void checkConf(Conf conf) { + checkConfLocal(conf); + } + + private void checkConfLocal(Conf conf) { + if (log.isDebugEnabled()) { + if (conf.getRules() != null) { + log.debug("inited with " + conf.getRules().size() + " rules"); + } + log.debug("conf is " + (conf.isOk() ? "ok" : "NOT ok")); + } + confLastLoaded = conf; + if (conf.isOk() && conf.isEngineEnabled()) { + urlRewriter = new UrlRewriter(conf); + log.info("loaded (conf ok)"); + + } else { + if (!conf.isOk()) { + log.error("Conf failed to load"); + } + if (!conf.isEngineEnabled()) { + log.error("Engine explicitly disabled in conf"); // not really an error but we want ot to show in logs + } + if (urlRewriter != null) { + log.error("unloading existing conf"); + urlRewriter = null; + } + } + } + + /** + * Destroy is called by the application server when it unloads this filter. + */ + public void destroy() { + log.info("destroy called"); + destroyActual(); + Log.resetAll(); + } + + public void destroyActual() { + destroyUrlRewriter(); + context = null; + confLastLoad = 0; + confPath = DEFAULT_WEB_CONF_PATH; + confReloadCheckEnabled = false; + confReloadCheckInterval = 0; + confReloadInProgress = false; + } + + protected void destroyUrlRewriter() { + if (urlRewriter != null) { + urlRewriter.destroy(); + urlRewriter = null; + } + } + + /** + * The main method called for each request that this filter is mapped for. + * + * @param request the request to filter + * @param response the response to filter + * @param chain the chain for the filtering + * @throws IOException + * @throws ServletException + */ + public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) + throws IOException, ServletException { + + UrlRewriter urlRewriter = getUrlRewriter(request, response, chain); + + final HttpServletRequest hsRequest = (HttpServletRequest) request; + final HttpServletResponse hsResponse = (HttpServletResponse) response; + UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(hsResponse, hsRequest, + urlRewriter); + + // check for status request + if (statusEnabled && statusServerNameMatcher.isMatch(request.getServerName())) { + String uri = hsRequest.getRequestURI(); + if (log.isDebugEnabled()) { + log.debug("checking for status path on " + uri); + } + String contextPath = hsRequest.getContextPath(); + if (uri != null && uri.startsWith(contextPath + statusPath)) { + showStatus(hsRequest, urlRewriteWrappedResponse); + return; + } + } + + boolean requestRewritten = false; + if (urlRewriter != null) { + + // process the request + requestRewritten = urlRewriter.processRequest(hsRequest, urlRewriteWrappedResponse, chain); + + } else { + if (log.isDebugEnabled()) { + log.debug("urlRewriter engine not loaded ignoring request (could be a conf file problem)"); + } + } + + // if no rewrite has taken place continue as normal + if (!requestRewritten) { + chain.doFilter(hsRequest, urlRewriteWrappedResponse); + } + } + + + /** + * Called for every request. + *

    + * Split from doFilter so that it can be overriden. + */ + protected UrlRewriter getUrlRewriter(ServletRequest request, ServletResponse response, FilterChain chain) { + // check to see if the conf needs reloading + if (isTimeToReloadConf()) { + reloadConf(); + } + return urlRewriter; + } + + /** + * Is it time to reload the configuration now. Depends on is conf reloading is enabled. + */ + public boolean isTimeToReloadConf() { + if (!confLoadedFromFile) return false; + long now = System.currentTimeMillis(); + return confReloadCheckEnabled && !confReloadInProgress && (now - confReloadCheckInterval) > confReloadLastCheck; + } + + /** + * Forcibly reload the configuration now. + */ + public void reloadConf() { + long now = System.currentTimeMillis(); + confReloadInProgress = true; + confReloadLastCheck = now; + + log.debug("starting conf reload check"); + long confFileCurrentTime = getConfFileLastModified(); + if (confLastLoad < confFileCurrentTime) { + // reload conf + confLastLoad = System.currentTimeMillis(); + log.info("conf file modified since last load, reloading"); + try{ + loadUrlRewriterLocal(); + } catch(Exception ex){ + log.error("Error in reloading the conf file. No rules to be applied for subsequent requests.", ex); + } + } else { + log.debug("conf is not modified"); + } + confReloadInProgress = false; + } + + /** + * Gets the last modified date of the conf file. + * + * @return time as a long + */ + private long getConfFileLastModified() { + if (context != null) { + File confFile = new File(confPath); + if (confFile.exists()) { + return confFile.lastModified(); + } else if (context.getRealPath(confPath) != null) { + confFile = new File(context.getRealPath(confPath)); + return confFile.lastModified(); + } + } + return INITIALISED_TIME; + } + private static long INITIALISED_TIME = System.currentTimeMillis(); + + + /** + * Show the status of the conf and the filter to the user. + * + * @param request to get status info from + * @param response response to show the status on. + * @throws java.io.IOException if the output cannot be written + */ + private void showStatus(final HttpServletRequest request, final ServletResponse response) + throws IOException { + + log.debug("showing status"); + + if ( allowConfSwapViaHttp ) { + String newConfPath = request.getParameter("conf"); + if ( !StringUtils.isBlank(newConfPath)) { + confPath = newConfPath; + loadUrlRewriterLocal(); + } + } + + Status status = new Status(confLastLoaded, this); + status.displayStatusInContainer(request); + + response.setContentType("text/html; charset=UTF-8"); + response.setContentLength(status.getBuffer().length()); + + final PrintWriter out = response.getWriter(); + out.write(status.getBuffer().toString()); + out.close(); + + } + + public boolean isConfReloadCheckEnabled() { + return confReloadCheckEnabled; + } + + /** + * The amount of seconds between reload checks. + * + * @return int number of millis + */ + public int getConfReloadCheckInterval() { + return confReloadCheckInterval / 1000; + } + + public Date getConfReloadLastCheck() { + return new Date(confReloadLastCheck); + } + + public boolean isStatusEnabled() { + return statusEnabled; + } + + public String getStatusPath() { + return statusPath; + } + + public boolean isLoaded() { + return urlRewriter != null; + } + + public static String getFullVersionString() { + Properties props = new Properties(); + String buildNumberStr = ""; + try { + InputStream is = UrlRewriteFilter.class.getResourceAsStream("build.number.properties"); + if ( is != null ) { + try { + props.load(is); + String buildNumber = (String) props.get("build.number"); + if (!StringUtils.isBlank(buildNumber)){ + buildNumberStr = props.get("project.version") + " build " + props.get("build.number"); + } + } finally { + is.close(); + } + } + } catch (IOException e) { + log.error(e); + } + return buildNumberStr; + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteServlet.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteServlet.java index 8241120f..3b11327f 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteServlet.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteServlet.java @@ -1,124 +1,124 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.UnavailableException; -import jakarta.servlet.http.HttpServlet; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Enumeration; - -/** - * Servlet for use if you cannot load filters in your environment for some strange reason. This will - * work very differently from the filter (obviously), but it can be used for "run" items where there - * is no "to". - * - * This servlet just loads an instance of the filter and calls it as if it were the container. - */ -public class UrlRewriteServlet extends HttpServlet { - private static final long serialVersionUID = 2186203405866227539L; - - private UrlRewriteFilter urlRewriteFilter = new UrlRewriteFilter(); - - public void init(ServletConfig servletConfig) throws ServletException { - - urlRewriteFilter.init(new ConfigWrapper(servletConfig)); - } - - public void service(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - if (!urlRewriteFilter.isLoaded()) { - throw new UnavailableException("not initialised"); - - } else { - FilterChainWrapper filterChainWrapper = new FilterChainWrapper(); - urlRewriteFilter.doFilter(request, response, filterChainWrapper); - - } - } - - public void destroy() { - urlRewriteFilter.destroy(); - } - - - /** - * Simple empty wrapper on top of FilterChain. - */ - static class FilterChainWrapper implements FilterChain { - - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) - throws IOException, ServletException { - // do nothing! - } - } - - /** - * Simple wrapper for filter config to make it useful when we have a ServletConfig. - */ - static class ConfigWrapper implements FilterConfig { - - private ServletConfig servletConfig; - - public ConfigWrapper(ServletConfig servletConfig) { - this.servletConfig = servletConfig; - } - - public String getFilterName() { - return this.servletConfig.getServletName(); - } - - public ServletContext getServletContext() { - return servletConfig.getServletContext(); - } - - public String getInitParameter(String string) { - return servletConfig.getInitParameter(string); - } - - public Enumeration getInitParameterNames() { - return servletConfig.getInitParameterNames(); - } - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.UnavailableException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Enumeration; + +/** + * Servlet for use if you cannot load filters in your environment for some strange reason. This will + * work very differently from the filter (obviously), but it can be used for "run" items where there + * is no "to". + * + * This servlet just loads an instance of the filter and calls it as if it were the container. + */ +public class UrlRewriteServlet extends HttpServlet { + private static final long serialVersionUID = 2186203405866227539L; + + private UrlRewriteFilter urlRewriteFilter = new UrlRewriteFilter(); + + public void init(ServletConfig servletConfig) throws ServletException { + + urlRewriteFilter.init(new ConfigWrapper(servletConfig)); + } + + public void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + if (!urlRewriteFilter.isLoaded()) { + throw new UnavailableException("not initialised"); + + } else { + FilterChainWrapper filterChainWrapper = new FilterChainWrapper(); + urlRewriteFilter.doFilter(request, response, filterChainWrapper); + + } + } + + public void destroy() { + urlRewriteFilter.destroy(); + } + + + /** + * Simple empty wrapper on top of FilterChain. + */ + static class FilterChainWrapper implements FilterChain { + + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) + throws IOException, ServletException { + // do nothing! + } + } + + /** + * Simple wrapper for filter config to make it useful when we have a ServletConfig. + */ + static class ConfigWrapper implements FilterConfig { + + private ServletConfig servletConfig; + + public ConfigWrapper(ServletConfig servletConfig) { + this.servletConfig = servletConfig; + } + + public String getFilterName() { + return this.servletConfig.getServletName(); + } + + public ServletContext getServletContext() { + return servletConfig.getServletContext(); + } + + public String getInitParameter(String string) { + return servletConfig.getInitParameter(string); + } + + public Enumeration getInitParameterNames() { + return servletConfig.getInitParameterNames(); + } + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedRequest.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedRequest.java index 02a89c66..0d38481d 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedRequest.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedRequest.java @@ -1,111 +1,111 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletRequestWrapper; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Handles wrapping the request if necessary. - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class UrlRewriteWrappedRequest extends HttpServletRequestWrapper { - - HashMap overridenParameters; - String overridenMethod; - - public UrlRewriteWrappedRequest(HttpServletRequest httpServletRequest) { - super(httpServletRequest); - } - - public UrlRewriteWrappedRequest(HttpServletRequest httpServletRequest, - HashMap overridenParameters, String overridenMethod) { - super(httpServletRequest); - this.overridenParameters = overridenParameters; - this.overridenMethod = overridenMethod; - } - - public Enumeration getParameterNames() { - if (overridenParameters != null) { - List keys = Collections.list(super.getParameterNames()); - keys.addAll(overridenParameters.keySet()); - return Collections.enumeration(keys); - } - return super.getParameterNames(); - } - - public Map getParameterMap() { - if (overridenParameters != null) { - Map superMap = super.getParameterMap(); - //superMap is an unmodifiable map, hence creating a new one. - Map overriddenMap = new HashMap(superMap.size() + overridenParameters.size()); - overriddenMap.putAll(superMap); - overriddenMap.putAll(overridenParameters); - return overriddenMap; - } - return super.getParameterMap(); - } - - public String[] getParameterValues(String s) { - if (overridenParameters != null && overridenParameters.containsKey(s)) { - return (String[]) overridenParameters.get(s); - } - return super.getParameterValues(s); - } - - public String getParameter(String s) { - if (overridenParameters != null && overridenParameters.containsKey(s)) { - String[] values = (String[]) overridenParameters.get(s); - if (values == null || values.length == 0) { - return null; - } else { - return values[0]; - } - } - return super.getParameter(s); - } - - public String getMethod() { - if (overridenMethod != null) return overridenMethod; - return super.getMethod(); - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Handles wrapping the request if necessary. + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class UrlRewriteWrappedRequest extends HttpServletRequestWrapper { + + HashMap overridenParameters; + String overridenMethod; + + public UrlRewriteWrappedRequest(HttpServletRequest httpServletRequest) { + super(httpServletRequest); + } + + public UrlRewriteWrappedRequest(HttpServletRequest httpServletRequest, + HashMap overridenParameters, String overridenMethod) { + super(httpServletRequest); + this.overridenParameters = overridenParameters; + this.overridenMethod = overridenMethod; + } + + public Enumeration getParameterNames() { + if (overridenParameters != null) { + List keys = Collections.list(super.getParameterNames()); + keys.addAll(overridenParameters.keySet()); + return Collections.enumeration(keys); + } + return super.getParameterNames(); + } + + public Map getParameterMap() { + if (overridenParameters != null) { + Map superMap = super.getParameterMap(); + //superMap is an unmodifiable map, hence creating a new one. + Map overriddenMap = new HashMap(superMap.size() + overridenParameters.size()); + overriddenMap.putAll(superMap); + overriddenMap.putAll(overridenParameters); + return overriddenMap; + } + return super.getParameterMap(); + } + + public String[] getParameterValues(String s) { + if (overridenParameters != null && overridenParameters.containsKey(s)) { + return (String[]) overridenParameters.get(s); + } + return super.getParameterValues(s); + } + + public String getParameter(String s) { + if (overridenParameters != null && overridenParameters.containsKey(s)) { + String[] values = (String[]) overridenParameters.get(s); + if (values == null || values.length == 0) { + return null; + } else { + return values[0]; + } + } + return super.getParameter(s); + } + + public String getMethod() { + if (overridenMethod != null) return overridenMethod; + return super.getMethod(); + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponse.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponse.java index 4717d9e5..33629c7d 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponse.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponse.java @@ -1,158 +1,158 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpServletResponseWrapper; -import java.util.HashMap; - -/** - * Handles wrapping the response so we can encode the url's on the way "out" (ie, in JSP or servlet generation). - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class UrlRewriteWrappedResponse extends HttpServletResponseWrapper { - - private UrlRewriter urlRerwiter; - private HttpServletResponse httpServletResponse; - private HttpServletRequest httpServletRequest; - - //is a map - HashMap overridenRequestParameters; - String overridenMethod; - - public UrlRewriteWrappedResponse(HttpServletResponse httpServletResponse, HttpServletRequest httpServletRequest, - UrlRewriter urlRerwiter) { - super(httpServletResponse); - this.httpServletResponse = httpServletResponse; - this.httpServletRequest = httpServletRequest; - this.urlRerwiter = urlRerwiter; - } - - public String encodeURL(String s) { - RewrittenOutboundUrl rou = processPreEncodeURL(s); - if (rou == null) { - return super.encodeURL(s); - } - if (rou.isEncode()) { - rou.setTarget(super.encodeURL(rou.getTarget())); - } - return processPostEncodeURL(rou.getTarget()).getTarget(); - } - - public String encodeRedirectURL(String s) { - RewrittenOutboundUrl rou = processPreEncodeURL(s); - if (rou == null) { - return super.encodeURL(s); - } - if (rou.isEncode()) { - rou.setTarget(super.encodeRedirectURL(rou.getTarget())); - } - return processPostEncodeURL(rou.getTarget()).getTarget(); - } - - public String encodeUrl(String s) { - RewrittenOutboundUrl rou = processPreEncodeURL(s); - if (rou == null) { - return super.encodeURL(s); - } - if (rou.isEncode()) { - rou.setTarget(super.encodeURL(rou.getTarget())); - } - return processPostEncodeURL(rou.getTarget()).getTarget(); - } - - public String encodeRedirectUrl(String s) { - RewrittenOutboundUrl rou = processPreEncodeURL(s); - if (rou == null) { - return super.encodeURL(s); - } - if (rou.isEncode()) { - rou.setTarget(super.encodeRedirectURL(rou.getTarget())); - } - return processPostEncodeURL(rou.getTarget()).getTarget(); - } - - /** - * Handle rewriting. - * - * @param s - */ - private RewrittenOutboundUrl processPreEncodeURL(String s) { - if (urlRerwiter == null) { - return null; - } - return urlRerwiter.processEncodeURL(httpServletResponse, httpServletRequest, false, s); - } - - /** - * Handle rewriting after the containers encodeUrl has been called. - * - * @param s - */ - private RewrittenOutboundUrl processPostEncodeURL(String s) { - if (urlRerwiter == null) { - return null; - } - return urlRerwiter.processEncodeURL(httpServletResponse, httpServletRequest, true, s); - } - - public void addOverridenRequestParameter(String k, String v) { - if (overridenRequestParameters == null) overridenRequestParameters = new HashMap(); - if (overridenRequestParameters.get(k) == null) { - overridenRequestParameters.put(k, new String[]{v}); - } else { - String[] currentValues = (String[]) overridenRequestParameters.get(k); - String[] finalValues = new String[currentValues.length + 1]; - System.arraycopy(currentValues, 0, finalValues, 0, currentValues.length); - finalValues[finalValues.length - 1] = v; - overridenRequestParameters.put(k, finalValues); - } - } - - public HashMap getOverridenRequestParameters() { - return overridenRequestParameters; - } - - public String getOverridenMethod() { - return overridenMethod; - } - - public void setOverridenMethod(String overridenMethod) { - this.overridenMethod = overridenMethod; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponseWrapper; +import java.util.HashMap; + +/** + * Handles wrapping the response so we can encode the url's on the way "out" (ie, in JSP or servlet generation). + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class UrlRewriteWrappedResponse extends HttpServletResponseWrapper { + + private UrlRewriter urlRerwiter; + private HttpServletResponse httpServletResponse; + private HttpServletRequest httpServletRequest; + + //is a map + HashMap overridenRequestParameters; + String overridenMethod; + + public UrlRewriteWrappedResponse(HttpServletResponse httpServletResponse, HttpServletRequest httpServletRequest, + UrlRewriter urlRerwiter) { + super(httpServletResponse); + this.httpServletResponse = httpServletResponse; + this.httpServletRequest = httpServletRequest; + this.urlRerwiter = urlRerwiter; + } + + public String encodeURL(String s) { + RewrittenOutboundUrl rou = processPreEncodeURL(s); + if (rou == null) { + return super.encodeURL(s); + } + if (rou.isEncode()) { + rou.setTarget(super.encodeURL(rou.getTarget())); + } + return processPostEncodeURL(rou.getTarget()).getTarget(); + } + + public String encodeRedirectURL(String s) { + RewrittenOutboundUrl rou = processPreEncodeURL(s); + if (rou == null) { + return super.encodeURL(s); + } + if (rou.isEncode()) { + rou.setTarget(super.encodeRedirectURL(rou.getTarget())); + } + return processPostEncodeURL(rou.getTarget()).getTarget(); + } + + public String encodeUrl(String s) { + RewrittenOutboundUrl rou = processPreEncodeURL(s); + if (rou == null) { + return super.encodeURL(s); + } + if (rou.isEncode()) { + rou.setTarget(super.encodeURL(rou.getTarget())); + } + return processPostEncodeURL(rou.getTarget()).getTarget(); + } + + public String encodeRedirectUrl(String s) { + RewrittenOutboundUrl rou = processPreEncodeURL(s); + if (rou == null) { + return super.encodeURL(s); + } + if (rou.isEncode()) { + rou.setTarget(super.encodeRedirectURL(rou.getTarget())); + } + return processPostEncodeURL(rou.getTarget()).getTarget(); + } + + /** + * Handle rewriting. + * + * @param s + */ + private RewrittenOutboundUrl processPreEncodeURL(String s) { + if (urlRerwiter == null) { + return null; + } + return urlRerwiter.processEncodeURL(httpServletResponse, httpServletRequest, false, s); + } + + /** + * Handle rewriting after the containers encodeUrl has been called. + * + * @param s + */ + private RewrittenOutboundUrl processPostEncodeURL(String s) { + if (urlRerwiter == null) { + return null; + } + return urlRerwiter.processEncodeURL(httpServletResponse, httpServletRequest, true, s); + } + + public void addOverridenRequestParameter(String k, String v) { + if (overridenRequestParameters == null) overridenRequestParameters = new HashMap(); + if (overridenRequestParameters.get(k) == null) { + overridenRequestParameters.put(k, new String[]{v}); + } else { + String[] currentValues = (String[]) overridenRequestParameters.get(k); + String[] finalValues = new String[currentValues.length + 1]; + System.arraycopy(currentValues, 0, finalValues, 0, currentValues.length); + finalValues[finalValues.length - 1] = v; + overridenRequestParameters.put(k, finalValues); + } + } + + public HashMap getOverridenRequestParameters() { + return overridenRequestParameters; + } + + public String getOverridenMethod() { + return overridenMethod; + } + + public void setOverridenMethod(String overridenMethod) { + this.overridenMethod = overridenMethod; + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriter.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriter.java index a421263c..2aa878cb 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriter.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriter.java @@ -1,362 +1,362 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; -import org.tuckey.web.filters.urlrewrite.utils.URLDecoder; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.net.URISyntaxException; -import java.util.List; - -/** - * The main rewriter. - * - * @author Paul Tuckey - * @version $Revision: 52 $ $Date: 2007-02-26 07:00:28 +1300 (Mon, 26 Feb 2007) $ - */ -public class UrlRewriter { - - private static Log log = Log.getLog(UrlRewriter.class); - - /** - * The conf for this filter. - */ - private Conf conf; - - public UrlRewriter(Conf conf) { - this.conf = conf; - } - - /** - * Helpful for testing but otherwise, don't use. - */ - public RewrittenUrl processRequest(final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse) - throws IOException, ServletException, InvocationTargetException { - RuleChain chain = getNewChain(hsRequest, null); - if (chain == null) return null; - chain.process(hsRequest, hsResponse); - return chain.getFinalRewrittenRequest(); - } - - /** - * The main method called for each request that this filter is mapped for. - * - * @param hsRequest The request to process. - * @return returns true when response has been handled by url rewriter false when it hasn't. - */ - public boolean processRequest(final HttpServletRequest hsRequest, final HttpServletResponse hsResponse, - FilterChain parentChain) - throws IOException, ServletException { - RuleChain chain = getNewChain(hsRequest, parentChain); - if (chain == null) return false; - chain.doRules(hsRequest, hsResponse); - return chain.isResponseHandled(); - } - - - /** - * Return the path within the web application for the given request. - *

    Detects include request URL if called within a RequestDispatcher include. - */ - public String getPathWithinApplication(HttpServletRequest request) { - String requestUri = request.getRequestURI(); - if (requestUri == null) requestUri = ""; - String decodedRequestUri = decodeRequestString(request, requestUri); - String contextPath = getContextPath(request); - String path; - if (StringUtils.startsWithIgnoreCase(decodedRequestUri, contextPath) && !conf.isUseContext()) { - // Normal case: URI contains context path. - path = decodedRequestUri.substring(contextPath.length()); - - } else if (!StringUtils.startsWithIgnoreCase(decodedRequestUri, contextPath) && conf.isUseContext()) { - // add the context path on - path = contextPath + decodedRequestUri; - - } else { - path = decodedRequestUri; - } - return StringUtils.isBlank(path) ? "/" : path; - } - - /** - * Return the context path for the given request, detecting an include request - * URL if called within a RequestDispatcher include. - *

    As the value returned by request.getContextPath() is not - * decoded by the servlet container, this method will decode it. - */ - public String getContextPath(HttpServletRequest request) { - String contextPath = request.getContextPath(); - if ("/".equals(contextPath)) { - // Invalid case, but happens for includes on Jetty: silently adapt it. - contextPath = ""; - } - return decodeRequestString(request, contextPath); - } - - /** - * Decode the string with a URLDecoder. The encoding will be taken - * from the request, falling back to the default for your platform ("ISO-8859-1" on windows). - */ - public String decodeRequestString(HttpServletRequest request, String source) { - if (conf.isDecodeUsingEncodingHeader()) { - String enc = request.getCharacterEncoding(); - if (enc != null) { - try { - return URLDecoder.decodeURL(source, enc); - } catch (URISyntaxException ex) { - if (log.isWarnEnabled()) { - log.warn("Could not decode: " + source + " (header encoding: '" + enc + "'); exception: " + ex.getMessage()); - } - } - } - } - if (conf.isDecodeUsingCustomCharsetRequired()) { - String enc = conf.getDecodeUsing(); - if (enc != null) { - try { - return URLDecoder.decodeURL(source, enc); - } catch (URISyntaxException ex) { - if (log.isWarnEnabled()) { - log.warn("Could not decode: " + source + " (encoding: '" + enc + "') using default encoding; exception: " + ex.getMessage()); - } - } - } - } - return source; - } - - - private RuleChain getNewChain(final HttpServletRequest hsRequest, FilterChain parentChain) { - - String originalUrl = getPathWithinApplication(hsRequest); - - if (originalUrl == null) { - // for some reason the engine is not giving us the url - // this isn't good - log.debug("unable to fetch request uri from request. This shouldn't happen, it may indicate that " + - "the web application server has a bug or that the request was not pased correctly."); - return null; - } - - if (log.isDebugEnabled()) { - log.debug("processing request for " + originalUrl); - } - - // add the query string on uri (note, some web app containers do this) - if (originalUrl != null && originalUrl.indexOf("?") == -1 && conf.isUseQueryString()) { - String query = hsRequest.getQueryString(); - if (query != null) { - query = query.trim(); - if (query.length() > 0) { - originalUrl = originalUrl + "?" + query; - log.debug("query string added"); - } - } - } - - if (!conf.isOk()) { - // when conf cannot be loaded for some sort of error - // continue as normal without looking at the non-existent rules - log.debug("configuration is not ok. not rewriting request."); - return null; - } - - final List rules = conf.getRules(); - if (rules.size() == 0) { - // no rules defined - log.debug("there are no rules setup. not rewriting request."); - return null; - } - - return new RuleChain(this, originalUrl, parentChain); - } - - - /** - * Handle an exception thrown by a Run element. - */ - public RewrittenUrl handleInvocationTargetException(final HttpServletRequest hsRequest, - final HttpServletResponse hsResponse, InvocationTargetException e) - throws ServletException, IOException { - - Throwable originalThrowable = getOriginalException(e); - - if (log.isDebugEnabled()) { - log.debug("attampting to find catch for exception " + originalThrowable.getClass().getName()); - } - - List catchElems = conf.getCatchElems(); - for (int i = 0; i < catchElems.size(); i++) { - CatchElem catchElem = (CatchElem) catchElems.get(i); - if (!catchElem.matches(originalThrowable)) continue; - try { - return catchElem.execute(hsRequest, hsResponse, originalThrowable); - - } catch (InvocationTargetException invocationExceptionInner) { - originalThrowable = getOriginalException(invocationExceptionInner); - log.warn("had exception processing catch, trying the rest of the catches with " + - originalThrowable.getClass().getName()); - } - } - - if (log.isDebugEnabled()) { - log.debug("exception unhandled", e); - } - if (originalThrowable instanceof Error) throw (Error) originalThrowable; - if (originalThrowable instanceof RuntimeException) throw (RuntimeException) originalThrowable; - if (originalThrowable instanceof ServletException) throw (ServletException) originalThrowable; - if (originalThrowable instanceof IOException) throw (IOException) originalThrowable; - throw new ServletException(originalThrowable); - } - - /** - * Get the original exception that caused the InvocationTargetException. - * - * @param e the InvocationTargetException - * @return the original exception. - * @throws javax.servlet.ServletException If the exception is a servlet exception, it will be thrown. - */ - private Throwable getOriginalException(InvocationTargetException e) throws ServletException { - Throwable originalThrowable = e.getTargetException(); - if (originalThrowable == null) { - originalThrowable = e.getCause(); - if (originalThrowable == null) { - throw new ServletException(e); - } - } - // unwrap if exception is a ServletException - if (originalThrowable instanceof ServletException) { - ServletException se = (ServletException) originalThrowable; - // go 5 deep to see if we can get a real exception - for (int i = 0; i < 5 && se.getCause() instanceof ServletException; i++) { - se = (ServletException) se.getCause(); - } - if (se.getCause() instanceof InvocationTargetException) { - return getOriginalException((InvocationTargetException) se.getCause()); - } else { - throw se; - } - } - return originalThrowable; - } - - - public Conf getConf() { - return conf; - } - - - /** - * Handles rewriting urls in jsp's etc, i.e. response.encodeURL() is overriden in the response wrapper. - * - * @param hsResponse response - * @param hsRequest request - * @param encodeUrlHasBeenRun if encodeUrl has already been run on the originalOutboundUrl speficy this to be true - * @param outboundUrl url - * @return RewrittenOutboundUrl - * @see UrlRewriteWrappedResponse - */ - protected RewrittenOutboundUrl processEncodeURL(HttpServletResponse hsResponse, HttpServletRequest hsRequest, - boolean encodeUrlHasBeenRun, String outboundUrl) { - - if (log.isDebugEnabled()) { - log.debug("processing outbound url for " + outboundUrl); - } - - if (outboundUrl == null) { - // this probably means encode called with no url - return new RewrittenOutboundUrl(null, true); - } - - // attempt to match the rules - boolean finalEncodeOutboundUrl = true; - String finalToUrl = outboundUrl; - final List outboundRules = conf.getOutboundRules(); - try { - for (int i = 0; i < outboundRules.size(); i++) { - final OutboundRule outboundRule = (OutboundRule) outboundRules.get(i); - if (!encodeUrlHasBeenRun && outboundRule.isEncodeFirst()) { - continue; - } - if (encodeUrlHasBeenRun && !outboundRule.isEncodeFirst()) { - continue; - } - final RewrittenOutboundUrl rewrittenUrl = outboundRule.execute(finalToUrl, hsRequest, hsResponse); - if (rewrittenUrl != null) { - // means this rule has matched - if (log.isDebugEnabled()) { - log.debug("\"" + outboundRule.getDisplayName() + "\" matched"); - } - finalToUrl = rewrittenUrl.getTarget(); - finalEncodeOutboundUrl = rewrittenUrl.isEncode(); - if (outboundRule.isLast()) { - log.debug("rule is last"); - // there can be no more matches on this request - break; - } - } - } - } catch (InvocationTargetException e) { - try { - handleInvocationTargetException(hsRequest, hsResponse, e); - } catch (ServletException e1) { - log.error(e1); - } catch (IOException e1) { - log.error(e1); - } - } - - return new RewrittenOutboundUrl(finalToUrl, finalEncodeOutboundUrl); - } - - /** - * Destory the rewriter gracefully. - */ - public void destroy() { - conf.destroy(); - } - -} - - - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; +import org.tuckey.web.filters.urlrewrite.utils.URLDecoder; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URISyntaxException; +import java.util.List; + +/** + * The main rewriter. + * + * @author Paul Tuckey + * @version $Revision: 52 $ $Date: 2007-02-26 07:00:28 +1300 (Mon, 26 Feb 2007) $ + */ +public class UrlRewriter { + + private static Log log = Log.getLog(UrlRewriter.class); + + /** + * The conf for this filter. + */ + private Conf conf; + + public UrlRewriter(Conf conf) { + this.conf = conf; + } + + /** + * Helpful for testing but otherwise, don't use. + */ + public RewrittenUrl processRequest(final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse) + throws IOException, ServletException, InvocationTargetException { + RuleChain chain = getNewChain(hsRequest, null); + if (chain == null) return null; + chain.process(hsRequest, hsResponse); + return chain.getFinalRewrittenRequest(); + } + + /** + * The main method called for each request that this filter is mapped for. + * + * @param hsRequest The request to process. + * @return returns true when response has been handled by url rewriter false when it hasn't. + */ + public boolean processRequest(final HttpServletRequest hsRequest, final HttpServletResponse hsResponse, + FilterChain parentChain) + throws IOException, ServletException { + RuleChain chain = getNewChain(hsRequest, parentChain); + if (chain == null) return false; + chain.doRules(hsRequest, hsResponse); + return chain.isResponseHandled(); + } + + + /** + * Return the path within the web application for the given request. + *

    Detects include request URL if called within a RequestDispatcher include. + */ + public String getPathWithinApplication(HttpServletRequest request) { + String requestUri = request.getRequestURI(); + if (requestUri == null) requestUri = ""; + String decodedRequestUri = decodeRequestString(request, requestUri); + String contextPath = getContextPath(request); + String path; + if (StringUtils.startsWithIgnoreCase(decodedRequestUri, contextPath) && !conf.isUseContext()) { + // Normal case: URI contains context path. + path = decodedRequestUri.substring(contextPath.length()); + + } else if (!StringUtils.startsWithIgnoreCase(decodedRequestUri, contextPath) && conf.isUseContext()) { + // add the context path on + path = contextPath + decodedRequestUri; + + } else { + path = decodedRequestUri; + } + return StringUtils.isBlank(path) ? "/" : path; + } + + /** + * Return the context path for the given request, detecting an include request + * URL if called within a RequestDispatcher include. + *

    As the value returned by request.getContextPath() is not + * decoded by the servlet container, this method will decode it. + */ + public String getContextPath(HttpServletRequest request) { + String contextPath = request.getContextPath(); + if ("/".equals(contextPath)) { + // Invalid case, but happens for includes on Jetty: silently adapt it. + contextPath = ""; + } + return decodeRequestString(request, contextPath); + } + + /** + * Decode the string with a URLDecoder. The encoding will be taken + * from the request, falling back to the default for your platform ("ISO-8859-1" on windows). + */ + public String decodeRequestString(HttpServletRequest request, String source) { + if (conf.isDecodeUsingEncodingHeader()) { + String enc = request.getCharacterEncoding(); + if (enc != null) { + try { + return URLDecoder.decodeURL(source, enc); + } catch (URISyntaxException ex) { + if (log.isWarnEnabled()) { + log.warn("Could not decode: " + source + " (header encoding: '" + enc + "'); exception: " + ex.getMessage()); + } + } + } + } + if (conf.isDecodeUsingCustomCharsetRequired()) { + String enc = conf.getDecodeUsing(); + if (enc != null) { + try { + return URLDecoder.decodeURL(source, enc); + } catch (URISyntaxException ex) { + if (log.isWarnEnabled()) { + log.warn("Could not decode: " + source + " (encoding: '" + enc + "') using default encoding; exception: " + ex.getMessage()); + } + } + } + } + return source; + } + + + private RuleChain getNewChain(final HttpServletRequest hsRequest, FilterChain parentChain) { + + String originalUrl = getPathWithinApplication(hsRequest); + + if (originalUrl == null) { + // for some reason the engine is not giving us the url + // this isn't good + log.debug("unable to fetch request uri from request. This shouldn't happen, it may indicate that " + + "the web application server has a bug or that the request was not pased correctly."); + return null; + } + + if (log.isDebugEnabled()) { + log.debug("processing request for " + originalUrl); + } + + // add the query string on uri (note, some web app containers do this) + if (originalUrl != null && originalUrl.indexOf("?") == -1 && conf.isUseQueryString()) { + String query = hsRequest.getQueryString(); + if (query != null) { + query = query.trim(); + if (query.length() > 0) { + originalUrl = originalUrl + "?" + query; + log.debug("query string added"); + } + } + } + + if (!conf.isOk()) { + // when conf cannot be loaded for some sort of error + // continue as normal without looking at the non-existent rules + log.debug("configuration is not ok. not rewriting request."); + return null; + } + + final List rules = conf.getRules(); + if (rules.size() == 0) { + // no rules defined + log.debug("there are no rules setup. not rewriting request."); + return null; + } + + return new RuleChain(this, originalUrl, parentChain); + } + + + /** + * Handle an exception thrown by a Run element. + */ + public RewrittenUrl handleInvocationTargetException(final HttpServletRequest hsRequest, + final HttpServletResponse hsResponse, InvocationTargetException e) + throws ServletException, IOException { + + Throwable originalThrowable = getOriginalException(e); + + if (log.isDebugEnabled()) { + log.debug("attampting to find catch for exception " + originalThrowable.getClass().getName()); + } + + List catchElems = conf.getCatchElems(); + for (int i = 0; i < catchElems.size(); i++) { + CatchElem catchElem = (CatchElem) catchElems.get(i); + if (!catchElem.matches(originalThrowable)) continue; + try { + return catchElem.execute(hsRequest, hsResponse, originalThrowable); + + } catch (InvocationTargetException invocationExceptionInner) { + originalThrowable = getOriginalException(invocationExceptionInner); + log.warn("had exception processing catch, trying the rest of the catches with " + + originalThrowable.getClass().getName()); + } + } + + if (log.isDebugEnabled()) { + log.debug("exception unhandled", e); + } + if (originalThrowable instanceof Error) throw (Error) originalThrowable; + if (originalThrowable instanceof RuntimeException) throw (RuntimeException) originalThrowable; + if (originalThrowable instanceof ServletException) throw (ServletException) originalThrowable; + if (originalThrowable instanceof IOException) throw (IOException) originalThrowable; + throw new ServletException(originalThrowable); + } + + /** + * Get the original exception that caused the InvocationTargetException. + * + * @param e the InvocationTargetException + * @return the original exception. + * @throws javax.servlet.ServletException If the exception is a servlet exception, it will be thrown. + */ + private Throwable getOriginalException(InvocationTargetException e) throws ServletException { + Throwable originalThrowable = e.getTargetException(); + if (originalThrowable == null) { + originalThrowable = e.getCause(); + if (originalThrowable == null) { + throw new ServletException(e); + } + } + // unwrap if exception is a ServletException + if (originalThrowable instanceof ServletException) { + ServletException se = (ServletException) originalThrowable; + // go 5 deep to see if we can get a real exception + for (int i = 0; i < 5 && se.getCause() instanceof ServletException; i++) { + se = (ServletException) se.getCause(); + } + if (se.getCause() instanceof InvocationTargetException) { + return getOriginalException((InvocationTargetException) se.getCause()); + } else { + throw se; + } + } + return originalThrowable; + } + + + public Conf getConf() { + return conf; + } + + + /** + * Handles rewriting urls in jsp's etc, i.e. response.encodeURL() is overriden in the response wrapper. + * + * @param hsResponse response + * @param hsRequest request + * @param encodeUrlHasBeenRun if encodeUrl has already been run on the originalOutboundUrl speficy this to be true + * @param outboundUrl url + * @return RewrittenOutboundUrl + * @see UrlRewriteWrappedResponse + */ + protected RewrittenOutboundUrl processEncodeURL(HttpServletResponse hsResponse, HttpServletRequest hsRequest, + boolean encodeUrlHasBeenRun, String outboundUrl) { + + if (log.isDebugEnabled()) { + log.debug("processing outbound url for " + outboundUrl); + } + + if (outboundUrl == null) { + // this probably means encode called with no url + return new RewrittenOutboundUrl(null, true); + } + + // attempt to match the rules + boolean finalEncodeOutboundUrl = true; + String finalToUrl = outboundUrl; + final List outboundRules = conf.getOutboundRules(); + try { + for (int i = 0; i < outboundRules.size(); i++) { + final OutboundRule outboundRule = (OutboundRule) outboundRules.get(i); + if (!encodeUrlHasBeenRun && outboundRule.isEncodeFirst()) { + continue; + } + if (encodeUrlHasBeenRun && !outboundRule.isEncodeFirst()) { + continue; + } + final RewrittenOutboundUrl rewrittenUrl = outboundRule.execute(finalToUrl, hsRequest, hsResponse); + if (rewrittenUrl != null) { + // means this rule has matched + if (log.isDebugEnabled()) { + log.debug("\"" + outboundRule.getDisplayName() + "\" matched"); + } + finalToUrl = rewrittenUrl.getTarget(); + finalEncodeOutboundUrl = rewrittenUrl.isEncode(); + if (outboundRule.isLast()) { + log.debug("rule is last"); + // there can be no more matches on this request + break; + } + } + } + } catch (InvocationTargetException e) { + try { + handleInvocationTargetException(hsRequest, hsResponse, e); + } catch (ServletException e1) { + log.error(e1); + } catch (IOException e1) { + log.error(e1); + } + } + + return new RewrittenOutboundUrl(finalToUrl, finalEncodeOutboundUrl); + } + + /** + * Destory the rewriter gracefully. + */ + public void destroy() { + conf.destroy(); + } + +} + + + diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteMatch.java b/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteMatch.java index 94946a1f..211b0aa5 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteMatch.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteMatch.java @@ -1,74 +1,74 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.extend; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.ServletException; -import java.io.IOException; - -/** - * Service the request with a clean object. - * Perform any business logic data retrival etc then prepare an object for presentation of the data. - */ -public class RewriteMatch { - - /** - * When future rules are processed they need to have a URL to compare against. If this method is not implemented - * then the url before this rule will be used. If isLast() returns true then this will never be called. - * @return String - */ - public String getMatchingUrl() { - return null; - } - - /** - * If this rule has been matched and has not been "stolen" by another rule then process the request. - * - * If you return true then the filter chain will NOT continue. - * - * @return boolean true if the request was rewritten, false if not. - */ - public boolean execute(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - // do nothing by default - return true; - } - -} - - - - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.extend; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import java.io.IOException; + +/** + * Service the request with a clean object. + * Perform any business logic data retrival etc then prepare an object for presentation of the data. + */ +public class RewriteMatch { + + /** + * When future rules are processed they need to have a URL to compare against. If this method is not implemented + * then the url before this rule will be used. If isLast() returns true then this will never be called. + * @return String + */ + public String getMatchingUrl() { + return null; + } + + /** + * If this rule has been matched and has not been "stolen" by another rule then process the request. + * + * If you return true then the filter chain will NOT continue. + * + * @return boolean true if the request was rewritten, false if not. + */ + public boolean execute(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + // do nothing by default + return true; + } + +} + + + + diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteRule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteRule.java index b4a0a02a..ee0a0142 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteRule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteRule.java @@ -1,74 +1,74 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.extend; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -/** - * A RewriteRule is basically the class that will figure out the answer to "Can we service this http request?". If we - * can we return a match object that will actually service the request. - */ -public class RewriteRule { - - /** - * Initialise the rule. - * If you return false here the rule will be marked as disabled. - */ - public boolean initialise(ServletContext servletContext) { - // by default do nothing - return true; - } - - /** - * Prepare to be shut down. There will be no more calls to "matches" after this is called. - */ - public void destroy() { - // by default do nothing - } - - /** - * Can we match the current request? null means no. Return a valid RuleMatch object or - * new SimpleRewriteMatch() (or an object that extends RewriteMatch) if this rule matches. - * - * @param request - * @param response - */ - public RewriteMatch matches(HttpServletRequest request, HttpServletResponse response) { - return null; - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.extend; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +/** + * A RewriteRule is basically the class that will figure out the answer to "Can we service this http request?". If we + * can we return a match object that will actually service the request. + */ +public class RewriteRule { + + /** + * Initialise the rule. + * If you return false here the rule will be marked as disabled. + */ + public boolean initialise(ServletContext servletContext) { + // by default do nothing + return true; + } + + /** + * Prepare to be shut down. There will be no more calls to "matches" after this is called. + */ + public void destroy() { + // by default do nothing + } + + /** + * Can we match the current request? null means no. Return a valid RuleMatch object or + * new SimpleRewriteMatch() (or an object that extends RewriteMatch) if this rule matches. + * + * @param request + * @param response + */ + public RewriteMatch matches(HttpServletRequest request, HttpServletResponse response) { + return null; + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/functions/CssVarFunction.java b/src/main/java/org/tuckey/web/filters/urlrewrite/functions/CssVarFunction.java index db9120ba..8734e506 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/functions/CssVarFunction.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/functions/CssVarFunction.java @@ -1,103 +1,137 @@ -package org.tuckey.web.filters.urlrewrite.functions; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -/** - * todo: turn into a css vars filter plugin - * Quick and dirty limited implementation of css Variables in Java - *

    - * http://disruptive-innovations.com/zoo/cssvariables/ - * http://trac.webkit.org/browser/trunk/LayoutTests/fast/css/variables - */ -public class CssVarFunction { - - /* - - set variables, these bay be overriden by request attributes - -@variables { - gadgetBodyLinkColor: #c0c0c0; -} - -h1 { - border-color: var(gadgetBodyLinkColor); -} - - */ - - - static Pattern VARIABLE_SET_PATTERN = Pattern.compile("\\s*([a-zA-Z0-9-]+)\\s*\\:(.*);"); - static Pattern VARIABLE_REF_PATTERN = Pattern.compile("var\\(([a-zA-Z0-9-]+)\\)"); - static Pattern VARIABLES_BLOCK_START_PATTERN = Pattern.compile("@variables"); - - public static void parse(InputStream cssFile, Map variables, OutputStream os) throws IOException { - BufferedReader br = new BufferedReader(new InputStreamReader(cssFile)); - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); - Map defaultVariables = new HashMap(); - - if (variables == null) variables = new HashMap(); - String line; - boolean readingVars = false; - boolean emitNewLine = false; - while ((line = br.readLine()) != null) { - - if (emitNewLine && !readingVars) bw.newLine(); - emitNewLine = true; - - if (!readingVars && VARIABLES_BLOCK_START_PATTERN.matcher(line).find()) readingVars = true; - - if (readingVars) { - Matcher m = VARIABLE_SET_PATTERN.matcher(line); - while (m.find()) { - defaultVariables.put(m.group(1), m.group(2)); - } - } - if (!readingVars) { - Matcher m2 = VARIABLE_REF_PATTERN.matcher(line); - StringBuffer sb = new StringBuffer(); - while (m2.find()) { - String var = m2.group(1); - String varValue = (String) variables.get(var); - if (varValue == null) varValue = (String) defaultVariables.get(var); - if (varValue == null) varValue = ""; - m2.appendReplacement(sb, varValue); - } - m2.appendTail(sb); - line = sb.toString(); - - bw.write(line); - } - if (readingVars && line.matches("}")) { - readingVars = false; - emitNewLine = false; - } - } - bw.flush(); - } - - public static String parse(String css, Map variables) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ByteArrayInputStream bais = new ByteArrayInputStream(css.getBytes()); - try { - parse(bais, variables, baos); - } catch (IOException e) { - throw new RuntimeException(e); - } - return baos.toString(); - } - -} - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.functions; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +/** + * todo: turn into a css vars filter plugin + * Quick and dirty limited implementation of css Variables in Java + *

    + * http://disruptive-innovations.com/zoo/cssvariables/ + * http://trac.webkit.org/browser/trunk/LayoutTests/fast/css/variables + */ +public class CssVarFunction { + + /* + + set variables, these bay be overriden by request attributes + +@variables { + gadgetBodyLinkColor: #c0c0c0; +} + +h1 { + border-color: var(gadgetBodyLinkColor); +} + + */ + + + static Pattern VARIABLE_SET_PATTERN = Pattern.compile("\\s*([a-zA-Z0-9-]+)\\s*\\:(.*);"); + static Pattern VARIABLE_REF_PATTERN = Pattern.compile("var\\(([a-zA-Z0-9-]+)\\)"); + static Pattern VARIABLES_BLOCK_START_PATTERN = Pattern.compile("@variables"); + + public static void parse(InputStream cssFile, Map variables, OutputStream os) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(cssFile)); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); + Map defaultVariables = new HashMap(); + + if (variables == null) variables = new HashMap(); + String line; + boolean readingVars = false; + boolean emitNewLine = false; + while ((line = br.readLine()) != null) { + + if (emitNewLine && !readingVars) bw.newLine(); + emitNewLine = true; + + if (!readingVars && VARIABLES_BLOCK_START_PATTERN.matcher(line).find()) readingVars = true; + + if (readingVars) { + Matcher m = VARIABLE_SET_PATTERN.matcher(line); + while (m.find()) { + defaultVariables.put(m.group(1), m.group(2)); + } + } + if (!readingVars) { + Matcher m2 = VARIABLE_REF_PATTERN.matcher(line); + StringBuffer sb = new StringBuffer(); + while (m2.find()) { + String var = m2.group(1); + String varValue = (String) variables.get(var); + if (varValue == null) varValue = (String) defaultVariables.get(var); + if (varValue == null) varValue = ""; + m2.appendReplacement(sb, varValue); + } + m2.appendTail(sb); + line = sb.toString(); + + bw.write(line); + } + if (readingVars && line.matches("}")) { + readingVars = false; + emitNewLine = false; + } + } + bw.flush(); + } + + public static String parse(String css, Map variables) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ByteArrayInputStream bais = new ByteArrayInputStream(css.getBytes()); + try { + parse(bais, variables, baos); + } catch (IOException e) { + throw new RuntimeException(e); + } + return baos.toString(); + } + +} + diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/functions/StringFunctions.java b/src/main/java/org/tuckey/web/filters/urlrewrite/functions/StringFunctions.java index b4315feb..30d24f69 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/functions/StringFunctions.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/functions/StringFunctions.java @@ -1,166 +1,200 @@ -package org.tuckey.web.filters.urlrewrite.functions; - -import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionContext; -import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionFilterChain; -import org.tuckey.web.filters.urlrewrite.utils.Log; - -import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.nio.charset.Charset; -import java.util.regex.Pattern; - - -public class StringFunctions { - - private static Log log = Log.getLog(StringFunctions.class); - private static final Pattern FIND_COLON_PATTERN = Pattern.compile("(? + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.functions; + +import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionContext; +import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionFilterChain; +import org.tuckey.web.filters.urlrewrite.utils.Log; + +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.util.regex.Pattern; + + +public class StringFunctions { + + private static Log log = Log.getLog(StringFunctions.class); + private static final Pattern FIND_COLON_PATTERN = Pattern.compile("(? + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.sample; + +import org.tuckey.web.filters.urlrewrite.Conf; +import org.w3c.dom.Document; + +import java.io.InputStream; + + +public class SampleConfExt extends Conf { + + public SampleConfExt() { + // do something + } + + protected synchronized void loadDom(InputStream inputStream) { + // do something + super.loadDom(inputStream); + } + + protected void processConfDoc(Document doc) { + // do something else + super.processConfDoc(doc); + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleMultiUrlRewriteFilter.java b/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleMultiUrlRewriteFilter.java index c3b18bd7..c20b9aa3 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleMultiUrlRewriteFilter.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleMultiUrlRewriteFilter.java @@ -1,49 +1,83 @@ -package org.tuckey.web.filters.urlrewrite.sample; - -import org.tuckey.web.filters.urlrewrite.Conf; -import org.tuckey.web.filters.urlrewrite.UrlRewriteFilter; -import org.tuckey.web.filters.urlrewrite.UrlRewriter; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import java.io.FileInputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * Sample of how you might load multiple configuration files. (NOT to be used verbatim!!) - */ -public class SampleMultiUrlRewriteFilter extends UrlRewriteFilter { - - private List urlrewriters = new ArrayList(); - - public void loadUrlRewriter(FilterConfig filterConfig) throws ServletException { - // add configurations - try { - Conf conf1 = new Conf(filterConfig.getServletContext(), new FileInputStream("someconf.xml"), "someconf.xml", ""); - urlrewriters.add(new UrlRewriter(conf1)); - - Conf conf2 = new SampleConfExt(); - urlrewriters.add(new UrlRewriter(conf2)); - - } catch (Exception e) { - throw new ServletException(e); - } - } - - public UrlRewriter getUrlRewriter(ServletRequest request, ServletResponse response, FilterChain chain) { - // do some logic to decide what urlrewriter to use (possibly do a reload check on the conf file) - return (UrlRewriter) urlrewriters.get(0); - } - - public void destroyUrlRewriter() { - for (int i = 0; i < urlrewriters.size(); i++) { - UrlRewriter urlRewriter = (UrlRewriter) urlrewriters.get(i); - urlRewriter.destroy(); - } - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.sample; + +import org.tuckey.web.filters.urlrewrite.Conf; +import org.tuckey.web.filters.urlrewrite.UrlRewriteFilter; +import org.tuckey.web.filters.urlrewrite.UrlRewriter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * Sample of how you might load multiple configuration files. (NOT to be used verbatim!!) + */ +public class SampleMultiUrlRewriteFilter extends UrlRewriteFilter { + + private List urlrewriters = new ArrayList(); + + public void loadUrlRewriter(FilterConfig filterConfig) throws ServletException { + // add configurations + try { + Conf conf1 = new Conf(filterConfig.getServletContext(), new FileInputStream("someconf.xml"), "someconf.xml", ""); + urlrewriters.add(new UrlRewriter(conf1)); + + Conf conf2 = new SampleConfExt(); + urlrewriters.add(new UrlRewriter(conf2)); + + } catch (Exception e) { + throw new ServletException(e); + } + } + + public UrlRewriter getUrlRewriter(ServletRequest request, ServletResponse response, FilterChain chain) { + // do some logic to decide what urlrewriter to use (possibly do a reload check on the conf file) + return (UrlRewriter) urlrewriters.get(0); + } + + public void destroyUrlRewriter() { + for (int i = 0; i < urlrewriters.size(); i++) { + UrlRewriter urlRewriter = (UrlRewriter) urlrewriters.get(i); + urlRewriter.destroy(); + } + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteMatch.java b/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteMatch.java index 36a35ce1..7be22824 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteMatch.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteMatch.java @@ -1,73 +1,73 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.sample; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; - -import jakarta.servlet.RequestDispatcher; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; - - -/** - * A sample of how you might write a custom match. - */ -class SampleRewriteMatch extends RewriteMatch { - private int id; - - SampleRewriteMatch(int i) { - id = i; - } - - int getId() { - return id; - } - - public boolean execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - - // lookup things in the db based on id - - // do something like forward to a jsp - request.setAttribute("sampleRewriteMatch", this); - RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/jsp/some-view.jsp"); - rd.forward(request, response); - // in the jsp you can use request.getAttribute("sampleRewriteMatch") to fetch this object - - return true; - } - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.sample; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; + +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + + +/** + * A sample of how you might write a custom match. + */ +class SampleRewriteMatch extends RewriteMatch { + private int id; + + SampleRewriteMatch(int i) { + id = i; + } + + int getId() { + return id; + } + + public boolean execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + + // lookup things in the db based on id + + // do something like forward to a jsp + request.setAttribute("sampleRewriteMatch", this); + RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/jsp/some-view.jsp"); + rd.forward(request, response); + // in the jsp you can use request.getAttribute("sampleRewriteMatch") to fetch this object + + return true; + } + } \ No newline at end of file diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteRule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteRule.java index 49c6fad2..9de0a9d7 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteRule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteRule.java @@ -1,68 +1,68 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.sample; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteRule; -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -/** - * A sample of how you might write a custom rule. - */ -public class SampleRewriteRule extends RewriteRule { - - - public RewriteMatch matches(HttpServletRequest request, HttpServletResponse response) { - - // return null if we don't want the request - if (!request.getRequestURI().startsWith("/staff/")) return null; - - Integer id = null; - try { - // grab the things out of the url we need - id = Integer.valueOf(request.getRequestURI().replaceFirst( - "/staff/([0-9]+)/", "$1")); - } catch (NumberFormatException e) { - // if we don't get a good id then return null - return null; - } - - // match required with clean parameters - return new SampleRewriteMatch(id.intValue()); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.sample; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteRule; +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +/** + * A sample of how you might write a custom rule. + */ +public class SampleRewriteRule extends RewriteRule { + + + public RewriteMatch matches(HttpServletRequest request, HttpServletResponse response) { + + // return null if we don't want the request + if (!request.getRequestURI().startsWith("/staff/")) return null; + + Integer id = null; + try { + // grab the things out of the url we need + id = Integer.valueOf(request.getRequestURI().replaceFirst( + "/staff/([0-9]+)/", "$1")); + } catch (NumberFormatException e) { + // if we don't get a good id then return null + return null; + } + + // match required with clean parameters + return new SampleRewriteMatch(id.intValue()); + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/BackReferenceReplacer.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/BackReferenceReplacer.java index 969f8c53..f875bf81 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/BackReferenceReplacer.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/BackReferenceReplacer.java @@ -1,135 +1,135 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.substitution; - -import org.tuckey.web.filters.urlrewrite.ConditionMatch; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Back references (eg, %1, %2 etc) replacer. - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class BackReferenceReplacer implements SubstitutionFilter { - - private static Log log = Log.getLog(BackReferenceReplacer.class); - - private static Pattern backRefPattern = Pattern.compile("(? 0) { - - Matcher backRefMatcher = backRefPattern.matcher(subjectOfReplacement); - - StringBuffer sb = new StringBuffer(); - boolean anyMatches = false; - int lastAppendPosition = 0; - while (backRefMatcher.find()) { - anyMatches = true; - int groupCount = backRefMatcher.groupCount(); - if (groupCount < 1) { - log.error("group count on backref finder regex is not as expected"); - if (log.isDebugEnabled()) { - log.error("backRefMatcher: " + backRefMatcher.toString()); - } - continue; - } - String varStr = backRefMatcher.group(1); - - boolean validBackref = false; - int varInt = 0; - log.debug("found " + varStr); - // now grab this match from lastConditionMatchMatcher - try { - varInt = Integer.parseInt(varStr); - if (varInt > lastCondMatcherGroupCount) { - log.error("backref %" + varInt + " not found in conditon "); - if (log.isDebugEnabled()) { - log.debug("condition matcher: " + lastConditionMatchMatcher.toString()); - } - } else { - validBackref = true; - } - } catch (NumberFormatException nfe) { - log.error("could not parse backref " + varStr + " to number"); - } - String conditionMatch = ""; - if (validBackref) { - conditionMatch = lastConditionMatchMatcher.group(varInt); - } - String stringBeforeMatch = subjectOfReplacement.substring(lastAppendPosition, backRefMatcher.start()); - sb.append(nextFilter.substitute(stringBeforeMatch, ctx)); - sb.append(conditionMatch); - lastAppendPosition = backRefMatcher.end(); - } - if (anyMatches) { - String stringAfterMatch = subjectOfReplacement.substring(lastAppendPosition); - sb.append(nextFilter.substitute(stringAfterMatch, ctx)); - if (log.isDebugEnabled()) log.debug("replaced sb is " + sb); - return sb.toString(); - } - } - } - - return nextFilter.substitute(subjectOfReplacement, ctx); - } - - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.substitution; + +import org.tuckey.web.filters.urlrewrite.ConditionMatch; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Back references (eg, %1, %2 etc) replacer. + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class BackReferenceReplacer implements SubstitutionFilter { + + private static Log log = Log.getLog(BackReferenceReplacer.class); + + private static Pattern backRefPattern = Pattern.compile("(? 0) { + + Matcher backRefMatcher = backRefPattern.matcher(subjectOfReplacement); + + StringBuffer sb = new StringBuffer(); + boolean anyMatches = false; + int lastAppendPosition = 0; + while (backRefMatcher.find()) { + anyMatches = true; + int groupCount = backRefMatcher.groupCount(); + if (groupCount < 1) { + log.error("group count on backref finder regex is not as expected"); + if (log.isDebugEnabled()) { + log.error("backRefMatcher: " + backRefMatcher.toString()); + } + continue; + } + String varStr = backRefMatcher.group(1); + + boolean validBackref = false; + int varInt = 0; + log.debug("found " + varStr); + // now grab this match from lastConditionMatchMatcher + try { + varInt = Integer.parseInt(varStr); + if (varInt > lastCondMatcherGroupCount) { + log.error("backref %" + varInt + " not found in conditon "); + if (log.isDebugEnabled()) { + log.debug("condition matcher: " + lastConditionMatchMatcher.toString()); + } + } else { + validBackref = true; + } + } catch (NumberFormatException nfe) { + log.error("could not parse backref " + varStr + " to number"); + } + String conditionMatch = ""; + if (validBackref) { + conditionMatch = lastConditionMatchMatcher.group(varInt); + } + String stringBeforeMatch = subjectOfReplacement.substring(lastAppendPosition, backRefMatcher.start()); + sb.append(nextFilter.substitute(stringBeforeMatch, ctx)); + sb.append(conditionMatch); + lastAppendPosition = backRefMatcher.end(); + } + if (anyMatches) { + String stringAfterMatch = subjectOfReplacement.substring(lastAppendPosition); + sb.append(nextFilter.substitute(stringAfterMatch, ctx)); + if (log.isDebugEnabled()) log.debug("replaced sb is " + sb); + return sb.toString(); + } + } + } + + return nextFilter.substitute(subjectOfReplacement, ctx); + } + + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/ChainedSubstitutionFilters.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/ChainedSubstitutionFilters.java index a48085a3..7bf5b02f 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/ChainedSubstitutionFilters.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/ChainedSubstitutionFilters.java @@ -1,55 +1,89 @@ -package org.tuckey.web.filters.urlrewrite.substitution; - -import jakarta.servlet.ServletContext; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - - -public class ChainedSubstitutionFilters implements SubstitutionFilterChain { - - private List filters; - private int nextFilter = 0; - - public ChainedSubstitutionFilters(List filters) { - this.filters = filters; - } - - public String substitute(String string, SubstitutionContext ctx){ - if(nextFilter >= filters.size()) - return string; - String ret = ((SubstitutionFilter)filters.get(nextFilter++)).substitute(string, ctx, this); - nextFilter--; - return ret; - } - - public static String substitute(String string, SubstitutionFilter singleFilter){ - ArrayList list = new ArrayList(1); - list.add(singleFilter); - SubstitutionFilterChain filterChain = new ChainedSubstitutionFilters(list); - return filterChain.substitute(string, null); - } - - public static SubstitutionFilterChain getDefaultSubstitutionChain( - boolean withPattern, boolean withFunction, boolean withVariable, - boolean withBackReference) { - return getDefaultSubstitutionChain(withPattern, withFunction, withVariable, withBackReference, null); - } - - public static SubstitutionFilterChain getDefaultSubstitutionChain(boolean withPattern, boolean withFunction, boolean withVariable, boolean withBackReference, ServletContext sc){ - List substitutionFilters = new LinkedList(); - - if(withPattern) - substitutionFilters.add(new PatternReplacer()); - if(withFunction) - substitutionFilters.add(new FunctionReplacer()); - if(withVariable) - substitutionFilters.add(sc == null ? new VariableReplacer() : new VariableReplacer(sc)); - if(withBackReference) - substitutionFilters.add(new BackReferenceReplacer()); - substitutionFilters.add(new MatcherReplacer()); - substitutionFilters.add(new UnescapeReplacer()); - - return new ChainedSubstitutionFilters(substitutionFilters); - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.substitution; + +import jakarta.servlet.ServletContext; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + + +public class ChainedSubstitutionFilters implements SubstitutionFilterChain { + + private List filters; + private int nextFilter = 0; + + public ChainedSubstitutionFilters(List filters) { + this.filters = filters; + } + + public String substitute(String string, SubstitutionContext ctx){ + if(nextFilter >= filters.size()) + return string; + String ret = ((SubstitutionFilter)filters.get(nextFilter++)).substitute(string, ctx, this); + nextFilter--; + return ret; + } + + public static String substitute(String string, SubstitutionFilter singleFilter){ + ArrayList list = new ArrayList(1); + list.add(singleFilter); + SubstitutionFilterChain filterChain = new ChainedSubstitutionFilters(list); + return filterChain.substitute(string, null); + } + + public static SubstitutionFilterChain getDefaultSubstitutionChain( + boolean withPattern, boolean withFunction, boolean withVariable, + boolean withBackReference) { + return getDefaultSubstitutionChain(withPattern, withFunction, withVariable, withBackReference, null); + } + + public static SubstitutionFilterChain getDefaultSubstitutionChain(boolean withPattern, boolean withFunction, boolean withVariable, boolean withBackReference, ServletContext sc){ + List substitutionFilters = new LinkedList(); + + if(withPattern) + substitutionFilters.add(new PatternReplacer()); + if(withFunction) + substitutionFilters.add(new FunctionReplacer()); + if(withVariable) + substitutionFilters.add(sc == null ? new VariableReplacer() : new VariableReplacer(sc)); + if(withBackReference) + substitutionFilters.add(new BackReferenceReplacer()); + substitutionFilters.add(new MatcherReplacer()); + substitutionFilters.add(new UnescapeReplacer()); + + return new ChainedSubstitutionFilters(substitutionFilters); + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/FunctionReplacer.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/FunctionReplacer.java index 30b73556..3688af69 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/FunctionReplacer.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/FunctionReplacer.java @@ -1,158 +1,158 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.substitution; - -import org.tuckey.web.filters.urlrewrite.functions.StringFunctions; -import org.tuckey.web.filters.urlrewrite.utils.Log; - -import java.util.Collections; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Helper class for function replacement. - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class FunctionReplacer implements SubstitutionFilter { - - private static Log log = Log.getLog(VariableReplacer.class); - - private static Pattern functionPattern = Pattern.compile("(? conditionMatcherGroupCount) { - log.error("backref %" + varInt + " not found in conditon "); - if (log.isDebugEnabled()) { - log.debug("condition matcher: " + conditionMatcher.toString()); - } - } else { - validBackref = true; - } - } catch (NumberFormatException nfe) { - log.error("could not parse backref " + varStr + " to number"); - } - String conditionMatch = null; - if (validBackref) { - conditionMatch = conditionMatcher.group(varInt); - } - String stringBeforeMatch = replacePattern.substring(lastAppendPosition, backRefMatcher.start()); - sb.append(nextFilter.substitute(stringBeforeMatch, ctx)); - if (conditionMatch != null) - sb.append(conditionMatch); - lastAppendPosition = backRefMatcher.end(); - } - if (anyMatches) { - String stringAfterMatch = replacePattern.substring(lastAppendPosition); - sb.append(nextFilter.substitute(stringAfterMatch, ctx)); - if (log.isDebugEnabled()) log.debug("replaced sb is " + sb); - return sb.toString(); - } - return nextFilter.substitute(replacePattern, ctx); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.substitution; + +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Back references (eg, $1, $2 etc) replacer. + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class MatcherReplacer implements SubstitutionFilter { + + private static Log log = Log.getLog(MatcherReplacer.class); + + private static Pattern backRefPattern = Pattern.compile("(? conditionMatcherGroupCount) { + log.error("backref %" + varInt + " not found in conditon "); + if (log.isDebugEnabled()) { + log.debug("condition matcher: " + conditionMatcher.toString()); + } + } else { + validBackref = true; + } + } catch (NumberFormatException nfe) { + log.error("could not parse backref " + varStr + " to number"); + } + String conditionMatch = null; + if (validBackref) { + conditionMatch = conditionMatcher.group(varInt); + } + String stringBeforeMatch = replacePattern.substring(lastAppendPosition, backRefMatcher.start()); + sb.append(nextFilter.substitute(stringBeforeMatch, ctx)); + if (conditionMatch != null) + sb.append(conditionMatch); + lastAppendPosition = backRefMatcher.end(); + } + if (anyMatches) { + String stringAfterMatch = replacePattern.substring(lastAppendPosition); + sb.append(nextFilter.substitute(stringAfterMatch, ctx)); + if (log.isDebugEnabled()) log.debug("replaced sb is " + sb); + return sb.toString(); + } + return nextFilter.substitute(replacePattern, ctx); + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/PatternReplacer.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/PatternReplacer.java index aa383d06..e35a7f6d 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/PatternReplacer.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/PatternReplacer.java @@ -1,75 +1,75 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.substitution; - -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; - -/** - * Replaces each match of the condition to the given substituted pattern - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class PatternReplacer implements SubstitutionFilter { - - public String substitute(String from, SubstitutionContext ctx, - SubstitutionFilterChain nextFilter) { - - StringMatchingMatcher conditionMatcher = ctx.getMatcher(); - conditionMatcher.reset(); - StringBuffer sb = new StringBuffer(); - int lastMatchEnd = 0; - while (conditionMatcher.find()) { - // we do not substitute on the non-matched string since it is straight from the URL - String notMatched = from.substring(lastMatchEnd, conditionMatcher.start()); - sb.append(notMatched); - // we will replace the matched string with the appropriately expanded pattern - String substitutedReplacement = nextFilter.substitute(ctx.getReplacePattern(), ctx); - sb.append(substitutedReplacement); - lastMatchEnd = conditionMatcher.end(); - // get out of there for wildcard patterns - if (!conditionMatcher.isMultipleMatchingSupported() || notMatched.isEmpty()) - break; - if (conditionMatcher.hitEnd()){ - break; - } - } - // put the remaining ending non-matched string - if (lastMatchEnd < from.length()) - sb.append(from.substring(lastMatchEnd)); - return sb.toString(); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.substitution; + +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; + +/** + * Replaces each match of the condition to the given substituted pattern + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class PatternReplacer implements SubstitutionFilter { + + public String substitute(String from, SubstitutionContext ctx, + SubstitutionFilterChain nextFilter) { + + StringMatchingMatcher conditionMatcher = ctx.getMatcher(); + conditionMatcher.reset(); + StringBuffer sb = new StringBuffer(); + int lastMatchEnd = 0; + while (conditionMatcher.find()) { + // we do not substitute on the non-matched string since it is straight from the URL + String notMatched = from.substring(lastMatchEnd, conditionMatcher.start()); + sb.append(notMatched); + // we will replace the matched string with the appropriately expanded pattern + String substitutedReplacement = nextFilter.substitute(ctx.getReplacePattern(), ctx); + sb.append(substitutedReplacement); + lastMatchEnd = conditionMatcher.end(); + // get out of there for wildcard patterns + if (!conditionMatcher.isMultipleMatchingSupported() || notMatched.isEmpty()) + break; + if (conditionMatcher.hitEnd()){ + break; + } + } + // put the remaining ending non-matched string + if (lastMatchEnd < from.length()) + sb.append(from.substring(lastMatchEnd)); + return sb.toString(); + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionContext.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionContext.java index 7d53e9d4..4f2be14c 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionContext.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionContext.java @@ -1,42 +1,76 @@ -package org.tuckey.web.filters.urlrewrite.substitution; - -import org.tuckey.web.filters.urlrewrite.ConditionMatch; -import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; - -import jakarta.servlet.http.HttpServletRequest; - -public class SubstitutionContext { - - - private HttpServletRequest hsRequest; - private StringMatchingMatcher matcher; - private ConditionMatch lastConditionMatch; - private String replacePattern; - - public SubstitutionContext(HttpServletRequest hsRequest, - StringMatchingMatcher matcher, ConditionMatch lastConditionMatch, - String replacePattern) { - super(); - this.hsRequest = hsRequest; - this.matcher = matcher; - this.lastConditionMatch = lastConditionMatch; - this.replacePattern = replacePattern; - } - - public HttpServletRequest getHsRequest() { - return hsRequest; - } - - public StringMatchingMatcher getMatcher() { - return matcher; - } - - public ConditionMatch getLastConditionMatch() { - return lastConditionMatch; - } - - public String getReplacePattern() { - return replacePattern; - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.substitution; + +import org.tuckey.web.filters.urlrewrite.ConditionMatch; +import org.tuckey.web.filters.urlrewrite.utils.StringMatchingMatcher; + +import jakarta.servlet.http.HttpServletRequest; + +public class SubstitutionContext { + + + private HttpServletRequest hsRequest; + private StringMatchingMatcher matcher; + private ConditionMatch lastConditionMatch; + private String replacePattern; + + public SubstitutionContext(HttpServletRequest hsRequest, + StringMatchingMatcher matcher, ConditionMatch lastConditionMatch, + String replacePattern) { + super(); + this.hsRequest = hsRequest; + this.matcher = matcher; + this.lastConditionMatch = lastConditionMatch; + this.replacePattern = replacePattern; + } + + public HttpServletRequest getHsRequest() { + return hsRequest; + } + + public StringMatchingMatcher getMatcher() { + return matcher; + } + + public ConditionMatch getLastConditionMatch() { + return lastConditionMatch; + } + + public String getReplacePattern() { + return replacePattern; + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionFilter.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionFilter.java index f5c5fc69..ec67d8c6 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionFilter.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionFilter.java @@ -1,5 +1,39 @@ -package org.tuckey.web.filters.urlrewrite.substitution; - -public interface SubstitutionFilter { - public String substitute(String string, SubstitutionContext ctx, SubstitutionFilterChain nextFilter); -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.substitution; + +public interface SubstitutionFilter { + public String substitute(String string, SubstitutionContext ctx, SubstitutionFilterChain nextFilter); +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionFilterChain.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionFilterChain.java index 5b472247..f7d08691 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionFilterChain.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/SubstitutionFilterChain.java @@ -1,7 +1,41 @@ -package org.tuckey.web.filters.urlrewrite.substitution; - -public interface SubstitutionFilterChain { - - public String substitute(String string, SubstitutionContext ctx); - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.substitution; + +public interface SubstitutionFilterChain { + + public String substitute(String string, SubstitutionContext ctx); + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/UnescapeReplacer.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/UnescapeReplacer.java index aa582bb1..45130ffa 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/UnescapeReplacer.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/UnescapeReplacer.java @@ -1,51 +1,51 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.substitution; - -/** - * Removes escape sequences from the string (\) - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class UnescapeReplacer implements SubstitutionFilter { - - public String substitute(String from, SubstitutionContext ctx, - SubstitutionFilterChain nextFilter) { - String unescaped = from.replaceAll("(? 0) notesBuffer.append("\n"); - String noteLine = StringUtils.trim(line.substring(1)); - notesBuffer.append(noteLine); - - } else if (line.startsWith("RewriteBase")) { - log.info("RewriteBase not supported, ignored"); - - } else if (line.startsWith("RewriteCond")) { - Condition condition = processRewriteCond(line); - if (condition != null) conditionsBuffer.add(condition); - - } else if (line.startsWith("RewriteEngine")) { - processRewriteEngine(conf, line); - - } else if (line.startsWith("RewriteLock")) { - log.error("RewriteLock not supported, ignored"); - - } else if (line.startsWith("RewriteLogLevel")) { - logLevelStr = parseLogLevel(logLevelStr, line); - - } else if (line.startsWith("RewriteLog")) { - logTypeStr = parseLogType(logTypeStr, line); - - } else if (line.startsWith("RewriteMap")) { - log.error("RewriteMap not supported, ignored"); - - } else if (line.startsWith("RewriteOptions")) { - log.error("RewriteOptions not supported, ignored"); - - } else if (line.startsWith("RewriteRule")) { - parseRule(conf, conditionsBuffer, notesBuffer, line); - notesBuffer = new StringBuffer(); - conditionsBuffer = new ArrayList(); - } else { - log.error("Unknown line: " + line); - } - } - if (logTypeStr != null || logLevelStr != null) { - String logStr = (logTypeStr == null ? "" : logTypeStr) + (logLevelStr == null ? "" : ":" + logLevelStr); - log.debug("setting log to: " + logStr); - Log.setLevel(logStr); - } - if (conditionsBuffer.size() > 0) { - log.error("conditions left over without a rule"); - } - } - - private void parseRule(Conf conf, List conditionsBuffer, StringBuffer notesBuffer, String line) { - NormalRule rule = processRule(line); - for (int j = 0; j < conditionsBuffer.size(); j++) { - Condition condition = (Condition) conditionsBuffer.get(j); - rule.addCondition(condition); - } - if (notesBuffer.length() > 0) rule.setNote(notesBuffer.toString()); - conf.addRule(rule); - } - - private String parseLogType(String logTypeStr, String line) { - Matcher logTypeMatcher = LOG_TYPE_PATTERN.matcher(line); - if (logTypeMatcher.matches()) { - logTypeStr = StringUtils.trimToNull(logTypeMatcher.group(1)); - if (logTypeStr != null) { - logTypeStr = logTypeStr.replaceAll("\"", ""); - log.debug("RewriteLog parsed as " + logTypeStr); - } - } - return logTypeStr; - } - - private String parseLogLevel(String logLevelStr, String line) { - log.debug("found a RewriteLogLevel"); - Matcher logLevelMatcher = LOG_LEVEL_PATTERN.matcher(line); - if (logLevelMatcher.matches()) { - int logLevel = NumberUtils.stringToInt(logLevelMatcher.group(1)); - if (logLevel <= 1) logLevelStr = "FATAL"; - else if (logLevel == 2) logLevelStr = "ERROR"; - else if (logLevel == 3) logLevelStr = "INFO"; - else if (logLevel == 4) logLevelStr = "WARN"; - else if (logLevel >= 5) logLevelStr = "DEBUG"; - log.debug("RewriteLogLevel parsed as " + logLevel); - - } else { - log.error("cannot parse " + line); - } - return logLevelStr; - } - - private NormalRule processRule(String line) { - NormalRule rule = new NormalRule(); - Matcher ruleMatcher = RULE_PATTERN.matcher(line); - if (ruleMatcher.matches()) { - String rulePartStr = StringUtils.trimToNull(ruleMatcher.group(1)); - if (rulePartStr != null) { - log.debug("got rule " + rulePartStr); - String[] ruleParts = rulePartStr.split("\\s"); - int partCounter = 0; - for (int j = 0; j < ruleParts.length; j++) { - String part = StringUtils.trimToNull(ruleParts[j]); - if (part == null) continue; - partCounter++; - log.debug("parsed rule part " + part); - if (partCounter == 1) { - rule.setFrom(part); - } - if (partCounter == 2) { - if (!"-".equals(part)) { - Matcher matcher = TO_VARIABLE_PATTERN.matcher(part); - if (matcher.find()) { - String knownType = getType(matcher.group(0).toString()); - if (knownType != "") { - part = part.replace(matcher.group(0).toString(), "%{" + knownType + "}"); - } - } - } - rule.setTo(part); - } - if (part.startsWith("[") && part.endsWith("]")) { - processRuleFlags(rule, part); - } - } - } else { - log.error("could not parse rule from " + line); - } - } else { - log.error("cannot parse " + line); - } - return rule; - } - - private void processRewriteEngine(Conf conf, String line) { - boolean enabled = true; - Matcher engineMatcher = ENGINE_PATTERN.matcher(line); - if (engineMatcher.matches()) { - String enabledStr = StringUtils.trim(engineMatcher.group(1)); - log.debug("RewriteEngine value parsed as '" + enabledStr + "'"); - if ("0".equalsIgnoreCase(enabledStr) || - "false".equalsIgnoreCase(enabledStr) || - "no".equalsIgnoreCase(enabledStr) || - "off".equalsIgnoreCase(enabledStr)) enabled = false; - log.debug("RewriteEngine as boolean '" + enabled + "'"); - } else { - log.error("cannot parse " + line); - } - conf.setEngineEnabled(enabled); - } - - private void processRuleFlags(NormalRule rule, String part) { - String rawFlags = StringUtils.trimToNull(part.substring(1, part.length() - 1)); - if (rawFlags != null) { - String[] flags = rawFlags.split(","); - for (int k = 0; k < flags.length; k++) { - String flag = flags[k]; - String flagValue = null; - if (flag.indexOf("=") != -1) { - flagValue = flag.substring(flag.indexOf("=") + 1); - flag = flag.substring(0, flag.indexOf("=")); - } - flag = flag.toLowerCase(); - /* - # 'chain|C' (chained with next rule) - This flag chains the current rule with the next rule (which itself can be chained with the following rule, and so on). This has the following effect: if a rule matches, then processing continues as usual - the flag has no effect. If the rule does not match, then all following chained rules are skipped. For instance, it can be used to remove the ``.www'' part, inside a per-directory rule set, when you let an external redirect happen (where the ``.www'' part should not occur!). - */ - if ("chain".equalsIgnoreCase(flag) || "C".equalsIgnoreCase(flag)) { - log.info("chain flag [C] not supported"); - } - /* - # 'cookie|CO=NAME:VAL:domain[:lifetime[:path]]' (set cookie) - This sets a cookie in the client's browser. The cookie's name is specified by NAME and the value is VAL. The domain field is the domain of the cookie, such as '.apache.org', the optional lifetime is the lifetime of the cookie in minutes, and the optional path is the path of the cookie - */ - if ("cookie".equalsIgnoreCase(flag) || "CO".equalsIgnoreCase(flag)) { - SetAttribute set = new SetAttribute(); - set.setType("cookie"); - String cookieName = flagValue; - String cookieValue = null; - if (flagValue != null) { - int colon = flagValue.indexOf(":"); - if (colon != -1) { - cookieValue = flagValue.substring(colon + 1); - cookieName = flagValue.substring(0, colon); - } - } - set.setName(cookieName); - // NOTE: The colon separated domain, lifetime, path are - // handled by SetAttribute.setValue() - set.setValue(cookieValue); - rule.addSetAttribute(set); - } - /* - # 'env|E=VAR:VAL' (set environment variable) - This forces an environment variable named VAR to be set to the value VAL, where VAL can contain regexp backreferences ($N and %N) which will be expanded. You can use this flag more than once, to set more than one variable. The variables can later be dereferenced in many situations, most commonly from within XSSI (via ) or CGI ($ENV{'VAR'}). You can also dereference the variable in a later RewriteCond pattern, using %{ENV:VAR}. Use this to strip information from URLs, while maintaining a record of that information. - */ - if ("env".equalsIgnoreCase(flag) || "E".equalsIgnoreCase(flag)) { - log.info("env flag [E] not supported"); - } - /* - # 'forbidden|F' (force URL to be forbidden) - This forces the current URL to be forbidden - it immediately sends back a HTTP response of 403 (FORBIDDEN). Use this flag in conjunction with appropriate RewriteConds to conditionally block some URLs. - */ - if ("forbidden".equalsIgnoreCase(flag) || "F".equalsIgnoreCase(flag)) { - SetAttribute set = new SetAttribute(); - set.setType("status"); - set.setValue("403"); - rule.addSetAttribute(set); - } - /* - # 'gone|G' (force URL to be gone) - This forces the current URL to be gone - it immediately sends back a HTTP response of 410 (GONE). Use this flag to mark pages which no longer exist as gone. - */ - if ("gone".equalsIgnoreCase(flag) || "G".equalsIgnoreCase(flag)) { - SetAttribute set = new SetAttribute(); - set.setType("status"); - set.setValue("410"); - rule.addSetAttribute(set); - } - /* - # 'last|L' (last rule) - Stop the rewriting process here and don't apply any more rewrite rules. This corresponds to the Perl last command or the break command in C. Use this flag to prevent the currently rewritten URL from being rewritten further by following rules. For example, use it to rewrite the root-path URL ('/') to a real one, e.g., '/e/www/'. - */ - if ("last".equalsIgnoreCase(flag) || "L".equalsIgnoreCase(flag)) { - rule.setToLast("true"); - } - /* - # 'next|N' (next round) - Re-run the rewriting process (starting again with the first rewriting rule). This time, the URL to match is no longer the original URL, but rather the URL returned by the last rewriting rule. This corresponds to the Perl next command or the continue command in C. Use this flag to restart the rewriting process - to immediately go to the top of the loop. - Be careful not to create an infinite loop! - */ - if ("next".equalsIgnoreCase(flag) || "N".equalsIgnoreCase(flag)) { - log.info("next flag [N] not supported"); - } - /* - # 'nocase|NC' (no case) - This makes the Pattern case-insensitive, ignoring difference between 'A-Z' and 'a-z' when Pattern is matched against the current URL. - */ - if ("nocase".equalsIgnoreCase(flag) || "NC".equalsIgnoreCase(flag)) { - rule.setFromCaseSensitive(false); - } else { - rule.setFromCaseSensitive(true); - } - /* - # 'noescape|NE' (no URI escaping of output) - This flag prevents mod_rewrite from applying the usual URI escaping rules to the result of a rewrite. Ordinarily, special characters (such as '%', '$', ';', and so on) will be escaped into their hexcode equivalents ('%25', '%24', and '%3B', respectively); this flag prevents this from happening. This allows percent symbols to appear in the output, as in - - RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE] - which would turn '/foo/zed' into a safe request for '/bar?arg=P1=zed'. - */ - if ("noescape".equalsIgnoreCase(flag) || "NE".equalsIgnoreCase(flag)) { - rule.setEncodeToUrl(false); - } - /* - # 'nosubreq|NS' ( not for internal sub-requests) - This flag forces the rewrite engine to skip a rewrite rule if the current request is an internal sub-request. For instance, sub-requests occur internally in Apache when mod_include tries to find out information about possible directory default files (index.xxx). On sub-requests it is not always useful, and can even cause errors, if the complete set of rules are applied. Use this flag to exclude some rules. - To decide whether or not to use this rule: if you prefix URLs with CGI-scripts, to force them to be processed by the CGI-script, it's likely that you will run into problems (or significant overhead) on sub-requests. In these cases, use this flag. - */ - if ("nosubreq".equalsIgnoreCase(flag) || "NS".equalsIgnoreCase(flag)) { - log.info("nosubreq flag [NS] not supported"); - } - /* - # 'proxy|P' (force proxy) - This flag forces the substitution part to be internally sent as a proxy request and immediately (rewrite processing stops here) put through the proxy module. You must make sure that the substitution string is a valid URI (typically starting with http://hostname) which can be handled by the Apache proxy module. If not, you will get an error from the proxy module. Use this flag to achieve a more powerful implementation of the ProxyPass directive, to map remote content into the namespace of the local server. - - Note: mod_proxy must be enabled in order to use this flag. - */ - if ("proxy".equalsIgnoreCase(flag) || "P".equalsIgnoreCase(flag)) { - rule.setToType("proxy"); - } - /* - # 'passthrough|PT' (pass through to next handler) - This flag forces the rewrite engine to set the uri field of the internal request_rec structure to the value of the filename field. This flag is just a hack to enable post-processing of the output of RewriteRule directives, using Alias, ScriptAlias, Redirect, and other directives from various URI-to-filename translators. For example, to rewrite /abc to /def using mod_rewrite, and then /def to /ghi using mod_alias: - - RewriteRule ^/abc(.*) /def$1 [PT] - Alias /def /ghi - If you omit the PT flag, mod_rewrite will rewrite uri=/abc/... to filename=/def/... as a full API-compliant URI-to-filename translator should do. Then mod_alias will try to do a URI-to-filename transition, which will fail. - - Note: You must use this flag if you want to mix directives from different modules which allow URL-to-filename translators. The typical example is the use of mod_alias and mod_rewrite. - */ - if ("passthrough".equalsIgnoreCase(flag) || "PT".equalsIgnoreCase(flag)) { - rule.setToType("forward"); - } - /* - # 'qsappend|QSA' (query string append) - This flag forces the rewrite engine to append a query string part of the substitution string to the existing string, instead of replacing it. Use this when you want to add more data to the query string via a rewrite rule. - */ - if ("qsappend".equalsIgnoreCase(flag) || "QSA".equalsIgnoreCase(flag)) { - rule.setQueryStringAppend("true"); - } - /* - # 'redirect|R [=code]' (force redirect) - Prefix Substitution with http://thishost[:thisport]/ (which makes the new URL a URI) to force a external redirection. If no code is given, a HTTP response of 302 (MOVED TEMPORARILY) will be returned. If you want to use other response codes in the range 300-400, simply specify the appropriate number or use one of the following symbolic names: temp (default), permanent, seeother. Use this for rules to canonicalize the URL and return it to the client - to translate ``/~'' into ``/u/'', or to always append a slash to /u/user, etc. - Note: When you use this flag, make sure that the substitution field is a valid URL! Otherwise, you will be redirecting to an invalid location. Remember that this flag on its own will only prepend http://thishost[:thisport]/ to the URL, and rewriting will continue. Usually, you will want to stop rewriting at this point, and redirect immediately. To stop rewriting, you should add the 'L' flag. - */ - if ("redirect".equalsIgnoreCase(flag) || "R".equalsIgnoreCase(flag)) { - if ("301".equals(flagValue)) { - rule.setToType("permanent-redirect"); - } else if ("302".equals(flagValue)) { - rule.setToType("temporary-redirect"); - } else { - rule.setToType("redirect"); - } - } - /* - # 'skip|S=num' (skip next rule(s)) - This flag forces the rewriting engine to skip the next num rules in sequence, if the current rule matches. Use this to make pseudo if-then-else constructs: The last rule of the then-clause becomes skip=N, where N is the number of rules in the else-clause. (This is not the same as the 'chain|C' flag!) - */ - if ("skip".equalsIgnoreCase(flag) || "S".equalsIgnoreCase(flag)) { - log.info("Skip flag [S] not supported"); - } - /* - # 'type|T=MIME-type' (force MIME type) - Force the MIME-type of the target file to be MIME-type. This can be used to set up the content-type based on some conditions. For example, the following snippet allows .php files to be displayed by mod_php if they are called with the .phps extension: - */ - if ("type".equalsIgnoreCase(flag) || "T".equalsIgnoreCase(flag)) { - SetAttribute set = new SetAttribute(); - set.setType("content-type"); - set.setValue(flagValue); - rule.addSetAttribute(set); - } - - } - - } else { - log.error("cannot parse flags from " + part); - } - } - - private Condition processRewriteCond(String rewriteCondLine) { - log.debug("about to parse condition"); - Condition condition = new Condition(); - Matcher condMatcher = CONDITION_PATTERN.matcher(rewriteCondLine); - if (condMatcher.matches()) { - String conditionParts = StringUtils.trimToNull(condMatcher.group(1)); - if (conditionParts != null) { - String[] condParts = conditionParts.split(" "); - for (int i = 0; i < condParts.length; i++) { - String part = StringUtils.trimToNull(condParts[i]); - if (part == null) continue; - if (part.equalsIgnoreCase("%{HTTP_USER_AGENT}")) { - condition.setType("header"); - condition.setName("user-agent"); - } else if (part.equalsIgnoreCase("%{HTTP_REFERER}")) { - condition.setType("header"); - condition.setName("referer"); - } else if (part.equalsIgnoreCase("%{HTTP_COOKIE}")) { - condition.setType("header"); - condition.setName("cookie"); - } else if (part.equalsIgnoreCase("%{HTTP_FORWARDED}")) { - condition.setType("header"); - condition.setName("forwarded"); - } else if (part.equalsIgnoreCase("%{HTTP_PROXY_CONNECTION}")) { - condition.setType("header"); - condition.setName("proxy-connection"); - } else if (part.equalsIgnoreCase("%{HTTP_ACCEPT}")) { - condition.setType("header"); - condition.setName("accept"); - } else if (part.equalsIgnoreCase("%{HTTP_HOST}")) { - condition.setType("server-name"); - - } else if (part.equalsIgnoreCase("%{REMOTE_ADDR}")) { - condition.setType("remote-addr"); - } else if (part.equalsIgnoreCase("%{REMOTE_HOST}")) { - condition.setType("remote-host"); - } else if (part.equalsIgnoreCase("%{REMOTE_USER}")) { - condition.setType("remote-user"); - } else if (part.equalsIgnoreCase("%{REQUEST_METHOD}")) { - condition.setType("method"); - } else if (part.equalsIgnoreCase("%{QUERY_STRING}")) { - condition.setType("query-string"); - - } else if (part.equalsIgnoreCase("%{TIME_YEAR}")) { - condition.setType("year"); - } else if (part.equalsIgnoreCase("%{TIME_MON}")) { - condition.setType("month"); - } else if (part.equalsIgnoreCase("%{TIME_DAY}")) { - condition.setType("dayofmonth"); - } else if (part.equalsIgnoreCase("%{TIME_WDAY}")) { - condition.setType("dayofweek"); - } else if (part.equalsIgnoreCase("%{TIME_HOUR}")) { - condition.setType("hourofday"); - } else if (part.equalsIgnoreCase("%{TIME_MIN}")) { - condition.setType("minute"); - } else if (part.equalsIgnoreCase("%{TIME_SEC}")) { - condition.setType("second"); - - } else if (part.equalsIgnoreCase("%{PATH_INFO}")) { - condition.setType("path-info"); - } else if (part.equalsIgnoreCase("%{AUTH_TYPE}")) { - condition.setType("auth-type"); - } else if (part.equalsIgnoreCase("%{SERVER_PORT}")) { - condition.setType("port"); - } else if (part.equalsIgnoreCase("%{REQUEST_URI}") || part.equalsIgnoreCase("$1")) { - condition.setType("request-uri"); - } else if (part.equalsIgnoreCase("%{REQUEST_FILENAME}")) { - condition.setType("request-filename"); - - } else if (part.equals("-f") || part.equals("-F")) { - condition.setOperator("isfile"); - } else if (part.equals("-d")) { - condition.setOperator("isdir"); - } else if (part.equalsIgnoreCase("-s")) { - condition.setOperator("isfilewithsize"); - } else if (part.equals("!-f") || part.equals("!-F")) { - condition.setOperator("notfile"); - } else if (part.equals("!-d")) { - condition.setOperator("notdir"); - } else if (part.equalsIgnoreCase("!-s")) { - condition.setOperator("notfilewithsize"); - - //todo: bits below this comment - } else if (part.equalsIgnoreCase("%{REMOTE_PORT}")) { - log.error("REMOTE_PORT currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{REMOTE_IDENT}")) { - log.error("REMOTE_IDENT currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SCRIPT_FILENAME}")) { - log.error("SCRIPT_FILENAME currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{DOCUMENT_ROOT}")) { - log.error("DOCUMENT_ROOT currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SERVER_ADMIN}")) { - log.error("SERVER_ADMIN currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SERVER_NAME}")) { - log.error("SERVER_NAME currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SERVER_ADDR}")) { - log.error("SERVER_ADDR currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SERVER_PROTOCOL}")) { - log.error("SERVER_PROTOCOL currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SERVER_SOFTWARE}")) { - log.error("SERVER_SOFTWARE currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{TIME}")) { - log.error("TIME currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{API_VERSION}")) { - log.error("API_VERSION currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{THE_REQUEST}")) { - log.error("THE_REQUEST currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{IS_SUBREQ}")) { - log.error("IS_SUBREQ currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{HTTPS}")) { - log.error("HTTPS currently unsupported, ignoring"); - //todo: note https in mod_rewrite means "on" in URF land it means true - - } else { - if(part.startsWith("!")) { - condition.setOperator("notequal"); - condition.setValue(part.replaceFirst("^!", "")); - } else { - condition.setValue(part); - } - } - - } - } else { - log.error("could not parse condition from " + rewriteCondLine); - } - } else { - log.error("cannot parse " + rewriteCondLine); - } - return condition; - } - - - - public String getType(String part) { - if (part.equalsIgnoreCase("%{HTTP_USER_AGENT}")) { - return "header:user-agent"; - } else if (part.equalsIgnoreCase("%{HTTP_REFERER}")) { - return "header:referer"; - } else if (part.equalsIgnoreCase("%{HTTP_COOKIE}")) { - return "header:cookie"; - } else if (part.equalsIgnoreCase("%{HTTP_FORWARDED}")) { - return "header:forwarded"; - } else if (part.equalsIgnoreCase("%{HTTP_PROXY_CONNECTION}")) { - return "header:proxy-connection"; - } else if (part.equalsIgnoreCase("%{HTTP_ACCEPT}")) { - return "header:accept"; - } else if (part.equalsIgnoreCase("%{HTTP_HOST}")) { - return "server-name"; - - } else if (part.equalsIgnoreCase("%{REMOTE_ADDR}")) { - return "remote-addr"; - } else if (part.equalsIgnoreCase("%{REMOTE_HOST}")) { - return "remote-host"; - } else if (part.equalsIgnoreCase("%{REMOTE_USER}")) { - return "remote-user"; - } else if (part.equalsIgnoreCase("%{REQUEST_METHOD}")) { - return "method"; - } else if (part.equalsIgnoreCase("%{QUERY_STRING}")) { - return "query-string"; - - } else if (part.equalsIgnoreCase("%{TIME_YEAR}")) { - return "year"; - } else if (part.equalsIgnoreCase("%{TIME_MON}")) { - return "month"; - } else if (part.equalsIgnoreCase("%{TIME_DAY}")) { - return "dayofmonth"; - } else if (part.equalsIgnoreCase("%{TIME_WDAY}")) { - return "dayofweek"; - } else if (part.equalsIgnoreCase("%{TIME_HOUR}")) { - return "hourofday"; - } else if (part.equalsIgnoreCase("%{TIME_MIN}")) { - return "minute"; - } else if (part.equalsIgnoreCase("%{TIME_SEC}")) { - return "second"; - - } else if (part.equalsIgnoreCase("%{PATH_INFO}")) { - return "path-info"; - } else if (part.equalsIgnoreCase("%{AUTH_TYPE}")) { - return "auth-type"; - } else if (part.equalsIgnoreCase("%{SERVER_PORT}")) { - return "port"; - } else if (part.equalsIgnoreCase("%{REQUEST_URI}") || part.equalsIgnoreCase("$1")) { - return "request-uri"; - } else if (part.equalsIgnoreCase("%{REQUEST_FILENAME}")) { - return "request-filename"; - - } else if (part.equalsIgnoreCase("%{REMOTE_PORT}")) { - log.error("REMOTE_PORT currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{REMOTE_IDENT}")) { - log.error("REMOTE_IDENT currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SCRIPT_FILENAME}")) { - log.error("SCRIPT_FILENAME currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{DOCUMENT_ROOT}")) { - log.error("DOCUMENT_ROOT currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SERVER_ADMIN}")) { - log.error("SERVER_ADMIN currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SERVER_NAME}")) { - log.error("SERVER_NAME currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SERVER_ADDR}")) { - log.error("SERVER_ADDR currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SERVER_PROTOCOL}")) { - log.error("SERVER_PROTOCOL currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{SERVER_SOFTWARE}")) { - log.error("SERVER_SOFTWARE currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{TIME}")) { - log.error("TIME currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{API_VERSION}")) { - log.error("API_VERSION currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{THE_REQUEST}")) { - log.error("THE_REQUEST currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{IS_SUBREQ}")) { - log.error("IS_SUBREQ currently unsupported, ignoring"); - } else if (part.equalsIgnoreCase("%{HTTPS}")) { - log.error("HTTPS currently unsupported, ignoring"); - } - - return ""; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +import org.tuckey.web.filters.urlrewrite.Condition; +import org.tuckey.web.filters.urlrewrite.Conf; +import org.tuckey.web.filters.urlrewrite.NormalRule; +import org.tuckey.web.filters.urlrewrite.SetAttribute; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Loader to enable loading of mod_rewrite style configuration for UrlRewriteFilter. + */ +public class ModRewriteConfLoader { + + private static Log log = Log.getLog(ModRewriteConfLoader.class); + + private final Pattern LOG_LEVEL_PATTERN = Pattern.compile("RewriteLogLevel\\s+([0-9]+)\\s*$"); + private final Pattern LOG_TYPE_PATTERN = Pattern.compile("RewriteLog\\s+(.*)$"); + private final Pattern ENGINE_PATTERN = Pattern.compile("RewriteEngine\\s+([a-zA-Z0-9]+)\\s*$"); + private final Pattern CONDITION_PATTERN = Pattern.compile("RewriteCond\\s+(.*)$"); + private final Pattern RULE_PATTERN = Pattern.compile("RewriteRule\\s+(.*)$"); + private final Pattern TO_VARIABLE_PATTERN = Pattern.compile("(? 0) notesBuffer.append("\n"); + String noteLine = StringUtils.trim(line.substring(1)); + notesBuffer.append(noteLine); + + } else if (line.startsWith("RewriteBase")) { + log.info("RewriteBase not supported, ignored"); + + } else if (line.startsWith("RewriteCond")) { + Condition condition = processRewriteCond(line); + if (condition != null) conditionsBuffer.add(condition); + + } else if (line.startsWith("RewriteEngine")) { + processRewriteEngine(conf, line); + + } else if (line.startsWith("RewriteLock")) { + log.error("RewriteLock not supported, ignored"); + + } else if (line.startsWith("RewriteLogLevel")) { + logLevelStr = parseLogLevel(logLevelStr, line); + + } else if (line.startsWith("RewriteLog")) { + logTypeStr = parseLogType(logTypeStr, line); + + } else if (line.startsWith("RewriteMap")) { + log.error("RewriteMap not supported, ignored"); + + } else if (line.startsWith("RewriteOptions")) { + log.error("RewriteOptions not supported, ignored"); + + } else if (line.startsWith("RewriteRule")) { + parseRule(conf, conditionsBuffer, notesBuffer, line); + notesBuffer = new StringBuffer(); + conditionsBuffer = new ArrayList(); + } else { + log.error("Unknown line: " + line); + } + } + if (logTypeStr != null || logLevelStr != null) { + String logStr = (logTypeStr == null ? "" : logTypeStr) + (logLevelStr == null ? "" : ":" + logLevelStr); + log.debug("setting log to: " + logStr); + Log.setLevel(logStr); + } + if (conditionsBuffer.size() > 0) { + log.error("conditions left over without a rule"); + } + } + + private void parseRule(Conf conf, List conditionsBuffer, StringBuffer notesBuffer, String line) { + NormalRule rule = processRule(line); + for (int j = 0; j < conditionsBuffer.size(); j++) { + Condition condition = (Condition) conditionsBuffer.get(j); + rule.addCondition(condition); + } + if (notesBuffer.length() > 0) rule.setNote(notesBuffer.toString()); + conf.addRule(rule); + } + + private String parseLogType(String logTypeStr, String line) { + Matcher logTypeMatcher = LOG_TYPE_PATTERN.matcher(line); + if (logTypeMatcher.matches()) { + logTypeStr = StringUtils.trimToNull(logTypeMatcher.group(1)); + if (logTypeStr != null) { + logTypeStr = logTypeStr.replaceAll("\"", ""); + log.debug("RewriteLog parsed as " + logTypeStr); + } + } + return logTypeStr; + } + + private String parseLogLevel(String logLevelStr, String line) { + log.debug("found a RewriteLogLevel"); + Matcher logLevelMatcher = LOG_LEVEL_PATTERN.matcher(line); + if (logLevelMatcher.matches()) { + int logLevel = NumberUtils.stringToInt(logLevelMatcher.group(1)); + if (logLevel <= 1) logLevelStr = "FATAL"; + else if (logLevel == 2) logLevelStr = "ERROR"; + else if (logLevel == 3) logLevelStr = "INFO"; + else if (logLevel == 4) logLevelStr = "WARN"; + else if (logLevel >= 5) logLevelStr = "DEBUG"; + log.debug("RewriteLogLevel parsed as " + logLevel); + + } else { + log.error("cannot parse " + line); + } + return logLevelStr; + } + + private NormalRule processRule(String line) { + NormalRule rule = new NormalRule(); + Matcher ruleMatcher = RULE_PATTERN.matcher(line); + if (ruleMatcher.matches()) { + String rulePartStr = StringUtils.trimToNull(ruleMatcher.group(1)); + if (rulePartStr != null) { + log.debug("got rule " + rulePartStr); + String[] ruleParts = rulePartStr.split("\\s"); + int partCounter = 0; + for (int j = 0; j < ruleParts.length; j++) { + String part = StringUtils.trimToNull(ruleParts[j]); + if (part == null) continue; + partCounter++; + log.debug("parsed rule part " + part); + if (partCounter == 1) { + rule.setFrom(part); + } + if (partCounter == 2) { + if (!"-".equals(part)) { + Matcher matcher = TO_VARIABLE_PATTERN.matcher(part); + if (matcher.find()) { + String knownType = getType(matcher.group(0).toString()); + if (knownType != "") { + part = part.replace(matcher.group(0).toString(), "%{" + knownType + "}"); + } + } + } + rule.setTo(part); + } + if (part.startsWith("[") && part.endsWith("]")) { + processRuleFlags(rule, part); + } + } + } else { + log.error("could not parse rule from " + line); + } + } else { + log.error("cannot parse " + line); + } + return rule; + } + + private void processRewriteEngine(Conf conf, String line) { + boolean enabled = true; + Matcher engineMatcher = ENGINE_PATTERN.matcher(line); + if (engineMatcher.matches()) { + String enabledStr = StringUtils.trim(engineMatcher.group(1)); + log.debug("RewriteEngine value parsed as '" + enabledStr + "'"); + if ("0".equalsIgnoreCase(enabledStr) || + "false".equalsIgnoreCase(enabledStr) || + "no".equalsIgnoreCase(enabledStr) || + "off".equalsIgnoreCase(enabledStr)) enabled = false; + log.debug("RewriteEngine as boolean '" + enabled + "'"); + } else { + log.error("cannot parse " + line); + } + conf.setEngineEnabled(enabled); + } + + private void processRuleFlags(NormalRule rule, String part) { + String rawFlags = StringUtils.trimToNull(part.substring(1, part.length() - 1)); + if (rawFlags != null) { + String[] flags = rawFlags.split(","); + for (int k = 0; k < flags.length; k++) { + String flag = flags[k]; + String flagValue = null; + if (flag.indexOf("=") != -1) { + flagValue = flag.substring(flag.indexOf("=") + 1); + flag = flag.substring(0, flag.indexOf("=")); + } + flag = flag.toLowerCase(); + /* + # 'chain|C' (chained with next rule) + This flag chains the current rule with the next rule (which itself can be chained with the following rule, and so on). This has the following effect: if a rule matches, then processing continues as usual - the flag has no effect. If the rule does not match, then all following chained rules are skipped. For instance, it can be used to remove the ``.www'' part, inside a per-directory rule set, when you let an external redirect happen (where the ``.www'' part should not occur!). + */ + if ("chain".equalsIgnoreCase(flag) || "C".equalsIgnoreCase(flag)) { + log.info("chain flag [C] not supported"); + } + /* + # 'cookie|CO=NAME:VAL:domain[:lifetime[:path]]' (set cookie) + This sets a cookie in the client's browser. The cookie's name is specified by NAME and the value is VAL. The domain field is the domain of the cookie, such as '.apache.org', the optional lifetime is the lifetime of the cookie in minutes, and the optional path is the path of the cookie + */ + if ("cookie".equalsIgnoreCase(flag) || "CO".equalsIgnoreCase(flag)) { + SetAttribute set = new SetAttribute(); + set.setType("cookie"); + String cookieName = flagValue; + String cookieValue = null; + if (flagValue != null) { + int colon = flagValue.indexOf(":"); + if (colon != -1) { + cookieValue = flagValue.substring(colon + 1); + cookieName = flagValue.substring(0, colon); + } + } + set.setName(cookieName); + // NOTE: The colon separated domain, lifetime, path are + // handled by SetAttribute.setValue() + set.setValue(cookieValue); + rule.addSetAttribute(set); + } + /* + # 'env|E=VAR:VAL' (set environment variable) + This forces an environment variable named VAR to be set to the value VAL, where VAL can contain regexp backreferences ($N and %N) which will be expanded. You can use this flag more than once, to set more than one variable. The variables can later be dereferenced in many situations, most commonly from within XSSI (via ) or CGI ($ENV{'VAR'}). You can also dereference the variable in a later RewriteCond pattern, using %{ENV:VAR}. Use this to strip information from URLs, while maintaining a record of that information. + */ + if ("env".equalsIgnoreCase(flag) || "E".equalsIgnoreCase(flag)) { + log.info("env flag [E] not supported"); + } + /* + # 'forbidden|F' (force URL to be forbidden) + This forces the current URL to be forbidden - it immediately sends back a HTTP response of 403 (FORBIDDEN). Use this flag in conjunction with appropriate RewriteConds to conditionally block some URLs. + */ + if ("forbidden".equalsIgnoreCase(flag) || "F".equalsIgnoreCase(flag)) { + SetAttribute set = new SetAttribute(); + set.setType("status"); + set.setValue("403"); + rule.addSetAttribute(set); + } + /* + # 'gone|G' (force URL to be gone) + This forces the current URL to be gone - it immediately sends back a HTTP response of 410 (GONE). Use this flag to mark pages which no longer exist as gone. + */ + if ("gone".equalsIgnoreCase(flag) || "G".equalsIgnoreCase(flag)) { + SetAttribute set = new SetAttribute(); + set.setType("status"); + set.setValue("410"); + rule.addSetAttribute(set); + } + /* + # 'last|L' (last rule) + Stop the rewriting process here and don't apply any more rewrite rules. This corresponds to the Perl last command or the break command in C. Use this flag to prevent the currently rewritten URL from being rewritten further by following rules. For example, use it to rewrite the root-path URL ('/') to a real one, e.g., '/e/www/'. + */ + if ("last".equalsIgnoreCase(flag) || "L".equalsIgnoreCase(flag)) { + rule.setToLast("true"); + } + /* + # 'next|N' (next round) + Re-run the rewriting process (starting again with the first rewriting rule). This time, the URL to match is no longer the original URL, but rather the URL returned by the last rewriting rule. This corresponds to the Perl next command or the continue command in C. Use this flag to restart the rewriting process - to immediately go to the top of the loop. + Be careful not to create an infinite loop! + */ + if ("next".equalsIgnoreCase(flag) || "N".equalsIgnoreCase(flag)) { + log.info("next flag [N] not supported"); + } + /* + # 'nocase|NC' (no case) + This makes the Pattern case-insensitive, ignoring difference between 'A-Z' and 'a-z' when Pattern is matched against the current URL. + */ + if ("nocase".equalsIgnoreCase(flag) || "NC".equalsIgnoreCase(flag)) { + rule.setFromCaseSensitive(false); + } else { + rule.setFromCaseSensitive(true); + } + /* + # 'noescape|NE' (no URI escaping of output) + This flag prevents mod_rewrite from applying the usual URI escaping rules to the result of a rewrite. Ordinarily, special characters (such as '%', '$', ';', and so on) will be escaped into their hexcode equivalents ('%25', '%24', and '%3B', respectively); this flag prevents this from happening. This allows percent symbols to appear in the output, as in + + RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE] + which would turn '/foo/zed' into a safe request for '/bar?arg=P1=zed'. + */ + if ("noescape".equalsIgnoreCase(flag) || "NE".equalsIgnoreCase(flag)) { + rule.setEncodeToUrl(false); + } + /* + # 'nosubreq|NS' ( not for internal sub-requests) + This flag forces the rewrite engine to skip a rewrite rule if the current request is an internal sub-request. For instance, sub-requests occur internally in Apache when mod_include tries to find out information about possible directory default files (index.xxx). On sub-requests it is not always useful, and can even cause errors, if the complete set of rules are applied. Use this flag to exclude some rules. + To decide whether or not to use this rule: if you prefix URLs with CGI-scripts, to force them to be processed by the CGI-script, it's likely that you will run into problems (or significant overhead) on sub-requests. In these cases, use this flag. + */ + if ("nosubreq".equalsIgnoreCase(flag) || "NS".equalsIgnoreCase(flag)) { + log.info("nosubreq flag [NS] not supported"); + } + /* + # 'proxy|P' (force proxy) + This flag forces the substitution part to be internally sent as a proxy request and immediately (rewrite processing stops here) put through the proxy module. You must make sure that the substitution string is a valid URI (typically starting with http://hostname) which can be handled by the Apache proxy module. If not, you will get an error from the proxy module. Use this flag to achieve a more powerful implementation of the ProxyPass directive, to map remote content into the namespace of the local server. + + Note: mod_proxy must be enabled in order to use this flag. + */ + if ("proxy".equalsIgnoreCase(flag) || "P".equalsIgnoreCase(flag)) { + rule.setToType("proxy"); + } + /* + # 'passthrough|PT' (pass through to next handler) + This flag forces the rewrite engine to set the uri field of the internal request_rec structure to the value of the filename field. This flag is just a hack to enable post-processing of the output of RewriteRule directives, using Alias, ScriptAlias, Redirect, and other directives from various URI-to-filename translators. For example, to rewrite /abc to /def using mod_rewrite, and then /def to /ghi using mod_alias: + + RewriteRule ^/abc(.*) /def$1 [PT] + Alias /def /ghi + If you omit the PT flag, mod_rewrite will rewrite uri=/abc/... to filename=/def/... as a full API-compliant URI-to-filename translator should do. Then mod_alias will try to do a URI-to-filename transition, which will fail. + + Note: You must use this flag if you want to mix directives from different modules which allow URL-to-filename translators. The typical example is the use of mod_alias and mod_rewrite. + */ + if ("passthrough".equalsIgnoreCase(flag) || "PT".equalsIgnoreCase(flag)) { + rule.setToType("forward"); + } + /* + # 'qsappend|QSA' (query string append) + This flag forces the rewrite engine to append a query string part of the substitution string to the existing string, instead of replacing it. Use this when you want to add more data to the query string via a rewrite rule. + */ + if ("qsappend".equalsIgnoreCase(flag) || "QSA".equalsIgnoreCase(flag)) { + rule.setQueryStringAppend("true"); + } + /* + # 'redirect|R [=code]' (force redirect) + Prefix Substitution with http://thishost[:thisport]/ (which makes the new URL a URI) to force a external redirection. If no code is given, a HTTP response of 302 (MOVED TEMPORARILY) will be returned. If you want to use other response codes in the range 300-400, simply specify the appropriate number or use one of the following symbolic names: temp (default), permanent, seeother. Use this for rules to canonicalize the URL and return it to the client - to translate ``/~'' into ``/u/'', or to always append a slash to /u/user, etc. + Note: When you use this flag, make sure that the substitution field is a valid URL! Otherwise, you will be redirecting to an invalid location. Remember that this flag on its own will only prepend http://thishost[:thisport]/ to the URL, and rewriting will continue. Usually, you will want to stop rewriting at this point, and redirect immediately. To stop rewriting, you should add the 'L' flag. + */ + if ("redirect".equalsIgnoreCase(flag) || "R".equalsIgnoreCase(flag)) { + if ("301".equals(flagValue)) { + rule.setToType("permanent-redirect"); + } else if ("302".equals(flagValue)) { + rule.setToType("temporary-redirect"); + } else { + rule.setToType("redirect"); + } + } + /* + # 'skip|S=num' (skip next rule(s)) + This flag forces the rewriting engine to skip the next num rules in sequence, if the current rule matches. Use this to make pseudo if-then-else constructs: The last rule of the then-clause becomes skip=N, where N is the number of rules in the else-clause. (This is not the same as the 'chain|C' flag!) + */ + if ("skip".equalsIgnoreCase(flag) || "S".equalsIgnoreCase(flag)) { + log.info("Skip flag [S] not supported"); + } + /* + # 'type|T=MIME-type' (force MIME type) + Force the MIME-type of the target file to be MIME-type. This can be used to set up the content-type based on some conditions. For example, the following snippet allows .php files to be displayed by mod_php if they are called with the .phps extension: + */ + if ("type".equalsIgnoreCase(flag) || "T".equalsIgnoreCase(flag)) { + SetAttribute set = new SetAttribute(); + set.setType("content-type"); + set.setValue(flagValue); + rule.addSetAttribute(set); + } + + } + + } else { + log.error("cannot parse flags from " + part); + } + } + + private Condition processRewriteCond(String rewriteCondLine) { + log.debug("about to parse condition"); + Condition condition = new Condition(); + Matcher condMatcher = CONDITION_PATTERN.matcher(rewriteCondLine); + if (condMatcher.matches()) { + String conditionParts = StringUtils.trimToNull(condMatcher.group(1)); + if (conditionParts != null) { + String[] condParts = conditionParts.split(" "); + for (int i = 0; i < condParts.length; i++) { + String part = StringUtils.trimToNull(condParts[i]); + if (part == null) continue; + if (part.equalsIgnoreCase("%{HTTP_USER_AGENT}")) { + condition.setType("header"); + condition.setName("user-agent"); + } else if (part.equalsIgnoreCase("%{HTTP_REFERER}")) { + condition.setType("header"); + condition.setName("referer"); + } else if (part.equalsIgnoreCase("%{HTTP_COOKIE}")) { + condition.setType("header"); + condition.setName("cookie"); + } else if (part.equalsIgnoreCase("%{HTTP_FORWARDED}")) { + condition.setType("header"); + condition.setName("forwarded"); + } else if (part.equalsIgnoreCase("%{HTTP_PROXY_CONNECTION}")) { + condition.setType("header"); + condition.setName("proxy-connection"); + } else if (part.equalsIgnoreCase("%{HTTP_ACCEPT}")) { + condition.setType("header"); + condition.setName("accept"); + } else if (part.equalsIgnoreCase("%{HTTP_HOST}")) { + condition.setType("server-name"); + + } else if (part.equalsIgnoreCase("%{REMOTE_ADDR}")) { + condition.setType("remote-addr"); + } else if (part.equalsIgnoreCase("%{REMOTE_HOST}")) { + condition.setType("remote-host"); + } else if (part.equalsIgnoreCase("%{REMOTE_USER}")) { + condition.setType("remote-user"); + } else if (part.equalsIgnoreCase("%{REQUEST_METHOD}")) { + condition.setType("method"); + } else if (part.equalsIgnoreCase("%{QUERY_STRING}")) { + condition.setType("query-string"); + + } else if (part.equalsIgnoreCase("%{TIME_YEAR}")) { + condition.setType("year"); + } else if (part.equalsIgnoreCase("%{TIME_MON}")) { + condition.setType("month"); + } else if (part.equalsIgnoreCase("%{TIME_DAY}")) { + condition.setType("dayofmonth"); + } else if (part.equalsIgnoreCase("%{TIME_WDAY}")) { + condition.setType("dayofweek"); + } else if (part.equalsIgnoreCase("%{TIME_HOUR}")) { + condition.setType("hourofday"); + } else if (part.equalsIgnoreCase("%{TIME_MIN}")) { + condition.setType("minute"); + } else if (part.equalsIgnoreCase("%{TIME_SEC}")) { + condition.setType("second"); + + } else if (part.equalsIgnoreCase("%{PATH_INFO}")) { + condition.setType("path-info"); + } else if (part.equalsIgnoreCase("%{AUTH_TYPE}")) { + condition.setType("auth-type"); + } else if (part.equalsIgnoreCase("%{SERVER_PORT}")) { + condition.setType("port"); + } else if (part.equalsIgnoreCase("%{REQUEST_URI}") || part.equalsIgnoreCase("$1")) { + condition.setType("request-uri"); + } else if (part.equalsIgnoreCase("%{REQUEST_FILENAME}")) { + condition.setType("request-filename"); + + } else if (part.equals("-f") || part.equals("-F")) { + condition.setOperator("isfile"); + } else if (part.equals("-d")) { + condition.setOperator("isdir"); + } else if (part.equalsIgnoreCase("-s")) { + condition.setOperator("isfilewithsize"); + } else if (part.equals("!-f") || part.equals("!-F")) { + condition.setOperator("notfile"); + } else if (part.equals("!-d")) { + condition.setOperator("notdir"); + } else if (part.equalsIgnoreCase("!-s")) { + condition.setOperator("notfilewithsize"); + + //todo: bits below this comment + } else if (part.equalsIgnoreCase("%{REMOTE_PORT}")) { + log.error("REMOTE_PORT currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{REMOTE_IDENT}")) { + log.error("REMOTE_IDENT currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SCRIPT_FILENAME}")) { + log.error("SCRIPT_FILENAME currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{DOCUMENT_ROOT}")) { + log.error("DOCUMENT_ROOT currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SERVER_ADMIN}")) { + log.error("SERVER_ADMIN currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SERVER_NAME}")) { + log.error("SERVER_NAME currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SERVER_ADDR}")) { + log.error("SERVER_ADDR currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SERVER_PROTOCOL}")) { + log.error("SERVER_PROTOCOL currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SERVER_SOFTWARE}")) { + log.error("SERVER_SOFTWARE currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{TIME}")) { + log.error("TIME currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{API_VERSION}")) { + log.error("API_VERSION currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{THE_REQUEST}")) { + log.error("THE_REQUEST currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{IS_SUBREQ}")) { + log.error("IS_SUBREQ currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{HTTPS}")) { + log.error("HTTPS currently unsupported, ignoring"); + //todo: note https in mod_rewrite means "on" in URF land it means true + + } else { + if(part.startsWith("!")) { + condition.setOperator("notequal"); + condition.setValue(part.replaceFirst("^!", "")); + } else { + condition.setValue(part); + } + } + + } + } else { + log.error("could not parse condition from " + rewriteCondLine); + } + } else { + log.error("cannot parse " + rewriteCondLine); + } + return condition; + } + + + + public String getType(String part) { + if (part.equalsIgnoreCase("%{HTTP_USER_AGENT}")) { + return "header:user-agent"; + } else if (part.equalsIgnoreCase("%{HTTP_REFERER}")) { + return "header:referer"; + } else if (part.equalsIgnoreCase("%{HTTP_COOKIE}")) { + return "header:cookie"; + } else if (part.equalsIgnoreCase("%{HTTP_FORWARDED}")) { + return "header:forwarded"; + } else if (part.equalsIgnoreCase("%{HTTP_PROXY_CONNECTION}")) { + return "header:proxy-connection"; + } else if (part.equalsIgnoreCase("%{HTTP_ACCEPT}")) { + return "header:accept"; + } else if (part.equalsIgnoreCase("%{HTTP_HOST}")) { + return "server-name"; + + } else if (part.equalsIgnoreCase("%{REMOTE_ADDR}")) { + return "remote-addr"; + } else if (part.equalsIgnoreCase("%{REMOTE_HOST}")) { + return "remote-host"; + } else if (part.equalsIgnoreCase("%{REMOTE_USER}")) { + return "remote-user"; + } else if (part.equalsIgnoreCase("%{REQUEST_METHOD}")) { + return "method"; + } else if (part.equalsIgnoreCase("%{QUERY_STRING}")) { + return "query-string"; + + } else if (part.equalsIgnoreCase("%{TIME_YEAR}")) { + return "year"; + } else if (part.equalsIgnoreCase("%{TIME_MON}")) { + return "month"; + } else if (part.equalsIgnoreCase("%{TIME_DAY}")) { + return "dayofmonth"; + } else if (part.equalsIgnoreCase("%{TIME_WDAY}")) { + return "dayofweek"; + } else if (part.equalsIgnoreCase("%{TIME_HOUR}")) { + return "hourofday"; + } else if (part.equalsIgnoreCase("%{TIME_MIN}")) { + return "minute"; + } else if (part.equalsIgnoreCase("%{TIME_SEC}")) { + return "second"; + + } else if (part.equalsIgnoreCase("%{PATH_INFO}")) { + return "path-info"; + } else if (part.equalsIgnoreCase("%{AUTH_TYPE}")) { + return "auth-type"; + } else if (part.equalsIgnoreCase("%{SERVER_PORT}")) { + return "port"; + } else if (part.equalsIgnoreCase("%{REQUEST_URI}") || part.equalsIgnoreCase("$1")) { + return "request-uri"; + } else if (part.equalsIgnoreCase("%{REQUEST_FILENAME}")) { + return "request-filename"; + + } else if (part.equalsIgnoreCase("%{REMOTE_PORT}")) { + log.error("REMOTE_PORT currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{REMOTE_IDENT}")) { + log.error("REMOTE_IDENT currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SCRIPT_FILENAME}")) { + log.error("SCRIPT_FILENAME currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{DOCUMENT_ROOT}")) { + log.error("DOCUMENT_ROOT currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SERVER_ADMIN}")) { + log.error("SERVER_ADMIN currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SERVER_NAME}")) { + log.error("SERVER_NAME currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SERVER_ADDR}")) { + log.error("SERVER_ADDR currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SERVER_PROTOCOL}")) { + log.error("SERVER_PROTOCOL currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{SERVER_SOFTWARE}")) { + log.error("SERVER_SOFTWARE currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{TIME}")) { + log.error("TIME currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{API_VERSION}")) { + log.error("API_VERSION currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{THE_REQUEST}")) { + log.error("THE_REQUEST currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{IS_SUBREQ}")) { + log.error("IS_SUBREQ currently unsupported, ignoring"); + } else if (part.equalsIgnoreCase("%{HTTPS}")) { + log.error("HTTPS currently unsupported, ignoring"); + } + + return ""; + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/NumberUtils.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/NumberUtils.java index 9012595a..ea31957b 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/NumberUtils.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/NumberUtils.java @@ -1,69 +1,69 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -/** - * Written in the style of commons-lang NumberUtils with only the with only two methods. - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class NumberUtils { - - public static int stringToInt(final String str) { - return stringToInt(str, 0); - } - - public static int stringToInt(final String str, final int defaultValue) { - try { - return Integer.parseInt(str); - } catch (NumberFormatException nfe) { - return defaultValue; - } - } - - public static long stringToLong(final String str) { - return stringToLong(str, 0); - } - - public static long stringToLong(final String str, final long defaultValue) { - try { - return Long.parseLong(str); - } catch (NumberFormatException nfe) { - return defaultValue; - } - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +/** + * Written in the style of commons-lang NumberUtils with only the with only two methods. + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class NumberUtils { + + public static int stringToInt(final String str) { + return stringToInt(str, 0); + } + + public static int stringToInt(final String str, final int defaultValue) { + try { + return Integer.parseInt(str); + } catch (NumberFormatException nfe) { + return defaultValue; + } + } + + public static long stringToLong(final String str) { + return stringToLong(str, 0); + } + + public static long stringToLong(final String str, final long defaultValue) { + try { + return Long.parseLong(str); + } catch (NumberFormatException nfe) { + return defaultValue; + } + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexMatcher.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexMatcher.java index 0cc24710..5925991c 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexMatcher.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexMatcher.java @@ -1,101 +1,101 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -import java.util.regex.Matcher; - -/** - * Simple wrapper for java.util.regex.Matcher. - * - * @see java.util.regex.Matcher - */ -public class RegexMatcher implements StringMatchingMatcher { - - private Matcher matcher; - private boolean found = false; - - public RegexMatcher(Matcher matcher) { - this.matcher = matcher; - } - - /** - * @see Matcher#find - */ - public boolean find() { - found = matcher.find(); - return found; - } - - public boolean isFound() { - return found; - } - - public void reset() { - matcher.reset(); - found = false; - } - - public String replaceAll(String replacement) { - String replaced = matcher.replaceAll(replacement); - reset(); - return replaced; - } - - public int groupCount() { - return matcher.groupCount(); - } - - public String group(int groupId) { - return matcher.group(groupId); - } - - public int end() { - return matcher.end(); - } - - public int start() { - return matcher.start(); - } - - public boolean isMultipleMatchingSupported() { - return true; - } - - public boolean hitEnd(){ - return matcher.hitEnd(); - } - - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +import java.util.regex.Matcher; + +/** + * Simple wrapper for java.util.regex.Matcher. + * + * @see java.util.regex.Matcher + */ +public class RegexMatcher implements StringMatchingMatcher { + + private Matcher matcher; + private boolean found = false; + + public RegexMatcher(Matcher matcher) { + this.matcher = matcher; + } + + /** + * @see Matcher#find + */ + public boolean find() { + found = matcher.find(); + return found; + } + + public boolean isFound() { + return found; + } + + public void reset() { + matcher.reset(); + found = false; + } + + public String replaceAll(String replacement) { + String replaced = matcher.replaceAll(replacement); + reset(); + return replaced; + } + + public int groupCount() { + return matcher.groupCount(); + } + + public String group(int groupId) { + return matcher.group(groupId); + } + + public int end() { + return matcher.end(); + } + + public int start() { + return matcher.start(); + } + + public boolean isMultipleMatchingSupported() { + return true; + } + + public boolean hitEnd(){ + return matcher.hitEnd(); + } + + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexPattern.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexPattern.java index 87299339..dae84de4 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexPattern.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexPattern.java @@ -1,67 +1,67 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -/** - * Simpe wrapper for java.util.regex.Pattern. - * - * @see java.util.regex.Pattern - */ -public class RegexPattern implements StringMatchingPattern { - - private Pattern pattern; - - public RegexPattern(String patternStr, boolean caseSensitive) - throws StringMatchingPatternSyntaxException { - patternStr = (patternStr.charAt(0) == '.') ? '^' + patternStr : patternStr ;// otherwise matcher.find() matches twice - try { - if (caseSensitive) { - pattern = Pattern.compile(patternStr); - } else { - pattern = Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE); - } - } catch (PatternSyntaxException e) { - throw new StringMatchingPatternSyntaxException(e); - } - } - - public StringMatchingMatcher matcher(String regex) { - return new RegexMatcher(pattern.matcher(regex)); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +/** + * Simpe wrapper for java.util.regex.Pattern. + * + * @see java.util.regex.Pattern + */ +public class RegexPattern implements StringMatchingPattern { + + private Pattern pattern; + + public RegexPattern(String patternStr, boolean caseSensitive) + throws StringMatchingPatternSyntaxException { + patternStr = (patternStr.charAt(0) == '.') ? '^' + patternStr : patternStr ;// otherwise matcher.find() matches twice + try { + if (caseSensitive) { + pattern = Pattern.compile(patternStr); + } else { + pattern = Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE); + } + } catch (PatternSyntaxException e) { + throw new StringMatchingPatternSyntaxException(e); + } + } + + public StringMatchingMatcher matcher(String regex) { + return new RegexMatcher(pattern.matcher(regex)); + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/ServerNameMatcher.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/ServerNameMatcher.java index 39bc11ed..795f68e5 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/ServerNameMatcher.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/ServerNameMatcher.java @@ -1,81 +1,81 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Utility class for matching server names. - * - * @author Paul Tuckey - * @version $Revision: 36 $ $Date: 2006-09-19 18:32:39 +1200 (Tue, 19 Sep 2006) $ - */ -public class ServerNameMatcher { - - private static Log log = Log.getLog(ServerNameMatcher.class); - - private List patterns = new ArrayList(); - WildcardHelper wh = new WildcardHelper(); - - public ServerNameMatcher(String options) { - String[] enableOnHostsArr = options.split(","); - for (int i = 0; i < enableOnHostsArr.length; i++) { - String s = enableOnHostsArr[i]; - if (StringUtils.isBlank(s)) continue; - String rawPattern = StringUtils.trim(enableOnHostsArr[i]).toLowerCase(); - int[] compiledPattern = wh.compilePattern(rawPattern); - patterns.add(compiledPattern); - } - } - - public boolean isMatch(String serverName) { - log.debug("looking for hostname match on current server name " + serverName); - if (patterns == null || StringUtils.isBlank(serverName)) { - return false; - } - serverName = StringUtils.trim(serverName).toLowerCase(); - for (int i = 0; i < patterns.size(); i++) { - int[] compiledPattern = (int[]) patterns.get(i); - Map map = new HashMap(); - if (wh.match(map, serverName, compiledPattern)) return true; - } - return false; - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Utility class for matching server names. + * + * @author Paul Tuckey + * @version $Revision: 36 $ $Date: 2006-09-19 18:32:39 +1200 (Tue, 19 Sep 2006) $ + */ +public class ServerNameMatcher { + + private static Log log = Log.getLog(ServerNameMatcher.class); + + private List patterns = new ArrayList(); + WildcardHelper wh = new WildcardHelper(); + + public ServerNameMatcher(String options) { + String[] enableOnHostsArr = options.split(","); + for (int i = 0; i < enableOnHostsArr.length; i++) { + String s = enableOnHostsArr[i]; + if (StringUtils.isBlank(s)) continue; + String rawPattern = StringUtils.trim(enableOnHostsArr[i]).toLowerCase(); + int[] compiledPattern = wh.compilePattern(rawPattern); + patterns.add(compiledPattern); + } + } + + public boolean isMatch(String serverName) { + log.debug("looking for hostname match on current server name " + serverName); + if (patterns == null || StringUtils.isBlank(serverName)) { + return false; + } + serverName = StringUtils.trim(serverName).toLowerCase(); + for (int i = 0; i < patterns.size(); i++) { + int[] compiledPattern = (int[]) patterns.get(i); + Map map = new HashMap(); + if (wh.match(map, serverName, compiledPattern)) return true; + } + return false; + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcher.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcher.java index e9e4777a..11497f13 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcher.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcher.java @@ -1,61 +1,61 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -/** - * A generic interface for StringMatching, method signature matches java.util.Matcher. - * - * @see java.util.regex.Matcher - */ -public interface StringMatchingMatcher { - - public boolean find(); - - boolean isMultipleMatchingSupported(); - - int start(); - - int end(); - - void reset(); - - public boolean isFound(); - - int groupCount(); - - String group(int groupId); - - public boolean hitEnd(); -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +/** + * A generic interface for StringMatching, method signature matches java.util.Matcher. + * + * @see java.util.regex.Matcher + */ +public interface StringMatchingMatcher { + + public boolean find(); + + boolean isMultipleMatchingSupported(); + + int start(); + + int end(); + + void reset(); + + public boolean isFound(); + + int groupCount(); + + String group(int groupId); + + public boolean hitEnd(); +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPattern.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPattern.java index ae94afe1..54af487f 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPattern.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPattern.java @@ -1,45 +1,45 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -/** - * - * - */ -public interface StringMatchingPattern { - - public StringMatchingMatcher matcher(String matchStr); - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +/** + * + * + */ +public interface StringMatchingPattern { + + public StringMatchingMatcher matcher(String matchStr); + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPatternSyntaxException.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPatternSyntaxException.java index c4474fac..f20c7db0 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPatternSyntaxException.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPatternSyntaxException.java @@ -1,49 +1,49 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -import java.util.regex.PatternSyntaxException; - -/** - * - * - */ -public class StringMatchingPatternSyntaxException extends Exception { - private static final long serialVersionUID = 4616654570576723975L; - - public StringMatchingPatternSyntaxException(PatternSyntaxException e) { - super(e); - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +import java.util.regex.PatternSyntaxException; + +/** + * + * + */ +public class StringMatchingPatternSyntaxException extends Exception { + private static final long serialVersionUID = 4616654570576723975L; + + public StringMatchingPatternSyntaxException(PatternSyntaxException e) { + super(e); + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringUtils.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringUtils.java index 8fb9face..1035adea 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringUtils.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringUtils.java @@ -1,102 +1,102 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -/** - * In the style of commons-lang StringUtils, but a bit smaller!. - * - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class StringUtils { - - public static String trim(final String str) { - if (str == null) { - return null; - } - return str.trim(); - } - - public static String trimToNull(String str) { - if (str == null) { - return null; - } - str = str.trim(); - if ("".equals(str)) { - return null; - } - return str; - } - - public static boolean isBlank(final String str) { - return str == null || "".equals(str) || "".equals(str.trim()); - } - - public static String notNull(final String str) { - if (str == null) { - return ""; - } - return str; - } - - public static String nl2br(String note) { - if (note == null) return null; - return note.replaceAll("\n", "
    "); - } - - /** - * Test if the given String starts with the specified prefix, - * ignoring upper/lower case. - * - * @param str the String to check - * @param prefix the prefix to look for - * @see java.lang.String#startsWith - */ - public static boolean startsWithIgnoreCase(String str, String prefix) { - if (str == null || prefix == null) { - return false; - } - if (str.startsWith(prefix)) { - return true; - } - if (str.length() < prefix.length()) { - return false; - } - String lcStr = str.substring(0, prefix.length()).toLowerCase(); - String lcPrefix = prefix.toLowerCase(); - return lcStr.equals(lcPrefix); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +/** + * In the style of commons-lang StringUtils, but a bit smaller!. + * + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class StringUtils { + + public static String trim(final String str) { + if (str == null) { + return null; + } + return str.trim(); + } + + public static String trimToNull(String str) { + if (str == null) { + return null; + } + str = str.trim(); + if ("".equals(str)) { + return null; + } + return str; + } + + public static boolean isBlank(final String str) { + return str == null || "".equals(str) || "".equals(str.trim()); + } + + public static String notNull(final String str) { + if (str == null) { + return ""; + } + return str; + } + + public static String nl2br(String note) { + if (note == null) return null; + return note.replaceAll("\n", "
    "); + } + + /** + * Test if the given String starts with the specified prefix, + * ignoring upper/lower case. + * + * @param str the String to check + * @param prefix the prefix to look for + * @see java.lang.String#startsWith + */ + public static boolean startsWithIgnoreCase(String str, String prefix) { + if (str == null || prefix == null) { + return false; + } + if (str.startsWith(prefix)) { + return true; + } + if (str.length() < prefix.length()) { + return false; + } + String lcStr = str.substring(0, prefix.length()).toLowerCase(); + String lcPrefix = prefix.toLowerCase(); + return lcStr.equals(lcPrefix); + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/TypeUtils.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/TypeUtils.java index 67f2d3f4..7467346b 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/TypeUtils.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/TypeUtils.java @@ -1,113 +1,147 @@ -package org.tuckey.web.filters.urlrewrite.utils; - -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - - -public class TypeUtils { - - - public static Class findClass(String param) { - Class paramClass = null; - if ("boolean".equals(param) || "bool".equals(param) || "z".equalsIgnoreCase(param)) paramClass = boolean.class; - if ("byte".equals(param) || "b".equalsIgnoreCase(param)) paramClass = byte.class; - if ("char".equals(param) || "c".equalsIgnoreCase(param)) paramClass = char.class; - if ("short".equals(param) || "s".equalsIgnoreCase(param)) paramClass = short.class; - if ("int".equals(param) || "i".equalsIgnoreCase(param)) paramClass = int.class; - if ("long".equals(param) || "l".equalsIgnoreCase(param)) paramClass = long.class; - if ("float".equals(param) || "f".equalsIgnoreCase(param)) paramClass = float.class; - if ("double".equals(param) || "d".equalsIgnoreCase(param)) paramClass = double.class; - - if ("Boolean".equals(param) || "Bool".equals(param)) paramClass = Boolean.class; - if ("Byte".equals(param)) paramClass = Byte.class; - if ("Character".equalsIgnoreCase(param) || "C".equals(param)) paramClass = Character.class; - if ("Short".equals(param)) paramClass = Short.class; - if ("Integer".equals(param)) paramClass = Integer.class; - if ("Long".equals(param)) paramClass = Long.class; - if ("Float".equals(param)) paramClass = Float.class; - if ("Double".equals(param)) paramClass = Double.class; - - if ("Class".equalsIgnoreCase(param)) paramClass = Class.class; - if ("Number".equalsIgnoreCase(param)) paramClass = Number.class; - if ("Object".equalsIgnoreCase(param)) paramClass = Object.class; - if ("String".equalsIgnoreCase(param) || "str".equalsIgnoreCase(param)) paramClass = String.class; - - if ("HttpServletRequest".equalsIgnoreCase(param) || "req".equalsIgnoreCase(param) || "request".equalsIgnoreCase(param)) - paramClass = HttpServletRequest.class; - if ("HttpServletResponse".equalsIgnoreCase(param) || "res".equalsIgnoreCase(param) || "response".equalsIgnoreCase(param)) - paramClass = HttpServletResponse.class; - if ("ServletRequest".equalsIgnoreCase(param)) paramClass = ServletRequest.class; - if ("ServletResponse".equalsIgnoreCase(param)) paramClass = ServletResponse.class; - return paramClass; - } - - - - public static Object getConvertedParam(Class runMethodParam, Object matchObj) { - // see http://jakarta.apache.org/commons/beanutils/api/org/apache/commons/beanutils/MethodUtils.html - // for how to handle methods better - Object param = null; - if (matchObj == null) { - if (runMethodParam.isPrimitive()) { - if (runMethodParam.equals(boolean.class)) param = Boolean.FALSE; - else if (runMethodParam.equals(char.class)) param = Character.valueOf('\u0000'); - else if (runMethodParam.equals(byte.class)) param = Byte.valueOf((byte) 0); - else if (runMethodParam.equals(short.class)) param = Short.valueOf((short) 0); - else if (runMethodParam.equals(int.class)) param = Integer.valueOf(0); - else if (runMethodParam.equals(long.class)) param = Long.valueOf(0L); - else if (runMethodParam.equals(float.class)) param = Float.valueOf(0f); - else if (runMethodParam.equals(double.class)) param = Double.valueOf(0d); - } - } else { - if (runMethodParam.equals(Boolean.class) || runMethodParam.equals(boolean.class)) - param = Boolean.valueOf((String) matchObj); - else if (runMethodParam.equals(Character.class) || runMethodParam.equals(char.class)) - param = Character.valueOf(((String) matchObj).charAt(0)); - else if (runMethodParam.equals(Byte.class) || runMethodParam.equals(byte.class)) - param = Byte.valueOf((String) matchObj); - else if (runMethodParam.equals(Short.class) || runMethodParam.equals(short.class)) - param = Short.valueOf((String) matchObj); - else if (runMethodParam.equals(Integer.class) || runMethodParam.equals(int.class)) - param = Integer.valueOf((String) matchObj); - else if (runMethodParam.equals(Long.class) || runMethodParam.equals(long.class)) - param = Long.valueOf((String) matchObj); - else if (runMethodParam.equals(Float.class) || runMethodParam.equals(float.class)) - param = Float.valueOf((String) matchObj); - else if (runMethodParam.equals(Double.class) || runMethodParam.equals(double.class)) - param = Double.valueOf((String) matchObj); - else if (matchObj instanceof Throwable && - runMethodParam.isAssignableFrom(matchObj.getClass())) - param = matchObj; - else { - try { - // last attempt - param = runMethodParam.cast(matchObj); - } catch (ClassCastException e) { - // do nothing - } - } - } - return param; - } - - public static String getMethodSignature(String methodStr, Class[] methodParams) { - if (methodStr == null) return null; - StringBuffer sb = new StringBuffer(methodStr); - if (methodParams != null) { - for (int i = 0; i < methodParams.length; i++) { - Class runMethodParam = methodParams[i]; - if (runMethodParam == null) continue; - if (i == 0) sb.append("("); - if (i > 0) sb.append(", "); - sb.append(runMethodParam.getName()); - if (i + 1 == methodParams.length) sb.append(")"); - } - } - return sb.toString(); - } - - - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + + +public class TypeUtils { + + + public static Class findClass(String param) { + Class paramClass = null; + if ("boolean".equals(param) || "bool".equals(param) || "z".equalsIgnoreCase(param)) paramClass = boolean.class; + if ("byte".equals(param) || "b".equalsIgnoreCase(param)) paramClass = byte.class; + if ("char".equals(param) || "c".equalsIgnoreCase(param)) paramClass = char.class; + if ("short".equals(param) || "s".equalsIgnoreCase(param)) paramClass = short.class; + if ("int".equals(param) || "i".equalsIgnoreCase(param)) paramClass = int.class; + if ("long".equals(param) || "l".equalsIgnoreCase(param)) paramClass = long.class; + if ("float".equals(param) || "f".equalsIgnoreCase(param)) paramClass = float.class; + if ("double".equals(param) || "d".equalsIgnoreCase(param)) paramClass = double.class; + + if ("Boolean".equals(param) || "Bool".equals(param)) paramClass = Boolean.class; + if ("Byte".equals(param)) paramClass = Byte.class; + if ("Character".equalsIgnoreCase(param) || "C".equals(param)) paramClass = Character.class; + if ("Short".equals(param)) paramClass = Short.class; + if ("Integer".equals(param)) paramClass = Integer.class; + if ("Long".equals(param)) paramClass = Long.class; + if ("Float".equals(param)) paramClass = Float.class; + if ("Double".equals(param)) paramClass = Double.class; + + if ("Class".equalsIgnoreCase(param)) paramClass = Class.class; + if ("Number".equalsIgnoreCase(param)) paramClass = Number.class; + if ("Object".equalsIgnoreCase(param)) paramClass = Object.class; + if ("String".equalsIgnoreCase(param) || "str".equalsIgnoreCase(param)) paramClass = String.class; + + if ("HttpServletRequest".equalsIgnoreCase(param) || "req".equalsIgnoreCase(param) || "request".equalsIgnoreCase(param)) + paramClass = HttpServletRequest.class; + if ("HttpServletResponse".equalsIgnoreCase(param) || "res".equalsIgnoreCase(param) || "response".equalsIgnoreCase(param)) + paramClass = HttpServletResponse.class; + if ("ServletRequest".equalsIgnoreCase(param)) paramClass = ServletRequest.class; + if ("ServletResponse".equalsIgnoreCase(param)) paramClass = ServletResponse.class; + return paramClass; + } + + + + public static Object getConvertedParam(Class runMethodParam, Object matchObj) { + // see http://jakarta.apache.org/commons/beanutils/api/org/apache/commons/beanutils/MethodUtils.html + // for how to handle methods better + Object param = null; + if (matchObj == null) { + if (runMethodParam.isPrimitive()) { + if (runMethodParam.equals(boolean.class)) param = Boolean.FALSE; + else if (runMethodParam.equals(char.class)) param = Character.valueOf('\u0000'); + else if (runMethodParam.equals(byte.class)) param = Byte.valueOf((byte) 0); + else if (runMethodParam.equals(short.class)) param = Short.valueOf((short) 0); + else if (runMethodParam.equals(int.class)) param = Integer.valueOf(0); + else if (runMethodParam.equals(long.class)) param = Long.valueOf(0L); + else if (runMethodParam.equals(float.class)) param = Float.valueOf(0f); + else if (runMethodParam.equals(double.class)) param = Double.valueOf(0d); + } + } else { + if (runMethodParam.equals(Boolean.class) || runMethodParam.equals(boolean.class)) + param = Boolean.valueOf((String) matchObj); + else if (runMethodParam.equals(Character.class) || runMethodParam.equals(char.class)) + param = Character.valueOf(((String) matchObj).charAt(0)); + else if (runMethodParam.equals(Byte.class) || runMethodParam.equals(byte.class)) + param = Byte.valueOf((String) matchObj); + else if (runMethodParam.equals(Short.class) || runMethodParam.equals(short.class)) + param = Short.valueOf((String) matchObj); + else if (runMethodParam.equals(Integer.class) || runMethodParam.equals(int.class)) + param = Integer.valueOf((String) matchObj); + else if (runMethodParam.equals(Long.class) || runMethodParam.equals(long.class)) + param = Long.valueOf((String) matchObj); + else if (runMethodParam.equals(Float.class) || runMethodParam.equals(float.class)) + param = Float.valueOf((String) matchObj); + else if (runMethodParam.equals(Double.class) || runMethodParam.equals(double.class)) + param = Double.valueOf((String) matchObj); + else if (matchObj instanceof Throwable && + runMethodParam.isAssignableFrom(matchObj.getClass())) + param = matchObj; + else { + try { + // last attempt + param = runMethodParam.cast(matchObj); + } catch (ClassCastException e) { + // do nothing + } + } + } + return param; + } + + public static String getMethodSignature(String methodStr, Class[] methodParams) { + if (methodStr == null) return null; + StringBuffer sb = new StringBuffer(methodStr); + if (methodParams != null) { + for (int i = 0; i < methodParams.length; i++) { + Class runMethodParam = methodParams[i]; + if (runMethodParam == null) continue; + if (i == 0) sb.append("("); + if (i > 0) sb.append(", "); + sb.append(runMethodParam.getName()); + if (i + 1 == methodParams.length) sb.append(")"); + } + } + return sb.toString(); + } + + + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLDecoder.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLDecoder.java index 0210b85c..a61b523d 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLDecoder.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLDecoder.java @@ -1,84 +1,118 @@ -package org.tuckey.web.filters.urlrewrite.utils; - -import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; - -public class URLDecoder { - - public static String decodeURL(String url, String charset) throws URISyntaxException{ - int queryPart = url.indexOf('?'); - String query = null; - String path = url; - if(queryPart != -1){ - query = url.substring(queryPart+1); - path = url.substring(0, queryPart); - } - String decodedPath = decodePath(path, charset); - if(query != null) - return decodedPath + '?' + decodeQuery(query, charset); - else - return decodedPath; - } - - public static String decodePath(String path, String charset) throws URISyntaxException{ - return decodeURLEncoded(path, false, charset); - } - - public static String decodeQuery(String query, String charset) throws URISyntaxException{ - return decodeURLEncoded(query, true, charset); - } - - public static String decodeURLEncoded(String part, boolean query, String charset) throws URISyntaxException{ - try{ - byte[] ascii = part.getBytes("ASCII"); - byte[] decoded = new byte[ascii.length]; - int j=0; - for(int i=0;i= ascii.length) - throw new URISyntaxException(part, "Invalid URL-encoded string at char "+i); - // get the next two bytes - byte first = ascii[++i]; - byte second = ascii[++i]; - decoded[j] = (byte) ((hexToByte(first) * 16) + hexToByte(second)); - }else if(query && ascii[i] == '+') - decoded[j] = ' '; - else - decoded[j] = ascii[i]; - } - // now decode - return new String(decoded, 0, j, charset); - }catch(UnsupportedEncodingException x){ - throw new URISyntaxException(part, "Invalid encoding: "+charset); - } - } - - - private static byte hexToByte(byte b) throws URISyntaxException{ - switch(b){ - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'a': - case 'A': return 10; - case 'b': - case 'B': return 11; - case 'c': - case 'C': return 12; - case 'd': - case 'D': return 13; - case 'e': - case 'E': return 14; - case 'f': - case 'F': return 15; - } - throw new URISyntaxException(String.valueOf(b), "Invalid URL-encoded string"); - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; + +public class URLDecoder { + + public static String decodeURL(String url, String charset) throws URISyntaxException{ + int queryPart = url.indexOf('?'); + String query = null; + String path = url; + if(queryPart != -1){ + query = url.substring(queryPart+1); + path = url.substring(0, queryPart); + } + String decodedPath = decodePath(path, charset); + if(query != null) + return decodedPath + '?' + decodeQuery(query, charset); + else + return decodedPath; + } + + public static String decodePath(String path, String charset) throws URISyntaxException{ + return decodeURLEncoded(path, false, charset); + } + + public static String decodeQuery(String query, String charset) throws URISyntaxException{ + return decodeURLEncoded(query, true, charset); + } + + public static String decodeURLEncoded(String part, boolean query, String charset) throws URISyntaxException{ + try{ + byte[] ascii = part.getBytes("ASCII"); + byte[] decoded = new byte[ascii.length]; + int j=0; + for(int i=0;i= ascii.length) + throw new URISyntaxException(part, "Invalid URL-encoded string at char "+i); + // get the next two bytes + byte first = ascii[++i]; + byte second = ascii[++i]; + decoded[j] = (byte) ((hexToByte(first) * 16) + hexToByte(second)); + }else if(query && ascii[i] == '+') + decoded[j] = ' '; + else + decoded[j] = ascii[i]; + } + // now decode + return new String(decoded, 0, j, charset); + }catch(UnsupportedEncodingException x){ + throw new URISyntaxException(part, "Invalid encoding: "+charset); + } + } + + + private static byte hexToByte(byte b) throws URISyntaxException{ + switch(b){ + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': + case 'A': return 10; + case 'b': + case 'B': return 11; + case 'c': + case 'C': return 12; + case 'd': + case 'D': return 13; + case 'e': + case 'E': return 14; + case 'f': + case 'F': return 15; + } + throw new URISyntaxException(String.valueOf(b), "Invalid URL-encoded string"); + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLEncoder.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLEncoder.java index 23bbd402..c9a20dd7 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLEncoder.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLEncoder.java @@ -1,208 +1,242 @@ -package org.tuckey.web.filters.urlrewrite.utils; - -import java.io.UnsupportedEncodingException; -import java.util.BitSet; - -/** - * URL-encoding utility for each URL part according to the RFC specs - * see the rfc at rfc2396 - * - * @author stephane - */ -public class URLEncoder { - - /** - * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" - */ - public final static BitSet MARK = new BitSet(); - - static { - MARK.set('-'); - MARK.set('_'); - MARK.set('.'); - MARK.set('!'); - MARK.set('~'); - MARK.set('*'); - MARK.set('\''); - MARK.set('('); - MARK.set(')'); - } - - /** - * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | - * "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" - */ - public final static BitSet LOW_ALPHA = new BitSet(); - - static { - LOW_ALPHA.set('a'); - LOW_ALPHA.set('b'); - LOW_ALPHA.set('c'); - LOW_ALPHA.set('d'); - LOW_ALPHA.set('e'); - LOW_ALPHA.set('f'); - LOW_ALPHA.set('g'); - LOW_ALPHA.set('h'); - LOW_ALPHA.set('i'); - LOW_ALPHA.set('j'); - LOW_ALPHA.set('k'); - LOW_ALPHA.set('l'); - LOW_ALPHA.set('m'); - LOW_ALPHA.set('n'); - LOW_ALPHA.set('o'); - LOW_ALPHA.set('p'); - LOW_ALPHA.set('q'); - LOW_ALPHA.set('r'); - LOW_ALPHA.set('s'); - LOW_ALPHA.set('t'); - LOW_ALPHA.set('u'); - LOW_ALPHA.set('v'); - LOW_ALPHA.set('w'); - LOW_ALPHA.set('x'); - LOW_ALPHA.set('y'); - LOW_ALPHA.set('z'); - } - - /** - * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | - * "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" - */ - public final static BitSet UP_ALPHA = new BitSet(); - - static { - UP_ALPHA.set('A'); - UP_ALPHA.set('B'); - UP_ALPHA.set('C'); - UP_ALPHA.set('D'); - UP_ALPHA.set('E'); - UP_ALPHA.set('F'); - UP_ALPHA.set('G'); - UP_ALPHA.set('H'); - UP_ALPHA.set('I'); - UP_ALPHA.set('J'); - UP_ALPHA.set('K'); - UP_ALPHA.set('L'); - UP_ALPHA.set('M'); - UP_ALPHA.set('N'); - UP_ALPHA.set('O'); - UP_ALPHA.set('P'); - UP_ALPHA.set('Q'); - UP_ALPHA.set('R'); - UP_ALPHA.set('S'); - UP_ALPHA.set('T'); - UP_ALPHA.set('U'); - UP_ALPHA.set('V'); - UP_ALPHA.set('W'); - UP_ALPHA.set('X'); - UP_ALPHA.set('Y'); - UP_ALPHA.set('Z'); - } - - /** - * alpha = lowalpha | upalpha - */ - public final static BitSet ALPHA = new BitSet(); - - static { - ALPHA.or(LOW_ALPHA); - ALPHA.or(UP_ALPHA); - } - - /** - * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" - */ - public final static BitSet DIGIT = new BitSet(); - - static { - DIGIT.set('0'); - DIGIT.set('1'); - DIGIT.set('2'); - DIGIT.set('3'); - DIGIT.set('4'); - DIGIT.set('5'); - DIGIT.set('6'); - DIGIT.set('7'); - DIGIT.set('8'); - DIGIT.set('9'); - } - - /** - * alphanum = alpha | digit - */ - public final static BitSet ALPHANUM = new BitSet(); - - static { - ALPHANUM.or(ALPHA); - ALPHANUM.or(DIGIT); - } - - /** - * unreserved = alphanum | mark - */ - public final static BitSet UNRESERVED = new BitSet(); - - static { - UNRESERVED.or(ALPHANUM); - UNRESERVED.or(MARK); - } - - /** - * pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | "," - * - * Note: we don't allow escaped here since we will escape it ourselves, so we don't want to allow them in the - * unescaped sequences - */ - public final static BitSet PCHAR = new BitSet(); - - static { - PCHAR.or(UNRESERVED); - PCHAR.set(':'); - PCHAR.set('@'); - PCHAR.set('&'); - PCHAR.set('='); - PCHAR.set('+'); - PCHAR.set('$'); - PCHAR.set(','); - } - - /** - * Encodes a string to be a valid path parameter URL, which means it can contain PCHAR* only (do not put the leading - * ";" or it will be escaped. - * - */ - public static String encodePathParam(final String pathParam, final String charset) throws UnsupportedEncodingException { - return encodePathSegment(pathParam, charset); - } - - /** - * Encodes a string to be a valid path segment URL, which means it can contain PCHAR* only (do not put path - * parameters or they will be escaped. - * - */ - public static String encodePathSegment(final String pathSegment, final String charset) throws UnsupportedEncodingException { - if (pathSegment == null) { - return null; - } - // start at *3 for the worst case when everything is %encoded on one byte - final StringBuffer encoded = new StringBuffer(pathSegment.length() * 3); - final char[] toEncode = pathSegment.toCharArray(); - for (int i = 0; i < toEncode.length; i++) { - char c = toEncode[i]; - if (PCHAR.get(c)) { - encoded.append(c); - } else { - final byte[] bytes = String.valueOf(c).getBytes(charset); - for (int j = 0; j < bytes.length; j++) { - byte b = bytes[j]; - // make it unsigned - final int u8 = b & 0xFF; - encoded.append("%"); - if (u8 < 16) - encoded.append("0"); - encoded.append(Integer.toHexString(u8)); - } - } - } - return encoded.toString(); - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +import java.io.UnsupportedEncodingException; +import java.util.BitSet; + +/** + * URL-encoding utility for each URL part according to the RFC specs + * see the rfc at rfc2396 + * + * @author stephane + */ +public class URLEncoder { + + /** + * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" + */ + public final static BitSet MARK = new BitSet(); + + static { + MARK.set('-'); + MARK.set('_'); + MARK.set('.'); + MARK.set('!'); + MARK.set('~'); + MARK.set('*'); + MARK.set('\''); + MARK.set('('); + MARK.set(')'); + } + + /** + * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | + * "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" + */ + public final static BitSet LOW_ALPHA = new BitSet(); + + static { + LOW_ALPHA.set('a'); + LOW_ALPHA.set('b'); + LOW_ALPHA.set('c'); + LOW_ALPHA.set('d'); + LOW_ALPHA.set('e'); + LOW_ALPHA.set('f'); + LOW_ALPHA.set('g'); + LOW_ALPHA.set('h'); + LOW_ALPHA.set('i'); + LOW_ALPHA.set('j'); + LOW_ALPHA.set('k'); + LOW_ALPHA.set('l'); + LOW_ALPHA.set('m'); + LOW_ALPHA.set('n'); + LOW_ALPHA.set('o'); + LOW_ALPHA.set('p'); + LOW_ALPHA.set('q'); + LOW_ALPHA.set('r'); + LOW_ALPHA.set('s'); + LOW_ALPHA.set('t'); + LOW_ALPHA.set('u'); + LOW_ALPHA.set('v'); + LOW_ALPHA.set('w'); + LOW_ALPHA.set('x'); + LOW_ALPHA.set('y'); + LOW_ALPHA.set('z'); + } + + /** + * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | + * "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" + */ + public final static BitSet UP_ALPHA = new BitSet(); + + static { + UP_ALPHA.set('A'); + UP_ALPHA.set('B'); + UP_ALPHA.set('C'); + UP_ALPHA.set('D'); + UP_ALPHA.set('E'); + UP_ALPHA.set('F'); + UP_ALPHA.set('G'); + UP_ALPHA.set('H'); + UP_ALPHA.set('I'); + UP_ALPHA.set('J'); + UP_ALPHA.set('K'); + UP_ALPHA.set('L'); + UP_ALPHA.set('M'); + UP_ALPHA.set('N'); + UP_ALPHA.set('O'); + UP_ALPHA.set('P'); + UP_ALPHA.set('Q'); + UP_ALPHA.set('R'); + UP_ALPHA.set('S'); + UP_ALPHA.set('T'); + UP_ALPHA.set('U'); + UP_ALPHA.set('V'); + UP_ALPHA.set('W'); + UP_ALPHA.set('X'); + UP_ALPHA.set('Y'); + UP_ALPHA.set('Z'); + } + + /** + * alpha = lowalpha | upalpha + */ + public final static BitSet ALPHA = new BitSet(); + + static { + ALPHA.or(LOW_ALPHA); + ALPHA.or(UP_ALPHA); + } + + /** + * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" + */ + public final static BitSet DIGIT = new BitSet(); + + static { + DIGIT.set('0'); + DIGIT.set('1'); + DIGIT.set('2'); + DIGIT.set('3'); + DIGIT.set('4'); + DIGIT.set('5'); + DIGIT.set('6'); + DIGIT.set('7'); + DIGIT.set('8'); + DIGIT.set('9'); + } + + /** + * alphanum = alpha | digit + */ + public final static BitSet ALPHANUM = new BitSet(); + + static { + ALPHANUM.or(ALPHA); + ALPHANUM.or(DIGIT); + } + + /** + * unreserved = alphanum | mark + */ + public final static BitSet UNRESERVED = new BitSet(); + + static { + UNRESERVED.or(ALPHANUM); + UNRESERVED.or(MARK); + } + + /** + * pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | "," + * + * Note: we don't allow escaped here since we will escape it ourselves, so we don't want to allow them in the + * unescaped sequences + */ + public final static BitSet PCHAR = new BitSet(); + + static { + PCHAR.or(UNRESERVED); + PCHAR.set(':'); + PCHAR.set('@'); + PCHAR.set('&'); + PCHAR.set('='); + PCHAR.set('+'); + PCHAR.set('$'); + PCHAR.set(','); + } + + /** + * Encodes a string to be a valid path parameter URL, which means it can contain PCHAR* only (do not put the leading + * ";" or it will be escaped. + * + */ + public static String encodePathParam(final String pathParam, final String charset) throws UnsupportedEncodingException { + return encodePathSegment(pathParam, charset); + } + + /** + * Encodes a string to be a valid path segment URL, which means it can contain PCHAR* only (do not put path + * parameters or they will be escaped. + * + */ + public static String encodePathSegment(final String pathSegment, final String charset) throws UnsupportedEncodingException { + if (pathSegment == null) { + return null; + } + // start at *3 for the worst case when everything is %encoded on one byte + final StringBuffer encoded = new StringBuffer(pathSegment.length() * 3); + final char[] toEncode = pathSegment.toCharArray(); + for (int i = 0; i < toEncode.length; i++) { + char c = toEncode[i]; + if (PCHAR.get(c)) { + encoded.append(c); + } else { + final byte[] bytes = String.valueOf(c).getBytes(charset); + for (int j = 0; j < bytes.length; j++) { + byte b = bytes[j]; + // make it unsigned + final int u8 = b & 0xFF; + encoded.append("%"); + if (u8 < 16) + encoded.append("0"); + encoded.append(Integer.toHexString(u8)); + } + } + } + return encoded.toString(); + } +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardMatcher.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardMatcher.java index 88953797..3b3d16e1 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardMatcher.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardMatcher.java @@ -1,171 +1,171 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Implements a regex like interface on top of WildcardMatcher, this is really just a convenience class - * so that it's easier for us to program against regex and wildcard patterns. - */ -public class WildcardMatcher implements StringMatchingMatcher { - - private static Log log = Log.getLog(WildcardMatcher.class); - - - private WildcardHelper wh; - private int[] compiledPattern; - private String matchStr; - private Map resultMap = new HashMap(); - private boolean found = false; - - - public WildcardMatcher(WildcardHelper wh, String patternStr, String matchStr) { - this.wh = wh; - this.compiledPattern = wh.compilePattern(patternStr); - this.matchStr = matchStr; - } - - public boolean find() { - found = wh.match(resultMap, matchStr, compiledPattern); - return found; - } - - public boolean isFound() { - return found; - } - - // the pattern for finding $1 $2 etc - private static Pattern variablePattern = Pattern.compile("(? lastCondMatcherGroupCount) { - log.error("variable $" + varInt + " not found"); - if (log.isDebugEnabled()) { - log.debug("wildcard matcher: " + this.toString()); - } - } else { - validVariable = true; - } - } catch (NumberFormatException nfe) { - log.error("could not parse variable " + varStr + " to number"); - } - String conditionMatch = ""; - if (validVariable) { - conditionMatch = this.group(varInt); - } - if (conditionMatch.contains("$")) { - // ensure any remaining $'s in the matched string are escaped before appending the replacement - conditionMatch = conditionMatch.replace("$", "\\$"); - } - variableMatcher.appendReplacement(sb, conditionMatch); - } - variableMatcher.appendTail(sb); - if (log.isDebugEnabled()) log.debug("replaced sb is " + sb); - String result = sb.toString(); - - Matcher escapedVariableMatcher = escapedVariablePattern.matcher(result); - result = escapedVariableMatcher.replaceAll("$1"); - - return result; - } - - public int groupCount() { - if (resultMap == null) return 0; - return resultMap.size() == 0 ? 0 : resultMap.size() - 1; - } - - public String group(int groupId) { - if (resultMap == null) return null; - return (String) resultMap.get("" + groupId); - } - - public int end() { - if(found) - return matchStr.length(); - return -1; - } - - public void reset() { - } - - public int start() { - if(found) - return 0; - return -1; - } - - public boolean isMultipleMatchingSupported() { - return false; - } - - public String getMatchedString() { - return matchStr; - } - - @Override - public boolean hitEnd() { - return false; - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Implements a regex like interface on top of WildcardMatcher, this is really just a convenience class + * so that it's easier for us to program against regex and wildcard patterns. + */ +public class WildcardMatcher implements StringMatchingMatcher { + + private static Log log = Log.getLog(WildcardMatcher.class); + + + private WildcardHelper wh; + private int[] compiledPattern; + private String matchStr; + private Map resultMap = new HashMap(); + private boolean found = false; + + + public WildcardMatcher(WildcardHelper wh, String patternStr, String matchStr) { + this.wh = wh; + this.compiledPattern = wh.compilePattern(patternStr); + this.matchStr = matchStr; + } + + public boolean find() { + found = wh.match(resultMap, matchStr, compiledPattern); + return found; + } + + public boolean isFound() { + return found; + } + + // the pattern for finding $1 $2 etc + private static Pattern variablePattern = Pattern.compile("(? lastCondMatcherGroupCount) { + log.error("variable $" + varInt + " not found"); + if (log.isDebugEnabled()) { + log.debug("wildcard matcher: " + this.toString()); + } + } else { + validVariable = true; + } + } catch (NumberFormatException nfe) { + log.error("could not parse variable " + varStr + " to number"); + } + String conditionMatch = ""; + if (validVariable) { + conditionMatch = this.group(varInt); + } + if (conditionMatch.contains("$")) { + // ensure any remaining $'s in the matched string are escaped before appending the replacement + conditionMatch = conditionMatch.replace("$", "\\$"); + } + variableMatcher.appendReplacement(sb, conditionMatch); + } + variableMatcher.appendTail(sb); + if (log.isDebugEnabled()) log.debug("replaced sb is " + sb); + String result = sb.toString(); + + Matcher escapedVariableMatcher = escapedVariablePattern.matcher(result); + result = escapedVariableMatcher.replaceAll("$1"); + + return result; + } + + public int groupCount() { + if (resultMap == null) return 0; + return resultMap.size() == 0 ? 0 : resultMap.size() - 1; + } + + public String group(int groupId) { + if (resultMap == null) return null; + return (String) resultMap.get("" + groupId); + } + + public int end() { + if(found) + return matchStr.length(); + return -1; + } + + public void reset() { + } + + public int start() { + if(found) + return 0; + return -1; + } + + public boolean isMultipleMatchingSupported() { + return false; + } + + public String getMatchedString() { + return matchStr; + } + + @Override + public boolean hitEnd() { + return false; + } + +} diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardPattern.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardPattern.java index 8b0f1515..21c1e5c4 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardPattern.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardPattern.java @@ -1,55 +1,55 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -/** - * - * - */ -public class WildcardPattern implements StringMatchingPattern { - - WildcardHelper wh; - private String patternStr; - - public WildcardPattern(String patternStr) { - this.wh = new WildcardHelper(); - this.patternStr = patternStr; - } - - - public StringMatchingMatcher matcher(String matchStr) { - return new WildcardMatcher(wh, patternStr, matchStr); - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +/** + * + * + */ +public class WildcardPattern implements StringMatchingPattern { + + WildcardHelper wh; + private String patternStr; + + public WildcardPattern(String patternStr) { + this.wh = new WildcardHelper(); + this.patternStr = patternStr; + } + + + public StringMatchingMatcher matcher(String matchStr) { + return new WildcardMatcher(wh, patternStr, matchStr); + } +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/ConditionTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/ConditionTest.java index 5814fd38..6874a888 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/ConditionTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/ConditionTest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2005-2007, Paul Tuckey + * Copyright (c) 2005-2023, Paul Tuckey * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/ConfTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/ConfTest.java index 2f2b367c..954183b2 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/ConfTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/ConfTest.java @@ -1,147 +1,147 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.testhelper.MockServletContext; - -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.util.List; - - -/** - * @author Paul Tuckey - * @version $Revision: 44 $ $Date: 2006-11-02 12:29:14 +1300 (Thu, 02 Nov 2006) $ - */ -public class ConfTest extends TestCase { - - public static final String BASE_XML_PATH = "/org/tuckey/web/filters/urlrewrite/"; - - public void setUp() { - Log.setLevel("DEBUG"); - } - - - public void testGoodNormalConf() throws FileNotFoundException { - InputStream is = ConfTest.class.getResourceAsStream(BASE_XML_PATH + "conf-test1.xml"); - assertNotNull(is); - Conf conf = new Conf(new MockServletContext(), is, "conf-test1.xml", "conf-test1.xml"); - assertTrue(conf.isOk()); - assertEquals("regex", conf.getDefaultMatchType()); - assertEquals(false, conf.isUseContext()); - assertEquals(false, conf.isUseQueryString()); - assertEquals("utf-8", conf.getDecodeUsing()); - - List rules = conf.getRules(); - List outboundRules = conf.getOutboundRules(); - List catches = conf.getCatchElems(); - - NormalRule rule = (NormalRule) rules.get(0); - assertEquals("basicfrom1", rule.getFrom()); - assertEquals("basicto1", rule.getTo()); - assertFalse("rule 1 last not loading correctly", rule.isLast()); - assertEquals("forward", rule.getToType()); - assertEquals(false, rule.isEncodeToUrl()); - SetAttribute set = (SetAttribute) rule.getSetAttributes().get(0); - assertEquals("name of set, it's " + set.getName(), "valuenull", set.getName()); - assertNull("value of set should be null, it's " + set.getValue(), set.getValue()); - assertEquals("othercontext", rule.getToContextStr()); - - NormalRule rule1 = (NormalRule) rules.get(1); - assertEquals("basicfrom2", rule1.getFrom()); - assertEquals("basicto2", rule1.getTo()); - assertTrue("rule 2 last not loading correctly", rule1.isLast()); - assertEquals("redirect", rule1.getToType()); - assertEquals("true", "" + rule1.isFromCaseSensitive()); - Condition cond = (Condition) rule1.getConditions().get(0); - assertEquals("true", "" + cond.isCaseSensitive()); - assertEquals("greater", cond.getOperator()); - - NormalRule rule2 = (NormalRule) rules.get(2); - SetAttribute set2 = (SetAttribute) rule2.getSetAttributes().get(0); - assertEquals("blah", set2.getName()); - assertEquals("$1", set2.getValue()); - - ClassRule rule4 = (ClassRule) rules.get(4); - assertEquals(true, rule4.isValid()); - - ClassRule rule5 = (ClassRule) rules.get(5); - assertEquals(true, rule5.isValid()); - - NormalRule rule6 = (NormalRule) rules.get(6); - Run run = (Run) rule6.getRuns().get(0); - assertEquals("testValue", run.getInitParam("testName")); - - OutboundRule outboundRule = (OutboundRule) outboundRules.get(0); - assertEquals("default encode on to test", outboundRule.getName()); - assertEquals(true, outboundRule.isEncodeToUrl()); - - CatchElem catchElem = (CatchElem) catches.get(0); - assertEquals(true, catchElem.isValid()); - } - - - public void testNoDtdConf() throws FileNotFoundException { - InputStream is = ConfTest.class.getResourceAsStream(BASE_XML_PATH + "conf-test-no-dtd.xml"); - assertNotNull(is); - Conf conf = new Conf(is, "conf-test-no-dtd.xml"); - assertTrue(conf.isOk()); - assertFalse(conf.isDecodeUsingCustomCharsetRequired()); - } - - public void testConfDefaults() throws FileNotFoundException { - System.out.println("testConfDefaults"); - Conf conf = new Conf(ConfTest.class.getResource("conf-test2.xml")); - assertTrue("Conf should have loaded ok", conf.isOk()); - assertEquals("use context should be true", true, conf.isUseContext()); - assertEquals("use query string should be true", true, conf.isUseQueryString()); - assertEquals("utf-16", conf.getDecodeUsing()); - assertEquals("wildcard", conf.getDefaultMatchType()); - assertEquals("wildcard", ((NormalRule) conf.getRules().get(0)).getMatchType()); - assertEquals("regex", ((NormalRule) conf.getRules().get(1)).getMatchType()); - assertEquals("wildcard", ((NormalRule) conf.getRules().get(2)).getMatchType()); - - assertEquals("Included Rule (rule 3)", ((Rule) conf.getRules().get(3)).getDisplayName()); - } - - public void testConfBadParse() throws FileNotFoundException { - Conf conf = new Conf(ConfTest.class.getResource("conf-test-bad-parse.xml")); - assertFalse("a validation error should make the conf fail to load", conf.isOk()); - } - -} - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.testhelper.MockServletContext; + +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.List; + + +/** + * @author Paul Tuckey + * @version $Revision: 44 $ $Date: 2006-11-02 12:29:14 +1300 (Thu, 02 Nov 2006) $ + */ +public class ConfTest extends TestCase { + + public static final String BASE_XML_PATH = "/org/tuckey/web/filters/urlrewrite/"; + + public void setUp() { + Log.setLevel("DEBUG"); + } + + + public void testGoodNormalConf() throws FileNotFoundException { + InputStream is = ConfTest.class.getResourceAsStream(BASE_XML_PATH + "conf-test1.xml"); + assertNotNull(is); + Conf conf = new Conf(new MockServletContext(), is, "conf-test1.xml", "conf-test1.xml"); + assertTrue(conf.isOk()); + assertEquals("regex", conf.getDefaultMatchType()); + assertEquals(false, conf.isUseContext()); + assertEquals(false, conf.isUseQueryString()); + assertEquals("utf-8", conf.getDecodeUsing()); + + List rules = conf.getRules(); + List outboundRules = conf.getOutboundRules(); + List catches = conf.getCatchElems(); + + NormalRule rule = (NormalRule) rules.get(0); + assertEquals("basicfrom1", rule.getFrom()); + assertEquals("basicto1", rule.getTo()); + assertFalse("rule 1 last not loading correctly", rule.isLast()); + assertEquals("forward", rule.getToType()); + assertEquals(false, rule.isEncodeToUrl()); + SetAttribute set = (SetAttribute) rule.getSetAttributes().get(0); + assertEquals("name of set, it's " + set.getName(), "valuenull", set.getName()); + assertNull("value of set should be null, it's " + set.getValue(), set.getValue()); + assertEquals("othercontext", rule.getToContextStr()); + + NormalRule rule1 = (NormalRule) rules.get(1); + assertEquals("basicfrom2", rule1.getFrom()); + assertEquals("basicto2", rule1.getTo()); + assertTrue("rule 2 last not loading correctly", rule1.isLast()); + assertEquals("redirect", rule1.getToType()); + assertEquals("true", "" + rule1.isFromCaseSensitive()); + Condition cond = (Condition) rule1.getConditions().get(0); + assertEquals("true", "" + cond.isCaseSensitive()); + assertEquals("greater", cond.getOperator()); + + NormalRule rule2 = (NormalRule) rules.get(2); + SetAttribute set2 = (SetAttribute) rule2.getSetAttributes().get(0); + assertEquals("blah", set2.getName()); + assertEquals("$1", set2.getValue()); + + ClassRule rule4 = (ClassRule) rules.get(4); + assertEquals(true, rule4.isValid()); + + ClassRule rule5 = (ClassRule) rules.get(5); + assertEquals(true, rule5.isValid()); + + NormalRule rule6 = (NormalRule) rules.get(6); + Run run = (Run) rule6.getRuns().get(0); + assertEquals("testValue", run.getInitParam("testName")); + + OutboundRule outboundRule = (OutboundRule) outboundRules.get(0); + assertEquals("default encode on to test", outboundRule.getName()); + assertEquals(true, outboundRule.isEncodeToUrl()); + + CatchElem catchElem = (CatchElem) catches.get(0); + assertEquals(true, catchElem.isValid()); + } + + + public void testNoDtdConf() throws FileNotFoundException { + InputStream is = ConfTest.class.getResourceAsStream(BASE_XML_PATH + "conf-test-no-dtd.xml"); + assertNotNull(is); + Conf conf = new Conf(is, "conf-test-no-dtd.xml"); + assertTrue(conf.isOk()); + assertFalse(conf.isDecodeUsingCustomCharsetRequired()); + } + + public void testConfDefaults() throws FileNotFoundException { + System.out.println("testConfDefaults"); + Conf conf = new Conf(ConfTest.class.getResource("conf-test2.xml")); + assertTrue("Conf should have loaded ok", conf.isOk()); + assertEquals("use context should be true", true, conf.isUseContext()); + assertEquals("use query string should be true", true, conf.isUseQueryString()); + assertEquals("utf-16", conf.getDecodeUsing()); + assertEquals("wildcard", conf.getDefaultMatchType()); + assertEquals("wildcard", ((NormalRule) conf.getRules().get(0)).getMatchType()); + assertEquals("regex", ((NormalRule) conf.getRules().get(1)).getMatchType()); + assertEquals("wildcard", ((NormalRule) conf.getRules().get(2)).getMatchType()); + + assertEquals("Included Rule (rule 3)", ((Rule) conf.getRules().get(3)).getDisplayName()); + } + + public void testConfBadParse() throws FileNotFoundException { + Conf conf = new Conf(ConfTest.class.getResource("conf-test-bad-parse.xml")); + assertFalse("a validation error should make the conf fail to load", conf.isOk()); + } + +} + diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/OutboundRuleTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/OutboundRuleTest.java index 771d2801..c95e8eb4 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/OutboundRuleTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/OutboundRuleTest.java @@ -1,219 +1,219 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.testhelper.MockRequest; -import org.tuckey.web.testhelper.MockResponse; - -/** - * @author Paul Tuckey - * @version $Revision: 52 $ $Date: 2007-02-26 07:00:28 +1300 (Mon, 26 Feb 2007) $ - */ -public class OutboundRuleTest extends TestCase { - - MockResponse response; - MockRequest request; - - public void setUp() { - Log.setLevel("DEBUG"); - response = new MockResponse(); - request = new MockRequest(); - } - - - public void testOutboundQueryStr() { - Conf conf = new Conf(); - OutboundRule rule1 = new OutboundRule(); - rule1.setFrom("^/jsp-examples/cal/links.jsp\\?id=([0-9]+)"); - rule1.setTo("/jsp-examples/cal/links/$1"); - conf.addOutboundRule(rule1); - conf.initialise(); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - MockRequest request = new MockRequest("/jsp-examples/cal/links.jsp?id=46"); - UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); - - assertEquals("/jsp-examples/cal/links/46;mockencoded=test", urlRewriteWrappedResponse.encodeURL("/jsp-examples/cal/links.jsp?id=46")); - - } - - public void testOutboundQueryStr2() { - Conf conf = new Conf(); - OutboundRule rule1 = new OutboundRule(); - rule1.setFrom("^/storeitem.html\\?vid=20060621001&iid=([0-9]+)&cid=([0-9]+)$"); - rule1.setTo("/storeitem/id$1/c$2"); - conf.addOutboundRule(rule1); - conf.initialise(); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); - assertEquals("/storeitem/id666/c555;mockencoded=test", urlRewriteWrappedResponse.encodeURL("/storeitem.html?vid=20060621001&iid=666&cid=555")); - - } - - public void testOutboundQueryStr3() { - Conf conf = new Conf(); - OutboundRule rule1 = new OutboundRule(); - rule1.setFrom("^/world\\.jsp\\?country=([a-z]+)&city=([a-z]+)$"); - rule1.setTo("/world/$1/$2"); - conf.addOutboundRule(rule1); - conf.initialise(); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); - assertEquals("/world/usa/nyc;mockencoded=test", urlRewriteWrappedResponse.encodeURL("/world.jsp?country=usa&city=nyc")); - - } - - - public void testOutbound2() { - // check mockencoded is being added - UrlRewriteWrappedResponse urlRewriteWrappedResponse2 = new UrlRewriteWrappedResponse(response, request, null); - assertEquals("a.jsp;mockencoded=test?aaa=bbb", urlRewriteWrappedResponse2.encodeURL("a.jsp?aaa=bbb")); - - // check we can strip it - Conf conf = new Conf(); - OutboundRule rule1 = new OutboundRule(); - rule1.setFrom("^(.*);mockencoded=.*?(\\?.*)?$"); - rule1.setTo("$1$2"); - rule1.setEncodeFirst(true); - conf.addOutboundRule(rule1); - conf.initialise(); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); - assertEquals("a.jsp?aaa=bbb", urlRewriteWrappedResponse.encodeURL("a.jsp?aaa=bbb")); - assertEquals("a.jsp", urlRewriteWrappedResponse.encodeURL("a.jsp")); - } - - /** - * To: UrlRewrite - * Date: Sep 9, 2005 9:07 AM - * Subject: Re: Hiding jsessionid from Google Bot (or everything!) - * this rule - *

    - * - * ^(.*);jsessionid=.*(\?.*)$ - * $1$2 - * - *

    - * with the following three links - *

    - * - *
    - * <%=response.encodeURL("/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")%> - *
    - * <%=response.encodeURL("http://localhost:8080/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")%> - *

    - * with the following output - *

    - * /boo.jsp;jsessionid=93DDACD0EB60D0B6301008A262DC58E4?somethingloi=1 - * /boo.jsp?somethingloi=1 - * http://localhost:8080/boo.jsp?somethingloi=1 - *

    - * The last 2 outputs, where I've manually included the session id give - * the rewrite I want, but the other one won't - regardless of the - * encodefirst setting. - *

    - * My thinking is that encodefirst="true" attribue isn't behaving as - * expected. - */ - public void testOutboundJsess() { - // check mockencoded is being added - - UrlRewriteWrappedResponse urlRewriteWrappedResponse2 = new UrlRewriteWrappedResponse(response, request, null); - - assertEquals("/boo.jsp;mockencoded=test?somethingloi=1", - urlRewriteWrappedResponse2.encodeURL("/boo.jsp?somethingloi=1")); - assertEquals("/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0;mockencoded=test?somethingloi=1", - urlRewriteWrappedResponse2.encodeURL("/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")); - assertEquals("http://localhost:8080/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1", - urlRewriteWrappedResponse2.encodeURL("http://localhost:8080/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")); - - // check we can strip it - Conf conf = new Conf(); - OutboundRule rule1 = new OutboundRule(); - rule1.setFrom("^(?![a-z]+:)(.*);jsessionid=.*?([\\?|\\#].*)?$"); - rule1.setTo("$1$2"); - rule1.setEncodeFirst(true); - conf.addOutboundRule(rule1); - conf.initialise(); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); - - assertEquals("/boo.jsp;mockencoded=test", - urlRewriteWrappedResponse.encodeURL("/boo.jsp")); - assertEquals("/boo.jsp;mockencoded=test?somethingloi=1", - urlRewriteWrappedResponse.encodeURL("/boo.jsp?somethingloi=1")); - assertEquals("/boo.jsp?somethingloi=1", - urlRewriteWrappedResponse.encodeURL("/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")); - assertEquals("http://localhost:8080/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1", - urlRewriteWrappedResponse.encodeURL("http://localhost:8080/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")); - - } - - //todo: test multiple outbound rules with encodefirst on and off - - - - public void testVarWithSpaces() { - Conf conf = new Conf(); - OutboundRule rule1 = new OutboundRule(); - rule1.setFrom("browse.ac\\?countryCode=([a-z]+)&stateCode=([a-z])&city=([a-z\\s]+)$"); - rule1.setTo("%{context-path}/location/$1/$2/$3"); - conf.addOutboundRule(rule1); - conf.initialise(); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - MockRequest request = new MockRequest("/"); - UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); - - assertEquals("browse.ac;mockencoded=test?countryCode=US&stateCode=NY&city=New York", urlRewriteWrappedResponse.encodeURL("browse.ac?countryCode=US&stateCode=NY&city=New York")); - - } - - -} - -// "^/dir/([\\&a-zA-Z0-9\\s\\+\\/\\%&]+).([a-zA-Z\\s\\+&\\/]+).([a-zA-Z\\s]{2,})$" +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.testhelper.MockRequest; +import org.tuckey.web.testhelper.MockResponse; + +/** + * @author Paul Tuckey + * @version $Revision: 52 $ $Date: 2007-02-26 07:00:28 +1300 (Mon, 26 Feb 2007) $ + */ +public class OutboundRuleTest extends TestCase { + + MockResponse response; + MockRequest request; + + public void setUp() { + Log.setLevel("DEBUG"); + response = new MockResponse(); + request = new MockRequest(); + } + + + public void testOutboundQueryStr() { + Conf conf = new Conf(); + OutboundRule rule1 = new OutboundRule(); + rule1.setFrom("^/jsp-examples/cal/links.jsp\\?id=([0-9]+)"); + rule1.setTo("/jsp-examples/cal/links/$1"); + conf.addOutboundRule(rule1); + conf.initialise(); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + MockRequest request = new MockRequest("/jsp-examples/cal/links.jsp?id=46"); + UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); + + assertEquals("/jsp-examples/cal/links/46;mockencoded=test", urlRewriteWrappedResponse.encodeURL("/jsp-examples/cal/links.jsp?id=46")); + + } + + public void testOutboundQueryStr2() { + Conf conf = new Conf(); + OutboundRule rule1 = new OutboundRule(); + rule1.setFrom("^/storeitem.html\\?vid=20060621001&iid=([0-9]+)&cid=([0-9]+)$"); + rule1.setTo("/storeitem/id$1/c$2"); + conf.addOutboundRule(rule1); + conf.initialise(); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); + assertEquals("/storeitem/id666/c555;mockencoded=test", urlRewriteWrappedResponse.encodeURL("/storeitem.html?vid=20060621001&iid=666&cid=555")); + + } + + public void testOutboundQueryStr3() { + Conf conf = new Conf(); + OutboundRule rule1 = new OutboundRule(); + rule1.setFrom("^/world\\.jsp\\?country=([a-z]+)&city=([a-z]+)$"); + rule1.setTo("/world/$1/$2"); + conf.addOutboundRule(rule1); + conf.initialise(); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); + assertEquals("/world/usa/nyc;mockencoded=test", urlRewriteWrappedResponse.encodeURL("/world.jsp?country=usa&city=nyc")); + + } + + + public void testOutbound2() { + // check mockencoded is being added + UrlRewriteWrappedResponse urlRewriteWrappedResponse2 = new UrlRewriteWrappedResponse(response, request, null); + assertEquals("a.jsp;mockencoded=test?aaa=bbb", urlRewriteWrappedResponse2.encodeURL("a.jsp?aaa=bbb")); + + // check we can strip it + Conf conf = new Conf(); + OutboundRule rule1 = new OutboundRule(); + rule1.setFrom("^(.*);mockencoded=.*?(\\?.*)?$"); + rule1.setTo("$1$2"); + rule1.setEncodeFirst(true); + conf.addOutboundRule(rule1); + conf.initialise(); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); + assertEquals("a.jsp?aaa=bbb", urlRewriteWrappedResponse.encodeURL("a.jsp?aaa=bbb")); + assertEquals("a.jsp", urlRewriteWrappedResponse.encodeURL("a.jsp")); + } + + /** + * To: UrlRewrite + * Date: Sep 9, 2005 9:07 AM + * Subject: Re: Hiding jsessionid from Google Bot (or everything!) + * this rule + *

    + * + * ^(.*);jsessionid=.*(\?.*)$ + * $1$2 + * + *

    + * with the following three links + *

    + * + *
    + * <%=response.encodeURL("/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")%> + *
    + * <%=response.encodeURL("http://localhost:8080/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")%> + *

    + * with the following output + *

    + * /boo.jsp;jsessionid=93DDACD0EB60D0B6301008A262DC58E4?somethingloi=1 + * /boo.jsp?somethingloi=1 + * http://localhost:8080/boo.jsp?somethingloi=1 + *

    + * The last 2 outputs, where I've manually included the session id give + * the rewrite I want, but the other one won't - regardless of the + * encodefirst setting. + *

    + * My thinking is that encodefirst="true" attribue isn't behaving as + * expected. + */ + public void testOutboundJsess() { + // check mockencoded is being added + + UrlRewriteWrappedResponse urlRewriteWrappedResponse2 = new UrlRewriteWrappedResponse(response, request, null); + + assertEquals("/boo.jsp;mockencoded=test?somethingloi=1", + urlRewriteWrappedResponse2.encodeURL("/boo.jsp?somethingloi=1")); + assertEquals("/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0;mockencoded=test?somethingloi=1", + urlRewriteWrappedResponse2.encodeURL("/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")); + assertEquals("http://localhost:8080/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1", + urlRewriteWrappedResponse2.encodeURL("http://localhost:8080/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")); + + // check we can strip it + Conf conf = new Conf(); + OutboundRule rule1 = new OutboundRule(); + rule1.setFrom("^(?![a-z]+:)(.*);jsessionid=.*?([\\?|\\#].*)?$"); + rule1.setTo("$1$2"); + rule1.setEncodeFirst(true); + conf.addOutboundRule(rule1); + conf.initialise(); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); + + assertEquals("/boo.jsp;mockencoded=test", + urlRewriteWrappedResponse.encodeURL("/boo.jsp")); + assertEquals("/boo.jsp;mockencoded=test?somethingloi=1", + urlRewriteWrappedResponse.encodeURL("/boo.jsp?somethingloi=1")); + assertEquals("/boo.jsp?somethingloi=1", + urlRewriteWrappedResponse.encodeURL("/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")); + assertEquals("http://localhost:8080/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1", + urlRewriteWrappedResponse.encodeURL("http://localhost:8080/boo.jsp;jsessionid=91C4977F91B3CF69D2085B1B42BD5EB0?somethingloi=1")); + + } + + //todo: test multiple outbound rules with encodefirst on and off + + + + public void testVarWithSpaces() { + Conf conf = new Conf(); + OutboundRule rule1 = new OutboundRule(); + rule1.setFrom("browse.ac\\?countryCode=([a-z]+)&stateCode=([a-z])&city=([a-z\\s]+)$"); + rule1.setTo("%{context-path}/location/$1/$2/$3"); + conf.addOutboundRule(rule1); + conf.initialise(); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + MockRequest request = new MockRequest("/"); + UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); + + assertEquals("browse.ac;mockencoded=test?countryCode=US&stateCode=NY&city=New York", urlRewriteWrappedResponse.encodeURL("browse.ac?countryCode=US&stateCode=NY&city=New York")); + + } + + +} + +// "^/dir/([\\&a-zA-Z0-9\\s\\+\\/\\%&]+).([a-zA-Z\\s\\+&\\/]+).([a-zA-Z\\s]{2,})$" diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlTest.java index 69d62316..2ad2455d 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlTest.java @@ -1,128 +1,128 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.testhelper.MockFilterChain; -import org.tuckey.web.testhelper.MockRequest; -import org.tuckey.web.testhelper.MockRequestDispatcher; -import org.tuckey.web.testhelper.MockResponse; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * @author Paul Tuckey - * @version $Revision: 40 $ $Date: 2006-10-27 15:12:37 +1300 (Fri, 27 Oct 2006) $ - */ -public class RewrittenUrlTest extends TestCase { - - MockResponse response; - MockRequest request; - MockFilterChain chain; - - public void setUp() { - Log.setLevel("SYSOUT:TRACE"); - response = new MockResponse(); - request = new MockRequest(); - chain = new MockFilterChain(); - } - - public void testPermanentRedir() throws IOException, ServletException { - NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); - rewrittenUrl.setPermanentRedirect(true); - rewrittenUrl.doRewrite(request, response, chain); - assertEquals("/hi", response.getHeader("Location")); - assertEquals(HttpServletResponse.SC_MOVED_PERMANENTLY, response.getStatus()); - } - - public void testTempRedir() throws IOException, ServletException { - NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); - rewrittenUrl.setTemporaryRedirect(true); - rewrittenUrl.doRewrite(request, response, chain); - assertEquals("/hi", response.getHeader("Location")); - assertEquals(HttpServletResponse.SC_MOVED_TEMPORARILY, response.getStatus()); - } - - public void testForward() throws IOException, ServletException { - NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); - rewrittenUrl.setForward(true); - rewrittenUrl.doRewrite(request, response, chain); - assertEquals("/hi", MockRequestDispatcher.getCurrent().getUrl()); - assertTrue(MockRequestDispatcher.getCurrent().isForwarded()); - } - - public void testRedir() throws IOException, ServletException { - NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); - rewrittenUrl.setRedirect(true); - rewrittenUrl.doRewrite(request, response, chain); - assertEquals("/hi", response.getRedirectedUrl()); - } - - public void testRedirEncoded() throws IOException, ServletException { - NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); - rewrittenUrl.setRedirect(true); - rewrittenUrl.setEncode(true); - rewrittenUrl.doRewrite(request, response, chain); - assertEquals("/hi;mockencoded=test", response.getRedirectedUrl()); - } - - public void testPreIncl() throws IOException, ServletException { - NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); - rewrittenUrl.setPreInclude(true); - rewrittenUrl.setEncode(true); - rewrittenUrl.doRewrite(request, response, chain); - assertTrue(MockRequestDispatcher.getCurrent().isIncluded() && chain.isDoFilterRun()); - } - - public void testPostIncl() throws IOException, ServletException { - NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); - rewrittenUrl.setPostInclude(true); - rewrittenUrl.setEncode(true); - rewrittenUrl.doRewrite(request, response, chain); - assertTrue(MockRequestDispatcher.getCurrent().isIncluded() && chain.isDoFilterRun()); - System.out.println("time diff: " + (MockRequestDispatcher.getCurrent().getIncludeLastCalled() - chain.getTimeInvoked()) + "ms" ); - assertTrue(chain.getTimeInvoked() < MockRequestDispatcher.getCurrent().getIncludeLastCalled()); - } - - public void testNoSubstitution() throws IOException, ServletException { - NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); - rewrittenUrl.setNoSubstitution(true); - assertFalse(rewrittenUrl.doRewrite(request, response, chain)); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.testhelper.MockFilterChain; +import org.tuckey.web.testhelper.MockRequest; +import org.tuckey.web.testhelper.MockRequestDispatcher; +import org.tuckey.web.testhelper.MockResponse; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author Paul Tuckey + * @version $Revision: 40 $ $Date: 2006-10-27 15:12:37 +1300 (Fri, 27 Oct 2006) $ + */ +public class RewrittenUrlTest extends TestCase { + + MockResponse response; + MockRequest request; + MockFilterChain chain; + + public void setUp() { + Log.setLevel("SYSOUT:TRACE"); + response = new MockResponse(); + request = new MockRequest(); + chain = new MockFilterChain(); + } + + public void testPermanentRedir() throws IOException, ServletException { + NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); + rewrittenUrl.setPermanentRedirect(true); + rewrittenUrl.doRewrite(request, response, chain); + assertEquals("/hi", response.getHeader("Location")); + assertEquals(HttpServletResponse.SC_MOVED_PERMANENTLY, response.getStatus()); + } + + public void testTempRedir() throws IOException, ServletException { + NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); + rewrittenUrl.setTemporaryRedirect(true); + rewrittenUrl.doRewrite(request, response, chain); + assertEquals("/hi", response.getHeader("Location")); + assertEquals(HttpServletResponse.SC_MOVED_TEMPORARILY, response.getStatus()); + } + + public void testForward() throws IOException, ServletException { + NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); + rewrittenUrl.setForward(true); + rewrittenUrl.doRewrite(request, response, chain); + assertEquals("/hi", MockRequestDispatcher.getCurrent().getUrl()); + assertTrue(MockRequestDispatcher.getCurrent().isForwarded()); + } + + public void testRedir() throws IOException, ServletException { + NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); + rewrittenUrl.setRedirect(true); + rewrittenUrl.doRewrite(request, response, chain); + assertEquals("/hi", response.getRedirectedUrl()); + } + + public void testRedirEncoded() throws IOException, ServletException { + NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); + rewrittenUrl.setRedirect(true); + rewrittenUrl.setEncode(true); + rewrittenUrl.doRewrite(request, response, chain); + assertEquals("/hi;mockencoded=test", response.getRedirectedUrl()); + } + + public void testPreIncl() throws IOException, ServletException { + NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); + rewrittenUrl.setPreInclude(true); + rewrittenUrl.setEncode(true); + rewrittenUrl.doRewrite(request, response, chain); + assertTrue(MockRequestDispatcher.getCurrent().isIncluded() && chain.isDoFilterRun()); + } + + public void testPostIncl() throws IOException, ServletException { + NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); + rewrittenUrl.setPostInclude(true); + rewrittenUrl.setEncode(true); + rewrittenUrl.doRewrite(request, response, chain); + assertTrue(MockRequestDispatcher.getCurrent().isIncluded() && chain.isDoFilterRun()); + System.out.println("time diff: " + (MockRequestDispatcher.getCurrent().getIncludeLastCalled() - chain.getTimeInvoked()) + "ms" ); + assertTrue(chain.getTimeInvoked() < MockRequestDispatcher.getCurrent().getIncludeLastCalled()); + } + + public void testNoSubstitution() throws IOException, ServletException { + NormalRewrittenUrl rewrittenUrl = new NormalRewrittenUrl("/hi"); + rewrittenUrl.setNoSubstitution(true); + assertFalse(rewrittenUrl.doRewrite(request, response, chain)); + } + +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/RuleTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/RuleTest.java index 7873b99b..4aa47580 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/RuleTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/RuleTest.java @@ -1,922 +1,922 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.testhelper.MockRequest; -import org.tuckey.web.testhelper.MockResponse; -import org.tuckey.web.testhelper.MockServletContext; - -import jakarta.servlet.ServletException; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; - -/** - * @author Paul Tuckey - * @version $Revision: 49 $ $Date: 2006-12-08 10:09:07 +1300 (Fri, 08 Dec 2006) $ - */ -public class RuleTest extends TestCase { - - MockResponse response; - MockRequest request; - - public void setUp() { - Log.setLevel("TRACE"); - response = new MockResponse(); - request = new MockRequest(); - } - - public void testRule01() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("simple(ass)"); - rule.setTo("$1simple"); - rule.initialise(null); - MockRequest request = new MockRequest("simpleass"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - - assertEquals("forward should be default type", "forward", rule.getToType()); - assertEquals("asssimple", rewrittenUrl.getTarget()); - assertTrue("Should be a forward", rewrittenUrl.isForward()); - } - - public void testRule01a() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("simple(ass)"); - rule.setTo("$1simple"); - rule.setQueryStringAppend("true"); - rule.initialise(null); - MockRequest request = new MockRequest("simpleass"); - request.setQueryString("aaa=bbb"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - - assertEquals("forward should be default type", "forward", rule.getToType()); - assertEquals("asssimple?aaa=bbb", rewrittenUrl.getTarget()); - assertTrue("Should be a forward", rewrittenUrl.isForward()); - } - - public void testRule01b() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("simple(ass)"); - rule.setTo("$1simple?d=f"); - rule.setQueryStringAppend("true"); - rule.initialise(null); - MockRequest request = new MockRequest("simpleass"); - request.setQueryString("aaa=bbb"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - - assertEquals("forward should be default type", "forward", rule.getToType()); - assertEquals("asssimple?d=f&aaa=bbb", rewrittenUrl.getTarget()); - assertTrue("Should be a forward", rewrittenUrl.isForward()); - } - - public void testRule03() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("^/visa.jsp/([0-9]+)$"); - rule.setTo("/visa.jsp?Idet=$1"); - rule.initialise(null); - MockRequest request = new MockRequest("/visa.jsp/974210592"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - - assertEquals("forward should be default type", "forward", rule.getToType()); - assertEquals("/visa.jsp?Idet=974210592", rewrittenUrl.getTarget()); - assertTrue("Should be a forward", rewrittenUrl.isForward()); - } - - /** - * Test gor Google app engine's use of dollar sign - * http://code.google.com/p/urlrewritefilter/issues/detail?id=71 - */ - public void testRuleGaeWildcard() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("/**"); - rule.setTo("/app/$1"); - rule.setMatchType("wildcard"); - rule.initialise(null); - MockRequest request = new MockRequest("/$%7Bfavicon%7D"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("forward should be default type", "forward", rule.getToType()); - assertEquals("/app/$%7Bfavicon%7D", rewrittenUrl.getTarget()); - assertTrue("Should be a forward", rewrittenUrl.isForward()); - } - - public void testRuleNullTo() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setTo("null"); - rule.initialise(null); - SetAttribute setAttribute1 = new SetAttribute(); - setAttribute1.setType("status"); - setAttribute1.setValue("302"); - rule.addSetAttribute(setAttribute1); - rule.initialise(null); - - MockRequest request = new MockRequest("from"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals(302, response.getStatus()); - assertTrue(rewrittenUrl.isStopFilterChain()); - - } - - public void testRuleInclude() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setTo("to"); - rule.setToType("pre-include"); - rule.initialise(null); - request.setRequestURI("from"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - - assertEquals("pre-include", rule.getToType()); - assertTrue("Should be an pre include", rewrittenUrl.isPreInclude()); - } - - public void testRuleBackRef() throws IOException, ServletException, InvocationTargetException { - Condition c = new Condition(); - c.setName("hdr"); - c.setValue("aaa([a-z]+)cc(c)"); - NormalRule rule = new NormalRule(); - rule.setFrom("([a-z])rom"); - rule.setTo("from match: $1, backref1: %1, backref2: %2, bad backref: %a % %99 %%88, escaped backref: \\%2"); - rule.addCondition(c); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - request.setHeader("hdr", "aaafffccc"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - - assertEquals("Should have replaced back reference", - "from match: f, backref1: fff, backref2: c, bad backref: %a % 9 %8, escaped backref: %2", rewrittenUrl.getTarget()); - - assertTrue(rule.isToContainsBackReference()); - assertFalse(rule.isToContainsVariable()); - } - - public void testRuleBackRefWildcard() throws IOException, ServletException, InvocationTargetException { - Condition c = new Condition(); - c.setName("hdr"); - c.setValue("aaa-*-cc-*"); - NormalRule rule = new NormalRule(); - rule.setFrom("*rom"); - rule.setTo("from match: $1, backref1: %1, backref2: %2, bad backref: %a % %99 %%88, escaped backref: \\%2"); - rule.setMatchType("wildcard"); - rule.addCondition(c); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - request.setHeader("hdr", "aaa-fff-cc-c"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - - assertEquals("Should have replaced back reference", - "from match: f, backref1: fff, backref2: c, bad backref: %a % 9 %8, escaped backref: %2", rewrittenUrl.getTarget()); - - assertTrue(rule.isToContainsBackReference()); - assertFalse(rule.isToContainsVariable()); - } - - /** - * here's my urlrewriter.xml : - * ^([^.]+)\.domain\.com - * ^/(.*) - * /%1/$1 - *

    - * Now the url with host header 'http://test.domain.com' should be - * redirected to 'http://domain.com/test'. But for some reason it doesnt - * replace the %1 with 'test'. The redirected url is : - * http://domain.com/%1 - */ - public void testRuleBackRefHost() throws IOException, ServletException, InvocationTargetException { - Condition c = new Condition(); - c.setType("server-name"); - c.setValue("^([^.]+)\\.domain\\.com"); - NormalRule rule = new NormalRule(); - rule.setFrom("^/(.*)"); - rule.setTo("/%1/$1"); - rule.setToType("redirect"); - rule.setToLast("true"); - rule.addCondition(c); - rule.initialise(null); - MockRequest request = new MockRequest("/from"); - request.setServerName("server.domain.com"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - - assertEquals("Should have replaced back reference", - "/server/from", rewrittenUrl.getTarget()); - - assertTrue(rule.isToContainsBackReference()); - - } - - public void testRuleBackRefMixed() throws IOException, ServletException, InvocationTargetException { - Condition c = new Condition(); - c.setName("hdr"); - c.setValue("aaa([a-z]+)ccc"); - NormalRule rule = new NormalRule(); - rule.setFrom("([a-z])rom"); - rule.setTo("$1 to %{remote-host} %1 here \\%2"); - rule.addCondition(c); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - request.setRemoteHost("server!"); - request.addHeader("hdr", "aaabbbccc"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - - assertTrue(rule.isToContainsBackReference()); - assertTrue(rule.isToContainsVariable()); - - assertEquals("Should have replaced back reference", "f to server! bbb here %2", rewrittenUrl.getTarget()); - } - - public void testRuleBackRefVar() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setTo("start ctx: %{context-path}, hdr: %{header:bananna} %{header:}%{::}%{%{}, escaped var: \\%{ignoreme!}, bad var: %{} %{wibble} end"); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - request.setContextPath("ctxpath"); - request.setRemoteHost("server!"); - request.addHeader("bananna", "bender"); - request.setServerPort(90210); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - - assertFalse(rule.isToContainsBackReference()); - assertTrue(rule.isToContainsVariable()); - - assertEquals("forward should be default type", "forward", rule.getToType()); - assertEquals("start ctx: ctxpath, hdr: bender %{, escaped var: %{ignoreme!}, bad var: end", rewrittenUrl.getTarget()); - assertTrue("Should be a forward", rewrittenUrl.isForward()); - } - - public void testRuleBadCondition() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setTo("to"); - Condition condition = new Condition(); - condition.setType("port"); - condition.setValue("aaa"); - rule.addCondition(condition); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull(rewrittenUrl); - } - - public void testRuleConditionsOr() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setTo("to"); - Condition condition = new Condition(); - condition.setType("port"); - condition.setValue("90"); - condition.setNext("or"); - rule.addCondition(condition); - Condition condition2 = new Condition(); - condition2.setType("port"); - condition2.setValue("99"); - rule.addCondition(condition2); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - request.setServerPort(88); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull("should not be rewritten", rewrittenUrl); - - request.setServerPort(90); - RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); - assertEquals("should not be rewritten", "to", rewrittenUrl2.getTarget()); - - request.setServerPort(99); - RewrittenUrl rewrittenUrl3 = rule.matches(request.getRequestURI(), request, response); - assertEquals("should not be rewritten", "to", rewrittenUrl3.getTarget()); - } - - public void testRuleConditionsAnd() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setTo("to"); - Condition condition = new Condition(); - condition.setType("port"); - condition.setValue("90"); - rule.addCondition(condition); - Condition condition2 = new Condition(); - condition2.setType("character-encoding"); - condition2.setValue("utf8"); - rule.addCondition(condition2); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - request.setServerPort(88); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull("should not be rewritten", rewrittenUrl); - - request.setServerPort(90); - RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); - assertNull("should not be rewritten", rewrittenUrl2); - - request.setCharacterEncoding("utf8"); - RewrittenUrl rewrittenUrl3 = rule.matches(request.getRequestURI(), request, response); - assertEquals("should be rewritten", "to", rewrittenUrl3.getTarget()); - } - - public void testRuleConditionsReplaceAll() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("-"); - rule.setTo("_"); - Condition condition = new Condition(); - condition.setType("request-uri"); - condition.setValue("/hi-something-to-to.html"); - rule.addCondition(condition); - rule.initialise(null); - MockRequest request = new MockRequest("/hi-something-to-to.html"); - request.setServerPort(88); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals("/hi_something_to_to.html", rewrittenUrl.getTarget()); - } - - public void testRuleBadRegex() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("fro[m"); - rule.setTo("to"); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull(rewrittenUrl); - } - - public void testRuleCaseInsensitive() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("fRom"); - rule.setTo("to"); - Condition condition = new Condition(); - condition.setName("agent"); - condition.setValue("aAa"); - rule.addCondition(condition); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - request.addHeader("agent", "aaa"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals(rewrittenUrl.getTarget(), "to"); - } - - public void testRuleRewriteReq() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setEncodeToUrl(true); - rule.setTo("to"); - rule.setToType("permanent-redirect"); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertTrue(rewrittenUrl.isEncode()); - assertTrue(rewrittenUrl.isPermanentRedirect()); - } - - public void testRuleNoInit() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setTo("to"); - MockRequest request = new MockRequest("from"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull(rewrittenUrl); - } - - public void testRuleNotEnabled() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setTo("to"); - rule.setEnabled(false); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull(rewrittenUrl); - } - - public void testRule02() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("/countries/([a-z]+)/"); - rule.setTo("/countries/index.jsp?c=$1"); - rule.setToType("redirect"); - rule.initialise(null); - - MockRequest request = new MockRequest("/countries/australia/"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - MockRequest request2 = new MockRequest("/blah/"); - NormalRewrittenUrl rewrittenUrl2 = (NormalRewrittenUrl) rule.matches(request2.getRequestURI(), request2, response); - - assertEquals("/countries/index.jsp?c=australia", rewrittenUrl.getTarget()); - assertEquals("redirect", rule.getToType()); - assertTrue(rewrittenUrl.isRedirect()); - assertNull("Rule should not match", rewrittenUrl2); - } - - - public void testRuleCondition() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setTo("to"); - Condition condition = new Condition(); - condition.setType("port"); - condition.setValue("5050"); - rule.addCondition(condition); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - request.setServerPort(5050); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals("to", rewrittenUrl.getTarget()); - } - - public void testRuleErikBug() throws IOException, ServletException, InvocationTargetException { - // see http://www.erikisaksson.com/blog/2004/07/27/1090952764000.html - NormalRule rule = new NormalRule(); - rule.setFrom("^(.*)$"); - rule.setTo("http://short.com/context$1"); - Condition condition = new Condition(); - condition.setName("host"); - condition.setOperator("notequal"); - condition.setValue("short\\.com"); - rule.addCondition(condition); - rule.initialise(null); - MockRequest request = new MockRequest("/blahurl"); - request.addHeader("host", "short.com"); - - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals("no rewriting should be necessary", null, rewrittenUrl); - - request.addHeader("host", "www.notexample.com"); - RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); - assertEquals("http://short.com/context/blahurl", rewrittenUrl2.getTarget()); - } - - public void testRuleHostBug() throws ServletException, IOException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setToLast("true"); - rule.setToType("permanent-redirect"); - rule.setQueryStringAppend("true"); - rule.setFrom("(.*)"); - rule.setTo("https://righthost.com%{request-uri}"); - - Condition condition = new Condition(); - condition.setName("host"); - condition.setOperator("notequal"); - condition.setValue("^righthost\\.com$"); - - rule.addCondition(condition); - rule.initialise(null); - - MockRequest request = new MockRequest("/test?param=val"); - request.addHeader("host", "wronghost.com"); - - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - - assertEquals("https://righthost.com/test?param=val", rewrittenUrl.getTarget()); - - rule.setTo("https://righthost.com$1"); - rule.initialise(null); - - rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals("https://righthost.com/test?param=val", rewrittenUrl.getTarget()); - } - - public void testRule08() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("/$"); - rule.setTo("/opencms/opencms/index.html"); - rule.initialise(null); - - MockRequest request = new MockRequest("/"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals("/opencms/opencms/index.html", rewrittenUrl.getTarget()); - - request = new MockRequest("/xyz"); - rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull(rewrittenUrl); - } - - - public void testRuleTrailingSlashRedirect() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("/~quux/foo$"); - rule.setTo("/~quux/foo/"); - rule.initialise(null); - - MockRequest request = new MockRequest("/~quux/foo"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals("/~quux/foo/", rewrittenUrl.getTarget()); - } - - public void testRule10() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("/products/([0-9]+)"); - rule.setTo("/index.jsp?product_id=$1"); - rule.initialise(null); - MockRequest request = new MockRequest("/products/105874"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals("/index.jsp?product_id=105874", rewrittenUrl.getTarget()); - } - - - public void testRule11() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("^/([a-z]+)/$"); - rule.setTo("/$1/index.jsp"); - rule.initialise(null); - MockRequest request = new MockRequest("/dir/"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals("/dir/index.jsp", rewrittenUrl.getTarget()); - } - - - public void testFailedRule1() throws IOException, ServletException, InvocationTargetException { - String uri = "/article/blah/"; - NormalRule rule = new NormalRule(); - rule.setFrom("/article/([0-9]+)/([0-9]+)/([0-9]+)/([a-zA-Z0-9]+)/"); - rule.setTo("/article/index.jsp?year=$1&month=$2&day=$3&code=$4"); - rule.initialise(null); - - MockRequest request = new MockRequest(uri); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull(rewrittenUrl); - } - - - public void testRuleConditionsUserInRole() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.setTo("to"); - - Condition condition = new Condition(); - condition.setType("user-in-role"); - condition.setValue("admin"); - condition.setOperator("notequal"); - rule.addCondition(condition); - - Condition condition2 = new Condition(); - condition2.setType("user-in-role"); - condition2.setValue("boss"); - condition2.setOperator("notequal"); - rule.addCondition(condition2); - rule.initialise(null); - - MockRequest request = new MockRequest("from"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals("should be rewritten", "to", rewrittenUrl.getTarget()); - - request.addRole("boss"); - RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); - assertNull("should not be rewritten", rewrittenUrl2); - } - - /** - * - * Bild redirect test - * logo.gif - * http://de010009.de.ina.com:8080/urlrewrite/artifact_type.gif - * - */ - public void testBlindRedirect() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("^/logo\\.gif$"); - rule.setToType("permanent-redirect"); - rule.setTo("http://de010009\\.de\\.ina\\.com:8080/urlrewrite/artifact_type\\.gif"); - rule.initialise(null); - MockRequest request = new MockRequest("/logo.gif"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("http://de010009.de.ina.com:8080/urlrewrite/artifact_type.gif", rewrittenUrl.getTarget()); - assertTrue(rewrittenUrl.isPermanentRedirect()); - assertFalse(rewrittenUrl.isEncode()); - } - - - public void testRuleHighChar() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom("/aa\\?a=(.*)"); - rule.setEncodeToUrl(true); - rule.setTo("$1"); - rule.setToType("permanent-redirect"); - rule.initialise(null); - String highStr = new String("\u00F6\u236a\u2E88".getBytes(), "UTF8"); - MockRequest request = new MockRequest("/aa?a=" + highStr); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals(highStr, rewrittenUrl.getTarget()); - } - - /** - * - * - * /a\.jsp - * /b.jsp - * - *

    - * (Which I think it means: "if the user asks for a.jsp and the cookie - * SAJKLHDSKJHDSKJHD is not set, redirect him to b.jsp") the rule stops - * working. Maybe it's because the cookie is null instead of an empty - * string, I don't know. - */ - public void testRuleCookieEmpty() throws IOException, ServletException, InvocationTargetException { - Condition c = new Condition(); - c.setType("cookie"); - c.setName("abcdef"); - NormalRule rule = new NormalRule(); - rule.setFrom("/a\\.jsp"); - rule.setTo("/b.jsp"); - rule.addCondition(c); - rule.initialise(null); - RewrittenUrl rewrittenUrl = rule.matches("/a.jsp", request, response); - assertTrue(request.getCookies() == null); - assertTrue(rewrittenUrl == null); - - c = new Condition(); - c.setType("cookie"); - c.setName("abcdef"); - c.setOperator("notequal"); - rule = new NormalRule(); - rule.setFrom("/a\\.jsp"); - rule.setTo("/b.jsp"); - rule.addCondition(c); - rule.initialise(null); - rewrittenUrl = rule.matches("/a.jsp", request, response); - assertTrue(request.getCookies() == null); - assertEquals("/b.jsp", rewrittenUrl.getTarget()); - - } - - public void testRuleWildcard1() throws IOException, ServletException, InvocationTargetException { - wildcardRuleTestHelper("/*/", "/b/", "/a12sfg-+\\?#/", "/b/"); - wildcardRuleTestHelper("/*/*/", "/b/c/", "/z23434/-+=asd/", "/b/c/"); - wildcardRuleTestHelper("/*/*/", "/to/", "/a/b/c/", "/a/b/c/"); - wildcardRuleTestHelper("/**/", "/to/", "/a/b/c", "/a/b/c"); - wildcardRuleTestHelper("/**/", "/to/", "/a/b/c/", "/to/"); - wildcardRuleTestHelper("**.html", "/to/", "/a/b/c/sldwe.html", "/to/"); - wildcardRuleTestHelper("*.html", "/to/", "/a/b/c/sldwe.html", "/a/b/c/sldwe.html"); - wildcardRuleTestHelper("/a/b/c/*.html", "/to/", "/a/b/c/sldwe.html", "/to/"); - } - - - public void testRuleWildcard2() throws IOException, ServletException, InvocationTargetException { - wildcardRuleTestHelper("/*.h", "/$1", "/a.h", "/a"); - wildcardRuleTestHelper("/**", "/d/$1", "/a/b/c", "/d/a/b/c"); - // test same with conds - wildcardRuleTestHelper("/*/a/*/aa", "/a/$2$1", "/w/a/c/aa", "/a/cw"); - } - - - public void testRuleWildcardCond() throws IOException, ServletException, InvocationTargetException { - MockRequest request = new MockRequest("/from"); - - request.setServerName("dev.googil.com"); - ruleWildcardCondHelper("server-name", "dev*", request); - - request.setContentType("image/jpeg"); - ruleWildcardCondHelper("content-type", "image/*", request); - - request.setContextPath("/a/b/c"); - ruleWildcardCondHelper("context-path", "/a/**", request); - - } - - - public void ruleWildcardCondHelper(String type, String value, MockRequest request) throws IOException, ServletException, InvocationTargetException { - Condition condition = new Condition(); - condition.setType(type); - condition.setValue(value); - - NormalRule rule = new NormalRule(); - rule.setFrom("/from"); - rule.setMatchType(" wildcard "); - rule.setTo("/to"); - rule.addCondition(condition); - rule.initialise(null); - - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals("/to", rewrittenUrl == null ? "/from" : rewrittenUrl.getTarget()); - - } - - public void wildcardRuleTestHelper(String from, String to, String req, String assertEq) - throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setFrom(from); - rule.setMatchType(" wildcard "); - rule.setTo(to); - rule.initialise(null); - MockRequest request = new MockRequest(req); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertEquals(assertEq, rewrittenUrl == null ? req : rewrittenUrl.getTarget()); - } - - - public void testRuleNoFrom() throws IOException, ServletException, InvocationTargetException { - NormalRule rule = new NormalRule(); - rule.setTo("to"); - Condition condition = new Condition(); - condition.setType("port"); - condition.setValue("90"); - rule.addCondition(condition); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - request.setServerPort(88); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull("should not be rewritten", rewrittenUrl); - - request.setServerPort(90); - RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); - assertNotNull("should be rewritten", rewrittenUrl2); - } - - public void testConditionAndSet() throws IOException, ServletException, InvocationTargetException { - Condition condition = new Condition(); - condition.setType("header"); - condition.setName("user-agent"); - condition.setValue("iexplore"); - - SetAttribute s = new SetAttribute(); - s.setType("request"); - s.setName("browser"); - s.setValue("ie"); - - NormalRule rule = new NormalRule(); - rule.addCondition(condition); - rule.addSetAttribute(s); - rule.initialise(null); - - MockRequest request = new MockRequest("from"); - request.setHeader("user-agent", "firefox"); - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull("should not be rewritten", rewrittenUrl); - assertNull(request.getAttribute("browser")); - - request.setHeader("user-agent", "iexplore"); - RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); - assertNull("should not be rewritten", rewrittenUrl2); - assertEquals("ie", request.getAttribute("browser")); - } - - public void testForum20080613() throws InvocationTargetException, IOException, ServletException { - NormalRule rule = new NormalRule(); - rule.setFrom("^/[^/]+/(.+)-S_[0-9]+\\.html$"); - rule.setTo("/liste/query/${replace:$1:-:+}/"); - rule.initialise(null); - MockRequest request = new MockRequest("/ab/as-as-S_12.html"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - - assertEquals("forward should be default type", "forward", rule.getToType()); - assertEquals("/liste/query/as+as/", rewrittenUrl.getTarget()); - assertTrue("Should be a forward", rewrittenUrl.isForward()); - } - - - public void testContext() throws InvocationTargetException, IOException, ServletException { - NormalRule rule = new NormalRule(); - rule.setFrom("^/goanothercontext/"); - rule.setTo("/other/"); - rule.setToContextStr("othercontext"); - rule.initialise(new MockServletContext()); - MockRequest request = new MockRequest("/goanothercontext/aaa.html"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - - assertEquals("forward should be default type", "forward", rule.getToType()); - assertEquals("/other/aaa.html", rewrittenUrl.getTarget()); - assertNotNull("Should be not empty", rewrittenUrl.getTargetContext()); - } - - public void testFilename() throws InvocationTargetException, IOException, ServletException { - NormalRule rule = new NormalRule(); - rule.setTo("/found-the-file"); - Condition condition = new Condition(); - condition.setType("request-filename"); - condition.setOperator("isfile"); - rule.addCondition(condition); - rule.initialise(new MockServletContext()); - MockRequest request = new MockRequest("/conf-test1.xml"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("/found-the-file", rewrittenUrl.getTarget()); - } - - public void testEncodedFilename() throws InvocationTargetException, IOException, ServletException { - NormalRule rule = new NormalRule(); - rule.setTo("/found-the-file"); - Condition condition = new Condition(); - condition.setType("request-filename"); - condition.setOperator("isfile"); - rule.addCondition(condition); - rule.initialise(new MockServletContext()); - MockRequest request = new MockRequest("/conf%2Dtest1.xml"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("/found-the-file", rewrittenUrl.getTarget()); - } - - public void testNotFilename() throws InvocationTargetException, IOException, ServletException { - NormalRule rule = new NormalRule(); - rule.setTo("/not-found-the-file"); - Condition condition = new Condition(); - condition.setType("request-filename"); - condition.setOperator("notfile"); - rule.addCondition(condition); - rule.initialise(new MockServletContext()); - MockRequest request = new MockRequest("/AAAconf-test1.xml"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("/not-found-the-file", rewrittenUrl.getTarget()); - } - - public void testDirectory() throws InvocationTargetException, IOException, ServletException { - NormalRule rule = new NormalRule(); - rule.setTo("/found-the-dir"); - Condition condition = new Condition(); - condition.setType("request-filename"); - condition.setOperator("isdir"); - rule.addCondition(condition); - rule.initialise(new MockServletContext()); - MockRequest request = new MockRequest("/utils/"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("/found-the-dir", rewrittenUrl.getTarget()); - } - - public void testNotDirectory() throws InvocationTargetException, IOException, ServletException { - NormalRule rule = new NormalRule(); - rule.setTo("/not-found-the-dir"); - Condition condition = new Condition(); - condition.setType("request-filename"); - condition.setOperator("notdir"); - rule.addCondition(condition); - rule.initialise(new MockServletContext()); - MockRequest request = new MockRequest("/utAAAils/"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("/not-found-the-dir", rewrittenUrl.getTarget()); - } - - public void testIssue116() throws InvocationTargetException, IOException, ServletException { - NormalRule rule = new NormalRule(); - rule.setFrom("^/robots\\.txt$"); - rule.setTo("/en/robots.txt"); - rule.setToType("permanent-redirect"); - rule.setToLast("true"); - rule.setQueryStringAppend("true"); - rule.initialise(new MockServletContext()); - MockRequest request = new MockRequest("/robots.txt"); - request.setQueryString("param1=value1¶m2=value2"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("/en/robots.txt?param1=value1¶m2=value2", rewrittenUrl.getTarget()); - } - - public void testRegexIssueIssue() throws InvocationTargetException, IOException, ServletException { - NormalRule rule = new NormalRule(); - rule.setFrom(".*"); - rule.setTo("robots.txt"); - rule.setToType("permanent-redirect"); - rule.setToLast("true"); - rule.setQueryStringAppend("true"); - rule.initialise(new MockServletContext()); - MockRequest request = new MockRequest("/oddness"); - NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("robots.txt", rewrittenUrl.getTarget()); - - rule.setFrom(".+"); - rule.setTo("robots.txt"); - rule.setToType("permanent-redirect"); - rule.setToLast("true"); - rule.setQueryStringAppend("true"); - rule.initialise(new MockServletContext()); - request = new MockRequest("/oddness"); - rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("robots.txt", rewrittenUrl.getTarget()); - - rule.setFrom(".?"); - rule.setTo("robots.txt"); - rule.setToType("permanent-redirect"); - rule.setToLast("true"); - rule.setQueryStringAppend("true"); - rule.initialise(new MockServletContext()); - request = new MockRequest("/oddness"); - rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); - assertEquals("robots.txtoddness", rewrittenUrl.getTarget()); - - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.testhelper.MockRequest; +import org.tuckey.web.testhelper.MockResponse; +import org.tuckey.web.testhelper.MockServletContext; + +import jakarta.servlet.ServletException; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +/** + * @author Paul Tuckey + * @version $Revision: 49 $ $Date: 2006-12-08 10:09:07 +1300 (Fri, 08 Dec 2006) $ + */ +public class RuleTest extends TestCase { + + MockResponse response; + MockRequest request; + + public void setUp() { + Log.setLevel("TRACE"); + response = new MockResponse(); + request = new MockRequest(); + } + + public void testRule01() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("simple(ass)"); + rule.setTo("$1simple"); + rule.initialise(null); + MockRequest request = new MockRequest("simpleass"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + + assertEquals("forward should be default type", "forward", rule.getToType()); + assertEquals("asssimple", rewrittenUrl.getTarget()); + assertTrue("Should be a forward", rewrittenUrl.isForward()); + } + + public void testRule01a() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("simple(ass)"); + rule.setTo("$1simple"); + rule.setQueryStringAppend("true"); + rule.initialise(null); + MockRequest request = new MockRequest("simpleass"); + request.setQueryString("aaa=bbb"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + + assertEquals("forward should be default type", "forward", rule.getToType()); + assertEquals("asssimple?aaa=bbb", rewrittenUrl.getTarget()); + assertTrue("Should be a forward", rewrittenUrl.isForward()); + } + + public void testRule01b() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("simple(ass)"); + rule.setTo("$1simple?d=f"); + rule.setQueryStringAppend("true"); + rule.initialise(null); + MockRequest request = new MockRequest("simpleass"); + request.setQueryString("aaa=bbb"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + + assertEquals("forward should be default type", "forward", rule.getToType()); + assertEquals("asssimple?d=f&aaa=bbb", rewrittenUrl.getTarget()); + assertTrue("Should be a forward", rewrittenUrl.isForward()); + } + + public void testRule03() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("^/visa.jsp/([0-9]+)$"); + rule.setTo("/visa.jsp?Idet=$1"); + rule.initialise(null); + MockRequest request = new MockRequest("/visa.jsp/974210592"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + + assertEquals("forward should be default type", "forward", rule.getToType()); + assertEquals("/visa.jsp?Idet=974210592", rewrittenUrl.getTarget()); + assertTrue("Should be a forward", rewrittenUrl.isForward()); + } + + /** + * Test gor Google app engine's use of dollar sign + * http://code.google.com/p/urlrewritefilter/issues/detail?id=71 + */ + public void testRuleGaeWildcard() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("/**"); + rule.setTo("/app/$1"); + rule.setMatchType("wildcard"); + rule.initialise(null); + MockRequest request = new MockRequest("/$%7Bfavicon%7D"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("forward should be default type", "forward", rule.getToType()); + assertEquals("/app/$%7Bfavicon%7D", rewrittenUrl.getTarget()); + assertTrue("Should be a forward", rewrittenUrl.isForward()); + } + + public void testRuleNullTo() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setTo("null"); + rule.initialise(null); + SetAttribute setAttribute1 = new SetAttribute(); + setAttribute1.setType("status"); + setAttribute1.setValue("302"); + rule.addSetAttribute(setAttribute1); + rule.initialise(null); + + MockRequest request = new MockRequest("from"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals(302, response.getStatus()); + assertTrue(rewrittenUrl.isStopFilterChain()); + + } + + public void testRuleInclude() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setTo("to"); + rule.setToType("pre-include"); + rule.initialise(null); + request.setRequestURI("from"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + + assertEquals("pre-include", rule.getToType()); + assertTrue("Should be an pre include", rewrittenUrl.isPreInclude()); + } + + public void testRuleBackRef() throws IOException, ServletException, InvocationTargetException { + Condition c = new Condition(); + c.setName("hdr"); + c.setValue("aaa([a-z]+)cc(c)"); + NormalRule rule = new NormalRule(); + rule.setFrom("([a-z])rom"); + rule.setTo("from match: $1, backref1: %1, backref2: %2, bad backref: %a % %99 %%88, escaped backref: \\%2"); + rule.addCondition(c); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + request.setHeader("hdr", "aaafffccc"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + + assertEquals("Should have replaced back reference", + "from match: f, backref1: fff, backref2: c, bad backref: %a % 9 %8, escaped backref: %2", rewrittenUrl.getTarget()); + + assertTrue(rule.isToContainsBackReference()); + assertFalse(rule.isToContainsVariable()); + } + + public void testRuleBackRefWildcard() throws IOException, ServletException, InvocationTargetException { + Condition c = new Condition(); + c.setName("hdr"); + c.setValue("aaa-*-cc-*"); + NormalRule rule = new NormalRule(); + rule.setFrom("*rom"); + rule.setTo("from match: $1, backref1: %1, backref2: %2, bad backref: %a % %99 %%88, escaped backref: \\%2"); + rule.setMatchType("wildcard"); + rule.addCondition(c); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + request.setHeader("hdr", "aaa-fff-cc-c"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + + assertEquals("Should have replaced back reference", + "from match: f, backref1: fff, backref2: c, bad backref: %a % 9 %8, escaped backref: %2", rewrittenUrl.getTarget()); + + assertTrue(rule.isToContainsBackReference()); + assertFalse(rule.isToContainsVariable()); + } + + /** + * here's my urlrewriter.xml : + * ^([^.]+)\.domain\.com + * ^/(.*) + * /%1/$1 + *

    + * Now the url with host header 'http://test.domain.com' should be + * redirected to 'http://domain.com/test'. But for some reason it doesnt + * replace the %1 with 'test'. The redirected url is : + * http://domain.com/%1 + */ + public void testRuleBackRefHost() throws IOException, ServletException, InvocationTargetException { + Condition c = new Condition(); + c.setType("server-name"); + c.setValue("^([^.]+)\\.domain\\.com"); + NormalRule rule = new NormalRule(); + rule.setFrom("^/(.*)"); + rule.setTo("/%1/$1"); + rule.setToType("redirect"); + rule.setToLast("true"); + rule.addCondition(c); + rule.initialise(null); + MockRequest request = new MockRequest("/from"); + request.setServerName("server.domain.com"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + + assertEquals("Should have replaced back reference", + "/server/from", rewrittenUrl.getTarget()); + + assertTrue(rule.isToContainsBackReference()); + + } + + public void testRuleBackRefMixed() throws IOException, ServletException, InvocationTargetException { + Condition c = new Condition(); + c.setName("hdr"); + c.setValue("aaa([a-z]+)ccc"); + NormalRule rule = new NormalRule(); + rule.setFrom("([a-z])rom"); + rule.setTo("$1 to %{remote-host} %1 here \\%2"); + rule.addCondition(c); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + request.setRemoteHost("server!"); + request.addHeader("hdr", "aaabbbccc"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + + assertTrue(rule.isToContainsBackReference()); + assertTrue(rule.isToContainsVariable()); + + assertEquals("Should have replaced back reference", "f to server! bbb here %2", rewrittenUrl.getTarget()); + } + + public void testRuleBackRefVar() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setTo("start ctx: %{context-path}, hdr: %{header:bananna} %{header:}%{::}%{%{}, escaped var: \\%{ignoreme!}, bad var: %{} %{wibble} end"); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + request.setContextPath("ctxpath"); + request.setRemoteHost("server!"); + request.addHeader("bananna", "bender"); + request.setServerPort(90210); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + + assertFalse(rule.isToContainsBackReference()); + assertTrue(rule.isToContainsVariable()); + + assertEquals("forward should be default type", "forward", rule.getToType()); + assertEquals("start ctx: ctxpath, hdr: bender %{, escaped var: %{ignoreme!}, bad var: end", rewrittenUrl.getTarget()); + assertTrue("Should be a forward", rewrittenUrl.isForward()); + } + + public void testRuleBadCondition() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setTo("to"); + Condition condition = new Condition(); + condition.setType("port"); + condition.setValue("aaa"); + rule.addCondition(condition); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull(rewrittenUrl); + } + + public void testRuleConditionsOr() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setTo("to"); + Condition condition = new Condition(); + condition.setType("port"); + condition.setValue("90"); + condition.setNext("or"); + rule.addCondition(condition); + Condition condition2 = new Condition(); + condition2.setType("port"); + condition2.setValue("99"); + rule.addCondition(condition2); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + request.setServerPort(88); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull("should not be rewritten", rewrittenUrl); + + request.setServerPort(90); + RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); + assertEquals("should not be rewritten", "to", rewrittenUrl2.getTarget()); + + request.setServerPort(99); + RewrittenUrl rewrittenUrl3 = rule.matches(request.getRequestURI(), request, response); + assertEquals("should not be rewritten", "to", rewrittenUrl3.getTarget()); + } + + public void testRuleConditionsAnd() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setTo("to"); + Condition condition = new Condition(); + condition.setType("port"); + condition.setValue("90"); + rule.addCondition(condition); + Condition condition2 = new Condition(); + condition2.setType("character-encoding"); + condition2.setValue("utf8"); + rule.addCondition(condition2); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + request.setServerPort(88); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull("should not be rewritten", rewrittenUrl); + + request.setServerPort(90); + RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); + assertNull("should not be rewritten", rewrittenUrl2); + + request.setCharacterEncoding("utf8"); + RewrittenUrl rewrittenUrl3 = rule.matches(request.getRequestURI(), request, response); + assertEquals("should be rewritten", "to", rewrittenUrl3.getTarget()); + } + + public void testRuleConditionsReplaceAll() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("-"); + rule.setTo("_"); + Condition condition = new Condition(); + condition.setType("request-uri"); + condition.setValue("/hi-something-to-to.html"); + rule.addCondition(condition); + rule.initialise(null); + MockRequest request = new MockRequest("/hi-something-to-to.html"); + request.setServerPort(88); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals("/hi_something_to_to.html", rewrittenUrl.getTarget()); + } + + public void testRuleBadRegex() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("fro[m"); + rule.setTo("to"); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull(rewrittenUrl); + } + + public void testRuleCaseInsensitive() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("fRom"); + rule.setTo("to"); + Condition condition = new Condition(); + condition.setName("agent"); + condition.setValue("aAa"); + rule.addCondition(condition); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + request.addHeader("agent", "aaa"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals(rewrittenUrl.getTarget(), "to"); + } + + public void testRuleRewriteReq() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setEncodeToUrl(true); + rule.setTo("to"); + rule.setToType("permanent-redirect"); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertTrue(rewrittenUrl.isEncode()); + assertTrue(rewrittenUrl.isPermanentRedirect()); + } + + public void testRuleNoInit() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setTo("to"); + MockRequest request = new MockRequest("from"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull(rewrittenUrl); + } + + public void testRuleNotEnabled() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setTo("to"); + rule.setEnabled(false); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull(rewrittenUrl); + } + + public void testRule02() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("/countries/([a-z]+)/"); + rule.setTo("/countries/index.jsp?c=$1"); + rule.setToType("redirect"); + rule.initialise(null); + + MockRequest request = new MockRequest("/countries/australia/"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + MockRequest request2 = new MockRequest("/blah/"); + NormalRewrittenUrl rewrittenUrl2 = (NormalRewrittenUrl) rule.matches(request2.getRequestURI(), request2, response); + + assertEquals("/countries/index.jsp?c=australia", rewrittenUrl.getTarget()); + assertEquals("redirect", rule.getToType()); + assertTrue(rewrittenUrl.isRedirect()); + assertNull("Rule should not match", rewrittenUrl2); + } + + + public void testRuleCondition() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setTo("to"); + Condition condition = new Condition(); + condition.setType("port"); + condition.setValue("5050"); + rule.addCondition(condition); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + request.setServerPort(5050); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals("to", rewrittenUrl.getTarget()); + } + + public void testRuleErikBug() throws IOException, ServletException, InvocationTargetException { + // see http://www.erikisaksson.com/blog/2004/07/27/1090952764000.html + NormalRule rule = new NormalRule(); + rule.setFrom("^(.*)$"); + rule.setTo("http://short.com/context$1"); + Condition condition = new Condition(); + condition.setName("host"); + condition.setOperator("notequal"); + condition.setValue("short\\.com"); + rule.addCondition(condition); + rule.initialise(null); + MockRequest request = new MockRequest("/blahurl"); + request.addHeader("host", "short.com"); + + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals("no rewriting should be necessary", null, rewrittenUrl); + + request.addHeader("host", "www.notexample.com"); + RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); + assertEquals("http://short.com/context/blahurl", rewrittenUrl2.getTarget()); + } + + public void testRuleHostBug() throws ServletException, IOException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setToLast("true"); + rule.setToType("permanent-redirect"); + rule.setQueryStringAppend("true"); + rule.setFrom("(.*)"); + rule.setTo("https://righthost.com%{request-uri}"); + + Condition condition = new Condition(); + condition.setName("host"); + condition.setOperator("notequal"); + condition.setValue("^righthost\\.com$"); + + rule.addCondition(condition); + rule.initialise(null); + + MockRequest request = new MockRequest("/test?param=val"); + request.addHeader("host", "wronghost.com"); + + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + + assertEquals("https://righthost.com/test?param=val", rewrittenUrl.getTarget()); + + rule.setTo("https://righthost.com$1"); + rule.initialise(null); + + rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals("https://righthost.com/test?param=val", rewrittenUrl.getTarget()); + } + + public void testRule08() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("/$"); + rule.setTo("/opencms/opencms/index.html"); + rule.initialise(null); + + MockRequest request = new MockRequest("/"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals("/opencms/opencms/index.html", rewrittenUrl.getTarget()); + + request = new MockRequest("/xyz"); + rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull(rewrittenUrl); + } + + + public void testRuleTrailingSlashRedirect() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("/~quux/foo$"); + rule.setTo("/~quux/foo/"); + rule.initialise(null); + + MockRequest request = new MockRequest("/~quux/foo"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals("/~quux/foo/", rewrittenUrl.getTarget()); + } + + public void testRule10() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("/products/([0-9]+)"); + rule.setTo("/index.jsp?product_id=$1"); + rule.initialise(null); + MockRequest request = new MockRequest("/products/105874"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals("/index.jsp?product_id=105874", rewrittenUrl.getTarget()); + } + + + public void testRule11() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("^/([a-z]+)/$"); + rule.setTo("/$1/index.jsp"); + rule.initialise(null); + MockRequest request = new MockRequest("/dir/"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals("/dir/index.jsp", rewrittenUrl.getTarget()); + } + + + public void testFailedRule1() throws IOException, ServletException, InvocationTargetException { + String uri = "/article/blah/"; + NormalRule rule = new NormalRule(); + rule.setFrom("/article/([0-9]+)/([0-9]+)/([0-9]+)/([a-zA-Z0-9]+)/"); + rule.setTo("/article/index.jsp?year=$1&month=$2&day=$3&code=$4"); + rule.initialise(null); + + MockRequest request = new MockRequest(uri); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull(rewrittenUrl); + } + + + public void testRuleConditionsUserInRole() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.setTo("to"); + + Condition condition = new Condition(); + condition.setType("user-in-role"); + condition.setValue("admin"); + condition.setOperator("notequal"); + rule.addCondition(condition); + + Condition condition2 = new Condition(); + condition2.setType("user-in-role"); + condition2.setValue("boss"); + condition2.setOperator("notequal"); + rule.addCondition(condition2); + rule.initialise(null); + + MockRequest request = new MockRequest("from"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals("should be rewritten", "to", rewrittenUrl.getTarget()); + + request.addRole("boss"); + RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); + assertNull("should not be rewritten", rewrittenUrl2); + } + + /** + * + * Bild redirect test + * logo.gif + * http://de010009.de.ina.com:8080/urlrewrite/artifact_type.gif + * + */ + public void testBlindRedirect() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("^/logo\\.gif$"); + rule.setToType("permanent-redirect"); + rule.setTo("http://de010009\\.de\\.ina\\.com:8080/urlrewrite/artifact_type\\.gif"); + rule.initialise(null); + MockRequest request = new MockRequest("/logo.gif"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("http://de010009.de.ina.com:8080/urlrewrite/artifact_type.gif", rewrittenUrl.getTarget()); + assertTrue(rewrittenUrl.isPermanentRedirect()); + assertFalse(rewrittenUrl.isEncode()); + } + + + public void testRuleHighChar() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom("/aa\\?a=(.*)"); + rule.setEncodeToUrl(true); + rule.setTo("$1"); + rule.setToType("permanent-redirect"); + rule.initialise(null); + String highStr = new String("\u00F6\u236a\u2E88".getBytes(), "UTF8"); + MockRequest request = new MockRequest("/aa?a=" + highStr); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals(highStr, rewrittenUrl.getTarget()); + } + + /** + * + * + * /a\.jsp + * /b.jsp + * + *

    + * (Which I think it means: "if the user asks for a.jsp and the cookie + * SAJKLHDSKJHDSKJHD is not set, redirect him to b.jsp") the rule stops + * working. Maybe it's because the cookie is null instead of an empty + * string, I don't know. + */ + public void testRuleCookieEmpty() throws IOException, ServletException, InvocationTargetException { + Condition c = new Condition(); + c.setType("cookie"); + c.setName("abcdef"); + NormalRule rule = new NormalRule(); + rule.setFrom("/a\\.jsp"); + rule.setTo("/b.jsp"); + rule.addCondition(c); + rule.initialise(null); + RewrittenUrl rewrittenUrl = rule.matches("/a.jsp", request, response); + assertTrue(request.getCookies() == null); + assertTrue(rewrittenUrl == null); + + c = new Condition(); + c.setType("cookie"); + c.setName("abcdef"); + c.setOperator("notequal"); + rule = new NormalRule(); + rule.setFrom("/a\\.jsp"); + rule.setTo("/b.jsp"); + rule.addCondition(c); + rule.initialise(null); + rewrittenUrl = rule.matches("/a.jsp", request, response); + assertTrue(request.getCookies() == null); + assertEquals("/b.jsp", rewrittenUrl.getTarget()); + + } + + public void testRuleWildcard1() throws IOException, ServletException, InvocationTargetException { + wildcardRuleTestHelper("/*/", "/b/", "/a12sfg-+\\?#/", "/b/"); + wildcardRuleTestHelper("/*/*/", "/b/c/", "/z23434/-+=asd/", "/b/c/"); + wildcardRuleTestHelper("/*/*/", "/to/", "/a/b/c/", "/a/b/c/"); + wildcardRuleTestHelper("/**/", "/to/", "/a/b/c", "/a/b/c"); + wildcardRuleTestHelper("/**/", "/to/", "/a/b/c/", "/to/"); + wildcardRuleTestHelper("**.html", "/to/", "/a/b/c/sldwe.html", "/to/"); + wildcardRuleTestHelper("*.html", "/to/", "/a/b/c/sldwe.html", "/a/b/c/sldwe.html"); + wildcardRuleTestHelper("/a/b/c/*.html", "/to/", "/a/b/c/sldwe.html", "/to/"); + } + + + public void testRuleWildcard2() throws IOException, ServletException, InvocationTargetException { + wildcardRuleTestHelper("/*.h", "/$1", "/a.h", "/a"); + wildcardRuleTestHelper("/**", "/d/$1", "/a/b/c", "/d/a/b/c"); + // test same with conds + wildcardRuleTestHelper("/*/a/*/aa", "/a/$2$1", "/w/a/c/aa", "/a/cw"); + } + + + public void testRuleWildcardCond() throws IOException, ServletException, InvocationTargetException { + MockRequest request = new MockRequest("/from"); + + request.setServerName("dev.googil.com"); + ruleWildcardCondHelper("server-name", "dev*", request); + + request.setContentType("image/jpeg"); + ruleWildcardCondHelper("content-type", "image/*", request); + + request.setContextPath("/a/b/c"); + ruleWildcardCondHelper("context-path", "/a/**", request); + + } + + + public void ruleWildcardCondHelper(String type, String value, MockRequest request) throws IOException, ServletException, InvocationTargetException { + Condition condition = new Condition(); + condition.setType(type); + condition.setValue(value); + + NormalRule rule = new NormalRule(); + rule.setFrom("/from"); + rule.setMatchType(" wildcard "); + rule.setTo("/to"); + rule.addCondition(condition); + rule.initialise(null); + + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals("/to", rewrittenUrl == null ? "/from" : rewrittenUrl.getTarget()); + + } + + public void wildcardRuleTestHelper(String from, String to, String req, String assertEq) + throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setFrom(from); + rule.setMatchType(" wildcard "); + rule.setTo(to); + rule.initialise(null); + MockRequest request = new MockRequest(req); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertEquals(assertEq, rewrittenUrl == null ? req : rewrittenUrl.getTarget()); + } + + + public void testRuleNoFrom() throws IOException, ServletException, InvocationTargetException { + NormalRule rule = new NormalRule(); + rule.setTo("to"); + Condition condition = new Condition(); + condition.setType("port"); + condition.setValue("90"); + rule.addCondition(condition); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + request.setServerPort(88); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull("should not be rewritten", rewrittenUrl); + + request.setServerPort(90); + RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); + assertNotNull("should be rewritten", rewrittenUrl2); + } + + public void testConditionAndSet() throws IOException, ServletException, InvocationTargetException { + Condition condition = new Condition(); + condition.setType("header"); + condition.setName("user-agent"); + condition.setValue("iexplore"); + + SetAttribute s = new SetAttribute(); + s.setType("request"); + s.setName("browser"); + s.setValue("ie"); + + NormalRule rule = new NormalRule(); + rule.addCondition(condition); + rule.addSetAttribute(s); + rule.initialise(null); + + MockRequest request = new MockRequest("from"); + request.setHeader("user-agent", "firefox"); + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull("should not be rewritten", rewrittenUrl); + assertNull(request.getAttribute("browser")); + + request.setHeader("user-agent", "iexplore"); + RewrittenUrl rewrittenUrl2 = rule.matches(request.getRequestURI(), request, response); + assertNull("should not be rewritten", rewrittenUrl2); + assertEquals("ie", request.getAttribute("browser")); + } + + public void testForum20080613() throws InvocationTargetException, IOException, ServletException { + NormalRule rule = new NormalRule(); + rule.setFrom("^/[^/]+/(.+)-S_[0-9]+\\.html$"); + rule.setTo("/liste/query/${replace:$1:-:+}/"); + rule.initialise(null); + MockRequest request = new MockRequest("/ab/as-as-S_12.html"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + + assertEquals("forward should be default type", "forward", rule.getToType()); + assertEquals("/liste/query/as+as/", rewrittenUrl.getTarget()); + assertTrue("Should be a forward", rewrittenUrl.isForward()); + } + + + public void testContext() throws InvocationTargetException, IOException, ServletException { + NormalRule rule = new NormalRule(); + rule.setFrom("^/goanothercontext/"); + rule.setTo("/other/"); + rule.setToContextStr("othercontext"); + rule.initialise(new MockServletContext()); + MockRequest request = new MockRequest("/goanothercontext/aaa.html"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + + assertEquals("forward should be default type", "forward", rule.getToType()); + assertEquals("/other/aaa.html", rewrittenUrl.getTarget()); + assertNotNull("Should be not empty", rewrittenUrl.getTargetContext()); + } + + public void testFilename() throws InvocationTargetException, IOException, ServletException { + NormalRule rule = new NormalRule(); + rule.setTo("/found-the-file"); + Condition condition = new Condition(); + condition.setType("request-filename"); + condition.setOperator("isfile"); + rule.addCondition(condition); + rule.initialise(new MockServletContext()); + MockRequest request = new MockRequest("/conf-test1.xml"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("/found-the-file", rewrittenUrl.getTarget()); + } + + public void testEncodedFilename() throws InvocationTargetException, IOException, ServletException { + NormalRule rule = new NormalRule(); + rule.setTo("/found-the-file"); + Condition condition = new Condition(); + condition.setType("request-filename"); + condition.setOperator("isfile"); + rule.addCondition(condition); + rule.initialise(new MockServletContext()); + MockRequest request = new MockRequest("/conf%2Dtest1.xml"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("/found-the-file", rewrittenUrl.getTarget()); + } + + public void testNotFilename() throws InvocationTargetException, IOException, ServletException { + NormalRule rule = new NormalRule(); + rule.setTo("/not-found-the-file"); + Condition condition = new Condition(); + condition.setType("request-filename"); + condition.setOperator("notfile"); + rule.addCondition(condition); + rule.initialise(new MockServletContext()); + MockRequest request = new MockRequest("/AAAconf-test1.xml"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("/not-found-the-file", rewrittenUrl.getTarget()); + } + + public void testDirectory() throws InvocationTargetException, IOException, ServletException { + NormalRule rule = new NormalRule(); + rule.setTo("/found-the-dir"); + Condition condition = new Condition(); + condition.setType("request-filename"); + condition.setOperator("isdir"); + rule.addCondition(condition); + rule.initialise(new MockServletContext()); + MockRequest request = new MockRequest("/utils/"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("/found-the-dir", rewrittenUrl.getTarget()); + } + + public void testNotDirectory() throws InvocationTargetException, IOException, ServletException { + NormalRule rule = new NormalRule(); + rule.setTo("/not-found-the-dir"); + Condition condition = new Condition(); + condition.setType("request-filename"); + condition.setOperator("notdir"); + rule.addCondition(condition); + rule.initialise(new MockServletContext()); + MockRequest request = new MockRequest("/utAAAils/"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("/not-found-the-dir", rewrittenUrl.getTarget()); + } + + public void testIssue116() throws InvocationTargetException, IOException, ServletException { + NormalRule rule = new NormalRule(); + rule.setFrom("^/robots\\.txt$"); + rule.setTo("/en/robots.txt"); + rule.setToType("permanent-redirect"); + rule.setToLast("true"); + rule.setQueryStringAppend("true"); + rule.initialise(new MockServletContext()); + MockRequest request = new MockRequest("/robots.txt"); + request.setQueryString("param1=value1¶m2=value2"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("/en/robots.txt?param1=value1¶m2=value2", rewrittenUrl.getTarget()); + } + + public void testRegexIssueIssue() throws InvocationTargetException, IOException, ServletException { + NormalRule rule = new NormalRule(); + rule.setFrom(".*"); + rule.setTo("robots.txt"); + rule.setToType("permanent-redirect"); + rule.setToLast("true"); + rule.setQueryStringAppend("true"); + rule.initialise(new MockServletContext()); + MockRequest request = new MockRequest("/oddness"); + NormalRewrittenUrl rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("robots.txt", rewrittenUrl.getTarget()); + + rule.setFrom(".+"); + rule.setTo("robots.txt"); + rule.setToType("permanent-redirect"); + rule.setToLast("true"); + rule.setQueryStringAppend("true"); + rule.initialise(new MockServletContext()); + request = new MockRequest("/oddness"); + rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("robots.txt", rewrittenUrl.getTarget()); + + rule.setFrom(".?"); + rule.setTo("robots.txt"); + rule.setToType("permanent-redirect"); + rule.setToLast("true"); + rule.setQueryStringAppend("true"); + rule.initialise(new MockServletContext()); + request = new MockRequest("/oddness"); + rewrittenUrl = (NormalRewrittenUrl) rule.matches(request.getRequestURI(), request, response); + assertEquals("robots.txtoddness", rewrittenUrl.getTarget()); + + } +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/RunTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/RunTest.java index c233a932..a7272fc1 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/RunTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/RunTest.java @@ -1,362 +1,362 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.testhelper.MockRequest; -import org.tuckey.web.testhelper.MockResponse; -import org.tuckey.web.testhelper.MockServletContext; -import org.tuckey.web.testhelper.MockFilterChain; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.test.TestRunObj; - -import jakarta.servlet.ServletException; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; - - -/** - * @author Paul Tuckey - * @version $Revision: 40 $ $Date: 2006-10-27 15:12:37 +1300 (Fri, 27 Oct 2006) $ - */ -public class RunTest extends TestCase { - - MockResponse response; - MockRequest request; - MockServletContext servletContext; - - public void setUp() { - Log.setLevel("DEBUG"); - response = new MockResponse(); - request = new MockRequest(); - servletContext = new MockServletContext(); - TestRunObj.resetTestFlags(); - } - - public void testRun01() throws IllegalAccessException, InvocationTargetException, InstantiationException, IOException, ServletException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.initialise(servletContext); - assertTrue("Should be a initialised " + run.getError(), run.isValid()); - assertTrue("Should be created now", TestRunObj.getCreatedCount() == 1); - assertTrue("Should be inited now", TestRunObj.isInitCalled()); - run.execute(request, response, null, null); - assertTrue("Should be invoked", TestRunObj.isRunCalled()); - assertTrue("Should not have been created again", TestRunObj.getCreatedCount() == 1); - assertFalse("Should not be destroyed", TestRunObj.isDestroyCalled()); - run.destroy(); - assertTrue("Should be destroyed", TestRunObj.isDestroyCalled()); - } - - public void testRunBadObj() throws IllegalAccessException, InvocationTargetException, InstantiationException, IOException, ServletException { - Run run = new Run(); - run.setClassStr("this.is.an.not.found.Class"); - run.initialise(servletContext); - assertFalse("Should not be initialised " + run.getError(), run.isValid()); - run.execute(request, response, null, null); - // Should not error just do nothing - } - - public void testRunBadMethod() throws IOException, ServletException, InvocationTargetException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setMethodStr("badMethod"); - run.initialise(servletContext); - assertFalse("Should not be initialised " + run.getError(), run.isValid()); - run.execute(request, response, null, null); - // Should not error just do nothing - } - - public void testRunThatReturns() throws IOException, ServletException, InvocationTargetException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setMethodStr("runThatReturns"); - run.initialise(servletContext); - assertTrue("Should be initialised " + run.getError(), run.isValid()); - run.execute(request, response, null, null); - // Should not error just do nothing - } - - public void testRunNoParams() throws IOException, ServletException, InvocationTargetException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setMethodStr("runWithNoParams()"); - run.initialise(servletContext); - assertTrue("Should be initialised " + run.getError(), run.isValid()); - run.execute(request, response, null, null); - // Should not error just do nothing - assertEquals("[no params]", TestRunObj.getParamStr()); - } - - public void testRunCustomMethod() throws IOException, ServletException, InvocationTargetException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setMethodStr("nonDefaultRun"); - run.initialise(servletContext); - assertTrue("Should be initialised " + run.getError(), run.isValid()); - run.execute(request, response, null, null); - assertTrue("Should be invoked", TestRunObj.isNonDefaultRunCalled()); - // Should not error just do nothing - } - - - public void testRunMethodParams() throws IOException, ServletException, InvocationTargetException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - // run.setMethodStr("runWithParam( int, String, d, long, req, res )"); - run.setMethodStr("runWithParam( int )"); - run.initialise(servletContext); - assertTrue("Should be initialised " + run.getError(), run.isValid()); - run.execute(request, response, new Object[]{"99"}, null ); - assertEquals("Should be invoked", "99", TestRunObj.getParamStr()); - // Should not error just do nothing - } - - public void testRunMethodParamNamed() throws IOException, ServletException, InvocationTargetException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - // run.setMethodStr("runWithParam( int, String, d, long, req, res )"); - run.setMethodStr("runWithParam( int id )"); - run.initialise(servletContext); - assertTrue("Should be initialised " + run.getError(), run.isValid()); - request.setParameter("id", "99"); - run.execute(request, response, null, null); - assertEquals("Should be invoked", "99", TestRunObj.getParamStr()); - // Should not error just do nothing - } - - public void testRunWithChainParam() throws IOException, ServletException, InvocationTargetException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - // run.setMethodStr("runWithParam( int, String, d, long, req, res )"); - run.setMethodStr("runWithChainParam( req, res, chain )"); - run.initialise(servletContext); - assertTrue("Should be initialised " + run.getError(), run.isValid()); - MockFilterChain chain = new MockFilterChain(); - - run.execute(request, response, null, chain ); - assertEquals("Should have invoked once only", 1, chain.getInvocationCount()); - assertTrue(run.isFilter()); - // Should not error just do nothing - } - - public void testParamsPrimitive() throws Exception { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setMethodStr("runWithPrimitiveParam(int, char , double, float,short, byte , boolean , String)"); - run.initialise(servletContext); - assertTrue("Should be initialised " + run.getError(), run.isValid()); - - assertEquals("runWithPrimitiveParam(int, char, double, float, short, byte, boolean, java.lang.String)", run.getMethodSignature()); - - // check null's - run.execute(request, response, null, null); - assertEquals("0,\u0000,0.0,0.0,0,0,false,null", TestRunObj.getParamStr()); - - // check values - Object[] args = {"12", "xyz", "11", "11.58", "2", "1", "true", "abcd"}; - run.execute(request, response, args, null); - assertEquals("12,x,11.0,11.58,2,1,true,abcd", TestRunObj.getParamStr()); - - } - - - public void testParamsObj() throws Exception { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setMethodStr("runWithObjParam(Integer , Character , Double , Float , Short , Byte , Boolean , String )"); - run.initialise(servletContext); - assertTrue("Should be initialised " + run.getError(), run.isValid()); - - assertEquals("runWithObjParam(java.lang.Integer, java.lang.Character, java.lang.Double, java.lang.Float, " + - "java.lang.Short, java.lang.Byte, java.lang.Boolean, java.lang.String)", run.getMethodSignature()); - - // check null's - run.execute(request, response, null, null); - assertEquals("null,null,null,null,null,null,null,null", TestRunObj.getParamStr()); - - // check values - Object[] args = {"12", "xyz", "11", "11.58", "2", "1", "true", "abcd"}; - run.execute(request, response, args, null); - assertEquals("12,x,11.0,11.58,2,1,true,abcd", TestRunObj.getParamStr()); - - } - - - private Throwable doExceptionRun(String methodName) { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setMethodStr(methodName); - run.initialise(servletContext); - assertTrue("Should be initialised, but: " + run.getError(), run.isValid()); - - Throwable throwableViaRun = null; - - System.out.println("this..."); - try { - run.execute(request, response, null, null); - } catch (Throwable t) { - throwableViaRun = t; - t.printStackTrace(System.out); - } - //noinspection ConstantConditions - return throwableViaRun.getCause(); - } - - public void testRunExceptionMethod() { - Throwable throwableViaRun = doExceptionRun("runNullPointerException"); - Throwable throwableRaw = null; - System.out.println("should look the same as this..."); - try { - new TestRunObj().runNullPointerException(null, null); - } catch (Throwable t) { - throwableRaw = t; - t.printStackTrace(System.out); - } - //noinspection ConstantConditions - assertEquals(throwableRaw.toString(), throwableViaRun.toString()); - } - - public void testRunServletExceptionMethod() { - Throwable throwableViaRun = doExceptionRun("runServletException"); - Throwable throwableRaw = null; - System.out.println("should look the same as this..."); - TestRunObj testRunObj = new TestRunObj(); - try { - testRunObj.runServletException(null, null); - } catch (Throwable t) { - throwableRaw = t; - t.printStackTrace(System.out); - } - //noinspection ConstantConditions - assertEquals(throwableRaw.toString(), throwableViaRun.toString()); - } - - public void testRunCustomExceptionMethod() { - Throwable throwableViaRun = doExceptionRun("runCustomException"); - Throwable throwableRaw = null; - System.out.println("should look the same as this..."); - TestRunObj testRunObj = new TestRunObj(); - try { - testRunObj.runCustomException(null, null); - } catch (Throwable t) { - throwableRaw = t; - t.printStackTrace(System.out); - } - //noinspection ConstantConditions - assertEquals(throwableRaw.toString(), throwableViaRun.toString()); - } - - public void testRunIOExceptionMethod() { - Throwable throwableViaRun = doExceptionRun("runIOException"); - Throwable throwableRaw = null; - System.out.println("should look the same as this..."); - TestRunObj testRunObj = new TestRunObj(); - try { - testRunObj.runIOException(null, null); - } catch (Throwable t) { - throwableRaw = t; - t.printStackTrace(System.out); - } - //noinspection ConstantConditions - assertEquals(throwableRaw.toString(), throwableViaRun.toString()); - } - - public void testRunRuntimeExceptionMethod() { - Throwable throwableViaRun = doExceptionRun("runRuntiumeException"); - Throwable throwableRaw = null; - System.out.println("should look the same as this..."); - TestRunObj testRunObj = new TestRunObj(); - try { - testRunObj.runRuntiumeException(null, null); - } catch (Throwable t) { - throwableRaw = t; - t.printStackTrace(System.out); - } - //noinspection ConstantConditions - assertEquals(throwableRaw.toString(), throwableViaRun.toString()); - } - - public void testRunPrivateMethod() throws IOException, ServletException, InvocationTargetException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setMethodStr("privateRun"); - run.initialise(servletContext); - assertFalse("Should not be initialised " + run.getError(), run.isValid()); - run.execute(request, response, null, null); - // Should not error just do nothing, check log msgs - } - - public void testRunNewEach() throws IOException, ServletException, InvocationTargetException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setNewEachTime(true); - run.initialise(servletContext); - assertTrue("Should not have been created yet", TestRunObj.getCreatedCount() == 0); - run.execute(request, response, null, null); - assertTrue("Should be created now", TestRunObj.getCreatedCount() == 1); - run.execute(request, response, null, null); - assertTrue("Should be created twice", TestRunObj.getCreatedCount() == 2); - assertTrue("Should be destroyed", TestRunObj.isDestroyCalled()); - } - - public void testInitParams() { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.addInitParam("horse", "golden"); - run.addInitParam("debs", "nightout"); - run.initialise(servletContext); - assertEquals("golden", TestRunObj.getTestServletConfig().getInitParameter("horse")); - assertEquals("nightout", TestRunObj.getTestServletConfig().getInitParameter("debs")); - } - - - public void testRuleNoToWithRun() throws IOException, ServletException, InvocationTargetException { - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setMethodStr("run"); - NormalRule rule = new NormalRule(); - rule.setFrom("from"); - rule.addRun(run); - rule.initialise(null); - MockRequest request = new MockRequest("from"); - - RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); - assertNull(rewrittenUrl); - assertTrue(TestRunObj.isRunCalled()); - } - - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.testhelper.MockRequest; +import org.tuckey.web.testhelper.MockResponse; +import org.tuckey.web.testhelper.MockServletContext; +import org.tuckey.web.testhelper.MockFilterChain; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.test.TestRunObj; + +import jakarta.servlet.ServletException; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + + +/** + * @author Paul Tuckey + * @version $Revision: 40 $ $Date: 2006-10-27 15:12:37 +1300 (Fri, 27 Oct 2006) $ + */ +public class RunTest extends TestCase { + + MockResponse response; + MockRequest request; + MockServletContext servletContext; + + public void setUp() { + Log.setLevel("DEBUG"); + response = new MockResponse(); + request = new MockRequest(); + servletContext = new MockServletContext(); + TestRunObj.resetTestFlags(); + } + + public void testRun01() throws IllegalAccessException, InvocationTargetException, InstantiationException, IOException, ServletException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.initialise(servletContext); + assertTrue("Should be a initialised " + run.getError(), run.isValid()); + assertTrue("Should be created now", TestRunObj.getCreatedCount() == 1); + assertTrue("Should be inited now", TestRunObj.isInitCalled()); + run.execute(request, response, null, null); + assertTrue("Should be invoked", TestRunObj.isRunCalled()); + assertTrue("Should not have been created again", TestRunObj.getCreatedCount() == 1); + assertFalse("Should not be destroyed", TestRunObj.isDestroyCalled()); + run.destroy(); + assertTrue("Should be destroyed", TestRunObj.isDestroyCalled()); + } + + public void testRunBadObj() throws IllegalAccessException, InvocationTargetException, InstantiationException, IOException, ServletException { + Run run = new Run(); + run.setClassStr("this.is.an.not.found.Class"); + run.initialise(servletContext); + assertFalse("Should not be initialised " + run.getError(), run.isValid()); + run.execute(request, response, null, null); + // Should not error just do nothing + } + + public void testRunBadMethod() throws IOException, ServletException, InvocationTargetException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setMethodStr("badMethod"); + run.initialise(servletContext); + assertFalse("Should not be initialised " + run.getError(), run.isValid()); + run.execute(request, response, null, null); + // Should not error just do nothing + } + + public void testRunThatReturns() throws IOException, ServletException, InvocationTargetException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setMethodStr("runThatReturns"); + run.initialise(servletContext); + assertTrue("Should be initialised " + run.getError(), run.isValid()); + run.execute(request, response, null, null); + // Should not error just do nothing + } + + public void testRunNoParams() throws IOException, ServletException, InvocationTargetException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setMethodStr("runWithNoParams()"); + run.initialise(servletContext); + assertTrue("Should be initialised " + run.getError(), run.isValid()); + run.execute(request, response, null, null); + // Should not error just do nothing + assertEquals("[no params]", TestRunObj.getParamStr()); + } + + public void testRunCustomMethod() throws IOException, ServletException, InvocationTargetException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setMethodStr("nonDefaultRun"); + run.initialise(servletContext); + assertTrue("Should be initialised " + run.getError(), run.isValid()); + run.execute(request, response, null, null); + assertTrue("Should be invoked", TestRunObj.isNonDefaultRunCalled()); + // Should not error just do nothing + } + + + public void testRunMethodParams() throws IOException, ServletException, InvocationTargetException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + // run.setMethodStr("runWithParam( int, String, d, long, req, res )"); + run.setMethodStr("runWithParam( int )"); + run.initialise(servletContext); + assertTrue("Should be initialised " + run.getError(), run.isValid()); + run.execute(request, response, new Object[]{"99"}, null ); + assertEquals("Should be invoked", "99", TestRunObj.getParamStr()); + // Should not error just do nothing + } + + public void testRunMethodParamNamed() throws IOException, ServletException, InvocationTargetException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + // run.setMethodStr("runWithParam( int, String, d, long, req, res )"); + run.setMethodStr("runWithParam( int id )"); + run.initialise(servletContext); + assertTrue("Should be initialised " + run.getError(), run.isValid()); + request.setParameter("id", "99"); + run.execute(request, response, null, null); + assertEquals("Should be invoked", "99", TestRunObj.getParamStr()); + // Should not error just do nothing + } + + public void testRunWithChainParam() throws IOException, ServletException, InvocationTargetException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + // run.setMethodStr("runWithParam( int, String, d, long, req, res )"); + run.setMethodStr("runWithChainParam( req, res, chain )"); + run.initialise(servletContext); + assertTrue("Should be initialised " + run.getError(), run.isValid()); + MockFilterChain chain = new MockFilterChain(); + + run.execute(request, response, null, chain ); + assertEquals("Should have invoked once only", 1, chain.getInvocationCount()); + assertTrue(run.isFilter()); + // Should not error just do nothing + } + + public void testParamsPrimitive() throws Exception { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setMethodStr("runWithPrimitiveParam(int, char , double, float,short, byte , boolean , String)"); + run.initialise(servletContext); + assertTrue("Should be initialised " + run.getError(), run.isValid()); + + assertEquals("runWithPrimitiveParam(int, char, double, float, short, byte, boolean, java.lang.String)", run.getMethodSignature()); + + // check null's + run.execute(request, response, null, null); + assertEquals("0,\u0000,0.0,0.0,0,0,false,null", TestRunObj.getParamStr()); + + // check values + Object[] args = {"12", "xyz", "11", "11.58", "2", "1", "true", "abcd"}; + run.execute(request, response, args, null); + assertEquals("12,x,11.0,11.58,2,1,true,abcd", TestRunObj.getParamStr()); + + } + + + public void testParamsObj() throws Exception { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setMethodStr("runWithObjParam(Integer , Character , Double , Float , Short , Byte , Boolean , String )"); + run.initialise(servletContext); + assertTrue("Should be initialised " + run.getError(), run.isValid()); + + assertEquals("runWithObjParam(java.lang.Integer, java.lang.Character, java.lang.Double, java.lang.Float, " + + "java.lang.Short, java.lang.Byte, java.lang.Boolean, java.lang.String)", run.getMethodSignature()); + + // check null's + run.execute(request, response, null, null); + assertEquals("null,null,null,null,null,null,null,null", TestRunObj.getParamStr()); + + // check values + Object[] args = {"12", "xyz", "11", "11.58", "2", "1", "true", "abcd"}; + run.execute(request, response, args, null); + assertEquals("12,x,11.0,11.58,2,1,true,abcd", TestRunObj.getParamStr()); + + } + + + private Throwable doExceptionRun(String methodName) { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setMethodStr(methodName); + run.initialise(servletContext); + assertTrue("Should be initialised, but: " + run.getError(), run.isValid()); + + Throwable throwableViaRun = null; + + System.out.println("this..."); + try { + run.execute(request, response, null, null); + } catch (Throwable t) { + throwableViaRun = t; + t.printStackTrace(System.out); + } + //noinspection ConstantConditions + return throwableViaRun.getCause(); + } + + public void testRunExceptionMethod() { + Throwable throwableViaRun = doExceptionRun("runNullPointerException"); + Throwable throwableRaw = null; + System.out.println("should look the same as this..."); + try { + new TestRunObj().runNullPointerException(null, null); + } catch (Throwable t) { + throwableRaw = t; + t.printStackTrace(System.out); + } + //noinspection ConstantConditions + assertEquals(throwableRaw.toString(), throwableViaRun.toString()); + } + + public void testRunServletExceptionMethod() { + Throwable throwableViaRun = doExceptionRun("runServletException"); + Throwable throwableRaw = null; + System.out.println("should look the same as this..."); + TestRunObj testRunObj = new TestRunObj(); + try { + testRunObj.runServletException(null, null); + } catch (Throwable t) { + throwableRaw = t; + t.printStackTrace(System.out); + } + //noinspection ConstantConditions + assertEquals(throwableRaw.toString(), throwableViaRun.toString()); + } + + public void testRunCustomExceptionMethod() { + Throwable throwableViaRun = doExceptionRun("runCustomException"); + Throwable throwableRaw = null; + System.out.println("should look the same as this..."); + TestRunObj testRunObj = new TestRunObj(); + try { + testRunObj.runCustomException(null, null); + } catch (Throwable t) { + throwableRaw = t; + t.printStackTrace(System.out); + } + //noinspection ConstantConditions + assertEquals(throwableRaw.toString(), throwableViaRun.toString()); + } + + public void testRunIOExceptionMethod() { + Throwable throwableViaRun = doExceptionRun("runIOException"); + Throwable throwableRaw = null; + System.out.println("should look the same as this..."); + TestRunObj testRunObj = new TestRunObj(); + try { + testRunObj.runIOException(null, null); + } catch (Throwable t) { + throwableRaw = t; + t.printStackTrace(System.out); + } + //noinspection ConstantConditions + assertEquals(throwableRaw.toString(), throwableViaRun.toString()); + } + + public void testRunRuntimeExceptionMethod() { + Throwable throwableViaRun = doExceptionRun("runRuntiumeException"); + Throwable throwableRaw = null; + System.out.println("should look the same as this..."); + TestRunObj testRunObj = new TestRunObj(); + try { + testRunObj.runRuntiumeException(null, null); + } catch (Throwable t) { + throwableRaw = t; + t.printStackTrace(System.out); + } + //noinspection ConstantConditions + assertEquals(throwableRaw.toString(), throwableViaRun.toString()); + } + + public void testRunPrivateMethod() throws IOException, ServletException, InvocationTargetException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setMethodStr("privateRun"); + run.initialise(servletContext); + assertFalse("Should not be initialised " + run.getError(), run.isValid()); + run.execute(request, response, null, null); + // Should not error just do nothing, check log msgs + } + + public void testRunNewEach() throws IOException, ServletException, InvocationTargetException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setNewEachTime(true); + run.initialise(servletContext); + assertTrue("Should not have been created yet", TestRunObj.getCreatedCount() == 0); + run.execute(request, response, null, null); + assertTrue("Should be created now", TestRunObj.getCreatedCount() == 1); + run.execute(request, response, null, null); + assertTrue("Should be created twice", TestRunObj.getCreatedCount() == 2); + assertTrue("Should be destroyed", TestRunObj.isDestroyCalled()); + } + + public void testInitParams() { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.addInitParam("horse", "golden"); + run.addInitParam("debs", "nightout"); + run.initialise(servletContext); + assertEquals("golden", TestRunObj.getTestServletConfig().getInitParameter("horse")); + assertEquals("nightout", TestRunObj.getTestServletConfig().getInitParameter("debs")); + } + + + public void testRuleNoToWithRun() throws IOException, ServletException, InvocationTargetException { + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setMethodStr("run"); + NormalRule rule = new NormalRule(); + rule.setFrom("from"); + rule.addRun(run); + rule.initialise(null); + MockRequest request = new MockRequest("from"); + + RewrittenUrl rewrittenUrl = rule.matches(request.getRequestURI(), request, response); + assertNull(rewrittenUrl); + assertTrue(TestRunObj.isRunCalled()); + } + + +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/SetAttributeTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/SetAttributeTest.java index 43214e1f..6d79b71d 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/SetAttributeTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/SetAttributeTest.java @@ -1,233 +1,233 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.NumberUtils; -import org.tuckey.web.filters.urlrewrite.utils.RegexMatcher; -import org.tuckey.web.testhelper.MockRequest; -import org.tuckey.web.testhelper.MockResponse; - -import jakarta.servlet.http.Cookie; -import java.util.regex.Pattern; - -/** - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class SetAttributeTest extends TestCase { - - private RegexMatcher toMatcher; - - public void setUp() { - Log.setLevel("DEBUG"); - // Create a matcher to pass to execute - toMatcher = new RegexMatcher(Pattern.compile("^(.*)$").matcher("/query")); - toMatcher.find(); - } - - - public void testBasic() { - SetAttribute set = new SetAttribute(); - set.setName("blah"); - set.setValue("mercuryrev"); - MockRequest request = new MockRequest(); - MockResponse response = new MockResponse(); - - set.initialise(); - set.execute(null, toMatcher, request, response); - assertTrue(request.getAttribute("blah").equals("mercuryrev")); - - } - - public void testCaptureGroup() { - SetAttribute set = new SetAttribute(); - set.setName("blah"); - set.setValue("Capture group 1 is $1"); - MockRequest request = new MockRequest(); - MockResponse response = new MockResponse(); - - set.initialise(); - set.execute(null, toMatcher, request, response); - assertTrue(request.getAttribute("blah").equals("Capture group 1 is /query")); - } - - public void testVariable() { - SetAttribute set = new SetAttribute(); - set.setType("cookie"); - set.setName("v"); - set.setValue("%{parameter:v}"); - MockRequest request = new MockRequest(); - request.setParameter("v", "1234"); - MockResponse response = new MockResponse(); - - set.initialise(); - set.execute(null, toMatcher, request, response); - assertEquals("v", ((Cookie) response.getCookies().get(0)).getName()); - assertEquals("1234", ((Cookie) response.getCookies().get(0)).getValue()); - - } - - public void testVariableWithDollar() { - SetAttribute set = new SetAttribute(); - set.setName("v"); - set.setValue("%{parameter:v}"); - MockRequest request = new MockRequest(); - request.setParameter("v", "$2"); - MockResponse response = new MockResponse(); - - set.initialise(); - set.execute(null, toMatcher, request, response); - assertEquals("$2", request.getAttribute("v")); - - } - - public void testExpires() throws InterruptedException { - SetAttribute set = new SetAttribute(); - - assertEquals(1000 * 60 * 60 * 24, set.parseTimeValue("1 days")); - assertEquals(1000 * 60 * 60 * 24, set.parseTimeValue("1 day")); - assertEquals(1000 * 60 * 60 * 24, set.parseTimeValue(" 1 day ")); - assertEquals((1000 * 60 * 60 * 24) + 4000, set.parseTimeValue("1 day 4 seconds")); - assertEquals(Math.round(1000 * 60 * 60 * 24 * 365.25), set.parseTimeValue("1 year")); - - set.setType("expires"); - set.setValue("access plus 1 day 2 hours"); - MockRequest request = new MockRequest(); - MockResponse response = new MockResponse(); - set.initialise(); - - long oneDayPlusTwoHours = (1000 * 60 * 60 * 24) + (2 * 1000 * 60 * 60); - long before = System.currentTimeMillis() + oneDayPlusTwoHours; - Thread.sleep(100); - - set.execute(null, toMatcher, request, response); - - Thread.sleep(100); - long after = System.currentTimeMillis() + oneDayPlusTwoHours; - long expiresValue = NumberUtils.stringToLong(response.getHeader("Expires")); - assertTrue(expiresValue + " needs to be greater than " + before, expiresValue > before); - assertTrue(expiresValue + " needs to be less than " + after, expiresValue < after); - } - - public void testTypeStatus() { - SetAttribute set = new SetAttribute(); - set.setType("status"); - set.setValue("999"); - MockRequest request = new MockRequest(); - MockResponse response = new MockResponse(); - set.initialise(); - set.execute(null, toMatcher, request, response); - assertEquals(999, response.getStatus()); - } - - public void testTypeEmptyStr() { - SetAttribute set = new SetAttribute(); - set.setType("parameter"); - set.setName("version_id"); - set.setValue(null); - MockRequest request = new MockRequest(); - set.initialise(); - UrlRewriteWrappedResponse wrappedResponse = new UrlRewriteWrappedResponse(new MockResponse(), request, null); - set.execute(null, toMatcher, request, wrappedResponse); - - UrlRewriteWrappedRequest wrappedRequest = new UrlRewriteWrappedRequest(request, wrappedResponse.getOverridenRequestParameters(), null); - assertEquals(null, wrappedRequest.getParameter("version_id")); - } - - public void testTypeCookie() { - SetAttribute set = new SetAttribute(); - set.setType("cookie"); - set.setName("mycook"); - set.setValue("someval dasd:blah.com:89009:/ass"); - MockRequest request = new MockRequest(); - MockResponse response = new MockResponse(); - set.initialise(); - set.execute(null, toMatcher, request, response); - Cookie cookie = (Cookie) response.getCookies().get(0); - assertEquals("blah.com", cookie.getDomain()); - assertEquals(89009, cookie.getMaxAge()); - assertEquals("someval dasd", cookie.getValue()); - assertEquals("/ass", cookie.getPath()); - } - - public void testTypeLocale() { - SetAttribute set = new SetAttribute(); - set.setType("locale"); - set.setValue("en"); - assertTrue(set.initialise()); - - set.setValue("en-NZ"); - assertTrue(set.initialise()); - - set.setValue("en-NZ-slang"); - MockRequest request = new MockRequest(); - MockResponse response = new MockResponse(); - set.initialise(); - set.execute(null, toMatcher, request, response); - assertEquals("slang", response.getLocale().getVariant()); - } - - public void testSetParam() { - SetAttribute set = new SetAttribute(); - set.setName("blah"); - set.setType("parameter"); - set.setValue("Capture group 1 is $1"); - MockRequest request = new MockRequest(); - UrlRewriteWrappedResponse response = new UrlRewriteWrappedResponse(new MockResponse(), request, null); - - set.initialise(); - set.execute(null, toMatcher, request, response); - - UrlRewriteWrappedRequest wrappedRequest = new UrlRewriteWrappedRequest(request, response.getOverridenRequestParameters(), null); - assertEquals("Capture group 1 is /query", wrappedRequest.getParameter("blah")); - assertEquals("Capture group 1 is /query", wrappedRequest.getParameterValues("blah")[0]); - - } - - public void testSetMethod() { - SetAttribute set = new SetAttribute(); - set.setType("method"); - set.setValue("PUT"); - MockRequest request = new MockRequest(); - UrlRewriteWrappedResponse response = new UrlRewriteWrappedResponse(new MockResponse(), request, null); - - set.initialise(); - set.execute(null, toMatcher, request, response); - assertTrue(response.getOverridenMethod().equals("PUT")); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.NumberUtils; +import org.tuckey.web.filters.urlrewrite.utils.RegexMatcher; +import org.tuckey.web.testhelper.MockRequest; +import org.tuckey.web.testhelper.MockResponse; + +import jakarta.servlet.http.Cookie; +import java.util.regex.Pattern; + +/** + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class SetAttributeTest extends TestCase { + + private RegexMatcher toMatcher; + + public void setUp() { + Log.setLevel("DEBUG"); + // Create a matcher to pass to execute + toMatcher = new RegexMatcher(Pattern.compile("^(.*)$").matcher("/query")); + toMatcher.find(); + } + + + public void testBasic() { + SetAttribute set = new SetAttribute(); + set.setName("blah"); + set.setValue("mercuryrev"); + MockRequest request = new MockRequest(); + MockResponse response = new MockResponse(); + + set.initialise(); + set.execute(null, toMatcher, request, response); + assertTrue(request.getAttribute("blah").equals("mercuryrev")); + + } + + public void testCaptureGroup() { + SetAttribute set = new SetAttribute(); + set.setName("blah"); + set.setValue("Capture group 1 is $1"); + MockRequest request = new MockRequest(); + MockResponse response = new MockResponse(); + + set.initialise(); + set.execute(null, toMatcher, request, response); + assertTrue(request.getAttribute("blah").equals("Capture group 1 is /query")); + } + + public void testVariable() { + SetAttribute set = new SetAttribute(); + set.setType("cookie"); + set.setName("v"); + set.setValue("%{parameter:v}"); + MockRequest request = new MockRequest(); + request.setParameter("v", "1234"); + MockResponse response = new MockResponse(); + + set.initialise(); + set.execute(null, toMatcher, request, response); + assertEquals("v", ((Cookie) response.getCookies().get(0)).getName()); + assertEquals("1234", ((Cookie) response.getCookies().get(0)).getValue()); + + } + + public void testVariableWithDollar() { + SetAttribute set = new SetAttribute(); + set.setName("v"); + set.setValue("%{parameter:v}"); + MockRequest request = new MockRequest(); + request.setParameter("v", "$2"); + MockResponse response = new MockResponse(); + + set.initialise(); + set.execute(null, toMatcher, request, response); + assertEquals("$2", request.getAttribute("v")); + + } + + public void testExpires() throws InterruptedException { + SetAttribute set = new SetAttribute(); + + assertEquals(1000 * 60 * 60 * 24, set.parseTimeValue("1 days")); + assertEquals(1000 * 60 * 60 * 24, set.parseTimeValue("1 day")); + assertEquals(1000 * 60 * 60 * 24, set.parseTimeValue(" 1 day ")); + assertEquals((1000 * 60 * 60 * 24) + 4000, set.parseTimeValue("1 day 4 seconds")); + assertEquals(Math.round(1000 * 60 * 60 * 24 * 365.25), set.parseTimeValue("1 year")); + + set.setType("expires"); + set.setValue("access plus 1 day 2 hours"); + MockRequest request = new MockRequest(); + MockResponse response = new MockResponse(); + set.initialise(); + + long oneDayPlusTwoHours = (1000 * 60 * 60 * 24) + (2 * 1000 * 60 * 60); + long before = System.currentTimeMillis() + oneDayPlusTwoHours; + Thread.sleep(100); + + set.execute(null, toMatcher, request, response); + + Thread.sleep(100); + long after = System.currentTimeMillis() + oneDayPlusTwoHours; + long expiresValue = NumberUtils.stringToLong(response.getHeader("Expires")); + assertTrue(expiresValue + " needs to be greater than " + before, expiresValue > before); + assertTrue(expiresValue + " needs to be less than " + after, expiresValue < after); + } + + public void testTypeStatus() { + SetAttribute set = new SetAttribute(); + set.setType("status"); + set.setValue("999"); + MockRequest request = new MockRequest(); + MockResponse response = new MockResponse(); + set.initialise(); + set.execute(null, toMatcher, request, response); + assertEquals(999, response.getStatus()); + } + + public void testTypeEmptyStr() { + SetAttribute set = new SetAttribute(); + set.setType("parameter"); + set.setName("version_id"); + set.setValue(null); + MockRequest request = new MockRequest(); + set.initialise(); + UrlRewriteWrappedResponse wrappedResponse = new UrlRewriteWrappedResponse(new MockResponse(), request, null); + set.execute(null, toMatcher, request, wrappedResponse); + + UrlRewriteWrappedRequest wrappedRequest = new UrlRewriteWrappedRequest(request, wrappedResponse.getOverridenRequestParameters(), null); + assertEquals(null, wrappedRequest.getParameter("version_id")); + } + + public void testTypeCookie() { + SetAttribute set = new SetAttribute(); + set.setType("cookie"); + set.setName("mycook"); + set.setValue("someval dasd:blah.com:89009:/ass"); + MockRequest request = new MockRequest(); + MockResponse response = new MockResponse(); + set.initialise(); + set.execute(null, toMatcher, request, response); + Cookie cookie = (Cookie) response.getCookies().get(0); + assertEquals("blah.com", cookie.getDomain()); + assertEquals(89009, cookie.getMaxAge()); + assertEquals("someval dasd", cookie.getValue()); + assertEquals("/ass", cookie.getPath()); + } + + public void testTypeLocale() { + SetAttribute set = new SetAttribute(); + set.setType("locale"); + set.setValue("en"); + assertTrue(set.initialise()); + + set.setValue("en-NZ"); + assertTrue(set.initialise()); + + set.setValue("en-NZ-slang"); + MockRequest request = new MockRequest(); + MockResponse response = new MockResponse(); + set.initialise(); + set.execute(null, toMatcher, request, response); + assertEquals("slang", response.getLocale().getVariant()); + } + + public void testSetParam() { + SetAttribute set = new SetAttribute(); + set.setName("blah"); + set.setType("parameter"); + set.setValue("Capture group 1 is $1"); + MockRequest request = new MockRequest(); + UrlRewriteWrappedResponse response = new UrlRewriteWrappedResponse(new MockResponse(), request, null); + + set.initialise(); + set.execute(null, toMatcher, request, response); + + UrlRewriteWrappedRequest wrappedRequest = new UrlRewriteWrappedRequest(request, response.getOverridenRequestParameters(), null); + assertEquals("Capture group 1 is /query", wrappedRequest.getParameter("blah")); + assertEquals("Capture group 1 is /query", wrappedRequest.getParameterValues("blah")[0]); + + } + + public void testSetMethod() { + SetAttribute set = new SetAttribute(); + set.setType("method"); + set.setValue("PUT"); + MockRequest request = new MockRequest(); + UrlRewriteWrappedResponse response = new UrlRewriteWrappedResponse(new MockResponse(), request, null); + + set.initialise(); + set.execute(null, toMatcher, request, response); + assertTrue(response.getOverridenMethod().equals("PUT")); + } + +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/StatusTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/StatusTest.java index a48ce56c..157a9c33 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/StatusTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/StatusTest.java @@ -1,85 +1,85 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.testhelper.MockRequest; -import org.tuckey.web.testhelper.MockServletContext; -import org.tuckey.web.filters.urlrewrite.utils.Log; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class StatusTest extends TestCase { - - public void setUp() { - Log.setLevel("DEBUG"); - } - - - public void testSimple() throws IOException { - - MockRequest hsRequest = new MockRequest(); - InputStream is = ConfTest.class.getResourceAsStream(ConfTest.BASE_XML_PATH + "conf-test1.xml"); - Conf conf = new Conf(new MockServletContext(), is, "conf-test1.xml", "conf-test1.xml"); - assertTrue(conf.getErrors().toString(), conf.isOk()); - UrlRewriter urlRewriter = new UrlRewriter(conf); - UrlRewriteFilter urlRewriteFilter = new UrlRewriteFilter(); - - Status status = new Status(urlRewriter.getConf(), urlRewriteFilter); - status.displayStatusInContainer(hsRequest); - assertNotNull(status.getBuffer()); - assertFalse(status.getBuffer().length() == 0); - - // save it so we can view it - File buildDir = new File("build"); - if ( ! buildDir.exists() ) buildDir.mkdir(); - BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(buildDir, "status.html"))); - try { - bos.write(status.getBuffer().toString().getBytes()); - } finally { - bos.close(); - } - - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.testhelper.MockRequest; +import org.tuckey.web.testhelper.MockServletContext; +import org.tuckey.web.filters.urlrewrite.utils.Log; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class StatusTest extends TestCase { + + public void setUp() { + Log.setLevel("DEBUG"); + } + + + public void testSimple() throws IOException { + + MockRequest hsRequest = new MockRequest(); + InputStream is = ConfTest.class.getResourceAsStream(ConfTest.BASE_XML_PATH + "conf-test1.xml"); + Conf conf = new Conf(new MockServletContext(), is, "conf-test1.xml", "conf-test1.xml"); + assertTrue(conf.getErrors().toString(), conf.isOk()); + UrlRewriter urlRewriter = new UrlRewriter(conf); + UrlRewriteFilter urlRewriteFilter = new UrlRewriteFilter(); + + Status status = new Status(urlRewriter.getConf(), urlRewriteFilter); + status.displayStatusInContainer(hsRequest); + assertNotNull(status.getBuffer()); + assertFalse(status.getBuffer().length() == 0); + + // save it so we can view it + File buildDir = new File("build"); + if ( ! buildDir.exists() ) buildDir.mkdir(); + BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(buildDir, "status.html"))); + try { + bos.write(status.getBuffer().toString().getBytes()); + } finally { + bos.close(); + } + + } + +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/TestRewriteMatch.java b/src/test/java/org/tuckey/web/filters/urlrewrite/TestRewriteMatch.java index f42e1735..95255c79 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/TestRewriteMatch.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/TestRewriteMatch.java @@ -1,50 +1,50 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.ServletException; -import java.io.IOException; - -public class TestRewriteMatch extends RewriteMatch { - - public boolean execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException { - // - return true; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import java.io.IOException; + +public class TestRewriteMatch extends RewriteMatch { + + public boolean execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException { + // + return true; + } +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/TestRuleObj.java b/src/test/java/org/tuckey/web/filters/urlrewrite/TestRuleObj.java index 712d8911..aef0a02c 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/TestRuleObj.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/TestRuleObj.java @@ -1,51 +1,51 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteRule; -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -public class TestRuleObj extends RewriteRule { - public RewriteMatch matches(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { - return new TestRewriteMatch(); - } - - public RewriteMatch trial(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { - return new TestRewriteMatch(); - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteRule; +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +public class TestRuleObj extends RewriteRule { + public RewriteMatch matches(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { + return new TestRewriteMatch(); + } + + public RewriteMatch trial(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { + return new TestRewriteMatch(); + } +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/TestServlet.java b/src/test/java/org/tuckey/web/filters/urlrewrite/TestServlet.java index 610f44b5..86462a58 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/TestServlet.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/TestServlet.java @@ -1,128 +1,128 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServlet; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; - -/** - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class TestServlet extends HttpServlet { - private static final long serialVersionUID = 8797402387550458476L; - - private static boolean runCalled; - private static boolean destroyCalled; - private static boolean initCalled; - private static boolean nonDefaultRunCalled; - private static ServletConfig servletConfig; - - private static int createdCount = 0; - - public TestServlet() { - createdCount++; - } - - public void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - PrintWriter sos = httpServletResponse.getWriter(); - - sos.print("this is doGet on " + TestServlet.class.getName()); - sos.close(); - runCalled = true; - } - - public void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - PrintWriter sos = httpServletResponse.getWriter(); - - sos.print("this is doPost on " + TestServlet.class.getName()); - sos.close(); - runCalled = true; - } - - public void nonDefaultRun(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - nonDefaultRunCalled = true; - } - - public void destroy() { - destroyCalled = true; - } - - public void init(ServletConfig config) throws ServletException { - servletConfig = config; - initCalled = true; - } - - public static boolean isRunCalled() { - return runCalled; - } - - public static int getCreatedCount() { - return createdCount; - } - - public static void resetTestFlags() { - createdCount = 0; - runCalled = false; - destroyCalled = false; - initCalled = false; - nonDefaultRunCalled = false; - servletConfig = null; - } - - public static ServletConfig getTestServletConfig() { - return servletConfig; - } - - public static boolean isDestroyCalled() { - return destroyCalled; - } - - public static boolean isInitCalled() { - return initCalled; - } - - public static boolean isNonDefaultRunCalled() { - return nonDefaultRunCalled; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class TestServlet extends HttpServlet { + private static final long serialVersionUID = 8797402387550458476L; + + private static boolean runCalled; + private static boolean destroyCalled; + private static boolean initCalled; + private static boolean nonDefaultRunCalled; + private static ServletConfig servletConfig; + + private static int createdCount = 0; + + public TestServlet() { + createdCount++; + } + + public void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + PrintWriter sos = httpServletResponse.getWriter(); + + sos.print("this is doGet on " + TestServlet.class.getName()); + sos.close(); + runCalled = true; + } + + public void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + PrintWriter sos = httpServletResponse.getWriter(); + + sos.print("this is doPost on " + TestServlet.class.getName()); + sos.close(); + runCalled = true; + } + + public void nonDefaultRun(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + nonDefaultRunCalled = true; + } + + public void destroy() { + destroyCalled = true; + } + + public void init(ServletConfig config) throws ServletException { + servletConfig = config; + initCalled = true; + } + + public static boolean isRunCalled() { + return runCalled; + } + + public static int getCreatedCount() { + return createdCount; + } + + public static void resetTestFlags() { + createdCount = 0; + runCalled = false; + destroyCalled = false; + initCalled = false; + nonDefaultRunCalled = false; + servletConfig = null; + } + + public static ServletConfig getTestServletConfig() { + return servletConfig; + } + + public static boolean isDestroyCalled() { + return destroyCalled; + } + + public static boolean isInitCalled() { + return initCalled; + } + + public static boolean isNonDefaultRunCalled() { + return nonDefaultRunCalled; + } +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlDecoderTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlDecoderTest.java index 0405813c..914a73db 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlDecoderTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlDecoderTest.java @@ -1,92 +1,92 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.URLDecoder; - -import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; -import java.net.URLEncoder; - -/** - */ -public class UrlDecoderTest extends TestCase { - - final static String AllChars = "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?"; - - public void setUp() { - Log.setLevel("DEBUG"); - } - - public void testPathSpaces() throws URISyntaxException { - String encoded = "/foo%20bar/foo+bar"; - String decoded = URLDecoder.decodeURL(encoded, "UTF-8"); - assertEquals("/foo bar/foo+bar", decoded); - } - - public void testQuerySpacesFixed() throws URISyntaxException, UnsupportedEncodingException { - String encoded = URLEncoder.encode("/foo bar/foo+bar", "UTF-8"); - String decoded = URLDecoder.decodeURL(encoded, "UTF-8"); - assertEquals("/foo+bar/foo+bar", decoded); - } - - public void testQueryEncodingUTF8() throws URISyntaxException, UnsupportedEncodingException { - String encoded = "/?foo=" + URLEncoder.encode(AllChars, "UTF-8"); - String decoded = URLDecoder.decodeURL(encoded, "UTF-8"); - assertEquals("/?foo=" + AllChars, decoded); - } - - public void testQueryEncodingLatin1() throws URISyntaxException, UnsupportedEncodingException { - String encoded = "/?foo=" + URLEncoder.encode(AllChars, "ISO-8859-1"); - String decoded = URLDecoder.decodeURL(encoded, "ISO-8859-1"); - assertEquals("/?foo=" + AllChars, decoded); - } - - public void testRealEncoding() throws URISyntaxException, UnsupportedEncodingException { - String katakana = "/???????????????" + - "????????????????" + - "????????????????" + - "????????????????" + - "????????????????" + - "????????????????"; - String encoded = URLEncoder.encode(katakana, "UTF-8"); - String decoded = URLDecoder.decodeURL(encoded, "UTF-8"); - assertEquals(katakana, decoded); - } - -} - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.URLDecoder; + +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.net.URLEncoder; + +/** + */ +public class UrlDecoderTest extends TestCase { + + final static String AllChars = "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?"; + + public void setUp() { + Log.setLevel("DEBUG"); + } + + public void testPathSpaces() throws URISyntaxException { + String encoded = "/foo%20bar/foo+bar"; + String decoded = URLDecoder.decodeURL(encoded, "UTF-8"); + assertEquals("/foo bar/foo+bar", decoded); + } + + public void testQuerySpacesFixed() throws URISyntaxException, UnsupportedEncodingException { + String encoded = URLEncoder.encode("/foo bar/foo+bar", "UTF-8"); + String decoded = URLDecoder.decodeURL(encoded, "UTF-8"); + assertEquals("/foo+bar/foo+bar", decoded); + } + + public void testQueryEncodingUTF8() throws URISyntaxException, UnsupportedEncodingException { + String encoded = "/?foo=" + URLEncoder.encode(AllChars, "UTF-8"); + String decoded = URLDecoder.decodeURL(encoded, "UTF-8"); + assertEquals("/?foo=" + AllChars, decoded); + } + + public void testQueryEncodingLatin1() throws URISyntaxException, UnsupportedEncodingException { + String encoded = "/?foo=" + URLEncoder.encode(AllChars, "ISO-8859-1"); + String decoded = URLDecoder.decodeURL(encoded, "ISO-8859-1"); + assertEquals("/?foo=" + AllChars, decoded); + } + + public void testRealEncoding() throws URISyntaxException, UnsupportedEncodingException { + String katakana = "/???????????????" + + "????????????????" + + "????????????????" + + "????????????????" + + "????????????????" + + "????????????????"; + String encoded = URLEncoder.encode(katakana, "UTF-8"); + String decoded = URLDecoder.decodeURL(encoded, "UTF-8"); + assertEquals(katakana, decoded); + } + +} + diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilterTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilterTest.java index 087c622a..2262c130 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilterTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilterTest.java @@ -1,80 +1,80 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.testhelper.MockFilterConfig; -import org.tuckey.web.testhelper.MockServletContext; -import org.tuckey.web.filters.urlrewrite.utils.Log; - -import jakarta.servlet.ServletException; - -/** - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class UrlRewriteFilterTest extends TestCase { - - private UrlRewriteFilter filter; - - public void setUp() { - Log.setLevel("stdout:TRACE"); - filter = new UrlRewriteFilter(); - Log.setLevel("stdout:TRACE"); - } - - public void tearDown() { - filter.destroy(); - filter = null; - } - - public void testInit() throws ServletException { - filter.init(null); - filter.init(new MockFilterConfig()); - } - - public void testVersion() throws ServletException { - String ver = UrlRewriteFilter.getFullVersionString(); - System.out.println(ver); - assertTrue("Ver bad " + ver, ver.matches("[0-9]+\\.[0-9]+\\.[0-9]+(-SNAPSHOT)? build [0-9a-z]+")); - } - - public void testInitContext() throws ServletException { - MockFilterConfig mockFilterConfig = new MockFilterConfig(); - mockFilterConfig.setServletContext(new MockServletContext()); - filter.init(mockFilterConfig); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.testhelper.MockFilterConfig; +import org.tuckey.web.testhelper.MockServletContext; +import org.tuckey.web.filters.urlrewrite.utils.Log; + +import jakarta.servlet.ServletException; + +/** + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class UrlRewriteFilterTest extends TestCase { + + private UrlRewriteFilter filter; + + public void setUp() { + Log.setLevel("stdout:TRACE"); + filter = new UrlRewriteFilter(); + Log.setLevel("stdout:TRACE"); + } + + public void tearDown() { + filter.destroy(); + filter = null; + } + + public void testInit() throws ServletException { + filter.init(null); + filter.init(new MockFilterConfig()); + } + + public void testVersion() throws ServletException { + String ver = UrlRewriteFilter.getFullVersionString(); + System.out.println(ver); + assertTrue("Ver bad " + ver, ver.matches("[0-9]+\\.[0-9]+\\.[0-9]+(-SNAPSHOT)? build [0-9a-z]+")); + } + + public void testInitContext() throws ServletException { + MockFilterConfig mockFilterConfig = new MockFilterConfig(); + mockFilterConfig.setServletContext(new MockServletContext()); + filter.init(mockFilterConfig); + } + +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteTestCaseTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteTestCaseTest.java index ab9680e0..adede1f8 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteTestCaseTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteTestCaseTest.java @@ -1,51 +1,51 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.tuckey.web.filters.urlrewrite.test.UrlRewriteTestCase; - - -public class UrlRewriteTestCaseTest extends UrlRewriteTestCase { - - public void setUp() { - loadConf(UrlRewriteTestCaseTest.class.getResource("conf-test2.xml")); - } - - - public void testRule1() { - assertRuleMatches("BasicRule2", "basicfrom2"); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.tuckey.web.filters.urlrewrite.test.UrlRewriteTestCase; + + +public class UrlRewriteTestCaseTest extends UrlRewriteTestCase { + + public void setUp() { + loadConf(UrlRewriteTestCaseTest.class.getResource("conf-test2.xml")); + } + + + public void testRule1() { + assertRuleMatches("BasicRule2", "basicfrom2"); + } + +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponseTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponseTest.java index 019eddd2..28dcf3c4 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponseTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponseTest.java @@ -1,72 +1,72 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.testhelper.MockRequest; -import org.tuckey.web.testhelper.MockResponse; -import org.tuckey.web.filters.urlrewrite.utils.Log; - -/** - * @author Paul Tuckey - * @version $Revision: 12 $ $Date: 2006-08-20 20:53:09 +1200 (Sun, 20 Aug 2006) $ - */ -public class UrlRewriteWrappedResponseTest extends TestCase { - - MockResponse response; - - public void setUp() { - Log.setLevel("DEBUG"); - response = new MockResponse(); - } - - public void testUrlEncode() { - Conf conf = new Conf(); - OutboundRule rule1 = new OutboundRule(); - rule1.setFrom("/aaa"); - rule1.setTo("/bbb"); - conf.addOutboundRule(rule1); - conf.initialise(); - UrlRewriter urlRewriter = new UrlRewriter(conf); - - MockRequest request = new MockRequest("doesn't matter"); - UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); - - assertEquals("/bbb;mockencoded=test", urlRewriteWrappedResponse.encodeURL("/aaa")); - - } - -} - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.testhelper.MockRequest; +import org.tuckey.web.testhelper.MockResponse; +import org.tuckey.web.filters.urlrewrite.utils.Log; + +/** + * @author Paul Tuckey + * @version $Revision: 12 $ $Date: 2006-08-20 20:53:09 +1200 (Sun, 20 Aug 2006) $ + */ +public class UrlRewriteWrappedResponseTest extends TestCase { + + MockResponse response; + + public void setUp() { + Log.setLevel("DEBUG"); + response = new MockResponse(); + } + + public void testUrlEncode() { + Conf conf = new Conf(); + OutboundRule rule1 = new OutboundRule(); + rule1.setFrom("/aaa"); + rule1.setTo("/bbb"); + conf.addOutboundRule(rule1); + conf.initialise(); + UrlRewriter urlRewriter = new UrlRewriter(conf); + + MockRequest request = new MockRequest("doesn't matter"); + UrlRewriteWrappedResponse urlRewriteWrappedResponse = new UrlRewriteWrappedResponse(response, request, urlRewriter); + + assertEquals("/bbb;mockencoded=test", urlRewriteWrappedResponse.encodeURL("/aaa")); + + } + +} + diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriterTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriterTest.java index 3e92d344..83ad802b 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriterTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriterTest.java @@ -1,436 +1,436 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import junit.framework.TestCase; -import org.tuckey.web.filters.urlrewrite.test.MockRewriteMatch; -import org.tuckey.web.filters.urlrewrite.test.TestRunObj; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.testhelper.MockFilterChain; -import org.tuckey.web.testhelper.MockRequest; -import org.tuckey.web.testhelper.MockResponse; -import org.tuckey.web.testhelper.MockServletContext; - -import jakarta.servlet.ServletException; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; - -/** - * @author Paul Tuckey - * @version $Revision: 44 $ $Date: 2006-11-02 12:29:14 +1300 (Thu, 02 Nov 2006) $ - */ -public class UrlRewriterTest extends TestCase { - - MockResponse response; - MockRequest request; - MockServletContext servletContext; - MockFilterChain chain; - - public void setUp() { - Log.setLevel("DEBUG"); - response = new MockResponse(); - request = new MockRequest("/"); - servletContext = new MockServletContext(); - chain = new MockFilterChain(); - TestRunObj.resetTestFlags(); - } - - public void test1() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(); - NormalRule rule1 = new NormalRule(); - rule1.setFrom("/aaa"); - rule1.setTo("/bbb"); - conf.addRule(rule1); - conf.setUseQueryString(true); - conf.setDecodeUsing("null"); - conf.initialise(); - - assertFalse(conf.isDecodeUsingCustomCharsetRequired()); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - MockRequest request = new MockRequest("/aaa"); - NormalRewrittenUrl rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); - - assertTrue(rewrittenRequest.isForward()); - assertEquals("/bbb", rewrittenRequest.getTarget()); - - // test null url - request = new MockRequest(); - rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); - assertNull(rewrittenRequest); - - // test query string - request = new MockRequest("/aaa"); - request.setQueryString("bb=cc"); - rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); - assertEquals("/bbb?bb=cc", rewrittenRequest.getTarget()); - - request = new MockRequest("/aaa%20"); - rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); - assertEquals("/bbb%20", rewrittenRequest.getTarget()); - } - - public void testDefaultDecode() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(); - NormalRule rule1 = new NormalRule(); - rule1.setFrom("^/ca&t/(.*)$"); - rule1.setTo("/search/?c=y&q=$1"); - conf.addRule(rule1); - conf.initialise(); - - assertTrue("isDecodeUsingEncodingHeader should be true", conf.isDecodeUsingEncodingHeader()); - assertTrue("isDecodeUsingCustomCharsetRequired should be true", conf.isDecodeUsingCustomCharsetRequired()); - UrlRewriter urlRewriter = new UrlRewriter(conf); - MockRequest request = new MockRequest("/ca&t/abc"); - NormalRewrittenUrl rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); - - assertTrue("should be forward", rewrittenRequest.isForward()); - assertEquals("/search/?c=y&q=abc", rewrittenRequest.getTarget()); - } - - public void testAbsoluteRedir() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(); - NormalRule rule1 = new NormalRule(); - rule1.setFrom("^(.*)$"); - rule1.setToType("permanent-redirect"); - rule1.setTo("http://sss.sss.sss"); - conf.addRule(rule1); - conf.initialise(); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - MockRequest request = new MockRequest("/aaa"); - RewrittenUrl rewrittenRequest = urlRewriter.processRequest(request, response); - - rewrittenRequest.doRewrite(request, response, null); - assertEquals("http://sss.sss.sss", response.getHeader("Location")); - - } - - - public void testNoRules() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(); - conf.initialise(); - UrlRewriter urlRewriter = new UrlRewriter(conf); - MockRequest request = new MockRequest("/aaa"); - RewrittenUrl rewrittenRequest = urlRewriter.processRequest(request, response); - assertNull(rewrittenRequest); - } - - - public void testSetSimple() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(); - NormalRule rule1 = new NormalRule(); - rule1.setFrom("^/aaa([0-9]+)(.*)$"); - SetAttribute setAttribute1 = new SetAttribute(); - setAttribute1.setName("blah"); - setAttribute1.setValue("someval"); - rule1.addSetAttribute(setAttribute1); - - SetAttribute setAttribute2 = new SetAttribute(); - setAttribute2.setType("session"); - setAttribute2.setName("sblah"); - setAttribute2.setValue("$1"); - rule1.addSetAttribute(setAttribute2); - - SetAttribute setAttribute3 = new SetAttribute(); - setAttribute3.setType("response-header"); - setAttribute3.setName("Cache-control"); - setAttribute3.setValue("none"); - rule1.addSetAttribute(setAttribute3); - - SetAttribute setAttribute4 = new SetAttribute(); - setAttribute4.setName("action"); - setAttribute4.setValue("delete"); - rule1.addSetAttribute(setAttribute4); - - conf.addRule(rule1); - conf.initialise(); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - MockRequest request = new MockRequest("/aaa4?asdadasd"); - urlRewriter.processRequest(request, response); - - assertEquals("someval", request.getAttribute("blah")); - - assertEquals("4", request.getSession().getAttribute("sblah")); - assertEquals("delete", request.getAttribute("action")); - assertEquals("none", response.getHeader("Cache-control")); - - } - - public void testSetSimpleWithRule() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(); - NormalRule rule0 = new NormalRule(); - rule0.setFrom("/bbb([0-9]+)"); - rule0.setTo("/qqq"); - rule0.setToLast("false"); - - NormalRule rule1 = new NormalRule(); - rule1.setFrom("^/aaa([0-9]+)$"); - SetAttribute setAttribute1 = new SetAttribute(); - setAttribute1.setType("status"); - setAttribute1.setValue("404"); - rule1.addSetAttribute(setAttribute1); - - conf.addRule(rule0); - conf.addRule(rule1); - conf.initialise(); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - MockRequest request = new MockRequest("/bbb2?asdadasd"); - RewrittenUrl rewrittenRequest = urlRewriter.processRequest(request, response); - - assertEquals("/qqq?asdadasd", rewrittenRequest.getTarget()); - assertEquals(200, response.getStatus()); - - } - - public void testBadConf() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(); - NormalRule rule1 = new NormalRule(); - conf.addRule(rule1); - conf.initialise(); - UrlRewriter urlRewriter = new UrlRewriter(conf); - MockRequest request = new MockRequest("/aaa"); - RewrittenUrl rewrittenRequest = urlRewriter.processRequest(request, response); - assertNull(rewrittenRequest); - } - - /** - * Special test for rule application with no to element. - */ - public void testNoToElement() throws IOException, ServletException, InvocationTargetException { - NormalRule rule1 = new NormalRule(); - rule1.setFrom(".*"); - Condition condition1 = new Condition(); - condition1.setType("header"); - condition1.setName("accept"); - condition1.setValue(".*image/gif.*"); - SetAttribute setAttribute1 = new SetAttribute(); - setAttribute1.setName("imageType"); - setAttribute1.setValue("gif"); - rule1.addSetAttribute(setAttribute1); - rule1.addCondition(condition1); - rule1.initialise(null); - - NormalRule rule2 = new NormalRule(); - rule2.setFrom(".*"); - Condition condition2 = new Condition(); - condition2.setType("header"); - condition2.setName("accept"); - condition2.setValue(".*image/jpeg.*"); - SetAttribute setAttribute2 = new SetAttribute(); - setAttribute2.setName("imageType"); - setAttribute2.setValue("jpeg"); - rule2.addSetAttribute(setAttribute2); - rule2.addCondition(condition2); - rule2.initialise(null); - - NormalRule rule3 = new NormalRule(); - rule3.setFrom(".*"); - Condition condition3 = new Condition(); - condition3.setType("header"); - condition3.setName("accept"); - condition3.setValue(".*image/png.*"); - SetAttribute setAttribute3 = new SetAttribute(); - setAttribute3.setName("imageType"); - setAttribute3.setValue("png"); - rule3.addSetAttribute(setAttribute3); - rule3.addCondition(condition3); - rule3.initialise(null); - - NormalRule rule4 = new NormalRule(); - rule4.setFrom(".*"); - Condition condition4 = new Condition(); - condition4.setType("header"); - condition4.setName("user-agent"); - condition4.setValue("SonyEricssonT68.*"); - SetAttribute setAttribute4 = new SetAttribute(); - setAttribute4.setName("imageType"); - setAttribute4.setValue("png"); - rule4.addSetAttribute(setAttribute4); - rule4.addCondition(condition4); - rule4.initialise(null); - - Conf conf = new Conf(); - conf.addRule(rule1); - conf.addRule(rule2); - conf.addRule(rule3); - conf.addRule(rule4); - - conf.initialise(); - UrlRewriter urlRewriter = new UrlRewriter(conf); - - MockRequest request = new MockRequest("/images/my.png"); - request.setHeader("accept", "image/png,*/*;q=0.5"); - - RewrittenUrl rewrittenUrl1 = urlRewriter.processRequest(request, response); - - assertEquals("png", (String) request.getAttribute("imageType")); - assertEquals(null, rewrittenUrl1); - - } - - - public void testRuleDecode() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(); - NormalRule rule = new NormalRule(); - rule.setFrom("^/test decode/(.+?)$"); - rule.setTo("/TestHandler$1"); - conf.addRule(rule); - conf.setDecodeUsing("utf-8"); - conf.initialise(); - UrlRewriter urlRewriter = new UrlRewriter(conf); - MockRequest request = new MockRequest("/test%20decode/?string=black%26white+green"); - MockResponse response = new MockResponse(); - RewrittenUrl rewrittenUrl = urlRewriter.processRequest(request, response); - assertEquals("forward should be default type", "forward", rule.getToType()); - assertEquals("/TestHandler?string=black&white green", rewrittenUrl.getTarget()); - } - - - public void testRuleChain() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(servletContext, null, null, null); - - Run run = new Run(); - run.setClassStr(TestRunObj.class.getName()); - run.setMethodStr("runWithChainParam( req, res, chain )"); - - NormalRule rule = new NormalRule(); - rule.setFrom("^/$"); - rule.addRun(run); - conf.addRule(rule); - - Run run2 = new Run(); - run2.setClassStr(TestRunObj.class.getName()); - run2.setMethodStr("runWithReturnedObj"); - - NormalRule rule2 = new NormalRule(); - rule2.setFrom("^/$"); - rule2.setTo("null"); - rule2.addRun(run2); - rule2.setToLast("true"); - conf.addRule(rule2); - - conf.initialise(); - - assertTrue("conf should be initialised", conf.isOk()); - - UrlRewriter urlRewriter = new UrlRewriter(conf); - - run.execute(request, response, null, chain); - urlRewriter.processRequest(request, response); - - assertEquals("chain chould have been called once", 1, chain.getInvocationCount()); - assertEquals("forward should be default type", "forward", rule.getToType()); - long diff = TestRunObj.getRunWithChainParamAfterDoFilter() - MockRewriteMatch.getCalledTime(); - assertTrue("run2 should be invoked after chain " + diff, diff > 0); - } - - - public void testNoSubstitutionLast() throws IOException, ServletException, InvocationTargetException { - final NormalRule rule1 = new NormalRule(); - rule1.setFrom("noSub"); - rule1.setTo("-"); - rule1.setToLast("true"); - rule1.initialise(null); - - final NormalRule rule2 = new NormalRule(); - rule2.setFrom("noS"); - rule2.setTo("changed"); - rule2.initialise(null); - - final Conf conf = new Conf(); - conf.addRule(rule1); - conf.addRule(rule2); - - conf.initialise(); - final UrlRewriter urlRewriter = new UrlRewriter(conf); - - final MockRequest request1 = new MockRequest("/path/noSub"); - final RewrittenUrl rewrittenUrl1 = urlRewriter.processRequest(request1, response); - assertNotNull(rewrittenUrl1); - assertEquals("/path/noSub", rewrittenUrl1.getTarget()); - - final MockRequest request2 = new MockRequest("/path/noSu"); - final RewrittenUrl rewrittenUrl2 = urlRewriter.processRequest(request2, response); - assertNotNull(rewrittenUrl2); - assertEquals("/path/changedu", rewrittenUrl2.getTarget()); - } - - public void testQueryToPath() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(); - conf.setDecodeUsing("null"); - NormalRule rule1 = new NormalRule(); - rule1.setFrom("^/\\?q=(.*)$"); - rule1.setTo("/search/${escapePath:${unescape:$1}}"); - conf.addRule(rule1); - conf.initialise(); - - assertFalse("isDecodeUsingEncodingHeader should be false", conf.isDecodeUsingEncodingHeader()); - assertFalse("isDecodeUsingCustomCharsetRequired should be false", conf.isDecodeUsingCustomCharsetRequired()); - UrlRewriter urlRewriter = new UrlRewriter(conf); - MockRequest request = new MockRequest("/?q=foo+bar%2bgee"); - NormalRewrittenUrl rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); - - assertTrue("should be forward", rewrittenRequest.isForward()); - assertEquals("/search/foo%20bar+gee", rewrittenRequest.getTarget()); - } - - public void testPathToQuery() throws IOException, ServletException, InvocationTargetException { - Conf conf = new Conf(); - conf.setDecodeUsing("null"); - NormalRule rule1 = new NormalRule(); - rule1.setFrom("^/(.*)$"); - rule1.setTo("/?q=${escape:${unescapePath:$1}}"); - conf.addRule(rule1); - conf.initialise(); - - assertFalse("isDecodeUsingEncodingHeader should be false", conf.isDecodeUsingEncodingHeader()); - assertFalse("isDecodeUsingCustomCharsetRequired should be false", conf.isDecodeUsingCustomCharsetRequired()); - UrlRewriter urlRewriter = new UrlRewriter(conf); - MockRequest request = new MockRequest("/foo+bar%20gee"); - NormalRewrittenUrl rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); - - assertTrue("should be forward", rewrittenRequest.isForward()); - assertEquals("/?q=foo%2Bbar+gee", rewrittenRequest.getTarget()); - } - -} - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import junit.framework.TestCase; +import org.tuckey.web.filters.urlrewrite.test.MockRewriteMatch; +import org.tuckey.web.filters.urlrewrite.test.TestRunObj; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.testhelper.MockFilterChain; +import org.tuckey.web.testhelper.MockRequest; +import org.tuckey.web.testhelper.MockResponse; +import org.tuckey.web.testhelper.MockServletContext; + +import jakarta.servlet.ServletException; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +/** + * @author Paul Tuckey + * @version $Revision: 44 $ $Date: 2006-11-02 12:29:14 +1300 (Thu, 02 Nov 2006) $ + */ +public class UrlRewriterTest extends TestCase { + + MockResponse response; + MockRequest request; + MockServletContext servletContext; + MockFilterChain chain; + + public void setUp() { + Log.setLevel("DEBUG"); + response = new MockResponse(); + request = new MockRequest("/"); + servletContext = new MockServletContext(); + chain = new MockFilterChain(); + TestRunObj.resetTestFlags(); + } + + public void test1() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(); + NormalRule rule1 = new NormalRule(); + rule1.setFrom("/aaa"); + rule1.setTo("/bbb"); + conf.addRule(rule1); + conf.setUseQueryString(true); + conf.setDecodeUsing("null"); + conf.initialise(); + + assertFalse(conf.isDecodeUsingCustomCharsetRequired()); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + MockRequest request = new MockRequest("/aaa"); + NormalRewrittenUrl rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); + + assertTrue(rewrittenRequest.isForward()); + assertEquals("/bbb", rewrittenRequest.getTarget()); + + // test null url + request = new MockRequest(); + rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); + assertNull(rewrittenRequest); + + // test query string + request = new MockRequest("/aaa"); + request.setQueryString("bb=cc"); + rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); + assertEquals("/bbb?bb=cc", rewrittenRequest.getTarget()); + + request = new MockRequest("/aaa%20"); + rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); + assertEquals("/bbb%20", rewrittenRequest.getTarget()); + } + + public void testDefaultDecode() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(); + NormalRule rule1 = new NormalRule(); + rule1.setFrom("^/ca&t/(.*)$"); + rule1.setTo("/search/?c=y&q=$1"); + conf.addRule(rule1); + conf.initialise(); + + assertTrue("isDecodeUsingEncodingHeader should be true", conf.isDecodeUsingEncodingHeader()); + assertTrue("isDecodeUsingCustomCharsetRequired should be true", conf.isDecodeUsingCustomCharsetRequired()); + UrlRewriter urlRewriter = new UrlRewriter(conf); + MockRequest request = new MockRequest("/ca&t/abc"); + NormalRewrittenUrl rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); + + assertTrue("should be forward", rewrittenRequest.isForward()); + assertEquals("/search/?c=y&q=abc", rewrittenRequest.getTarget()); + } + + public void testAbsoluteRedir() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(); + NormalRule rule1 = new NormalRule(); + rule1.setFrom("^(.*)$"); + rule1.setToType("permanent-redirect"); + rule1.setTo("http://sss.sss.sss"); + conf.addRule(rule1); + conf.initialise(); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + MockRequest request = new MockRequest("/aaa"); + RewrittenUrl rewrittenRequest = urlRewriter.processRequest(request, response); + + rewrittenRequest.doRewrite(request, response, null); + assertEquals("http://sss.sss.sss", response.getHeader("Location")); + + } + + + public void testNoRules() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(); + conf.initialise(); + UrlRewriter urlRewriter = new UrlRewriter(conf); + MockRequest request = new MockRequest("/aaa"); + RewrittenUrl rewrittenRequest = urlRewriter.processRequest(request, response); + assertNull(rewrittenRequest); + } + + + public void testSetSimple() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(); + NormalRule rule1 = new NormalRule(); + rule1.setFrom("^/aaa([0-9]+)(.*)$"); + SetAttribute setAttribute1 = new SetAttribute(); + setAttribute1.setName("blah"); + setAttribute1.setValue("someval"); + rule1.addSetAttribute(setAttribute1); + + SetAttribute setAttribute2 = new SetAttribute(); + setAttribute2.setType("session"); + setAttribute2.setName("sblah"); + setAttribute2.setValue("$1"); + rule1.addSetAttribute(setAttribute2); + + SetAttribute setAttribute3 = new SetAttribute(); + setAttribute3.setType("response-header"); + setAttribute3.setName("Cache-control"); + setAttribute3.setValue("none"); + rule1.addSetAttribute(setAttribute3); + + SetAttribute setAttribute4 = new SetAttribute(); + setAttribute4.setName("action"); + setAttribute4.setValue("delete"); + rule1.addSetAttribute(setAttribute4); + + conf.addRule(rule1); + conf.initialise(); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + MockRequest request = new MockRequest("/aaa4?asdadasd"); + urlRewriter.processRequest(request, response); + + assertEquals("someval", request.getAttribute("blah")); + + assertEquals("4", request.getSession().getAttribute("sblah")); + assertEquals("delete", request.getAttribute("action")); + assertEquals("none", response.getHeader("Cache-control")); + + } + + public void testSetSimpleWithRule() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(); + NormalRule rule0 = new NormalRule(); + rule0.setFrom("/bbb([0-9]+)"); + rule0.setTo("/qqq"); + rule0.setToLast("false"); + + NormalRule rule1 = new NormalRule(); + rule1.setFrom("^/aaa([0-9]+)$"); + SetAttribute setAttribute1 = new SetAttribute(); + setAttribute1.setType("status"); + setAttribute1.setValue("404"); + rule1.addSetAttribute(setAttribute1); + + conf.addRule(rule0); + conf.addRule(rule1); + conf.initialise(); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + MockRequest request = new MockRequest("/bbb2?asdadasd"); + RewrittenUrl rewrittenRequest = urlRewriter.processRequest(request, response); + + assertEquals("/qqq?asdadasd", rewrittenRequest.getTarget()); + assertEquals(200, response.getStatus()); + + } + + public void testBadConf() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(); + NormalRule rule1 = new NormalRule(); + conf.addRule(rule1); + conf.initialise(); + UrlRewriter urlRewriter = new UrlRewriter(conf); + MockRequest request = new MockRequest("/aaa"); + RewrittenUrl rewrittenRequest = urlRewriter.processRequest(request, response); + assertNull(rewrittenRequest); + } + + /** + * Special test for rule application with no to element. + */ + public void testNoToElement() throws IOException, ServletException, InvocationTargetException { + NormalRule rule1 = new NormalRule(); + rule1.setFrom(".*"); + Condition condition1 = new Condition(); + condition1.setType("header"); + condition1.setName("accept"); + condition1.setValue(".*image/gif.*"); + SetAttribute setAttribute1 = new SetAttribute(); + setAttribute1.setName("imageType"); + setAttribute1.setValue("gif"); + rule1.addSetAttribute(setAttribute1); + rule1.addCondition(condition1); + rule1.initialise(null); + + NormalRule rule2 = new NormalRule(); + rule2.setFrom(".*"); + Condition condition2 = new Condition(); + condition2.setType("header"); + condition2.setName("accept"); + condition2.setValue(".*image/jpeg.*"); + SetAttribute setAttribute2 = new SetAttribute(); + setAttribute2.setName("imageType"); + setAttribute2.setValue("jpeg"); + rule2.addSetAttribute(setAttribute2); + rule2.addCondition(condition2); + rule2.initialise(null); + + NormalRule rule3 = new NormalRule(); + rule3.setFrom(".*"); + Condition condition3 = new Condition(); + condition3.setType("header"); + condition3.setName("accept"); + condition3.setValue(".*image/png.*"); + SetAttribute setAttribute3 = new SetAttribute(); + setAttribute3.setName("imageType"); + setAttribute3.setValue("png"); + rule3.addSetAttribute(setAttribute3); + rule3.addCondition(condition3); + rule3.initialise(null); + + NormalRule rule4 = new NormalRule(); + rule4.setFrom(".*"); + Condition condition4 = new Condition(); + condition4.setType("header"); + condition4.setName("user-agent"); + condition4.setValue("SonyEricssonT68.*"); + SetAttribute setAttribute4 = new SetAttribute(); + setAttribute4.setName("imageType"); + setAttribute4.setValue("png"); + rule4.addSetAttribute(setAttribute4); + rule4.addCondition(condition4); + rule4.initialise(null); + + Conf conf = new Conf(); + conf.addRule(rule1); + conf.addRule(rule2); + conf.addRule(rule3); + conf.addRule(rule4); + + conf.initialise(); + UrlRewriter urlRewriter = new UrlRewriter(conf); + + MockRequest request = new MockRequest("/images/my.png"); + request.setHeader("accept", "image/png,*/*;q=0.5"); + + RewrittenUrl rewrittenUrl1 = urlRewriter.processRequest(request, response); + + assertEquals("png", (String) request.getAttribute("imageType")); + assertEquals(null, rewrittenUrl1); + + } + + + public void testRuleDecode() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(); + NormalRule rule = new NormalRule(); + rule.setFrom("^/test decode/(.+?)$"); + rule.setTo("/TestHandler$1"); + conf.addRule(rule); + conf.setDecodeUsing("utf-8"); + conf.initialise(); + UrlRewriter urlRewriter = new UrlRewriter(conf); + MockRequest request = new MockRequest("/test%20decode/?string=black%26white+green"); + MockResponse response = new MockResponse(); + RewrittenUrl rewrittenUrl = urlRewriter.processRequest(request, response); + assertEquals("forward should be default type", "forward", rule.getToType()); + assertEquals("/TestHandler?string=black&white green", rewrittenUrl.getTarget()); + } + + + public void testRuleChain() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(servletContext, null, null, null); + + Run run = new Run(); + run.setClassStr(TestRunObj.class.getName()); + run.setMethodStr("runWithChainParam( req, res, chain )"); + + NormalRule rule = new NormalRule(); + rule.setFrom("^/$"); + rule.addRun(run); + conf.addRule(rule); + + Run run2 = new Run(); + run2.setClassStr(TestRunObj.class.getName()); + run2.setMethodStr("runWithReturnedObj"); + + NormalRule rule2 = new NormalRule(); + rule2.setFrom("^/$"); + rule2.setTo("null"); + rule2.addRun(run2); + rule2.setToLast("true"); + conf.addRule(rule2); + + conf.initialise(); + + assertTrue("conf should be initialised", conf.isOk()); + + UrlRewriter urlRewriter = new UrlRewriter(conf); + + run.execute(request, response, null, chain); + urlRewriter.processRequest(request, response); + + assertEquals("chain chould have been called once", 1, chain.getInvocationCount()); + assertEquals("forward should be default type", "forward", rule.getToType()); + long diff = TestRunObj.getRunWithChainParamAfterDoFilter() - MockRewriteMatch.getCalledTime(); + assertTrue("run2 should be invoked after chain " + diff, diff > 0); + } + + + public void testNoSubstitutionLast() throws IOException, ServletException, InvocationTargetException { + final NormalRule rule1 = new NormalRule(); + rule1.setFrom("noSub"); + rule1.setTo("-"); + rule1.setToLast("true"); + rule1.initialise(null); + + final NormalRule rule2 = new NormalRule(); + rule2.setFrom("noS"); + rule2.setTo("changed"); + rule2.initialise(null); + + final Conf conf = new Conf(); + conf.addRule(rule1); + conf.addRule(rule2); + + conf.initialise(); + final UrlRewriter urlRewriter = new UrlRewriter(conf); + + final MockRequest request1 = new MockRequest("/path/noSub"); + final RewrittenUrl rewrittenUrl1 = urlRewriter.processRequest(request1, response); + assertNotNull(rewrittenUrl1); + assertEquals("/path/noSub", rewrittenUrl1.getTarget()); + + final MockRequest request2 = new MockRequest("/path/noSu"); + final RewrittenUrl rewrittenUrl2 = urlRewriter.processRequest(request2, response); + assertNotNull(rewrittenUrl2); + assertEquals("/path/changedu", rewrittenUrl2.getTarget()); + } + + public void testQueryToPath() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(); + conf.setDecodeUsing("null"); + NormalRule rule1 = new NormalRule(); + rule1.setFrom("^/\\?q=(.*)$"); + rule1.setTo("/search/${escapePath:${unescape:$1}}"); + conf.addRule(rule1); + conf.initialise(); + + assertFalse("isDecodeUsingEncodingHeader should be false", conf.isDecodeUsingEncodingHeader()); + assertFalse("isDecodeUsingCustomCharsetRequired should be false", conf.isDecodeUsingCustomCharsetRequired()); + UrlRewriter urlRewriter = new UrlRewriter(conf); + MockRequest request = new MockRequest("/?q=foo+bar%2bgee"); + NormalRewrittenUrl rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); + + assertTrue("should be forward", rewrittenRequest.isForward()); + assertEquals("/search/foo%20bar+gee", rewrittenRequest.getTarget()); + } + + public void testPathToQuery() throws IOException, ServletException, InvocationTargetException { + Conf conf = new Conf(); + conf.setDecodeUsing("null"); + NormalRule rule1 = new NormalRule(); + rule1.setFrom("^/(.*)$"); + rule1.setTo("/?q=${escape:${unescapePath:$1}}"); + conf.addRule(rule1); + conf.initialise(); + + assertFalse("isDecodeUsingEncodingHeader should be false", conf.isDecodeUsingEncodingHeader()); + assertFalse("isDecodeUsingCustomCharsetRequired should be false", conf.isDecodeUsingCustomCharsetRequired()); + UrlRewriter urlRewriter = new UrlRewriter(conf); + MockRequest request = new MockRequest("/foo+bar%20gee"); + NormalRewrittenUrl rewrittenRequest = (NormalRewrittenUrl) urlRewriter.processRequest(request, response); + + assertTrue("should be forward", rewrittenRequest.isForward()); + assertEquals("/?q=foo%2Bbar+gee", rewrittenRequest.getTarget()); + } + +} + diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatchTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatchTest.java index 2b319d52..304e0783 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatchTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatchTest.java @@ -1,81 +1,81 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.json; - -import junit.framework.TestCase; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.testhelper.MockRequest; -import org.tuckey.web.testhelper.MockResponse; - -import jakarta.servlet.ServletException; -import java.io.IOException; - - -/** - * Test JsonRewriteMatch. - */ -public class JsonRewriteMatchTest extends TestCase { - - public void testSimple() throws IOException, ServletException { - Log.setLevel("SYSOUT:DEBUG"); - JsonRewriteMatch jsonRewriteMatch = new JsonRewriteMatch(null); - MockRequest request = new MockRequest(); - MockResponse response = new MockResponse(); - jsonRewriteMatch.execute(request, response); - assertEquals("{\"result\":null}", response.getOutputStreamAsString()); - } - - public void testEcho() throws IOException, ServletException { - Log.setLevel("SYSOUT:DEBUG"); - JsonRewriteMatch jsonRewriteMatch = new JsonRewriteMatch("Hello World"); - MockRequest request = new MockRequest(); - MockResponse response = new MockResponse(); - jsonRewriteMatch.execute(request, response); - assertEquals("{\"result\":\"Hello World\"}", response.getOutputStreamAsString()); - } - - /** - * @noinspection ThrowableInstanceNeverThrown - */ - public void testError() throws IOException, ServletException { - Log.setLevel("SYSOUT:DEBUG"); - JsonRewriteMatch jsonRewriteMatch = new JsonRewriteMatch(new Exception("Hello World")); - MockRequest request = new MockRequest(); - MockResponse response = new MockResponse(); - jsonRewriteMatch.execute(request, response); - assertEquals("{\"error\":{\"error\":\"java.lang.Exception: Hello World\",\"message\":\"Hello World\",\"name\":\"java.lang.Exception\"}}", response.getOutputStreamAsString()); - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.json; + +import junit.framework.TestCase; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.testhelper.MockRequest; +import org.tuckey.web.testhelper.MockResponse; + +import jakarta.servlet.ServletException; +import java.io.IOException; + + +/** + * Test JsonRewriteMatch. + */ +public class JsonRewriteMatchTest extends TestCase { + + public void testSimple() throws IOException, ServletException { + Log.setLevel("SYSOUT:DEBUG"); + JsonRewriteMatch jsonRewriteMatch = new JsonRewriteMatch(null); + MockRequest request = new MockRequest(); + MockResponse response = new MockResponse(); + jsonRewriteMatch.execute(request, response); + assertEquals("{\"result\":null}", response.getOutputStreamAsString()); + } + + public void testEcho() throws IOException, ServletException { + Log.setLevel("SYSOUT:DEBUG"); + JsonRewriteMatch jsonRewriteMatch = new JsonRewriteMatch("Hello World"); + MockRequest request = new MockRequest(); + MockResponse response = new MockResponse(); + jsonRewriteMatch.execute(request, response); + assertEquals("{\"result\":\"Hello World\"}", response.getOutputStreamAsString()); + } + + /** + * @noinspection ThrowableInstanceNeverThrown + */ + public void testError() throws IOException, ServletException { + Log.setLevel("SYSOUT:DEBUG"); + JsonRewriteMatch jsonRewriteMatch = new JsonRewriteMatch(new Exception("Hello World")); + MockRequest request = new MockRequest(); + MockResponse response = new MockResponse(); + jsonRewriteMatch.execute(request, response); + assertEquals("{\"error\":{\"error\":\"java.lang.Exception: Hello World\",\"message\":\"Hello World\",\"name\":\"java.lang.Exception\"}}", response.getOutputStreamAsString()); + } + +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRewriteMatch.java b/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRewriteMatch.java index c72babbe..6a69bc18 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRewriteMatch.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRewriteMatch.java @@ -1,70 +1,70 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.test; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; - - -/** - * Mock RewriteMatch that can be used for testing. Included here and not in test folder as it needs to be deployed with - * the main library. - * - * @author Paul Tuckey - * @version $Revision: 33 $ $Date: 2006-09-12 16:41:56 +1200 (Tue, 12 Sep 2006) $ - */ -public class MockRewriteMatch extends RewriteMatch { - - private static long calledTime = 0; - - public boolean execute(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - calledTime = System.currentTimeMillis(); - try { - Thread.sleep(10); - } catch (InterruptedException e) { - // don't worry - } - return true; - } - - public static long getCalledTime() { - return calledTime; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.test; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + + +/** + * Mock RewriteMatch that can be used for testing. Included here and not in test folder as it needs to be deployed with + * the main library. + * + * @author Paul Tuckey + * @version $Revision: 33 $ $Date: 2006-09-12 16:41:56 +1200 (Tue, 12 Sep 2006) $ + */ +public class MockRewriteMatch extends RewriteMatch { + + private static long calledTime = 0; + + public boolean execute(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + calledTime = System.currentTimeMillis(); + try { + Thread.sleep(10); + } catch (InterruptedException e) { + // don't worry + } + return true; + } + + public static long getCalledTime() { + return calledTime; + } +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/test/TestRunObj.java b/src/test/java/org/tuckey/web/filters/urlrewrite/test/TestRunObj.java index d3879a71..c88864dd 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/test/TestRunObj.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/test/TestRunObj.java @@ -1,248 +1,248 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.test; - -import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; - -/** - * RunObject that can be used for testing. Included here and not in test folder as it needs to be deployed with the - * main library. - * - * @author Paul Tuckey - * @version $Revision: 33 $ $Date: 2006-09-12 16:41:56 +1200 (Tue, 12 Sep 2006) $ - */ -public class TestRunObj { - private static boolean runCalled; - private static boolean destroyCalled; - private static boolean initCalled; - private static boolean nonDefaultRunCalled; - private static ServletConfig servletConfig; - - private static int createdCount = 0; - private static String paramStr = null; - private static long runWithChainParamAfterDoFilter = 0; - - public TestRunObj() { - createdCount++; - } - - public void run(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - runCalled = true; - - PrintWriter sos = httpServletResponse.getWriter(); - if (sos == null) return; - sos.print("this is " + TestRunObj.class.getName()); - sos.close(); - } - - - public MockRewriteMatch runWithReturnedObj(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - return new MockRewriteMatch(); - } - - public void nonDefaultRun(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - nonDefaultRunCalled = true; - } - - public String runThatReturns(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - return "aaabbb"; - } - - public String runWithParam(int i) - throws ServletException, IOException { - paramStr = "" + i; - return paramStr; - } - - public String runWithNoParams() - throws ServletException, IOException { - paramStr = "[no params]"; - return paramStr; - } - - public String runWithChainParam(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain c) - throws ServletException, IOException { - paramStr = "" + c; - c.doFilter(httpServletRequest, httpServletResponse); - try { - Thread.sleep(10); - } catch (InterruptedException e) { - // - } - runWithChainParamAfterDoFilter = System.currentTimeMillis(); - return paramStr; - } - - public static long getRunWithChainParamAfterDoFilter() { - return runWithChainParamAfterDoFilter; - } - - public String runWithPrimitiveParam(int i, char c, double d, float f, short s, byte b, boolean b2, String s2) - throws ServletException, IOException { - paramStr = i + "," + c + "," + d + "," + f + "," + s + "," + b + "," + b2 + "," + s2; - return paramStr; - } - - public String runWithObjParam(Integer i, Character c, Double d, Float f, Short s, Byte b, Boolean b2, String s2) - throws ServletException, IOException { - paramStr = i + "," + c + "," + d + "," + f + "," + s + "," + b + "," + b2 + "," + s2; - return paramStr; - } - - public static String getParamStr() { - return paramStr; - } - - public void runNullPointerException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - exceptionGenerator.doNullPointer(); - } - - public void runRuntiumeException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - exceptionGenerator.doRuntime(); - } - - public void runServletException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - exceptionGenerator.doServlet(); - } - - public void runIOException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws ServletException, IOException { - exceptionGenerator.doIO(); - } - - public void runCustomException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) - throws TestExceptionGenerator.CustomException { - exceptionGenerator.doCustom(); - } - - TestExceptionGenerator exceptionGenerator = new TestExceptionGenerator(); - - private class TestExceptionGenerator { - public void doNullPointer() { - String aaa = null; - // YES we WANT a null pointer here - aaa.toLowerCase(); - } - - public void doRuntime() { - throw new RuntimeException("shit!"); - } - - public void doServlet() throws ServletException { - throw new ServletException("serv"); - } - - public void doIO() throws IOException { - throw new IOException("me i.o. has gone crazy"); - } - - public void doCustom() throws CustomException { - throw new CustomException(); - } - - public class CustomException extends Exception { - - } - } - - public RewriteMatch trialException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, - ClassNotFoundException e) { - return new MockRewriteMatch(); - } - - /** - * Do not delete! used in RunTest. - */ - private void privateRun(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { - // do nothing - } - - public void destroy() { - destroyCalled = true; - } - - public void init(ServletConfig config) throws ServletException { - servletConfig = config; - initCalled = true; - } - - public static boolean isRunCalled() { - return runCalled; - } - - public static int getCreatedCount() { - return createdCount; - } - - public static void resetTestFlags() { - createdCount = 0; - runCalled = false; - destroyCalled = false; - initCalled = false; - nonDefaultRunCalled = false; - servletConfig = null; - } - - public static ServletConfig getTestServletConfig() { - return servletConfig; - } - - public static boolean isDestroyCalled() { - return destroyCalled; - } - - public static boolean isInitCalled() { - return initCalled; - } - - public static boolean isNonDefaultRunCalled() { - return nonDefaultRunCalled; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.test; + +import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * RunObject that can be used for testing. Included here and not in test folder as it needs to be deployed with the + * main library. + * + * @author Paul Tuckey + * @version $Revision: 33 $ $Date: 2006-09-12 16:41:56 +1200 (Tue, 12 Sep 2006) $ + */ +public class TestRunObj { + private static boolean runCalled; + private static boolean destroyCalled; + private static boolean initCalled; + private static boolean nonDefaultRunCalled; + private static ServletConfig servletConfig; + + private static int createdCount = 0; + private static String paramStr = null; + private static long runWithChainParamAfterDoFilter = 0; + + public TestRunObj() { + createdCount++; + } + + public void run(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + runCalled = true; + + PrintWriter sos = httpServletResponse.getWriter(); + if (sos == null) return; + sos.print("this is " + TestRunObj.class.getName()); + sos.close(); + } + + + public MockRewriteMatch runWithReturnedObj(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + return new MockRewriteMatch(); + } + + public void nonDefaultRun(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + nonDefaultRunCalled = true; + } + + public String runThatReturns(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + return "aaabbb"; + } + + public String runWithParam(int i) + throws ServletException, IOException { + paramStr = "" + i; + return paramStr; + } + + public String runWithNoParams() + throws ServletException, IOException { + paramStr = "[no params]"; + return paramStr; + } + + public String runWithChainParam(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain c) + throws ServletException, IOException { + paramStr = "" + c; + c.doFilter(httpServletRequest, httpServletResponse); + try { + Thread.sleep(10); + } catch (InterruptedException e) { + // + } + runWithChainParamAfterDoFilter = System.currentTimeMillis(); + return paramStr; + } + + public static long getRunWithChainParamAfterDoFilter() { + return runWithChainParamAfterDoFilter; + } + + public String runWithPrimitiveParam(int i, char c, double d, float f, short s, byte b, boolean b2, String s2) + throws ServletException, IOException { + paramStr = i + "," + c + "," + d + "," + f + "," + s + "," + b + "," + b2 + "," + s2; + return paramStr; + } + + public String runWithObjParam(Integer i, Character c, Double d, Float f, Short s, Byte b, Boolean b2, String s2) + throws ServletException, IOException { + paramStr = i + "," + c + "," + d + "," + f + "," + s + "," + b + "," + b2 + "," + s2; + return paramStr; + } + + public static String getParamStr() { + return paramStr; + } + + public void runNullPointerException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + exceptionGenerator.doNullPointer(); + } + + public void runRuntiumeException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + exceptionGenerator.doRuntime(); + } + + public void runServletException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + exceptionGenerator.doServlet(); + } + + public void runIOException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws ServletException, IOException { + exceptionGenerator.doIO(); + } + + public void runCustomException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) + throws TestExceptionGenerator.CustomException { + exceptionGenerator.doCustom(); + } + + TestExceptionGenerator exceptionGenerator = new TestExceptionGenerator(); + + private class TestExceptionGenerator { + public void doNullPointer() { + String aaa = null; + // YES we WANT a null pointer here + aaa.toLowerCase(); + } + + public void doRuntime() { + throw new RuntimeException("shit!"); + } + + public void doServlet() throws ServletException { + throw new ServletException("serv"); + } + + public void doIO() throws IOException { + throw new IOException("me i.o. has gone crazy"); + } + + public void doCustom() throws CustomException { + throw new CustomException(); + } + + public class CustomException extends Exception { + + } + } + + public RewriteMatch trialException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + ClassNotFoundException e) { + return new MockRewriteMatch(); + } + + /** + * Do not delete! used in RunTest. + */ + private void privateRun(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { + // do nothing + } + + public void destroy() { + destroyCalled = true; + } + + public void init(ServletConfig config) throws ServletException { + servletConfig = config; + initCalled = true; + } + + public static boolean isRunCalled() { + return runCalled; + } + + public static int getCreatedCount() { + return createdCount; + } + + public static void resetTestFlags() { + createdCount = 0; + runCalled = false; + destroyCalled = false; + initCalled = false; + nonDefaultRunCalled = false; + servletConfig = null; + } + + public static ServletConfig getTestServletConfig() { + return servletConfig; + } + + public static boolean isDestroyCalled() { + return destroyCalled; + } + + public static boolean isInitCalled() { + return initCalled; + } + + public static boolean isNonDefaultRunCalled() { + return nonDefaultRunCalled; + } +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/test/UrlRewriteTestCase.java b/src/test/java/org/tuckey/web/filters/urlrewrite/test/UrlRewriteTestCase.java index 7fdef6ef..af78aa3d 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/test/UrlRewriteTestCase.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/test/UrlRewriteTestCase.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2005-2007, Paul Tuckey + * Copyright (c) 2005-2023, Paul Tuckey * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/utils/LogTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/utils/LogTest.java index 21b23275..6f2d250a 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/utils/LogTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/utils/LogTest.java @@ -1,86 +1,86 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -import junit.framework.TestCase; -import org.tuckey.web.testhelper.MockFilterConfig; - -/** - * - * - */ -public class LogTest extends TestCase { - - public void testInitNull() { - Log.setConfiguration(null); - } - - public void testInitEmpty() { - Log.setConfiguration(new MockFilterConfig()); - } - - public void testNull() { - Log log = Log.getLog(null); - log.debug("hi"); - } - - public void testDebug() { - Log log = Log.getLog(null); - Log.setLevel("DEBUG"); - assertFalse(log.isTraceEnabled()); - assertTrue(log.isDebugEnabled()); - assertTrue(log.isInfoEnabled()); - assertTrue(log.isWarnEnabled()); - assertTrue(log.isErrorEnabled()); - assertTrue(log.isFatalEnabled()); - log.debug("hi"); - } - - public void testLevelCase() { - Log log = Log.getLog(null); - Log.setLevel("SysOut:DEbug"); - assertTrue("debug", log.isDebugEnabled()); - assertTrue("std out", log.isUsingSystemOut()); - log.debug("hi"); - } - - public void testLevelCaseErr() { - Log log = Log.getLog(null); - Log.setLevel("StdErR:DEbug"); - assertTrue("debug", log.isDebugEnabled()); - assertTrue("std err", log.isUsingSystemErr()); - log.debug("hi err"); - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +import junit.framework.TestCase; +import org.tuckey.web.testhelper.MockFilterConfig; + +/** + * + * + */ +public class LogTest extends TestCase { + + public void testInitNull() { + Log.setConfiguration(null); + } + + public void testInitEmpty() { + Log.setConfiguration(new MockFilterConfig()); + } + + public void testNull() { + Log log = Log.getLog(null); + log.debug("hi"); + } + + public void testDebug() { + Log log = Log.getLog(null); + Log.setLevel("DEBUG"); + assertFalse(log.isTraceEnabled()); + assertTrue(log.isDebugEnabled()); + assertTrue(log.isInfoEnabled()); + assertTrue(log.isWarnEnabled()); + assertTrue(log.isErrorEnabled()); + assertTrue(log.isFatalEnabled()); + log.debug("hi"); + } + + public void testLevelCase() { + Log log = Log.getLog(null); + Log.setLevel("SysOut:DEbug"); + assertTrue("debug", log.isDebugEnabled()); + assertTrue("std out", log.isUsingSystemOut()); + log.debug("hi"); + } + + public void testLevelCaseErr() { + Log log = Log.getLog(null); + Log.setLevel("StdErR:DEbug"); + assertTrue("debug", log.isDebugEnabled()); + assertTrue("std err", log.isUsingSystemErr()); + log.debug("hi err"); + } +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcherTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcherTest.java index 67b9108c..6983dfa4 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcherTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcherTest.java @@ -1,107 +1,107 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite.utils; - -import junit.framework.TestCase; -import org.tuckey.web.filters.urlrewrite.substitution.ChainedSubstitutionFilters; -import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionContext; -import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionFilterChain; - -/** - * @author Paul Tuckey - * @version $Revision: 36 $ $Date: 2006-09-19 18:32:39 +1200 (Tue, 19 Sep 2006) $ - */ -public class StringMatchingMatcherTest extends TestCase { - - - public static String replaceAll(StringMatchingMatcher matcher, String from, String replacement) { - SubstitutionContext substitutionContext = new SubstitutionContext(null, matcher, null, replacement); - SubstitutionFilterChain substitutionFilter = ChainedSubstitutionFilters.getDefaultSubstitutionChain(true, false, false, false); - return substitutionFilter.substitute(from, substitutionContext); - } - - public void testPatterns() throws StringMatchingPatternSyntaxException { - RegexPattern pat1 = new RegexPattern("a(a)", false); - StringMatchingMatcher mat1 = pat1.matcher("aaf"); - assertEquals("$1f", replaceAll(mat1, "aaf", "\\$1")); - - RegexPattern pat2 = new RegexPattern("aa", false); - StringMatchingMatcher mat2 = pat2.matcher("aaf"); - assertEquals("$1f", replaceAll(mat2, "aaf", "\\$1")); - - WildcardPattern pat3 = new WildcardPattern("/*/*/*/"); - StringMatchingMatcher mat3 = pat3.matcher("/aa/bb/cc/"); - assertTrue(mat3.find()); - assertEquals(3, mat3.groupCount()); - assertEquals("aabbcc$3$2", replaceAll(mat3, "/aa/bb/cc/", "$1$2$3\\$3\\$2")); - - // try again with no matches - WildcardPattern pat4 = new WildcardPattern("aa"); - StringMatchingMatcher mat4 = pat4.matcher("aaf"); - assertEquals("aaf", replaceAll(mat4, "aaf", "a\\$1b")); - - WildcardPattern pat5 = new WildcardPattern("/**"); - StringMatchingMatcher mat5 = pat5.matcher("/aa/bb/cc/?aa&bb#cc"); - assertTrue(mat5.find()); - assertEquals(1, mat5.groupCount()); - assertEquals("aa/bb/cc/?aa&bb#cc$3$2", replaceAll(mat5, "/aa/bb/cc/?aa&bb#cc", "$1$2$3\\$3\\$2")); - - WildcardPattern pat6 = new WildcardPattern("/aa/**"); - StringMatchingMatcher mat6 = pat6.matcher("/aa/bb/cc/?aa&bb#cc"); - assertTrue(mat6.find()); - assertEquals(1, mat6.groupCount()); - assertEquals("bb/cc/?aa&bb#cc$3$2", replaceAll(mat6, "/aa/bb/cc/?aa&bb#cc", "$1$2$3\\$3\\$2")); - - WildcardPattern pat7 = new WildcardPattern("/ee/**"); - StringMatchingMatcher mat7 = pat7.matcher("/aa/bb/cc/?aa&bb#cc"); - assertFalse(mat7.find()); - - } - - /** - * this was throwing an exception... it shouldn't. - */ - public void testStrangeProblem1() throws StringMatchingPatternSyntaxException { - RegexPattern pat = new RegexPattern("^(/.*)$", false); - StringMatchingMatcher mat = pat.matcher("/tester/one-level-sub/two-leel-sub/"); - mat.find(); - mat.groupCount(); - mat.groupCount(); - mat.groupCount(); - mat.group(1); - - } - -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite.utils; + +import junit.framework.TestCase; +import org.tuckey.web.filters.urlrewrite.substitution.ChainedSubstitutionFilters; +import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionContext; +import org.tuckey.web.filters.urlrewrite.substitution.SubstitutionFilterChain; + +/** + * @author Paul Tuckey + * @version $Revision: 36 $ $Date: 2006-09-19 18:32:39 +1200 (Tue, 19 Sep 2006) $ + */ +public class StringMatchingMatcherTest extends TestCase { + + + public static String replaceAll(StringMatchingMatcher matcher, String from, String replacement) { + SubstitutionContext substitutionContext = new SubstitutionContext(null, matcher, null, replacement); + SubstitutionFilterChain substitutionFilter = ChainedSubstitutionFilters.getDefaultSubstitutionChain(true, false, false, false); + return substitutionFilter.substitute(from, substitutionContext); + } + + public void testPatterns() throws StringMatchingPatternSyntaxException { + RegexPattern pat1 = new RegexPattern("a(a)", false); + StringMatchingMatcher mat1 = pat1.matcher("aaf"); + assertEquals("$1f", replaceAll(mat1, "aaf", "\\$1")); + + RegexPattern pat2 = new RegexPattern("aa", false); + StringMatchingMatcher mat2 = pat2.matcher("aaf"); + assertEquals("$1f", replaceAll(mat2, "aaf", "\\$1")); + + WildcardPattern pat3 = new WildcardPattern("/*/*/*/"); + StringMatchingMatcher mat3 = pat3.matcher("/aa/bb/cc/"); + assertTrue(mat3.find()); + assertEquals(3, mat3.groupCount()); + assertEquals("aabbcc$3$2", replaceAll(mat3, "/aa/bb/cc/", "$1$2$3\\$3\\$2")); + + // try again with no matches + WildcardPattern pat4 = new WildcardPattern("aa"); + StringMatchingMatcher mat4 = pat4.matcher("aaf"); + assertEquals("aaf", replaceAll(mat4, "aaf", "a\\$1b")); + + WildcardPattern pat5 = new WildcardPattern("/**"); + StringMatchingMatcher mat5 = pat5.matcher("/aa/bb/cc/?aa&bb#cc"); + assertTrue(mat5.find()); + assertEquals(1, mat5.groupCount()); + assertEquals("aa/bb/cc/?aa&bb#cc$3$2", replaceAll(mat5, "/aa/bb/cc/?aa&bb#cc", "$1$2$3\\$3\\$2")); + + WildcardPattern pat6 = new WildcardPattern("/aa/**"); + StringMatchingMatcher mat6 = pat6.matcher("/aa/bb/cc/?aa&bb#cc"); + assertTrue(mat6.find()); + assertEquals(1, mat6.groupCount()); + assertEquals("bb/cc/?aa&bb#cc$3$2", replaceAll(mat6, "/aa/bb/cc/?aa&bb#cc", "$1$2$3\\$3\\$2")); + + WildcardPattern pat7 = new WildcardPattern("/ee/**"); + StringMatchingMatcher mat7 = pat7.matcher("/aa/bb/cc/?aa&bb#cc"); + assertFalse(mat7.find()); + + } + + /** + * this was throwing an exception... it shouldn't. + */ + public void testStrangeProblem1() throws StringMatchingPatternSyntaxException { + RegexPattern pat = new RegexPattern("^(/.*)$", false); + StringMatchingMatcher mat = pat.matcher("/tester/one-level-sub/two-leel-sub/"); + mat.find(); + mat.groupCount(); + mat.groupCount(); + mat.groupCount(); + mat.group(1); + + } + +} diff --git a/src/test/java/org/tuckey/web/testhelper/BenchmarkRunner.java b/src/test/java/org/tuckey/web/testhelper/BenchmarkRunner.java index 88c5e35f..a8b941ab 100644 --- a/src/test/java/org/tuckey/web/testhelper/BenchmarkRunner.java +++ b/src/test/java/org/tuckey/web/testhelper/BenchmarkRunner.java @@ -1,319 +1,319 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.testhelper; - - -/** - * Used to extablish a system benchmark that other performance things can be compared to. - *

    - * Adapted from... - * http://mathsrv.ku-eichstaett.de/MGF/homes/grothmann/java/bench/BTest.java - * http://mathsrv.ku-eichstaett.de/MGF/homes/grothmann/java/bench/Bench.html - */ -public final class BenchmarkRunner { - private static final int ITER = 1000; - private final int n = 60; - private final int N = 1125; - private final double XTotal = 395113; - private final double[][] Data = { - {158.40, 0}, - {33.99, 0}, - {78.40, 0}, - {103.52, 0}, - {145.60, 56}, - {313.60, 78.40}, - {74.25, 0}, - {368.89, 0}, - {65.78, 0}, - {109.78, 0}, - {428.40, 59.12}, - {345.98, 0}, - {162.20, 0}, - {489.50, 0}, - {181.49, 0}, - {27.94, 0}, - {292.69, 0}, - {305.40, 0}, - {579.55, 0}, - {101.91, 0}, - {796.87, 78.40}, - {545.36, 0}, - {994.50, 0}, - {45.55, 0}, - {448, 0}, - {243.06, 0}, - {137.49, 0}, - {210.80, 65.90}, - {91.10, 0}, - {545.62, 56}, - {1785.90, 28}, - {90.20, 0}, - {265.36, 0}, - {215.53, 0}, - {181.45, 0}, - {67, 0}, - {123.20, 0}, - {78.40, 0}, - {51.52, 0}, - {203.16, 0}, - {133.33, 0}, - {22.40, 0}, - {579.08, 0}, - {150.58, 0}, - {89.60, 89.60}, - {805, 0}, - {826.69, 0}, - {1429.77, 0}, - {181.99, 44.80}, - {259.09, 0}, - {266.40, 0}, - {298.68, 0}, - {564.36, 0}, - {33.93, 0}, - {56, 0}, - {90.38, 0}, - {35, 0}, - {965.66, 313.60}, - {142.76, 0}, - {268.85, 0} - }; - - private long time; - - private int count = 0; - - /** - * Will give an amount of millisecs that is taken to run a specific complex chunk of code. - */ - public float establishBenchmark() { - return establishBenchmark(2); - } - - private float establishBenchmark(int numIters) { - // warm up - System.out.println("Establishing benchmark"); - BenchmarkRunner br = new BenchmarkRunner(); - br.compute(); - long benchStarted = System.currentTimeMillis(); - for (float i = 0; i < numIters; i++) { - BenchmarkRunner brIter = new BenchmarkRunner(); - brIter.compute(); - } - long totalBenchTook = System.currentTimeMillis() - benchStarted; - int benchAvg = Math.round((float) totalBenchTook / (float) numIters); - System.out.println("average of " + benchAvg + "ms after " + numIters + " iterations"); - return benchAvg; - } - - private void compute() { - int i; - double x[] = new double[n]; - double y[] = new double[n]; - for (i = 0; i < n; i++) { - x[i] = Data[i][0]; - y[i] = Data[i][1]; - } - time = System.currentTimeMillis(); - count = 1; - Benchmarker T = new Benchmarker(this, x, y, n, N, XTotal); - T.run(); - } - - private double Res = 0; - - public final synchronized void note(double res) { - count--; - Res += res; - if (count <= 0) { - int ms = (int) (System.currentTimeMillis() - time); - System.out.println("iteration took: " + ms + "ms (result: " + Res / 1 * 100 + ")"); - } - } - - - final class Benchmarker implements Runnable { - private final double[] x; - private final double[] y; - private final double xtotal; - private int Nboot; - private final int n; - private final int N; - private int[] I; - private int imin; - private double[] results; - private double resmin; - private int nresults; - private int ntop; - - private final BenchmarkRunner R; - - private final double alpha = 0.05; - - public Benchmarker(BenchmarkRunner r, double X[], double Y[], int nn, int NN, double XTotal) { - x = new double[X.length]; - System.arraycopy(X, 0, x, 0, X.length); - y = new double[Y.length]; - System.arraycopy(Y, 0, y, 0, Y.length); - N = NN; - n = nn; - xtotal = XTotal; - R = r; - } - - private void shuffle(int n, int I[], int N) { - int i, j, h; - for (i = 0; i < n; i++) { - j = i + (int) (Math.random() * (N - i)); - if (i != j) { - h = I[j]; - I[j] = I[i]; - I[i] = h; - } - } - } - - private void shuffle(int n, int I[], int start, int N) { - int i, j, h; - for (i = 0; i < n; i++) { - j = i + (int) (Math.random() * (N - i)); - if (i != j) { - h = I[start + j]; - I[start + j] = I[start + i]; - I[start + i] = h; - } - } - } - - private double sqr(double x) { - return x * x; - } - - private void bootstr100() { - int i, j, k; - double xsum, ysum, mux, h, p, vp, est, ptrue; - for (k = 0; k < 100; k++) { - for (i = 0; i < Nboot; i++) I[i] = i % n; - shuffle(N - (Nboot - n), I, Nboot - n, n); - shuffle(n, I, N); - - xsum = 0; - ysum = 0; - for (j = 0; j < n; j++) { - xsum += x[I[j]]; - ysum += y[I[j]]; - } - if (xsum == 0) est = -10; - else { - p = ysum / xsum; - xsum = 0; - ysum = 0; - for (int l = 0; l < N; l++) { - xsum += x[I[l]]; - ysum += y[I[l]]; - } - ptrue = ysum / xsum; - mux = xsum / N; - h = 0; - for (j = 0; j < n; j++) { - h += sqr(y[I[j]] - p * x[I[j]]); - } - vp = (1 - (double) (n - 1) / (N - 1)) / (n * mux * mux) * h / (n - 1); - if (vp == 0) est = -10; - else est = (p - ptrue) / Math.sqrt(vp); - } - - if (nresults == 0) { - results[0] = est; - imin = 0; - resmin = est; - nresults = 1; - } else if (nresults < ntop) { - results[nresults] = est; - if (est < resmin) { - resmin = est; - imin = nresults; - } - nresults++; - } else if (est > resmin) { - results[imin] = est; - resmin = results[0]; - imin = 0; - for (j = 0; j < ntop; j++) { - if (results[j] < resmin) { - resmin = results[j]; - imin = j; - } - } - } - } - } - - - public void run() { - int f, k, j; - double xsum, ysum, h, vp, ptrue, mux; - - f = N / n + 1; - Nboot = n * f; - I = new int[Nboot]; - - ntop = (int) (ITER * 100 * alpha); - results = new double[ntop]; - nresults = 0; - - for (k = 0; k < ITER; k++) bootstr100(); - - xsum = 0; - ysum = 0; - for (j = 0; j < n; j++) { - xsum += x[j]; - ysum += y[j]; - } - mux = xtotal / N; - h = 0; - ptrue = ysum / xsum; - for (j = 0; j < n; j++) { - h += sqr(y[j] - ptrue * x[j]); - } - vp = (1 - (double) (n - 1) / (N - 1)) / (n * mux * mux) * h / (n - 1); - - R.note(ptrue - Math.sqrt(vp) * resmin); - } - } - - -} - - +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.testhelper; + + +/** + * Used to extablish a system benchmark that other performance things can be compared to. + *

    + * Adapted from... + * http://mathsrv.ku-eichstaett.de/MGF/homes/grothmann/java/bench/BTest.java + * http://mathsrv.ku-eichstaett.de/MGF/homes/grothmann/java/bench/Bench.html + */ +public final class BenchmarkRunner { + private static final int ITER = 1000; + private final int n = 60; + private final int N = 1125; + private final double XTotal = 395113; + private final double[][] Data = { + {158.40, 0}, + {33.99, 0}, + {78.40, 0}, + {103.52, 0}, + {145.60, 56}, + {313.60, 78.40}, + {74.25, 0}, + {368.89, 0}, + {65.78, 0}, + {109.78, 0}, + {428.40, 59.12}, + {345.98, 0}, + {162.20, 0}, + {489.50, 0}, + {181.49, 0}, + {27.94, 0}, + {292.69, 0}, + {305.40, 0}, + {579.55, 0}, + {101.91, 0}, + {796.87, 78.40}, + {545.36, 0}, + {994.50, 0}, + {45.55, 0}, + {448, 0}, + {243.06, 0}, + {137.49, 0}, + {210.80, 65.90}, + {91.10, 0}, + {545.62, 56}, + {1785.90, 28}, + {90.20, 0}, + {265.36, 0}, + {215.53, 0}, + {181.45, 0}, + {67, 0}, + {123.20, 0}, + {78.40, 0}, + {51.52, 0}, + {203.16, 0}, + {133.33, 0}, + {22.40, 0}, + {579.08, 0}, + {150.58, 0}, + {89.60, 89.60}, + {805, 0}, + {826.69, 0}, + {1429.77, 0}, + {181.99, 44.80}, + {259.09, 0}, + {266.40, 0}, + {298.68, 0}, + {564.36, 0}, + {33.93, 0}, + {56, 0}, + {90.38, 0}, + {35, 0}, + {965.66, 313.60}, + {142.76, 0}, + {268.85, 0} + }; + + private long time; + + private int count = 0; + + /** + * Will give an amount of millisecs that is taken to run a specific complex chunk of code. + */ + public float establishBenchmark() { + return establishBenchmark(2); + } + + private float establishBenchmark(int numIters) { + // warm up + System.out.println("Establishing benchmark"); + BenchmarkRunner br = new BenchmarkRunner(); + br.compute(); + long benchStarted = System.currentTimeMillis(); + for (float i = 0; i < numIters; i++) { + BenchmarkRunner brIter = new BenchmarkRunner(); + brIter.compute(); + } + long totalBenchTook = System.currentTimeMillis() - benchStarted; + int benchAvg = Math.round((float) totalBenchTook / (float) numIters); + System.out.println("average of " + benchAvg + "ms after " + numIters + " iterations"); + return benchAvg; + } + + private void compute() { + int i; + double x[] = new double[n]; + double y[] = new double[n]; + for (i = 0; i < n; i++) { + x[i] = Data[i][0]; + y[i] = Data[i][1]; + } + time = System.currentTimeMillis(); + count = 1; + Benchmarker T = new Benchmarker(this, x, y, n, N, XTotal); + T.run(); + } + + private double Res = 0; + + public final synchronized void note(double res) { + count--; + Res += res; + if (count <= 0) { + int ms = (int) (System.currentTimeMillis() - time); + System.out.println("iteration took: " + ms + "ms (result: " + Res / 1 * 100 + ")"); + } + } + + + final class Benchmarker implements Runnable { + private final double[] x; + private final double[] y; + private final double xtotal; + private int Nboot; + private final int n; + private final int N; + private int[] I; + private int imin; + private double[] results; + private double resmin; + private int nresults; + private int ntop; + + private final BenchmarkRunner R; + + private final double alpha = 0.05; + + public Benchmarker(BenchmarkRunner r, double X[], double Y[], int nn, int NN, double XTotal) { + x = new double[X.length]; + System.arraycopy(X, 0, x, 0, X.length); + y = new double[Y.length]; + System.arraycopy(Y, 0, y, 0, Y.length); + N = NN; + n = nn; + xtotal = XTotal; + R = r; + } + + private void shuffle(int n, int I[], int N) { + int i, j, h; + for (i = 0; i < n; i++) { + j = i + (int) (Math.random() * (N - i)); + if (i != j) { + h = I[j]; + I[j] = I[i]; + I[i] = h; + } + } + } + + private void shuffle(int n, int I[], int start, int N) { + int i, j, h; + for (i = 0; i < n; i++) { + j = i + (int) (Math.random() * (N - i)); + if (i != j) { + h = I[start + j]; + I[start + j] = I[start + i]; + I[start + i] = h; + } + } + } + + private double sqr(double x) { + return x * x; + } + + private void bootstr100() { + int i, j, k; + double xsum, ysum, mux, h, p, vp, est, ptrue; + for (k = 0; k < 100; k++) { + for (i = 0; i < Nboot; i++) I[i] = i % n; + shuffle(N - (Nboot - n), I, Nboot - n, n); + shuffle(n, I, N); + + xsum = 0; + ysum = 0; + for (j = 0; j < n; j++) { + xsum += x[I[j]]; + ysum += y[I[j]]; + } + if (xsum == 0) est = -10; + else { + p = ysum / xsum; + xsum = 0; + ysum = 0; + for (int l = 0; l < N; l++) { + xsum += x[I[l]]; + ysum += y[I[l]]; + } + ptrue = ysum / xsum; + mux = xsum / N; + h = 0; + for (j = 0; j < n; j++) { + h += sqr(y[I[j]] - p * x[I[j]]); + } + vp = (1 - (double) (n - 1) / (N - 1)) / (n * mux * mux) * h / (n - 1); + if (vp == 0) est = -10; + else est = (p - ptrue) / Math.sqrt(vp); + } + + if (nresults == 0) { + results[0] = est; + imin = 0; + resmin = est; + nresults = 1; + } else if (nresults < ntop) { + results[nresults] = est; + if (est < resmin) { + resmin = est; + imin = nresults; + } + nresults++; + } else if (est > resmin) { + results[imin] = est; + resmin = results[0]; + imin = 0; + for (j = 0; j < ntop; j++) { + if (results[j] < resmin) { + resmin = results[j]; + imin = j; + } + } + } + } + } + + + public void run() { + int f, k, j; + double xsum, ysum, h, vp, ptrue, mux; + + f = N / n + 1; + Nboot = n * f; + I = new int[Nboot]; + + ntop = (int) (ITER * 100 * alpha); + results = new double[ntop]; + nresults = 0; + + for (k = 0; k < ITER; k++) bootstr100(); + + xsum = 0; + ysum = 0; + for (j = 0; j < n; j++) { + xsum += x[j]; + ysum += y[j]; + } + mux = xtotal / N; + h = 0; + ptrue = ysum / xsum; + for (j = 0; j < n; j++) { + h += sqr(y[j] - ptrue * x[j]); + } + vp = (1 - (double) (n - 1) / (N - 1)) / (n * mux * mux) * h / (n - 1); + + R.note(ptrue - Math.sqrt(vp) * resmin); + } + } + + +} + + diff --git a/src/test/java/org/tuckey/web/testhelper/MockFilterChain.java b/src/test/java/org/tuckey/web/testhelper/MockFilterChain.java index 37674fbc..2866f303 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockFilterChain.java +++ b/src/test/java/org/tuckey/web/testhelper/MockFilterChain.java @@ -1,74 +1,74 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.testhelper; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import java.io.IOException; - -/** - * @author Paul Tuckey - * @version $Revision: 26 $ $Date: 2006-09-05 22:21:17 +1200 (Tue, 05 Sep 2006) $ - */ -public class MockFilterChain implements FilterChain { - - private int invocationCount = 0; - private long timeInvoked = 0; - - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { - invocationCount++; - timeInvoked = System.currentTimeMillis(); - // make sure we wait a little so time elapses - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // - } - } - - public boolean isDoFilterRun() { - return invocationCount > 0; - } - - public int getInvocationCount() { - return invocationCount; - } - - public long getTimeInvoked() { - return timeInvoked; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.testhelper; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import java.io.IOException; + +/** + * @author Paul Tuckey + * @version $Revision: 26 $ $Date: 2006-09-05 22:21:17 +1200 (Tue, 05 Sep 2006) $ + */ +public class MockFilterChain implements FilterChain { + + private int invocationCount = 0; + private long timeInvoked = 0; + + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { + invocationCount++; + timeInvoked = System.currentTimeMillis(); + // make sure we wait a little so time elapses + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // + } + } + + public boolean isDoFilterRun() { + return invocationCount > 0; + } + + public int getInvocationCount() { + return invocationCount; + } + + public long getTimeInvoked() { + return timeInvoked; + } +} diff --git a/src/test/java/org/tuckey/web/testhelper/MockFilterConfig.java b/src/test/java/org/tuckey/web/testhelper/MockFilterConfig.java index 5f0436aa..776c993c 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockFilterConfig.java +++ b/src/test/java/org/tuckey/web/testhelper/MockFilterConfig.java @@ -1,67 +1,67 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.testhelper; - -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletContext; -import java.util.Enumeration; - -/** - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class MockFilterConfig implements FilterConfig { - private ServletContext servletContext; - - public String getFilterName() { - return null; - } - - public ServletContext getServletContext() { - return servletContext; - } - - public String getInitParameter(String string) { - return null; - } - - public Enumeration getInitParameterNames() { - return null; - } - - public void setServletContext(ServletContext servletContext) { - this.servletContext = servletContext; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.testhelper; + +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletContext; +import java.util.Enumeration; + +/** + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class MockFilterConfig implements FilterConfig { + private ServletContext servletContext; + + public String getFilterName() { + return null; + } + + public ServletContext getServletContext() { + return servletContext; + } + + public String getInitParameter(String string) { + return null; + } + + public Enumeration getInitParameterNames() { + return null; + } + + public void setServletContext(ServletContext servletContext) { + this.servletContext = servletContext; + } +} diff --git a/src/test/java/org/tuckey/web/testhelper/MockRequest.java b/src/test/java/org/tuckey/web/testhelper/MockRequest.java index e5490031..e412abaf 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockRequest.java +++ b/src/test/java/org/tuckey/web/testhelper/MockRequest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2005-2007, Paul Tuckey + * Copyright (c) 2005-2023, Paul Tuckey * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. diff --git a/src/test/java/org/tuckey/web/testhelper/MockRequestDispatcher.java b/src/test/java/org/tuckey/web/testhelper/MockRequestDispatcher.java index 3001c1af..f0baba09 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockRequestDispatcher.java +++ b/src/test/java/org/tuckey/web/testhelper/MockRequestDispatcher.java @@ -1,89 +1,89 @@ -/** - * Copyright (c) 2005-2007, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.testhelper; - -import jakarta.servlet.RequestDispatcher; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import java.io.IOException; - -/** - * @author Paul Tuckey - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class MockRequestDispatcher implements RequestDispatcher { - - private static MockRequestDispatcher current; - - private String url; - private boolean forwarded = false; - private boolean included = false; - private long includeLastCalled = 0; - - public MockRequestDispatcher(String url) { - this.url = url; - current = this; - } - - public void forward(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { - forwarded = true; - } - - public void include(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { - includeLastCalled = System.currentTimeMillis(); - included = true; - } - - public String getUrl() { - return url; - } - - public static MockRequestDispatcher getCurrent() { - return current; - } - - public boolean isForwarded() { - return forwarded; - } - - public boolean isIncluded() { - return included; - } - - public long getIncludeLastCalled() { - return includeLastCalled; - } -} +/** + * Copyright (c) 2005-2023, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.testhelper; + +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import java.io.IOException; + +/** + * @author Paul Tuckey + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class MockRequestDispatcher implements RequestDispatcher { + + private static MockRequestDispatcher current; + + private String url; + private boolean forwarded = false; + private boolean included = false; + private long includeLastCalled = 0; + + public MockRequestDispatcher(String url) { + this.url = url; + current = this; + } + + public void forward(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { + forwarded = true; + } + + public void include(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { + includeLastCalled = System.currentTimeMillis(); + included = true; + } + + public String getUrl() { + return url; + } + + public static MockRequestDispatcher getCurrent() { + return current; + } + + public boolean isForwarded() { + return forwarded; + } + + public boolean isIncluded() { + return included; + } + + public long getIncludeLastCalled() { + return includeLastCalled; + } +} diff --git a/src/test/java/org/tuckey/web/testhelper/MockResponse.java b/src/test/java/org/tuckey/web/testhelper/MockResponse.java index 231d53dd..661e4ac0 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockResponse.java +++ b/src/test/java/org/tuckey/web/testhelper/MockResponse.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2005-2007, Paul Tuckey + * Copyright (c) 2005-2023, Paul Tuckey * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. diff --git a/src/test/java/org/tuckey/web/testhelper/MockServletContext.java b/src/test/java/org/tuckey/web/testhelper/MockServletContext.java index 5b310e76..ca69827c 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockServletContext.java +++ b/src/test/java/org/tuckey/web/testhelper/MockServletContext.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2005-2007, Paul Tuckey + * Copyright (c) 2005-2023, Paul Tuckey * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. diff --git a/src/test/java/org/tuckey/web/testhelper/MockSession.java b/src/test/java/org/tuckey/web/testhelper/MockSession.java index ce0f7a95..5066023b 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockSession.java +++ b/src/test/java/org/tuckey/web/testhelper/MockSession.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2005-2007, Paul Tuckey + * Copyright (c) 2005-2023, Paul Tuckey * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. From bdfc6395f993d429ef49e7e51f799c3be9023167 Mon Sep 17 00:00:00 2001 From: Paul Tuckey Date: Mon, 3 Jul 2023 09:44:02 +1200 Subject: [PATCH 2/3] progress --- .../MockRewriteMatch.java | 6 +- .../urlrewriteviacontainer/TestRunObj.java | 6 +- .../WebappModStyleHttpITTest.java | 6 +- .../web/filters/urlrewrite/CatchElem.java | 6 +- .../web/filters/urlrewrite/ClassRule.java | 6 +- .../web/filters/urlrewrite/Condition.java | 6 +- .../filters/urlrewrite/ConditionMatch.java | 6 +- .../tuckey/web/filters/urlrewrite/Conf.java | 6 +- .../web/filters/urlrewrite/ConfHandler.java | 6 +- .../urlrewrite/NormalRewrittenUrl.java | 6 +- .../web/filters/urlrewrite/NormalRule.java | 6 +- .../web/filters/urlrewrite/OutboundRule.java | 6 +- .../web/filters/urlrewrite/RequestProxy.java | 672 +++++++------- .../urlrewrite/RewrittenOutboundUrl.java | 6 +- .../web/filters/urlrewrite/RewrittenUrl.java | 6 +- .../filters/urlrewrite/RewrittenUrlClass.java | 6 +- .../tuckey/web/filters/urlrewrite/Rule.java | 6 +- .../web/filters/urlrewrite/RuleBase.java | 6 +- .../web/filters/urlrewrite/RuleChain.java | 6 +- .../urlrewrite/RuleExecutionOutput.java | 6 +- .../tuckey/web/filters/urlrewrite/Run.java | 6 +- .../web/filters/urlrewrite/RunConfig.java | 6 +- .../web/filters/urlrewrite/Runnable.java | 6 +- .../web/filters/urlrewrite/SetAttribute.java | 16 +- .../tuckey/web/filters/urlrewrite/Status.java | 6 +- .../web/filters/urlrewrite/TypeConverter.java | 6 +- .../filters/urlrewrite/UrlRewriteDocTask.java | 6 +- .../filters/urlrewrite/UrlRewriteFilter.java | 6 +- .../filters/urlrewrite/UrlRewriteServlet.java | 8 +- .../urlrewrite/UrlRewriteWrappedRequest.java | 6 +- .../urlrewrite/UrlRewriteWrappedResponse.java | 6 +- .../web/filters/urlrewrite/UrlRewriter.java | 6 +- .../urlrewrite/extend/RewriteMatch.java | 8 +- .../urlrewrite/extend/RewriteRule.java | 6 +- .../gzip/FilterServletOutputStream.java | 8 +- .../gzip/GenericResponseWrapper.java | 8 +- .../filters/urlrewrite/gzip/GzipFilter.java | 8 +- .../filters/urlrewrite/gzip/ResponseUtil.java | 8 +- .../urlrewrite/json/JsonRewriteMatch.java | 6 +- .../urlrewrite/sample/SampleRewriteMatch.java | 6 +- .../urlrewrite/sample/SampleRewriteRule.java | 6 +- .../substitution/BackReferenceReplacer.java | 6 +- .../substitution/FunctionReplacer.java | 6 +- .../substitution/MatcherReplacer.java | 6 +- .../substitution/PatternReplacer.java | 6 +- .../substitution/UnescapeReplacer.java | 6 +- .../substitution/VariableReplacer.java | 6 +- .../web/filters/urlrewrite/utils/Log.java | 6 +- .../filters/urlrewrite/utils/NumberUtils.java | 6 +- .../urlrewrite/utils/RegexMatcher.java | 6 +- .../urlrewrite/utils/RegexPattern.java | 6 +- .../urlrewrite/utils/ServerNameMatcher.java | 6 +- .../utils/StringMatchingMatcher.java | 6 +- .../utils/StringMatchingPattern.java | 6 +- .../StringMatchingPatternSyntaxException.java | 6 +- .../filters/urlrewrite/utils/StringUtils.java | 6 +- .../filters/urlrewrite/utils/URLEncoder.java | 2 +- .../urlrewrite/utils/WildcardHelper.java | 842 +++++++++--------- .../urlrewrite/utils/WildcardMatcher.java | 6 +- .../urlrewrite/utils/WildcardPattern.java | 6 +- .../web/filters/urlrewrite/ConfTest.java | 6 +- .../filters/urlrewrite/OutboundRuleTest.java | 6 +- .../filters/urlrewrite/RewrittenUrlTest.java | 6 +- .../web/filters/urlrewrite/RuleTest.java | 6 +- .../web/filters/urlrewrite/RunTest.java | 6 +- .../filters/urlrewrite/SetAttributeTest.java | 6 +- .../web/filters/urlrewrite/StatusTest.java | 6 +- .../filters/urlrewrite/TestRewriteMatch.java | 6 +- .../web/filters/urlrewrite/TestRuleObj.java | 6 +- .../web/filters/urlrewrite/TestServlet.java | 6 +- .../filters/urlrewrite/UrlDecoderTest.java | 6 +- .../urlrewrite/UrlRewriteFilterTest.java | 6 +- .../urlrewrite/UrlRewriteTestCaseTest.java | 6 +- .../UrlRewriteWrappedResponseTest.java | 6 +- .../filters/urlrewrite/UrlRewriterTest.java | 6 +- .../urlrewrite/json/JsonRewriteMatchTest.java | 6 +- .../urlrewrite/test/MockRequestParser.java | 256 +++--- .../urlrewrite/test/MockRewriteMatch.java | 6 +- .../filters/urlrewrite/test/TestRunObj.java | 6 +- .../web/filters/urlrewrite/utils/LogTest.java | 6 +- .../utils/StringMatchingMatcherTest.java | 6 +- .../web/testhelper/BenchmarkRunner.java | 6 +- .../web/testhelper/MockFilterChain.java | 6 +- .../web/testhelper/MockFilterConfig.java | 6 +- .../tuckey/web/testhelper/MockRequest.java | 6 +- .../web/testhelper/MockRequestDispatcher.java | 6 +- .../tuckey/web/testhelper/MockResponse.java | 6 +- 87 files changed, 1146 insertions(+), 1146 deletions(-) diff --git a/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/MockRewriteMatch.java b/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/MockRewriteMatch.java index cf40d5f6..843cb84b 100644 --- a/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/MockRewriteMatch.java +++ b/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/MockRewriteMatch.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/TestRunObj.java b/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/TestRunObj.java index 5325c6e5..095df750 100644 --- a/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/TestRunObj.java +++ b/container-test/example-webapp/src/main/java/org/tuckey/web/filters/urlrewriteviacontainer/TestRunObj.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/container-test/test-with-testcontainers/src/test/java/org/tuckey/web/filters/urlrewriteviacontainer/WebappModStyleHttpITTest.java b/container-test/test-with-testcontainers/src/test/java/org/tuckey/web/filters/urlrewriteviacontainer/WebappModStyleHttpITTest.java index c6a512aa..14466c5a 100644 --- a/container-test/test-with-testcontainers/src/test/java/org/tuckey/web/filters/urlrewriteviacontainer/WebappModStyleHttpITTest.java +++ b/container-test/test-with-testcontainers/src/test/java/org/tuckey/web/filters/urlrewriteviacontainer/WebappModStyleHttpITTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/CatchElem.java b/src/main/java/org/tuckey/web/filters/urlrewrite/CatchElem.java index 512718e9..3bba790d 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/CatchElem.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/CatchElem.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/ClassRule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/ClassRule.java index 42af9269..cbd15efa 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/ClassRule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/ClassRule.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Condition.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Condition.java index 27a64256..45d72c2f 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Condition.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Condition.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/ConditionMatch.java b/src/main/java/org/tuckey/web/filters/urlrewrite/ConditionMatch.java index e2b79c82..9fe18096 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/ConditionMatch.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/ConditionMatch.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Conf.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Conf.java index 7b8068b3..f2852609 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Conf.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Conf.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/ConfHandler.java b/src/main/java/org/tuckey/web/filters/urlrewrite/ConfHandler.java index 81a3e29c..f9065a72 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/ConfHandler.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/ConfHandler.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRewrittenUrl.java b/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRewrittenUrl.java index b47492f4..884e0db6 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRewrittenUrl.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRewrittenUrl.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRule.java index ff8891d4..fdc4c0c2 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/NormalRule.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/OutboundRule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/OutboundRule.java index 98da38d7..9ca44845 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/OutboundRule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/OutboundRule.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RequestProxy.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RequestProxy.java index 663c5408..9ef65d94 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RequestProxy.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RequestProxy.java @@ -1,337 +1,337 @@ -/** - * Copyright (c) 2008, Paul Tuckey - * All rights reserved. - * ==================================================================== - * Licensed under the BSD License. Text as follows. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - Neither the name tuckey.org nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - */ -package org.tuckey.web.filters.urlrewrite; - -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HostConfiguration; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.ProxyHost; -import org.apache.commons.httpclient.SimpleHttpConnectionManager; -import org.apache.commons.httpclient.methods.*; -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Enumeration; - -/** - * This class is responsible for a proxy http request. - * It takes the incoming request and then it creates a new request to the target address and copies the response of that proxy request - * to the response of the original request. - *

    - * This class uses the commons-httpclient classes from Apache. - *

    - * User: Joachim Ansorg, jansorg AT ksi.gr - * Date: 19.06.2008 - * Time: 16:02:54 - */ -public class RequestProxy { - private static final Log log = Log.getLog(RequestProxy.class); - - /** - * This method performs the proxying of the request to the target address. - *

    - * Cookies will not be forwarded to client. - * - * @param target The target address. Has to be a fully qualified address. The request is send as-is to this address. - * @param hsRequest The request data which should be send to the - * @param hsResponse The response data which will contain the data returned by the proxied request to target. - * @throws java.io.IOException Passed on from the connection logic. - */ - public static void execute(final String target, final HttpServletRequest hsRequest, final HttpServletResponse hsResponse) throws IOException { - execute(target, hsRequest, hsResponse, true); - } - - /** - * This method performs the proxying of the request to the target address. - * - * @param target The target address. Has to be a fully qualified address. The request is send as-is to this address. - * @param hsRequest The request data which should be send to the - * @param hsResponse The response data which will contain the data returned by the proxied request to target. - * @throws java.io.IOException Passed on from the connection logic. - * @Param dropCookies Determinate whether cookies should be dropped (when {@code true}) or forwarded to client. - */ - public static void execute(final String target, final HttpServletRequest hsRequest, final HttpServletResponse hsResponse, boolean dropCookies) throws IOException { - if (log.isInfoEnabled()) { - log.info("execute, target is " + target); - log.info("response commit state: " + hsResponse.isCommitted()); - } - - if (StringUtils.isBlank(target)) { - log.error("The target address is not given. Please provide a target address."); - return; - } - - log.info("checking url"); - final URL url; - try { - url = new URL(target); - } catch (MalformedURLException e) { - log.error("The provided target url is not valid.", e); - return; - } - - log.info("seting up the host configuration"); - - final HostConfiguration config = new HostConfiguration(); - - ProxyHost proxyHost = getUseProxyServer((String) hsRequest.getAttribute("use-proxy")); - if (proxyHost != null) config.setProxyHost(proxyHost); - - final int port = url.getPort() != -1 ? url.getPort() : url.getDefaultPort(); - config.setHost(url.getHost(), port, url.getProtocol()); - - if ( log.isInfoEnabled() ) log.info("config is " + config.toString()); - - final HttpMethod targetRequest = setupProxyRequest(hsRequest, url, dropCookies); - if (targetRequest == null) { - log.error("Unsupported request method found: " + hsRequest.getMethod()); - return; - } - - //perform the reqeust to the target server - final HttpClient client = new HttpClient(new SimpleHttpConnectionManager()); - if (log.isInfoEnabled()) { - log.info("client state" + client.getState()); - log.info("client params" + client.getParams().toString()); - log.info("executeMethod / fetching data ..."); - } - - final int result; - if (targetRequest instanceof EntityEnclosingMethod) { - final RequestProxyCustomRequestEntity requestEntity = new RequestProxyCustomRequestEntity( - hsRequest.getInputStream(), hsRequest.getContentLength(), hsRequest.getContentType()); - final EntityEnclosingMethod entityEnclosingMethod = (EntityEnclosingMethod) targetRequest; - entityEnclosingMethod.setRequestEntity(requestEntity); - result = client.executeMethod(config, entityEnclosingMethod); - - } else { - result = client.executeMethod(config, targetRequest); - } - - //copy the target response headers to our response - setupResponseHeaders(targetRequest, hsResponse, dropCookies); - - InputStream originalResponseStream = targetRequest.getResponseBodyAsStream(); - //the body might be null, i.e. for responses with cache-headers which leave out the body - if (originalResponseStream != null) { - OutputStream responseStream = hsResponse.getOutputStream(); - copyStream(originalResponseStream, responseStream); - } - - log.info("set up response, result code was " + result); - } - - public static void copyStream(InputStream in, OutputStream out) throws IOException { - byte[] buf = new byte[65536]; - int count; - while ((count = in.read(buf)) != -1) { - out.write(buf, 0, count); - } - } - - - public static ProxyHost getUseProxyServer(String useProxyServer) { - ProxyHost proxyHost = null; - if (useProxyServer != null) { - String proxyHostStr = useProxyServer; - int colonIdx = proxyHostStr.indexOf(':'); - if (colonIdx != -1) { - proxyHostStr = proxyHostStr.substring(0, colonIdx); - String proxyPortStr = useProxyServer.substring(colonIdx + 1); - if (proxyPortStr != null && proxyPortStr.length() > 0 && proxyPortStr.matches("[0-9]+")) { - int proxyPort = Integer.parseInt(proxyPortStr); - proxyHost = new ProxyHost(proxyHostStr, proxyPort); - } else { - proxyHost = new ProxyHost(proxyHostStr); - } - } else { - proxyHost = new ProxyHost(proxyHostStr); - } - } - return proxyHost; - } - - private static HttpMethod setupProxyRequest(final HttpServletRequest hsRequest, final URL targetUrl, boolean dropCookies) throws IOException { - final String methodName = hsRequest.getMethod(); - final HttpMethod method; - if ("POST".equalsIgnoreCase(methodName)) { - PostMethod postMethod = new PostMethod(); - InputStreamRequestEntity inputStreamRequestEntity = new InputStreamRequestEntity(hsRequest.getInputStream()); - postMethod.setRequestEntity(inputStreamRequestEntity); - method = postMethod; - } else if ("GET".equalsIgnoreCase(methodName)) { - method = new GetMethod(); - } else if ("PUT".equalsIgnoreCase(methodName)) { - PutMethod putMethod = new PutMethod(); - InputStreamRequestEntity inputStreamRequestEntity = new InputStreamRequestEntity(hsRequest.getInputStream()); - putMethod.setRequestEntity(inputStreamRequestEntity); - method = putMethod; - } else if ("DELETE".equalsIgnoreCase(methodName)) { - method = new DeleteMethod(); - } else { - log.warn("Unsupported HTTP method requested: " + hsRequest.getMethod()); - return null; - } - - Enumeration p = hsRequest.getParameterNames(); - while (p.hasMoreElements()) { - String param = p.nextElement(); - method.getParams().setParameter(param, hsRequest.getParameter(param)); - } - - method.setFollowRedirects(false); - method.setPath(targetUrl.getPath()); - method.setQueryString(targetUrl.getQuery()); - - Enumeration e = hsRequest.getHeaderNames(); - if (e != null) { - while (e.hasMoreElements()) { - String headerName = (String) e.nextElement(); - if ("host".equalsIgnoreCase(headerName)) { - //the host value is set by the http client - continue; - } else if ("content-length".equalsIgnoreCase(headerName)) { - //the content-length is managed by the http client - continue; - } else if ("accept-encoding".equalsIgnoreCase(headerName)) { - //the accepted encoding should only be those accepted by the http client. - //The response stream should (afaik) be deflated. If our http client does not support - //gzip then the response can not be unzipped and is delivered wrong. - continue; - } else if (dropCookies && headerName.toLowerCase().startsWith("cookie")) { - //fixme : don't set any cookies in the proxied request, this needs a cleaner solution - continue; - } - - Enumeration values = hsRequest.getHeaders(headerName); - while (values.hasMoreElements()) { - String headerValue = (String) values.nextElement(); - log.info("setting proxy request parameter:" + headerName + ", value: " + headerValue); - method.addRequestHeader(headerName, headerValue); - } - } - } - - if ( log.isInfoEnabled() ) log.info("proxy query string " + method.getQueryString()); - return method; - } - - private static void setupResponseHeaders(HttpMethod httpMethod, HttpServletResponse hsResponse, boolean dropCookies) { - if (log.isInfoEnabled()) { - log.info("setupResponseHeaders"); - log.info("status text: " + httpMethod.getStatusText()); - log.info("status line: " + httpMethod.getStatusLine()); - } - - //filter the headers, which are copied from the proxy response. The http lib handles those itself. - //Filtered out: the content encoding, the content length and cookies - for (int i = 0; i < httpMethod.getResponseHeaders().length; i++) { - Header h = httpMethod.getResponseHeaders()[i]; - if ("content-encoding".equalsIgnoreCase(h.getName())) { - continue; - } else if ("content-length".equalsIgnoreCase(h.getName())) { - continue; - } else if ("transfer-encoding".equalsIgnoreCase(h.getName())) { - continue; - } else if (dropCookies) { - if (h.getName().toLowerCase().startsWith("cookie")) { - //retrieving a cookie which sets the session id will change the calling session: bad! So we skip this header. - continue; - } else if (h.getName().toLowerCase().startsWith("set-cookie")) { - //retrieving a cookie which sets the session id will change the calling session: bad! So we skip this header. - continue; - } - } - - hsResponse.setHeader(h.getName(), h.getValue()); - if ( log.isInfoEnabled() ) log.info("setting response parameter:" + h.getName() + ", value: " + h.getValue()); - } - //fixme what about the response footers? (httpMethod.getResponseFooters()) - - if (httpMethod.getStatusCode() != 200) { - hsResponse.setStatus(httpMethod.getStatusCode()); - } - } -} - -/** - * @author Gunnar Hillert - */ -class RequestProxyCustomRequestEntity implements RequestEntity { - - private InputStream is = null; - private long contentLength = 0; - private String contentType; - - public RequestProxyCustomRequestEntity(InputStream is, long contentLength, String contentType) { - super(); - this.is = is; - this.contentLength = contentLength; - this.contentType = contentType; - } - - public boolean isRepeatable() { - return true; - } - - public String getContentType() { - return this.contentType; - } - - public void writeRequest(OutputStream out) throws IOException { - - try { - int l; - byte[] buffer = new byte[10240]; - while ((l = is.read(buffer)) != -1) { - out.write(buffer, 0, l); - } - } finally { - is.close(); - } - } - - public long getContentLength() { - return this.contentLength; - } +/** + * Copyright (c) 2008, Paul Tuckey + * All rights reserved. + * ==================================================================== + * Licensed under the BSD License. Text as follows. + *

    + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + *

    + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * - Neither the name tuckey.org nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

    + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ +package org.tuckey.web.filters.urlrewrite; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HostConfiguration; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.ProxyHost; +import org.apache.commons.httpclient.SimpleHttpConnectionManager; +import org.apache.commons.httpclient.methods.*; +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; + +/** + * This class is responsible for a proxy http request. + * It takes the incoming request and then it creates a new request to the target address and copies the response of that proxy request + * to the response of the original request. + *

    + * This class uses the commons-httpclient classes from Apache. + *

    + * User: Joachim Ansorg, jansorg AT ksi.gr + * Date: 19.06.2008 + * Time: 16:02:54 + */ +public class RequestProxy { + private static final Log log = Log.getLog(RequestProxy.class); + + /** + * This method performs the proxying of the request to the target address. + *

    + * Cookies will not be forwarded to client. + * + * @param target The target address. Has to be a fully qualified address. The request is send as-is to this address. + * @param hsRequest The request data which should be send to the + * @param hsResponse The response data which will contain the data returned by the proxied request to target. + * @throws java.io.IOException Passed on from the connection logic. + */ + public static void execute(final String target, final HttpServletRequest hsRequest, final HttpServletResponse hsResponse) throws IOException { + execute(target, hsRequest, hsResponse, true); + } + + /** + * This method performs the proxying of the request to the target address. + * + * @param target The target address. Has to be a fully qualified address. The request is send as-is to this address. + * @param hsRequest The request data which should be send to the + * @param hsResponse The response data which will contain the data returned by the proxied request to target. + * @throws java.io.IOException Passed on from the connection logic. + * @Param dropCookies Determinate whether cookies should be dropped (when {@code true}) or forwarded to client. + */ + public static void execute(final String target, final HttpServletRequest hsRequest, final HttpServletResponse hsResponse, boolean dropCookies) throws IOException { + if (log.isInfoEnabled()) { + log.info("execute, target is " + target); + log.info("response commit state: " + hsResponse.isCommitted()); + } + + if (StringUtils.isBlank(target)) { + log.error("The target address is not given. Please provide a target address."); + return; + } + + log.info("checking url"); + final URL url; + try { + url = new URL(target); + } catch (MalformedURLException e) { + log.error("The provided target url is not valid.", e); + return; + } + + log.info("seting up the host configuration"); + + final HostConfiguration config = new HostConfiguration(); + + ProxyHost proxyHost = getUseProxyServer((String) hsRequest.getAttribute("use-proxy")); + if (proxyHost != null) config.setProxyHost(proxyHost); + + final int port = url.getPort() != -1 ? url.getPort() : url.getDefaultPort(); + config.setHost(url.getHost(), port, url.getProtocol()); + + if ( log.isInfoEnabled() ) log.info("config is " + config.toString()); + + final HttpMethod targetRequest = setupProxyRequest(hsRequest, url, dropCookies); + if (targetRequest == null) { + log.error("Unsupported request method found: " + hsRequest.getMethod()); + return; + } + + //perform the reqeust to the target server + final HttpClient client = new HttpClient(new SimpleHttpConnectionManager()); + if (log.isInfoEnabled()) { + log.info("client state" + client.getState()); + log.info("client params" + client.getParams().toString()); + log.info("executeMethod / fetching data ..."); + } + + final int result; + if (targetRequest instanceof EntityEnclosingMethod) { + final RequestProxyCustomRequestEntity requestEntity = new RequestProxyCustomRequestEntity( + hsRequest.getInputStream(), hsRequest.getContentLength(), hsRequest.getContentType()); + final EntityEnclosingMethod entityEnclosingMethod = (EntityEnclosingMethod) targetRequest; + entityEnclosingMethod.setRequestEntity(requestEntity); + result = client.executeMethod(config, entityEnclosingMethod); + + } else { + result = client.executeMethod(config, targetRequest); + } + + //copy the target response headers to our response + setupResponseHeaders(targetRequest, hsResponse, dropCookies); + + InputStream originalResponseStream = targetRequest.getResponseBodyAsStream(); + //the body might be null, i.e. for responses with cache-headers which leave out the body + if (originalResponseStream != null) { + OutputStream responseStream = hsResponse.getOutputStream(); + copyStream(originalResponseStream, responseStream); + } + + log.info("set up response, result code was " + result); + } + + public static void copyStream(InputStream in, OutputStream out) throws IOException { + byte[] buf = new byte[65536]; + int count; + while ((count = in.read(buf)) != -1) { + out.write(buf, 0, count); + } + } + + + public static ProxyHost getUseProxyServer(String useProxyServer) { + ProxyHost proxyHost = null; + if (useProxyServer != null) { + String proxyHostStr = useProxyServer; + int colonIdx = proxyHostStr.indexOf(':'); + if (colonIdx != -1) { + proxyHostStr = proxyHostStr.substring(0, colonIdx); + String proxyPortStr = useProxyServer.substring(colonIdx + 1); + if (proxyPortStr != null && proxyPortStr.length() > 0 && proxyPortStr.matches("[0-9]+")) { + int proxyPort = Integer.parseInt(proxyPortStr); + proxyHost = new ProxyHost(proxyHostStr, proxyPort); + } else { + proxyHost = new ProxyHost(proxyHostStr); + } + } else { + proxyHost = new ProxyHost(proxyHostStr); + } + } + return proxyHost; + } + + private static HttpMethod setupProxyRequest(final HttpServletRequest hsRequest, final URL targetUrl, boolean dropCookies) throws IOException { + final String methodName = hsRequest.getMethod(); + final HttpMethod method; + if ("POST".equalsIgnoreCase(methodName)) { + PostMethod postMethod = new PostMethod(); + InputStreamRequestEntity inputStreamRequestEntity = new InputStreamRequestEntity(hsRequest.getInputStream()); + postMethod.setRequestEntity(inputStreamRequestEntity); + method = postMethod; + } else if ("GET".equalsIgnoreCase(methodName)) { + method = new GetMethod(); + } else if ("PUT".equalsIgnoreCase(methodName)) { + PutMethod putMethod = new PutMethod(); + InputStreamRequestEntity inputStreamRequestEntity = new InputStreamRequestEntity(hsRequest.getInputStream()); + putMethod.setRequestEntity(inputStreamRequestEntity); + method = putMethod; + } else if ("DELETE".equalsIgnoreCase(methodName)) { + method = new DeleteMethod(); + } else { + log.warn("Unsupported HTTP method requested: " + hsRequest.getMethod()); + return null; + } + + Enumeration p = hsRequest.getParameterNames(); + while (p.hasMoreElements()) { + String param = p.nextElement(); + method.getParams().setParameter(param, hsRequest.getParameter(param)); + } + + method.setFollowRedirects(false); + method.setPath(targetUrl.getPath()); + method.setQueryString(targetUrl.getQuery()); + + Enumeration e = hsRequest.getHeaderNames(); + if (e != null) { + while (e.hasMoreElements()) { + String headerName = (String) e.nextElement(); + if ("host".equalsIgnoreCase(headerName)) { + //the host value is set by the http client + continue; + } else if ("content-length".equalsIgnoreCase(headerName)) { + //the content-length is managed by the http client + continue; + } else if ("accept-encoding".equalsIgnoreCase(headerName)) { + //the accepted encoding should only be those accepted by the http client. + //The response stream should (afaik) be deflated. If our http client does not support + //gzip then the response can not be unzipped and is delivered wrong. + continue; + } else if (dropCookies && headerName.toLowerCase().startsWith("cookie")) { + //fixme : don't set any cookies in the proxied request, this needs a cleaner solution + continue; + } + + Enumeration values = hsRequest.getHeaders(headerName); + while (values.hasMoreElements()) { + String headerValue = (String) values.nextElement(); + log.info("setting proxy request parameter:" + headerName + ", value: " + headerValue); + method.addRequestHeader(headerName, headerValue); + } + } + } + + if ( log.isInfoEnabled() ) log.info("proxy query string " + method.getQueryString()); + return method; + } + + private static void setupResponseHeaders(HttpMethod httpMethod, HttpServletResponse hsResponse, boolean dropCookies) { + if (log.isInfoEnabled()) { + log.info("setupResponseHeaders"); + log.info("status text: " + httpMethod.getStatusText()); + log.info("status line: " + httpMethod.getStatusLine()); + } + + //filter the headers, which are copied from the proxy response. The http lib handles those itself. + //Filtered out: the content encoding, the content length and cookies + for (int i = 0; i < httpMethod.getResponseHeaders().length; i++) { + Header h = httpMethod.getResponseHeaders()[i]; + if ("content-encoding".equalsIgnoreCase(h.getName())) { + continue; + } else if ("content-length".equalsIgnoreCase(h.getName())) { + continue; + } else if ("transfer-encoding".equalsIgnoreCase(h.getName())) { + continue; + } else if (dropCookies) { + if (h.getName().toLowerCase().startsWith("cookie")) { + //retrieving a cookie which sets the session id will change the calling session: bad! So we skip this header. + continue; + } else if (h.getName().toLowerCase().startsWith("set-cookie")) { + //retrieving a cookie which sets the session id will change the calling session: bad! So we skip this header. + continue; + } + } + + hsResponse.setHeader(h.getName(), h.getValue()); + if ( log.isInfoEnabled() ) log.info("setting response parameter:" + h.getName() + ", value: " + h.getValue()); + } + //fixme what about the response footers? (httpMethod.getResponseFooters()) + + if (httpMethod.getStatusCode() != 200) { + hsResponse.setStatus(httpMethod.getStatusCode()); + } + } +} + +/** + * @author Gunnar Hillert + */ +class RequestProxyCustomRequestEntity implements RequestEntity { + + private InputStream is = null; + private long contentLength = 0; + private String contentType; + + public RequestProxyCustomRequestEntity(InputStream is, long contentLength, String contentType) { + super(); + this.is = is; + this.contentLength = contentLength; + this.contentType = contentType; + } + + public boolean isRepeatable() { + return true; + } + + public String getContentType() { + return this.contentType; + } + + public void writeRequest(OutputStream out) throws IOException { + + try { + int l; + byte[] buffer = new byte[10240]; + while ((l = is.read(buffer)) != -1) { + out.write(buffer, 0, l); + } + } finally { + is.close(); + } + } + + public long getContentLength() { + return this.contentLength; + } } \ No newline at end of file diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenOutboundUrl.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenOutboundUrl.java index 1f68de05..3b4dfe35 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenOutboundUrl.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenOutboundUrl.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrl.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrl.java index f58d7b98..53b471a4 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrl.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrl.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlClass.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlClass.java index 06d589ec..556833e9 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlClass.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlClass.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Rule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Rule.java index ed086b44..98641b10 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Rule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Rule.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleBase.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleBase.java index 2cc1f0f7..c063cec6 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleBase.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleBase.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleChain.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleChain.java index 0010cd8c..bdadf6a2 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleChain.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleChain.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleExecutionOutput.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleExecutionOutput.java index 9e2e5f7c..78419902 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RuleExecutionOutput.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RuleExecutionOutput.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Run.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Run.java index 1c74647f..aeb8e298 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Run.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Run.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/RunConfig.java b/src/main/java/org/tuckey/web/filters/urlrewrite/RunConfig.java index 5b070185..62dad115 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/RunConfig.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/RunConfig.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Runnable.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Runnable.java index c8bdf9b8..51b539a6 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Runnable.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Runnable.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/SetAttribute.java b/src/main/java/org/tuckey/web/filters/urlrewrite/SetAttribute.java index c0676353..186c54c7 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/SetAttribute.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/SetAttribute.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -309,16 +309,16 @@ public boolean initialise() { /** * takes a string a number expression and converts it to a long. * syntax: number type - * + *

    * Valid examples: "1 day", "2 days", "1 hour", "1 hour 2 minutes", "34 months" - * + *

    * Any positive number is valid - * + *

    * Valid types are: years, months, weeks, days, hours, minutes, seconds - * + *

    * note, this syntax is a direct copy of mod_expires syntax * http://httpd.apache.org/docs/2.0/mod/mod_expires.html - * + *

    * note, a year is calculated as 365.25 days and a month as 365.25 days divided by 12. */ protected long parseTimeValue(String parsingValue) { diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/Status.java b/src/main/java/org/tuckey/web/filters/urlrewrite/Status.java index 83478566..5ce354a1 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/Status.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/Status.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/TypeConverter.java b/src/main/java/org/tuckey/web/filters/urlrewrite/TypeConverter.java index 9502064e..2449f193 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/TypeConverter.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/TypeConverter.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteDocTask.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteDocTask.java index 5394e4a3..9a995e99 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteDocTask.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteDocTask.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilter.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilter.java index cb90909b..1a4de935 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilter.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilter.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteServlet.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteServlet.java index 3b11327f..8cf40b80 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteServlet.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteServlet.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -52,7 +52,7 @@ * Servlet for use if you cannot load filters in your environment for some strange reason. This will * work very differently from the filter (obviously), but it can be used for "run" items where there * is no "to". - * + *

    * This servlet just loads an instance of the filter and calls it as if it were the container. */ public class UrlRewriteServlet extends HttpServlet { diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedRequest.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedRequest.java index 0d38481d..8ea8edce 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedRequest.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedRequest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponse.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponse.java index 33629c7d..4a99a2d0 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponse.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponse.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriter.java b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriter.java index 2aa878cb..6d93aa07 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriter.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/UrlRewriter.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteMatch.java b/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteMatch.java index 211b0aa5..1873be10 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteMatch.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteMatch.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -56,7 +56,7 @@ public String getMatchingUrl() { /** * If this rule has been matched and has not been "stolen" by another rule then process the request. - * + *

    * If you return true then the filter chain will NOT continue. * * @return boolean true if the request was rewritten, false if not. diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteRule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteRule.java index ee0a0142..9e02cde3 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteRule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/extend/RewriteRule.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/FilterServletOutputStream.java b/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/FilterServletOutputStream.java index a7bcfa75..cafd2170 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/FilterServletOutputStream.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/FilterServletOutputStream.java @@ -3,16 +3,16 @@ /** * Modified version of: * http://svn.terracotta.org/svn/ehcache/trunk/web/web/src/main/java/net/sf/ehcache/constructs/web/filter/FilterServletOutputStream.java - * + *

    * * Copyright 2003-2009 Terracotta, 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. diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/GenericResponseWrapper.java b/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/GenericResponseWrapper.java index 9cb11ccc..90b03a34 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/GenericResponseWrapper.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/GenericResponseWrapper.java @@ -3,16 +3,16 @@ /** * Modified version of: * http://svn.terracotta.org/svn/ehcache/trunk/web/web/src/main/java/net/sf/ehcache/constructs/web/GenericResponseWrapper.java - * + *

    * * Copyright 2003-2009 Terracotta, 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. diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/GzipFilter.java b/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/GzipFilter.java index 3ead9fc0..18c594cf 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/GzipFilter.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/GzipFilter.java @@ -3,15 +3,15 @@ /** * Modified version of: * http://svn.terracotta.org/svn/ehcache/trunk/web/web/src/main/java/net/sf/ehcache/constructs/web/filter/GzipFilter.java - * + *

    * Copyright 2003-2009 Terracotta, 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. diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/ResponseUtil.java b/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/ResponseUtil.java index a128e241..eb562beb 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/ResponseUtil.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/gzip/ResponseUtil.java @@ -3,16 +3,16 @@ /** * Modified version of: * http://svn.terracotta.org/svn/ehcache/trunk/web/web/src/main/java/net/sf/ehcache/constructs/web/ResponseUtil.java - * + *

    * * Copyright 2003-2009 Terracotta, 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. diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatch.java b/src/main/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatch.java index 051f65d1..73595016 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatch.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatch.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteMatch.java b/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteMatch.java index 7be22824..8fb8ccc6 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteMatch.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteMatch.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteRule.java b/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteRule.java index 9de0a9d7..c5496c05 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteRule.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/sample/SampleRewriteRule.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/BackReferenceReplacer.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/BackReferenceReplacer.java index f875bf81..094eeb7a 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/BackReferenceReplacer.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/BackReferenceReplacer.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/FunctionReplacer.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/FunctionReplacer.java index 3688af69..519d2dc2 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/FunctionReplacer.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/FunctionReplacer.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/MatcherReplacer.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/MatcherReplacer.java index d5bdfde7..8e763d8a 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/MatcherReplacer.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/MatcherReplacer.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/PatternReplacer.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/PatternReplacer.java index e35a7f6d..8fe0ad26 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/PatternReplacer.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/PatternReplacer.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/UnescapeReplacer.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/UnescapeReplacer.java index 45130ffa..f3eb94b3 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/UnescapeReplacer.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/UnescapeReplacer.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/VariableReplacer.java b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/VariableReplacer.java index ab6eda6c..fa0b1dc3 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/VariableReplacer.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/substitution/VariableReplacer.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/Log.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/Log.java index 7cf9230a..31227a6a 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/Log.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/Log.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/NumberUtils.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/NumberUtils.java index ea31957b..ed6e7b92 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/NumberUtils.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/NumberUtils.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexMatcher.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexMatcher.java index 5925991c..78db6a22 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexMatcher.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexMatcher.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexPattern.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexPattern.java index dae84de4..25743744 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexPattern.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/RegexPattern.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/ServerNameMatcher.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/ServerNameMatcher.java index 795f68e5..b1b53510 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/ServerNameMatcher.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/ServerNameMatcher.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcher.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcher.java index 11497f13..aac0e6bf 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcher.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcher.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPattern.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPattern.java index 54af487f..4346a333 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPattern.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPattern.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPatternSyntaxException.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPatternSyntaxException.java index f20c7db0..90164acc 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPatternSyntaxException.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingPatternSyntaxException.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringUtils.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringUtils.java index 1035adea..1bc2b981 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringUtils.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/StringUtils.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLEncoder.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLEncoder.java index c9a20dd7..173c413f 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLEncoder.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/URLEncoder.java @@ -182,7 +182,7 @@ public class URLEncoder { /** * pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | "," - * + *

    * Note: we don't allow escaped here since we will escape it ourselves, so we don't want to allow them in the * unescaped sequences */ diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardHelper.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardHelper.java index 66366a04..86c7e83b 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardHelper.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardHelper.java @@ -1,422 +1,422 @@ -/** - * This class is a modified version of one found in Apache Cocoon. - * - * Copyright 2003-2004 The Apache Software Foundation. - * - * 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 org.tuckey.web.filters.urlrewrite.utils; - - -import java.util.Map; - -/** - * This class is an utility class that perform wilcard-patterns matching and - * isolation taken from Apache Cocoon. - * - * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ - */ -public class WildcardHelper { - - /** - * The int representing '*' in the pattern int []. - */ - protected static final int MATCH_FILE = -1; - - /** - * The int representing '**' in the pattern int []. - */ - protected static final int MATCH_PATH = -2; - - /** - * The int representing begin in the pattern int []. - */ - protected static final int MATCH_BEGIN = -4; - - /** - * The int representing end in pattern int []. - */ - protected static final int MATCH_THEEND = -5; - - /** - * The int value that terminates the pattern int []. - */ - protected static final int MATCH_END = -3; - - - /** - * Translate the given String into a int [] - * representing the pattern matchable by this class. - *
    - * This function translates a String into an int array - * converting the special '*' and '\' characters. - *
    - * Here is how the conversion algorithm works: - *

    - * When more than two '*' characters, not separated by another character, - * are found their value is considered as '**' (MATCH_PATH). - *
    - * The array is always terminated by a special value (MATCH_END). - *
    - * All MATCH* values are less than zero, while normal characters are equal - * or greater. - * - * @param data The string to translate. - * @return The encoded string as an int array, terminated by the MATCH_END - * value (don't consider the array length). - * @throws NullPointerException If data is null. - */ - public int[] compilePattern(String data) { - - // Prepare the arrays - int expr[] = new int[data.length() + 2]; - char buff[] = data.toCharArray(); - - // Prepare variables for the translation loop - int y = 0; - boolean slash = false; - - // Must start from beginning - expr[y++] = MATCH_BEGIN; - - if (buff.length > 0) { - if (buff[0] == '\\') { - slash = true; - } else if (buff[0] == '*') { - expr[y++] = MATCH_FILE; - } else { - expr[y++] = buff[0]; - } - - // Main translation loop - for (int x = 1; x < buff.length; x++) { - // If the previous char was '\' simply copy this char. - if (slash) { - expr[y++] = buff[x]; - slash = false; - // If the previous char was not '\' we have to do a bunch of - // checks - } else { - // If this char is '\' declare that and continue - if (buff[x] == '\\') { - slash = true; - // If this char is '*' check the previous one - } else if (buff[x] == '*') { - // If the previous character als was '*' match a path - if (expr[y - 1] <= MATCH_FILE) { - expr[y - 1] = MATCH_PATH; - } else { - expr[y++] = MATCH_FILE; - } - } else { - expr[y++] = buff[x]; - } - } - } - } - - // Must match end at the end - expr[y] = MATCH_THEEND; - return expr; - } - - /** - * Match a pattern agains a string and isolates wildcard replacement into a - * Stack. - * - * @param map The map to store matched values - * @param data The string to match - * @param expr The compiled wildcard expression - * @return True if a match - * @throws NullPointerException If any parameters are null - */ - public boolean match(Map map, String data, int[] expr) { - if (map == null) { - throw new NullPointerException("No map provided"); - } - if (data == null) { - throw new NullPointerException("No data provided"); - } - if (expr == null) { - throw new NullPointerException("No pattern expression provided"); - } - - - char buff[] = data.toCharArray(); - // Allocate the result buffer - char rslt[] = new char[expr.length + buff.length]; - - // The previous and current position of the expression character - // (MATCH_*) - int charpos = 0; - - // The position in the expression, input, translation and result arrays - int exprpos = 0; - int buffpos = 0; - int rsltpos = 0; - int offset; - - // The matching count - int mcount = 0; - - // We want the complete data be in {0} - map.put(Integer.toString(mcount), data); - - // First check for MATCH_BEGIN - boolean matchBegin = false; - if (expr[charpos] == MATCH_BEGIN) { - matchBegin = true; - exprpos = ++charpos; - } - - // Search the fist expression character (except MATCH_BEGIN - already - // skipped) - while (expr[charpos] >= 0) { - charpos++; - } - - // The expression charater (MATCH_*) - int exprchr = expr[charpos]; - - while (true) { - // Check if the data in the expression array before the current - // expression character matches the data in the input buffer - if (matchBegin) { - if (!matchArray(expr, exprpos, charpos, buff, buffpos)) { - return (false); - } - matchBegin = false; - } else { - offset = indexOfArray(expr, exprpos, charpos, buff, - buffpos); - if (offset < 0) { - return (false); - } - } - - // Advance buffpos - buffpos += (charpos - exprpos); - - // Check for END's - if (exprchr == MATCH_END) { - if (rsltpos > 0) { - map.put(Integer.toString(++mcount), - new String(rslt, 0, rsltpos)); - } - // Don't care about rest of input buffer - return (true); - } else if (exprchr == MATCH_THEEND) { - if (rsltpos > 0) { - map.put(Integer.toString(++mcount), - new String(rslt, 0, rsltpos)); - } - // Check that we reach buffer's end - return (buffpos == buff.length); - } - - // Search the next expression character - exprpos = ++charpos; - while (expr[charpos] >= 0) { - charpos++; - } - int prevchr = exprchr; - exprchr = expr[charpos]; - - // We have here prevchr == * or **. - offset = (prevchr == MATCH_FILE) - ? indexOfArray(expr, exprpos, charpos, buff, buffpos) - : lastIndexOfArray(expr, exprpos, charpos, buff, - buffpos); - - if (offset < 0) { - return (false); - } - - // Copy the data from the source buffer into the result buffer - // to substitute the expression character - if (prevchr == MATCH_PATH) { - while (buffpos < offset) { - rslt[rsltpos++] = buff[buffpos++]; - } - } else { - // Matching file, don't copy '/' - while (buffpos < offset) { - if (buff[buffpos] == '/') { - return (false); - } - rslt[rsltpos++] = buff[buffpos++]; - } - } - - map.put(Integer.toString(++mcount), new String(rslt, 0, rsltpos)); - rsltpos = 0; - } - } - - /** - * Get the offset of a part of an int array within a char array. - *
    - * This method return the index in d of the first occurrence after dpos of - * that part of array specified by r, starting at rpos and terminating at - * rend. - * - * @param r The array containing the data that need to be matched in d. - * @param rpos The index of the first character in r to look for. - * @param rend The index of the last character in r to look for plus 1. - * @param d The array of char that should contain a part of r. - * @param dpos The starting offset in d for the matching. - * @return The offset in d of the part of r matched in d or -1 if that was - * not found. - */ - protected int indexOfArray(int r[], int rpos, int rend, - char d[], int dpos) { - - // Check if pos and len are legal - if (rend < rpos) { - throw new IllegalArgumentException("rend < rpos"); - } - // If we need to match a zero length string return current dpos - if (rend == rpos) { - return (d.length); //?? dpos? - } - // If we need to match a 1 char length string do it simply - if ((rend - rpos) == 1) { - // Search for the specified character - for (int x = dpos; x < d.length; x++) { - if (r[rpos] == d[x]) { - return (x); - } - } - } - // Main string matching loop. It gets executed if the characters to - // match are less then the characters left in the d buffer - while ((dpos + rend - rpos) <= d.length) { - // Set current startpoint in d - int y = dpos; - // Check every character in d for equity. If the string is matched - // return dpos - for (int x = rpos; x <= rend; x++) { - if (x == rend) { - return (dpos); - } - if (r[x] != d[y++]) { - break; - } - } - // Increase dpos to search for the same string at next offset - dpos++; - } - // The remaining chars in d buffer were not enough or the string - // wasn't matched - return (-1); - } - - /** - * Get the offset of a last occurance of an int array within a char array. - *
    - * This method return the index in d of the last occurrence after dpos of - * that part of array specified by r, starting at rpos and terminating at - * rend. - * - * @param r The array containing the data that need to be matched in d. - * @param rpos The index of the first character in r to look for. - * @param rend The index of the last character in r to look for plus 1. - * @param d The array of char that should contain a part of r. - * @param dpos The starting offset in d for the matching. - * @return The offset in d of the last part of r matched in d or -1 if - * that was not found. - */ - protected int lastIndexOfArray(int r[], int rpos, int rend, - char d[], int dpos) { - // Check if pos and len are legal - if (rend < rpos) { - throw new IllegalArgumentException("rend < rpos"); - } - // If we need to match a zero length string return current dpos - if (rend == rpos) { - return (d.length); //?? dpos? - } - - // If we need to match a 1 char length string do it simply - if ((rend - rpos) == 1) { - // Search for the specified character - for (int x = d.length - 1; x > dpos; x--) { - if (r[rpos] == d[x]) { - return (x); - } - } - } - - // Main string matching loop. It gets executed if the characters to - // match are less then the characters left in the d buffer - int l = d.length - (rend - rpos); - while (l >= dpos) { - // Set current startpoint in d - int y = l; - // Check every character in d for equity. If the string is matched - // return dpos - for (int x = rpos; x <= rend; x++) { - if (x == rend) { - return (l); - } - if (r[x] != d[y++]) { - break; - } - } - // Decrease l to search for the same string at next offset - l--; - } - // The remaining chars in d buffer were not enough or the string - // wasn't matched - return (-1); - } - - /** - * Matches elements of array r from rpos to rend with array d, starting - * from dpos. - *
    - * This method return true if elements of array r from rpos to rend - * equals elements of array d starting from dpos to dpos+(rend-rpos). - * - * @param r The array containing the data that need to be matched in d. - * @param rpos The index of the first character in r to look for. - * @param rend The index of the last character in r to look for. - * @param d The array of char that should start from a part of r. - * @param dpos The starting offset in d for the matching. - * @return true if array d starts from portion of array r. - */ - protected boolean matchArray(int r[], int rpos, int rend, - char d[], int dpos) { - if (d.length - dpos < rend - rpos) { - return (false); - } - for (int i = rpos; i < rend; i++) { - if (r[i] != d[dpos++]) { - return (false); - } - } - return (true); - } +/** + * This class is a modified version of one found in Apache Cocoon. + *

    + * Copyright 2003-2004 The Apache Software Foundation. + *

    + * 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 org.tuckey.web.filters.urlrewrite.utils; + + +import java.util.Map; + +/** + * This class is an utility class that perform wilcard-patterns matching and + * isolation taken from Apache Cocoon. + * + * @version $Revision: 1 $ $Date: 2006-08-01 21:40:28 +1200 (Tue, 01 Aug 2006) $ + */ +public class WildcardHelper { + + /** + * The int representing '*' in the pattern int []. + */ + protected static final int MATCH_FILE = -1; + + /** + * The int representing '**' in the pattern int []. + */ + protected static final int MATCH_PATH = -2; + + /** + * The int representing begin in the pattern int []. + */ + protected static final int MATCH_BEGIN = -4; + + /** + * The int representing end in pattern int []. + */ + protected static final int MATCH_THEEND = -5; + + /** + * The int value that terminates the pattern int []. + */ + protected static final int MATCH_END = -3; + + + /** + * Translate the given String into a int [] + * representing the pattern matchable by this class. + *
    + * This function translates a String into an int array + * converting the special '*' and '\' characters. + *
    + * Here is how the conversion algorithm works: + *

    + * When more than two '*' characters, not separated by another character, + * are found their value is considered as '**' (MATCH_PATH). + *
    + * The array is always terminated by a special value (MATCH_END). + *
    + * All MATCH* values are less than zero, while normal characters are equal + * or greater. + * + * @param data The string to translate. + * @return The encoded string as an int array, terminated by the MATCH_END + * value (don't consider the array length). + * @throws NullPointerException If data is null. + */ + public int[] compilePattern(String data) { + + // Prepare the arrays + int expr[] = new int[data.length() + 2]; + char buff[] = data.toCharArray(); + + // Prepare variables for the translation loop + int y = 0; + boolean slash = false; + + // Must start from beginning + expr[y++] = MATCH_BEGIN; + + if (buff.length > 0) { + if (buff[0] == '\\') { + slash = true; + } else if (buff[0] == '*') { + expr[y++] = MATCH_FILE; + } else { + expr[y++] = buff[0]; + } + + // Main translation loop + for (int x = 1; x < buff.length; x++) { + // If the previous char was '\' simply copy this char. + if (slash) { + expr[y++] = buff[x]; + slash = false; + // If the previous char was not '\' we have to do a bunch of + // checks + } else { + // If this char is '\' declare that and continue + if (buff[x] == '\\') { + slash = true; + // If this char is '*' check the previous one + } else if (buff[x] == '*') { + // If the previous character als was '*' match a path + if (expr[y - 1] <= MATCH_FILE) { + expr[y - 1] = MATCH_PATH; + } else { + expr[y++] = MATCH_FILE; + } + } else { + expr[y++] = buff[x]; + } + } + } + } + + // Must match end at the end + expr[y] = MATCH_THEEND; + return expr; + } + + /** + * Match a pattern agains a string and isolates wildcard replacement into a + * Stack. + * + * @param map The map to store matched values + * @param data The string to match + * @param expr The compiled wildcard expression + * @return True if a match + * @throws NullPointerException If any parameters are null + */ + public boolean match(Map map, String data, int[] expr) { + if (map == null) { + throw new NullPointerException("No map provided"); + } + if (data == null) { + throw new NullPointerException("No data provided"); + } + if (expr == null) { + throw new NullPointerException("No pattern expression provided"); + } + + + char buff[] = data.toCharArray(); + // Allocate the result buffer + char rslt[] = new char[expr.length + buff.length]; + + // The previous and current position of the expression character + // (MATCH_*) + int charpos = 0; + + // The position in the expression, input, translation and result arrays + int exprpos = 0; + int buffpos = 0; + int rsltpos = 0; + int offset; + + // The matching count + int mcount = 0; + + // We want the complete data be in {0} + map.put(Integer.toString(mcount), data); + + // First check for MATCH_BEGIN + boolean matchBegin = false; + if (expr[charpos] == MATCH_BEGIN) { + matchBegin = true; + exprpos = ++charpos; + } + + // Search the fist expression character (except MATCH_BEGIN - already + // skipped) + while (expr[charpos] >= 0) { + charpos++; + } + + // The expression charater (MATCH_*) + int exprchr = expr[charpos]; + + while (true) { + // Check if the data in the expression array before the current + // expression character matches the data in the input buffer + if (matchBegin) { + if (!matchArray(expr, exprpos, charpos, buff, buffpos)) { + return (false); + } + matchBegin = false; + } else { + offset = indexOfArray(expr, exprpos, charpos, buff, + buffpos); + if (offset < 0) { + return (false); + } + } + + // Advance buffpos + buffpos += (charpos - exprpos); + + // Check for END's + if (exprchr == MATCH_END) { + if (rsltpos > 0) { + map.put(Integer.toString(++mcount), + new String(rslt, 0, rsltpos)); + } + // Don't care about rest of input buffer + return (true); + } else if (exprchr == MATCH_THEEND) { + if (rsltpos > 0) { + map.put(Integer.toString(++mcount), + new String(rslt, 0, rsltpos)); + } + // Check that we reach buffer's end + return (buffpos == buff.length); + } + + // Search the next expression character + exprpos = ++charpos; + while (expr[charpos] >= 0) { + charpos++; + } + int prevchr = exprchr; + exprchr = expr[charpos]; + + // We have here prevchr == * or **. + offset = (prevchr == MATCH_FILE) + ? indexOfArray(expr, exprpos, charpos, buff, buffpos) + : lastIndexOfArray(expr, exprpos, charpos, buff, + buffpos); + + if (offset < 0) { + return (false); + } + + // Copy the data from the source buffer into the result buffer + // to substitute the expression character + if (prevchr == MATCH_PATH) { + while (buffpos < offset) { + rslt[rsltpos++] = buff[buffpos++]; + } + } else { + // Matching file, don't copy '/' + while (buffpos < offset) { + if (buff[buffpos] == '/') { + return (false); + } + rslt[rsltpos++] = buff[buffpos++]; + } + } + + map.put(Integer.toString(++mcount), new String(rslt, 0, rsltpos)); + rsltpos = 0; + } + } + + /** + * Get the offset of a part of an int array within a char array. + *
    + * This method return the index in d of the first occurrence after dpos of + * that part of array specified by r, starting at rpos and terminating at + * rend. + * + * @param r The array containing the data that need to be matched in d. + * @param rpos The index of the first character in r to look for. + * @param rend The index of the last character in r to look for plus 1. + * @param d The array of char that should contain a part of r. + * @param dpos The starting offset in d for the matching. + * @return The offset in d of the part of r matched in d or -1 if that was + * not found. + */ + protected int indexOfArray(int r[], int rpos, int rend, + char d[], int dpos) { + + // Check if pos and len are legal + if (rend < rpos) { + throw new IllegalArgumentException("rend < rpos"); + } + // If we need to match a zero length string return current dpos + if (rend == rpos) { + return (d.length); //?? dpos? + } + // If we need to match a 1 char length string do it simply + if ((rend - rpos) == 1) { + // Search for the specified character + for (int x = dpos; x < d.length; x++) { + if (r[rpos] == d[x]) { + return (x); + } + } + } + // Main string matching loop. It gets executed if the characters to + // match are less then the characters left in the d buffer + while ((dpos + rend - rpos) <= d.length) { + // Set current startpoint in d + int y = dpos; + // Check every character in d for equity. If the string is matched + // return dpos + for (int x = rpos; x <= rend; x++) { + if (x == rend) { + return (dpos); + } + if (r[x] != d[y++]) { + break; + } + } + // Increase dpos to search for the same string at next offset + dpos++; + } + // The remaining chars in d buffer were not enough or the string + // wasn't matched + return (-1); + } + + /** + * Get the offset of a last occurance of an int array within a char array. + *
    + * This method return the index in d of the last occurrence after dpos of + * that part of array specified by r, starting at rpos and terminating at + * rend. + * + * @param r The array containing the data that need to be matched in d. + * @param rpos The index of the first character in r to look for. + * @param rend The index of the last character in r to look for plus 1. + * @param d The array of char that should contain a part of r. + * @param dpos The starting offset in d for the matching. + * @return The offset in d of the last part of r matched in d or -1 if + * that was not found. + */ + protected int lastIndexOfArray(int r[], int rpos, int rend, + char d[], int dpos) { + // Check if pos and len are legal + if (rend < rpos) { + throw new IllegalArgumentException("rend < rpos"); + } + // If we need to match a zero length string return current dpos + if (rend == rpos) { + return (d.length); //?? dpos? + } + + // If we need to match a 1 char length string do it simply + if ((rend - rpos) == 1) { + // Search for the specified character + for (int x = d.length - 1; x > dpos; x--) { + if (r[rpos] == d[x]) { + return (x); + } + } + } + + // Main string matching loop. It gets executed if the characters to + // match are less then the characters left in the d buffer + int l = d.length - (rend - rpos); + while (l >= dpos) { + // Set current startpoint in d + int y = l; + // Check every character in d for equity. If the string is matched + // return dpos + for (int x = rpos; x <= rend; x++) { + if (x == rend) { + return (l); + } + if (r[x] != d[y++]) { + break; + } + } + // Decrease l to search for the same string at next offset + l--; + } + // The remaining chars in d buffer were not enough or the string + // wasn't matched + return (-1); + } + + /** + * Matches elements of array r from rpos to rend with array d, starting + * from dpos. + *
    + * This method return true if elements of array r from rpos to rend + * equals elements of array d starting from dpos to dpos+(rend-rpos). + * + * @param r The array containing the data that need to be matched in d. + * @param rpos The index of the first character in r to look for. + * @param rend The index of the last character in r to look for. + * @param d The array of char that should start from a part of r. + * @param dpos The starting offset in d for the matching. + * @return true if array d starts from portion of array r. + */ + protected boolean matchArray(int r[], int rpos, int rend, + char d[], int dpos) { + if (d.length - dpos < rend - rpos) { + return (false); + } + for (int i = rpos; i < rend; i++) { + if (r[i] != d[dpos++]) { + return (false); + } + } + return (true); + } } \ No newline at end of file diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardMatcher.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardMatcher.java index 3b3d16e1..aad503c7 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardMatcher.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardMatcher.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardPattern.java b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardPattern.java index 21c1e5c4..903fe20f 100644 --- a/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardPattern.java +++ b/src/main/java/org/tuckey/web/filters/urlrewrite/utils/WildcardPattern.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/ConfTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/ConfTest.java index 954183b2..297a6f90 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/ConfTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/ConfTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/OutboundRuleTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/OutboundRuleTest.java index c95e8eb4..f9c950e7 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/OutboundRuleTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/OutboundRuleTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlTest.java index 2ad2455d..ad59eb87 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/RewrittenUrlTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/RuleTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/RuleTest.java index 4aa47580..a0a69aa2 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/RuleTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/RuleTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/RunTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/RunTest.java index a7272fc1..b60c9e13 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/RunTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/RunTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/SetAttributeTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/SetAttributeTest.java index 6d79b71d..eb6bf2b0 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/SetAttributeTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/SetAttributeTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/StatusTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/StatusTest.java index 157a9c33..4649f6fd 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/StatusTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/StatusTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/TestRewriteMatch.java b/src/test/java/org/tuckey/web/filters/urlrewrite/TestRewriteMatch.java index 95255c79..01ecdd30 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/TestRewriteMatch.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/TestRewriteMatch.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/TestRuleObj.java b/src/test/java/org/tuckey/web/filters/urlrewrite/TestRuleObj.java index aef0a02c..771e93da 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/TestRuleObj.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/TestRuleObj.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/TestServlet.java b/src/test/java/org/tuckey/web/filters/urlrewrite/TestServlet.java index 86462a58..f28be40c 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/TestServlet.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/TestServlet.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlDecoderTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlDecoderTest.java index 914a73db..e2b9faf8 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlDecoderTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlDecoderTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilterTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilterTest.java index 2262c130..645305bd 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilterTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilterTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteTestCaseTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteTestCaseTest.java index adede1f8..cc23f0b8 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteTestCaseTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteTestCaseTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponseTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponseTest.java index 28dcf3c4..caf27b81 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponseTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriteWrappedResponseTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriterTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriterTest.java index 83ad802b..45352f18 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriterTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/UrlRewriterTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatchTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatchTest.java index 304e0783..7892cc9e 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatchTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/json/JsonRewriteMatchTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRequestParser.java b/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRequestParser.java index 0d847af2..0d7d1b77 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRequestParser.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRequestParser.java @@ -1,128 +1,128 @@ -package org.tuckey.web.filters.urlrewrite.test; - -import org.tuckey.web.filters.urlrewrite.utils.Log; -import org.tuckey.web.filters.urlrewrite.utils.StringUtils; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * todo: IN PROGRESS - * - * Class to decode a request from one of three inputs. Literally: - * - * /blah.jsp - * - * or - * - * GET /blah.jsp HTTP/1.1 - * - * or - * - * GET /blah.jsp HTTP/1.1 - * user-agent: Mozilla 1.2.3 - * cookie: a:aaa - * - */ -public class MockRequestParser { - - private static Log log = Log.getLog(MockRequestParser.class); - - public MockRequest decodeRequest(String requestString) { - return decodeRequest(requestString.split("\n")); - } - - Pattern FIRST_LINE_PATTERN = Pattern.compile("^([A-Z]+) (.*) ([A-Z0-9/\\.]+)$"); - - public MockRequest decodeRequest(String[] requestLines) { - MockRequest request = new MockRequest(); - request.setRemoteAddr("127.0.0.1"); - request.setRemoteHost("localhost"); - - String line1 = requestLines[0]; - Matcher line1Matcher = FIRST_LINE_PATTERN.matcher(line1); - - String requestPart; - if (line1Matcher.matches()) { - request.setMethod(line1Matcher.group(1)); - requestPart = line1Matcher.group(2); - request.setScheme(line1Matcher.group(3)); - } else { - requestPart = line1; - } - - String requestUri = requestPart; - int questionMarkIdx = requestPart.indexOf('?'); - if (questionMarkIdx != -1) { - String queryString = requestPart.substring(questionMarkIdx + 1); - setParams(request, queryString); - requestUri = requestPart.substring(0, questionMarkIdx); - } - int semiColonIdx = requestUri.indexOf(';'); - if (semiColonIdx != -1) { - String sessionId = requestUri.substring(semiColonIdx + 1); - int equalsIdx = sessionId.indexOf('='); - if ( equalsIdx != -1 ) { - sessionId = sessionId.substring(equalsIdx+1); - } - request.setRequestedSessionId(sessionId); - requestUri = requestUri.substring(0, semiColonIdx); - } - request.setRequestURI(requestUri); - - if (requestLines.length > 1) { - boolean parsingBody = false; - for (int i = 0; i < requestLines.length; i++) { - if (i == 0) continue; - String line = requestLines[i]; - if (!parsingBody) { - if (line.length() == 0) { - parsingBody = true; - continue; - } - int colonIdx = line.indexOf(':'); - if (colonIdx < 1) { - log.debug("cannot parse line " + line); - continue; - } - String headerName = StringUtils.trimToNull(line.substring(0, colonIdx)); - String headerValue = StringUtils.trimToNull(line.substring(colonIdx + 1)); - if (headerName == null) { - log.debug("cannot parse line " + line); - continue; - } - request.setHeader(headerName, headerValue); - if ("host".equals(headerName.toLowerCase())) { - request.setServerName(headerValue); - } - } else { - setParams(request, line); - } - } - } - return request; - } - - private void setParams(MockRequest request, String queryString) { - request.setQueryString(queryString); - if (queryString.indexOf('&') != -1) { - String[] paramSets = queryString.split("&"); - for (int i = 0; i < paramSets.length; i++) { - addParamSet(request, paramSets[i]); - } - } else { - addParamSet(request, queryString); - } - } - - private void addParamSet(MockRequest request, String paramSet) { - if (paramSet.indexOf("=") != -1) { - String[] nameVal = paramSet.split("=", 2); - request.addParameter(nameVal[0], nameVal[1]); - } else { - log.info("cannot find value of request parameter " + paramSet); - } - } - - -} +package org.tuckey.web.filters.urlrewrite.test; + +import org.tuckey.web.filters.urlrewrite.utils.Log; +import org.tuckey.web.filters.urlrewrite.utils.StringUtils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * todo: IN PROGRESS + *

    + * Class to decode a request from one of three inputs. Literally: + *

    + * /blah.jsp + *

    + * or + *

    + * GET /blah.jsp HTTP/1.1 + *

    + * or + *

    + * GET /blah.jsp HTTP/1.1 + * user-agent: Mozilla 1.2.3 + * cookie: a:aaa + * + */ +public class MockRequestParser { + + private static Log log = Log.getLog(MockRequestParser.class); + + public MockRequest decodeRequest(String requestString) { + return decodeRequest(requestString.split("\n")); + } + + Pattern FIRST_LINE_PATTERN = Pattern.compile("^([A-Z]+) (.*) ([A-Z0-9/\\.]+)$"); + + public MockRequest decodeRequest(String[] requestLines) { + MockRequest request = new MockRequest(); + request.setRemoteAddr("127.0.0.1"); + request.setRemoteHost("localhost"); + + String line1 = requestLines[0]; + Matcher line1Matcher = FIRST_LINE_PATTERN.matcher(line1); + + String requestPart; + if (line1Matcher.matches()) { + request.setMethod(line1Matcher.group(1)); + requestPart = line1Matcher.group(2); + request.setScheme(line1Matcher.group(3)); + } else { + requestPart = line1; + } + + String requestUri = requestPart; + int questionMarkIdx = requestPart.indexOf('?'); + if (questionMarkIdx != -1) { + String queryString = requestPart.substring(questionMarkIdx + 1); + setParams(request, queryString); + requestUri = requestPart.substring(0, questionMarkIdx); + } + int semiColonIdx = requestUri.indexOf(';'); + if (semiColonIdx != -1) { + String sessionId = requestUri.substring(semiColonIdx + 1); + int equalsIdx = sessionId.indexOf('='); + if ( equalsIdx != -1 ) { + sessionId = sessionId.substring(equalsIdx+1); + } + request.setRequestedSessionId(sessionId); + requestUri = requestUri.substring(0, semiColonIdx); + } + request.setRequestURI(requestUri); + + if (requestLines.length > 1) { + boolean parsingBody = false; + for (int i = 0; i < requestLines.length; i++) { + if (i == 0) continue; + String line = requestLines[i]; + if (!parsingBody) { + if (line.length() == 0) { + parsingBody = true; + continue; + } + int colonIdx = line.indexOf(':'); + if (colonIdx < 1) { + log.debug("cannot parse line " + line); + continue; + } + String headerName = StringUtils.trimToNull(line.substring(0, colonIdx)); + String headerValue = StringUtils.trimToNull(line.substring(colonIdx + 1)); + if (headerName == null) { + log.debug("cannot parse line " + line); + continue; + } + request.setHeader(headerName, headerValue); + if ("host".equals(headerName.toLowerCase())) { + request.setServerName(headerValue); + } + } else { + setParams(request, line); + } + } + } + return request; + } + + private void setParams(MockRequest request, String queryString) { + request.setQueryString(queryString); + if (queryString.indexOf('&') != -1) { + String[] paramSets = queryString.split("&"); + for (int i = 0; i < paramSets.length; i++) { + addParamSet(request, paramSets[i]); + } + } else { + addParamSet(request, queryString); + } + } + + private void addParamSet(MockRequest request, String paramSet) { + if (paramSet.indexOf("=") != -1) { + String[] nameVal = paramSet.split("=", 2); + request.addParameter(nameVal[0], nameVal[1]); + } else { + log.info("cannot find value of request parameter " + paramSet); + } + } + + +} diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRewriteMatch.java b/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRewriteMatch.java index 6a69bc18..c37a642b 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRewriteMatch.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/test/MockRewriteMatch.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/test/TestRunObj.java b/src/test/java/org/tuckey/web/filters/urlrewrite/test/TestRunObj.java index c88864dd..0caa9e13 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/test/TestRunObj.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/test/TestRunObj.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/utils/LogTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/utils/LogTest.java index 6f2d250a..7a817a37 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/utils/LogTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/utils/LogTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcherTest.java b/src/test/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcherTest.java index 6983dfa4..7f2a520f 100644 --- a/src/test/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcherTest.java +++ b/src/test/java/org/tuckey/web/filters/urlrewrite/utils/StringMatchingMatcherTest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/testhelper/BenchmarkRunner.java b/src/test/java/org/tuckey/web/testhelper/BenchmarkRunner.java index a8b941ab..ca51e9ee 100644 --- a/src/test/java/org/tuckey/web/testhelper/BenchmarkRunner.java +++ b/src/test/java/org/tuckey/web/testhelper/BenchmarkRunner.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/testhelper/MockFilterChain.java b/src/test/java/org/tuckey/web/testhelper/MockFilterChain.java index 2866f303..58135e1f 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockFilterChain.java +++ b/src/test/java/org/tuckey/web/testhelper/MockFilterChain.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/testhelper/MockFilterConfig.java b/src/test/java/org/tuckey/web/testhelper/MockFilterConfig.java index 776c993c..33cda02c 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockFilterConfig.java +++ b/src/test/java/org/tuckey/web/testhelper/MockFilterConfig.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/testhelper/MockRequest.java b/src/test/java/org/tuckey/web/testhelper/MockRequest.java index e412abaf..c3e07bd2 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockRequest.java +++ b/src/test/java/org/tuckey/web/testhelper/MockRequest.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/testhelper/MockRequestDispatcher.java b/src/test/java/org/tuckey/web/testhelper/MockRequestDispatcher.java index f0baba09..4281a3e4 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockRequestDispatcher.java +++ b/src/test/java/org/tuckey/web/testhelper/MockRequestDispatcher.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS diff --git a/src/test/java/org/tuckey/web/testhelper/MockResponse.java b/src/test/java/org/tuckey/web/testhelper/MockResponse.java index 661e4ac0..d5e9b04b 100644 --- a/src/test/java/org/tuckey/web/testhelper/MockResponse.java +++ b/src/test/java/org/tuckey/web/testhelper/MockResponse.java @@ -3,11 +3,11 @@ * All rights reserved. * ==================================================================== * Licensed under the BSD License. Text as follows. - * + *

    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + *

    * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * - Neither the name tuckey.org nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. - * + *

    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS From c8931eaeb879cb58e38badae26ee37b20055c56b Mon Sep 17 00:00:00 2001 From: Paul Tuckey Date: Mon, 3 Jul 2023 09:47:34 +1200 Subject: [PATCH 3/3] progress --- .../filters/urlrewrite/dtds/urlrewrite1.0.dtd | 103 +++++--- .../filters/urlrewrite/dtds/urlrewrite2.0.dtd | 113 +++++---- .../filters/urlrewrite/dtds/urlrewrite2.3.dtd | 163 +++++++------ .../filters/urlrewrite/dtds/urlrewrite2.4.dtd | 163 +++++++------ .../filters/urlrewrite/dtds/urlrewrite2.5.dtd | 167 +++++++------ .../filters/urlrewrite/dtds/urlrewrite2.6.dtd | 167 +++++++------ .../filters/urlrewrite/dtds/urlrewrite3.0.dtd | 205 +++++++++------- .../filters/urlrewrite/dtds/urlrewrite3.1.dtd | 205 +++++++++------- .../filters/urlrewrite/dtds/urlrewrite3.2.dtd | 209 ++++++++++------- .../filters/urlrewrite/dtds/urlrewrite3.3.dtd | 217 +++++++++-------- .../filters/urlrewrite/dtds/urlrewrite4.0.dtd | 221 ++++++++++-------- 11 files changed, 1126 insertions(+), 807 deletions(-) diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite1.0.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite1.0.dtd index 9f211981..c1e809d9 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite1.0.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite1.0.dtd @@ -1,37 +1,66 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.0.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.0.dtd index 18caf3b9..a2646a2c 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.0.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.0.dtd @@ -1,42 +1,71 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.3.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.3.dtd index 53d67799..9d2a3348 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.3.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.3.dtd @@ -1,67 +1,96 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.4.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.4.dtd index 85fdcfd8..3da110c4 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.4.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.4.dtd @@ -1,67 +1,96 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.5.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.5.dtd index e586251c..50e14fa2 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.5.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.5.dtd @@ -1,69 +1,98 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.6.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.6.dtd index df87494d..9088f4e7 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.6.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite2.6.dtd @@ -1,69 +1,98 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.0.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.0.dtd index afac561c..8a78b7b2 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.0.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.0.dtd @@ -1,88 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.1.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.1.dtd index ec6b1317..e360a073 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.1.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.1.dtd @@ -1,88 +1,117 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.2.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.2.dtd index 5c221d42..2c3886fc 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.2.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.2.dtd @@ -1,90 +1,119 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.3.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.3.dtd index bb812a3a..c0f211f7 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.3.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite3.3.dtd @@ -1,94 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite4.0.dtd b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite4.0.dtd index 60fa3aab..b97658d8 100644 --- a/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite4.0.dtd +++ b/src/main/resources/org/tuckey/web/filters/urlrewrite/dtds/urlrewrite4.0.dtd @@ -1,96 +1,125 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +