From db1479e571a30f5f20ed0e7e1107e5bfec04ea6f Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 8 Sep 2009 20:31:00 +0000 Subject: [PATCH] Merging from revision 787:HEAD on /branches/jetty-7.0.1/ to /trunk/ * Bumping up version to 7.0.1-SNAPSHOT * Adding jetty-webapp-verifier from /sandbox/ * Changes to jetty-webapp for jetty-centralized-logging from /sandbox/ * Fixes to jetty-policy to support jetty-webapp-verifier git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@835 7e9141cc-0065-0410-87d8-b60c137991c4 --- example-jetty-embedded/pom.xml | 2 +- jetty-aggregate/jetty-all-server/pom.xml | 2 +- jetty-aggregate/jetty-all/pom.xml | 2 +- jetty-aggregate/jetty-client/pom.xml | 2 +- jetty-aggregate/jetty-plus/pom.xml | 2 +- jetty-aggregate/jetty-server/pom.xml | 2 +- jetty-aggregate/jetty-servlet/pom.xml | 2 +- jetty-aggregate/jetty-webapp/pom.xml | 2 +- jetty-aggregate/pom.xml | 2 +- jetty-ajp/pom.xml | 2 +- jetty-annotations/pom.xml | 2 +- jetty-client/pom.xml | 2 +- jetty-continuation/pom.xml | 2 +- jetty-deploy/pom.xml | 2 +- jetty-distribution/pom.xml | 23 +- jetty-http/pom.xml | 2 +- jetty-io/pom.xml | 2 +- jetty-jaspi/pom.xml | 2 +- jetty-jmx/pom.xml | 2 +- jetty-jndi/pom.xml | 2 +- jetty-plus/pom.xml | 2 +- jetty-policy/pom.xml | 2 +- .../src/main/config/etc/jetty-policy.xml | 23 + .../org/eclipse/jetty/policy/JettyPolicy.java | 10 +- .../jetty/policy/JettyPolicyConfigurator.java | 58 ++ jetty-rewrite/pom.xml | 2 +- jetty-security/pom.xml | 2 +- jetty-server/pom.xml | 2 +- jetty-servlet/pom.xml | 2 +- jetty-servlets/pom.xml | 2 +- jetty-start/pom.xml | 2 +- jetty-util/pom.xml | 2 +- jetty-webapp-verifier/.gitignore | 9 + jetty-webapp-verifier/pom.xml | 111 ++++ .../etc/jetty-waver-default-ruleset.xml | 32 + .../verifier/AbstractArchiveScanningRule.java | 94 +++ .../jetty/webapp/verifier/AbstractRule.java | 215 +++++++ .../eclipse/jetty/webapp/verifier/Rule.java | 222 +++++++ .../jetty/webapp/verifier/RuleSet.java | 89 +++ .../jetty/webapp/verifier/Severity.java | 39 ++ .../jetty/webapp/verifier/Violation.java | 186 ++++++ .../webapp/verifier/ViolationComparator.java | 49 ++ .../webapp/verifier/ViolationListener.java | 21 + .../jetty/webapp/verifier/WebappVerifier.java | 570 ++++++++++++++++++ .../verifier/rules/ForbiddenClassesRule.java | 90 +++ .../verifier/rules/ForbiddenContentsRule.java | 58 ++ .../verifier/rules/JarSignatureRule.java | 231 +++++++ .../verifier/rules/JavaSupportLevelRule.java | 166 +++++ .../verifier/rules/JspPrecompileRule.java | 43 ++ .../verifier/rules/JspSupportLevelRule.java | 43 ++ .../webapp/verifier/rules/NoJspRule.java | 46 ++ .../webapp/verifier/rules/NoNativeRule.java | 68 +++ .../verifier/rules/NoScriptingRule.java | 235 ++++++++ .../verifier/rules/NoSourceControlRule.java | 151 +++++ .../webapp/verifier/rules/NoSourceRule.java | 70 +++ .../verifier/rules/RequiredContentsRule.java | 64 ++ .../verifier/rules/SaneArchiveRule.java | 59 ++ .../rules/ServletSupportLevelRule.java | 374 ++++++++++++ .../webapp/verifier/rules/asm/ASMUtil.java | 54 ++ .../rules/asm/AbstractClassVisitor.java | 77 +++ .../webapp/verifier/support/PathGlob.java | 58 ++ .../src/test/artifacts/.gitignore | 11 + .../artifacts/dummy-groovy-lib/.gitignore | 8 + .../test/artifacts/dummy-groovy-lib/pom.xml | 9 + .../services/javax.script.ScriptEngineFactory | 1 + .../src/main/resources/README.txt | 4 + .../artifacts/dummy-groovy-webapp/.gitignore | 8 + .../artifacts/dummy-groovy-webapp/pom.xml | 22 + .../src/main/webapp/README.txt | 4 + .../src/main/webapp/WEB-INF/web.xml | 7 + .../src/main/webapp/dummy.groovy | 0 .../src/main/webapp/other/lib.groovy | 0 .../artifacts/dummy-java11-lib/.gitignore | 8 + .../test/artifacts/dummy-java11-lib/pom.xml | 20 + .../jetty/testcase/verifier/DummyLib.java | 27 + .../src/main/resources/README.txt | 3 + .../artifacts/dummy-java12-lib/.gitignore | 8 + .../test/artifacts/dummy-java12-lib/pom.xml | 20 + .../testcase/verifier/DummyUpdatedLib.java | 27 + .../src/main/resources/README.txt | 3 + .../artifacts/dummy-java13-lib/.gitignore | 8 + .../test/artifacts/dummy-java13-lib/pom.xml | 20 + .../testcase/verifier/DummyCurrentLib.java | 27 + .../src/main/resources/README.txt | 3 + .../artifacts/dummy-java14-lib/.gitignore | 8 + .../test/artifacts/dummy-java14-lib/pom.xml | 20 + .../testcase/verifier/DummyFreshLib.java | 27 + .../src/main/resources/README.txt | 3 + .../artifacts/dummy-java15-lib/.gitignore | 8 + .../test/artifacts/dummy-java15-lib/pom.xml | 20 + .../testcase/verifier/DummyLatestLib.java | 27 + .../src/main/resources/README.txt | 3 + .../artifacts/dummy-java16-lib/.gitignore | 8 + .../test/artifacts/dummy-java16-lib/pom.xml | 20 + .../testcase/verifier/DummyModernLib.java | 27 + .../src/main/resources/README.txt | 3 + .../dummy-javaversions-webapp/.gitignore | 8 + .../dummy-javaversions-webapp/pom.xml | 84 +++ .../src/main/webapp/README.txt | 4 + .../src/main/webapp/WEB-INF/web.xml | 7 + .../test/artifacts/dummy-jruby-lib/.gitignore | 8 + .../test/artifacts/dummy-jruby-lib/pom.xml | 9 + .../src/main/resources/README.txt | 4 + .../src/main/resources/builtin/javasupport.rb | 0 .../artifacts/dummy-jruby-webapp/.gitignore | 8 + .../test/artifacts/dummy-jruby-webapp/pom.xml | 22 + .../src/main/webapp/README.txt | 4 + .../src/main/webapp/WEB-INF/web.xml | 7 + .../src/main/webapp/example.rb | 0 .../src/main/webapp/other/lib.rb | 0 .../src/main/webapp/output.rhtml | 0 .../artifacts/dummy-jython-lib/.gitignore | 8 + .../test/artifacts/dummy-jython-lib/pom.xml | 9 + .../src/main/java/org/python/Version.java | 28 + .../org/python/core/JythonInitializer.java | 28 + .../main/java/org/python/util/Generic.java | 28 + .../src/main/resources/README.txt | 4 + .../artifacts/dummy-jython-webapp/.gitignore | 8 + .../artifacts/dummy-jython-webapp/pom.xml | 22 + .../src/main/webapp/README.txt | 4 + .../src/main/webapp/WEB-INF/web.xml | 7 + .../src/main/webapp/dummy.py | 0 .../src/main/webapp/dummy.pyc | 0 .../src/main/webapp/other/lib.py | 0 .../dummy-nativeaccess-webapp/.gitignore | 8 + .../dummy-nativeaccess-webapp/pom.xml | 17 + .../src/main/webapp/README.txt | 4 + .../src/main/webapp/WEB-INF/web.xml | 7 + .../src/main/webapp/dummy.exe | 0 .../src/main/webapp/dummy.o | 0 .../src/main/webapp/dummy.so | 0 .../src/main/webapp/executable | 0 .../src/main/webapp/other/lib.dll | 0 .../src/main/webapp/other/lib.o | 0 .../src/main/webapp/other/lib.so | 0 .../src/main/webapp/other/lib.so.0.5.7 | 0 .../src/main/webapp/other/lib.so.1 | 0 .../src/main/webapp/other/lib.so.5 | 0 .../test/artifacts/dummy-scm-lib/.gitignore | 8 + .../src/test/artifacts/dummy-scm-lib/pom.xml | 84 +++ .../src/main/resources/README.txt | 3 + .../artifacts/dummy-scm-webapp/.gitignore | 8 + .../test/artifacts/dummy-scm-webapp/pom.xml | 116 ++++ .../src/main/webapp/README.txt | 4 + .../src/main/webapp/WEB-INF/web.xml | 7 + .../dummy-servlet23-webapp/.gitignore | 8 + .../artifacts/dummy-servlet23-webapp/pom.xml | 9 + .../src/main/webapp/WEB-INF/web.xml | 7 + .../dummy-servlet24-webapp/.gitignore | 8 + .../artifacts/dummy-servlet24-webapp/pom.xml | 9 + .../src/main/webapp/WEB-INF/web.xml | 10 + .../dummy-servlet25-webapp/.gitignore | 8 + .../artifacts/dummy-servlet25-webapp/pom.xml | 9 + .../src/main/webapp/WEB-INF/web.xml | 9 + .../dummy-servletmixed1-webapp/.gitignore | 8 + .../dummy-servletmixed1-webapp/pom.xml | 9 + .../src/main/webapp/WEB-INF/web.xml | 9 + .../dummy-servletmixed2-webapp/.gitignore | 8 + .../dummy-servletmixed2-webapp/pom.xml | 9 + .../src/main/webapp/WEB-INF/web.xml | 8 + .../dummy-shellscripts-webapp/.gitignore | 8 + .../dummy-shellscripts-webapp/pom.xml | 17 + .../src/main/webapp/README.txt | 4 + .../src/main/webapp/WEB-INF/web.xml | 7 + .../src/main/webapp/dummy.bat | 0 .../src/main/webapp/dummy.cmd | 0 .../src/main/webapp/dummy.sh | 0 .../src/main/webapp/dummy.vbs | 0 .../src/main/webapp/other/lib.bat | 0 .../src/main/webapp/other/lib.cmd | 0 .../src/main/webapp/other/lib.sh | 0 .../src/main/webapp/other/lib.vbs | 0 .../src/test/artifacts/pom.xml | 36 ++ .../verifier/AbstractTestWebappVerifier.java | 46 ++ .../jetty/webapp/verifier/CountingRule.java | 126 ++++ .../webapp/verifier/MavenTestingUtils.java | 166 +++++ .../jetty/webapp/verifier/PathAssert.java | 40 ++ .../jetty/webapp/verifier/RuleAssert.java | 184 ++++++ .../jetty/webapp/verifier/RuleAssertTest.java | 33 + .../jetty/webapp/verifier/RuleSetTest.java | 36 ++ .../webapp/verifier/WebappVerifierTest.java | 63 ++ .../verifier/rules/JarSignatureRuleTest.java | 39 ++ .../rules/JavaSupportLevelRuleTest.java | 18 + .../verifier/rules/NoNativeRuleTest.java | 13 + .../verifier/rules/NoScriptingRuleTest.java | 42 ++ .../rules/NoSourceControlRuleTest.java | 31 + .../rules/ServletSupportLevelRuleTest.java | 33 + .../src/test/resources/basic-ruleset.xml | 23 + .../content-verifier/WEB-INF/web.xml | 1 + .../test/resources/java_level_1.4.config.xml | 14 + .../resources/java_level_1.4.expectations.txt | 4 + .../test/resources/java_level_1.4.setup.txt | 1 + .../test/resources/java_level_1.5.config.xml | 14 + .../resources/java_level_1.5.expectations.txt | 2 + .../test/resources/java_level_1.5.setup.txt | 1 + .../src/test/resources/no_native.config.xml | 12 + .../test/resources/no_native.expectations.txt | 6 + .../src/test/resources/no_native.setup.txt | 1 + .../src/test/resources/no_scm.config.xml | 12 + .../test/resources/no_scm.expectations.txt | 36 ++ .../src/test/resources/no_scm.setup.txt | 1 + .../resources/no_scripting_groovy.config.xml | 14 + .../no_scripting_groovy.expectations.txt | 4 + .../resources/no_scripting_groovy.setup.txt | 1 + .../resources/no_scripting_jruby.config.xml | 14 + .../no_scripting_jruby.expectations.txt | 6 + .../resources/no_scripting_jruby.setup.txt | 1 + .../resources/no_scripting_jython.config.xml | 14 + .../no_scripting_jython.expectations.txt | 6 + .../resources/no_scripting_jython.setup.txt | 1 + .../resources/no_scripting_shell.config.xml | 14 + .../no_scripting_shell.expectations.txt | 8 + .../resources/no_scripting_shell.setup.txt | 1 + .../resources/servlet_level_2.3.config.xml | 14 + .../servlet_level_2.3.expectations.txt | 2 + .../resources/servlet_level_2.3.setup.txt | 1 + .../resources/servlet_level_2.4.config.xml | 14 + .../servlet_level_2.4.expectations.txt | 3 + .../resources/servlet_level_2.4.setup.txt | 1 + .../resources/servlet_level_2.5.config.xml | 14 + .../servlet_level_2.5.expectations.txt | 3 + .../resources/servlet_level_2.5.setup.txt | 1 + .../servlet_level_mixed_2.3_2.4.config.xml | 14 + ...rvlet_level_mixed_2.3_2.4.expectations.txt | 14 + .../servlet_level_mixed_2.3_2.4.setup.txt | 1 + .../servlet_level_mixed_2.3_2.5.config.xml | 14 + ...rvlet_level_mixed_2.3_2.5.expectations.txt | 15 + .../servlet_level_mixed_2.3_2.5.setup.txt | 1 + .../src/test/resources/webapps/README.txt | 10 + .../resources/webapps/dummy-groovy-webapp.war | Bin 0 -> 5519 bytes .../webapps/dummy-javaversions-webapp.war | Bin 0 -> 16665 bytes .../resources/webapps/dummy-jruby-webapp.war | Bin 0 -> 5210 bytes .../resources/webapps/dummy-jython-webapp.war | Bin 0 -> 5107 bytes .../webapps/dummy-nativeaccess-webapp.war | Bin 0 -> 3561 bytes .../resources/webapps/dummy-scm-webapp.war | Bin 0 -> 3718 bytes .../webapps/dummy-servlet23-webapp.war | Bin 0 -> 2118 bytes .../webapps/dummy-servlet24-webapp.war | Bin 0 -> 2172 bytes .../webapps/dummy-servlet25-webapp.war | Bin 0 -> 2173 bytes .../webapps/dummy-servletmixed1-webapp.war | Bin 0 -> 2287 bytes .../webapps/dummy-servletmixed2-webapp.war | Bin 0 -> 2216 bytes .../webapps/dummy-shellscripts-webapp.war | Bin 0 -> 3343 bytes .../webapps/signed-jar-test-webapp.war | Bin 0 -> 110306 bytes jetty-webapp/pom.xml | 7 +- .../eclipse/jetty/webapp/WebAppContext.java | 138 +++-- .../webapp/WebappVerifierConfiguration.java | 97 +++ jetty-xml/pom.xml | 2 +- pom.xml | 3 +- test-continuation-jetty6/pom.xml | 2 +- test-continuation/pom.xml | 2 +- test-jetty-servlet/pom.xml | 2 +- test-jetty-webapp/pom.xml | 2 +- tests/pom.xml | 2 +- tests/test-integration/pom.xml | 2 +- tests/test-webapps/pom.xml | 2 +- .../test-webapp-logging-commons/pom.xml | 2 +- .../test-webapp-logging-java/pom.xml | 2 +- .../test-webapp-logging-log4j/pom.xml | 2 +- .../test-webapp-logging-slf4j/pom.xml | 2 +- .../test-webapps/test-webapp-rfc2616/pom.xml | 2 +- 259 files changed, 6282 insertions(+), 86 deletions(-) create mode 100644 jetty-policy/src/main/config/etc/jetty-policy.xml create mode 100644 jetty-policy/src/main/java/org/eclipse/jetty/policy/JettyPolicyConfigurator.java create mode 100644 jetty-webapp-verifier/.gitignore create mode 100644 jetty-webapp-verifier/pom.xml create mode 100644 jetty-webapp-verifier/src/main/config/etc/jetty-waver-default-ruleset.xml create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/AbstractArchiveScanningRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/AbstractRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Rule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/RuleSet.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Severity.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Violation.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/ViolationComparator.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/ViolationListener.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/WebappVerifier.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ForbiddenClassesRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ForbiddenContentsRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JarSignatureRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JavaSupportLevelRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JspPrecompileRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JspSupportLevelRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoJspRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoNativeRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoScriptingRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceControlRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/RequiredContentsRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/SaneArchiveRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ServletSupportLevelRule.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/asm/ASMUtil.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/asm/AbstractClassVisitor.java create mode 100644 jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/support/PathGlob.java create mode 100644 jetty-webapp-verifier/src/test/artifacts/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/src/main/resources/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/dummy.groovy create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/other/lib.groovy create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyLib.java create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/src/main/resources/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyUpdatedLib.java create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/src/main/resources/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyCurrentLib.java create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/src/main/resources/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyFreshLib.java create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/src/main/resources/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyLatestLib.java create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/src/main/resources/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyModernLib.java create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/src/main/resources/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/src/main/webapp/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/src/main/resources/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/src/main/resources/builtin/javasupport.rb create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/example.rb create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/other/lib.rb create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/output.rhtml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/Version.java create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/core/JythonInitializer.java create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/util/Generic.java create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/resources/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/dummy.py create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/dummy.pyc create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/other/lib.py create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/dummy.exe create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/dummy.o create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/dummy.so create mode 100755 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/executable create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.dll create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.o create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so.0.5.7 create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so.1 create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so.5 create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/src/main/resources/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/src/main/webapp/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/.gitignore create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/pom.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/README.txt create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.bat create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.cmd create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.sh create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.vbs create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.bat create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.cmd create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.sh create mode 100644 jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.vbs create mode 100644 jetty-webapp-verifier/src/test/artifacts/pom.xml create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/AbstractTestWebappVerifier.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/CountingRule.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/MavenTestingUtils.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/PathAssert.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleAssert.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleAssertTest.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleSetTest.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/WebappVerifierTest.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/JarSignatureRuleTest.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/JavaSupportLevelRuleTest.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoNativeRuleTest.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoScriptingRuleTest.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceControlRuleTest.java create mode 100644 jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/ServletSupportLevelRuleTest.java create mode 100644 jetty-webapp-verifier/src/test/resources/basic-ruleset.xml create mode 100644 jetty-webapp-verifier/src/test/resources/content-verifier/WEB-INF/web.xml create mode 100644 jetty-webapp-verifier/src/test/resources/java_level_1.4.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/java_level_1.4.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/java_level_1.4.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/java_level_1.5.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/java_level_1.5.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/java_level_1.5.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_native.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/no_native.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_native.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_scm.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/no_scm.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_scm.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_groovy.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_groovy.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_groovy.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_jruby.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_jruby.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_jruby.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_jython.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_jython.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_jython.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_shell.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_shell.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/no_scripting_shell.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_2.3.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_2.3.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_2.3.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_2.4.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_2.4.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_2.4.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_2.5.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_2.5.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_2.5.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.config.xml create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.expectations.txt create mode 100644 jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.setup.txt create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/README.txt create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-groovy-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-javaversions-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-jruby-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-jython-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-nativeaccess-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-scm-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-servlet23-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-servlet24-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-servlet25-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-servletmixed1-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-servletmixed2-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/dummy-shellscripts-webapp.war create mode 100644 jetty-webapp-verifier/src/test/resources/webapps/signed-jar-test-webapp.war create mode 100644 jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebappVerifierConfiguration.java diff --git a/example-jetty-embedded/pom.xml b/example-jetty-embedded/pom.xml index 82d1dacbc72..5a7822d306f 100644 --- a/example-jetty-embedded/pom.xml +++ b/example-jetty-embedded/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 example-jetty-embedded diff --git a/jetty-aggregate/jetty-all-server/pom.xml b/jetty-aggregate/jetty-all-server/pom.xml index 77408e07cf6..615ac853116 100644 --- a/jetty-aggregate/jetty-all-server/pom.xml +++ b/jetty-aggregate/jetty-all-server/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty.aggregate jetty-aggregate-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 org.eclipse.jetty.aggregate diff --git a/jetty-aggregate/jetty-all/pom.xml b/jetty-aggregate/jetty-all/pom.xml index 139b372af22..723f4f8e7d9 100644 --- a/jetty-aggregate/jetty-all/pom.xml +++ b/jetty-aggregate/jetty-all/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty.aggregate jetty-aggregate-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 org.eclipse.jetty.aggregate diff --git a/jetty-aggregate/jetty-client/pom.xml b/jetty-aggregate/jetty-client/pom.xml index 6a5b360590d..2fed88be398 100644 --- a/jetty-aggregate/jetty-client/pom.xml +++ b/jetty-aggregate/jetty-client/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty.aggregate jetty-aggregate-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 org.eclipse.jetty.aggregate diff --git a/jetty-aggregate/jetty-plus/pom.xml b/jetty-aggregate/jetty-plus/pom.xml index be6d2925625..c818785f2cc 100644 --- a/jetty-aggregate/jetty-plus/pom.xml +++ b/jetty-aggregate/jetty-plus/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty.aggregate jetty-aggregate-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 org.eclipse.jetty.aggregate diff --git a/jetty-aggregate/jetty-server/pom.xml b/jetty-aggregate/jetty-server/pom.xml index 814319dce79..62a3ec7b9d7 100644 --- a/jetty-aggregate/jetty-server/pom.xml +++ b/jetty-aggregate/jetty-server/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty.aggregate jetty-aggregate-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 org.eclipse.jetty.aggregate diff --git a/jetty-aggregate/jetty-servlet/pom.xml b/jetty-aggregate/jetty-servlet/pom.xml index 581dad5c190..c7d3712856b 100644 --- a/jetty-aggregate/jetty-servlet/pom.xml +++ b/jetty-aggregate/jetty-servlet/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty.aggregate jetty-aggregate-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 org.eclipse.jetty.aggregate diff --git a/jetty-aggregate/jetty-webapp/pom.xml b/jetty-aggregate/jetty-webapp/pom.xml index af964317763..aea41b912d5 100644 --- a/jetty-aggregate/jetty-webapp/pom.xml +++ b/jetty-aggregate/jetty-webapp/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty.aggregate jetty-aggregate-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 org.eclipse.jetty.aggregate diff --git a/jetty-aggregate/pom.xml b/jetty-aggregate/pom.xml index 462ae76b087..16b432b6dd1 100644 --- a/jetty-aggregate/pom.xml +++ b/jetty-aggregate/pom.xml @@ -4,7 +4,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT org.eclipse.jetty.aggregate jetty-aggregate-project diff --git a/jetty-ajp/pom.xml b/jetty-ajp/pom.xml index e1c53733111..f88269051c4 100644 --- a/jetty-ajp/pom.xml +++ b/jetty-ajp/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-ajp diff --git a/jetty-annotations/pom.xml b/jetty-annotations/pom.xml index 2a7d4a40607..563d77e2197 100644 --- a/jetty-annotations/pom.xml +++ b/jetty-annotations/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-annotations diff --git a/jetty-client/pom.xml b/jetty-client/pom.xml index 85ad3f179f4..feab2d4d74b 100644 --- a/jetty-client/pom.xml +++ b/jetty-client/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-client diff --git a/jetty-continuation/pom.xml b/jetty-continuation/pom.xml index 552995a1229..2b1cd033338 100644 --- a/jetty-continuation/pom.xml +++ b/jetty-continuation/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-continuation diff --git a/jetty-deploy/pom.xml b/jetty-deploy/pom.xml index 91039d72d5f..2e42e687e94 100644 --- a/jetty-deploy/pom.xml +++ b/jetty-deploy/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-deploy diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml index 42dd09e601d..8f5c1e3e5a9 100644 --- a/jetty-distribution/pom.xml +++ b/jetty-distribution/pom.xml @@ -3,7 +3,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT jetty-distribution Jetty :: Distribution Assemblies @@ -140,6 +140,16 @@ ** ${assembly.directory} + + org.eclipse.jetty + jetty-webapp-verifier + ${project.version} + config + jar + true + ** + ${assembly.directory} + org.eclipse.jetty jetty-plus @@ -261,6 +271,15 @@ true ** ${assembly.directory}/lib + + + org.eclipse.jetty + jetty-webapp-verifier + ${project.version} + jar + true + ** + ${assembly.directory}/lib org.eclipse.jetty @@ -496,4 +515,4 @@ ${project.version} - \ No newline at end of file + diff --git a/jetty-http/pom.xml b/jetty-http/pom.xml index 912cc35c341..d1fa2afd272 100644 --- a/jetty-http/pom.xml +++ b/jetty-http/pom.xml @@ -2,7 +2,7 @@ jetty-project org.eclipse.jetty - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 org.eclipse.jetty diff --git a/jetty-io/pom.xml b/jetty-io/pom.xml index 1226373759b..46f1957b987 100644 --- a/jetty-io/pom.xml +++ b/jetty-io/pom.xml @@ -2,7 +2,7 @@ jetty-project org.eclipse.jetty - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 org.eclipse.jetty diff --git a/jetty-jaspi/pom.xml b/jetty-jaspi/pom.xml index 0721cb962b4..e56dd6ef1a0 100644 --- a/jetty-jaspi/pom.xml +++ b/jetty-jaspi/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-jaspi diff --git a/jetty-jmx/pom.xml b/jetty-jmx/pom.xml index 18bad4a4acc..9456c3789a6 100644 --- a/jetty-jmx/pom.xml +++ b/jetty-jmx/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-jmx diff --git a/jetty-jndi/pom.xml b/jetty-jndi/pom.xml index 574e1393a13..596600ee0a8 100644 --- a/jetty-jndi/pom.xml +++ b/jetty-jndi/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-jndi diff --git a/jetty-plus/pom.xml b/jetty-plus/pom.xml index 9396114f385..2195586e4c5 100644 --- a/jetty-plus/pom.xml +++ b/jetty-plus/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-plus diff --git a/jetty-policy/pom.xml b/jetty-policy/pom.xml index 9307e573c5c..b87d7ea525e 100644 --- a/jetty-policy/pom.xml +++ b/jetty-policy/pom.xml @@ -3,7 +3,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT org.eclipse.jetty jetty-policy diff --git a/jetty-policy/src/main/config/etc/jetty-policy.xml b/jetty-policy/src/main/config/etc/jetty-policy.xml new file mode 100644 index 00000000000..6d8848cc4bc --- /dev/null +++ b/jetty-policy/src/main/config/etc/jetty-policy.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + /lib/policy/jetty.policy + + + + jetty.home + + + + + diff --git a/jetty-policy/src/main/java/org/eclipse/jetty/policy/JettyPolicy.java b/jetty-policy/src/main/java/org/eclipse/jetty/policy/JettyPolicy.java index ac9b0379643..04b105d82be 100644 --- a/jetty-policy/src/main/java/org/eclipse/jetty/policy/JettyPolicy.java +++ b/jetty-policy/src/main/java/org/eclipse/jetty/policy/JettyPolicy.java @@ -73,6 +73,8 @@ public class JettyPolicy extends Policy public JettyPolicy(Set policies, Map properties) { + System.out.println("Activating the JettyPolicy"); + try { __DEBUG = Boolean.getBoolean("org.eclipse.jetty.policy.DEBUG"); @@ -288,11 +290,13 @@ public class JettyPolicy extends Policy initialize(); } - for (Iterator i = _cache.keySet().iterator(); i.hasNext();) + synchronized (_cache) { - System.out.println(i.next().toString()); + for (Iterator i = _cache.keySet().iterator(); i.hasNext();) + { + System.out.println(i.next().toString()); + } } - if (__DEBUG) { diff --git a/jetty-policy/src/main/java/org/eclipse/jetty/policy/JettyPolicyConfigurator.java b/jetty-policy/src/main/java/org/eclipse/jetty/policy/JettyPolicyConfigurator.java new file mode 100644 index 00000000000..d397a1f5dda --- /dev/null +++ b/jetty-policy/src/main/java/org/eclipse/jetty/policy/JettyPolicyConfigurator.java @@ -0,0 +1,58 @@ +package org.eclipse.jetty.policy; + +//======================================================================== +//Copyright (c) Webtide LLC +//------------------------------------------------------------------------ +//All rights reserved. This program and the accompanying materials +//are made available under the terms of the Eclipse Public License v1.0 +//and Apache License v2.0 which accompanies this distribution. +// +//The Eclipse Public License is available at +//http://www.eclipse.org/legal/epl-v10.html +// +//The Apache License v2.0 is available at +//http://www.opensource.org/licenses/apache2.0.php +// +//You may elect to redistribute this code under either of these licenses. +//======================================================================== + +import java.security.Policy; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * + * + */ +public class JettyPolicyConfigurator +{ + Set _policies= new HashSet(); + Map _properties = new HashMap(); + + public JettyPolicyConfigurator() + { + + } + + public void addPolicy( String policy ) + { + _policies.add(policy); + } + + public void addProperty( String name, String value ) + { + _properties.put(name,value); + } + + public void initialize() + { + System.out.println("Initializing Jetty Policy"); + + JettyPolicy jpolicy = new JettyPolicy( _policies, _properties ); + Policy.setPolicy(jpolicy); + System.setSecurityManager(new SecurityManager()); + } + +} diff --git a/jetty-rewrite/pom.xml b/jetty-rewrite/pom.xml index af06f3668e1..651e3226cdc 100644 --- a/jetty-rewrite/pom.xml +++ b/jetty-rewrite/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-rewrite diff --git a/jetty-security/pom.xml b/jetty-security/pom.xml index 26b6d607ba1..04e3856c314 100644 --- a/jetty-security/pom.xml +++ b/jetty-security/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-security diff --git a/jetty-server/pom.xml b/jetty-server/pom.xml index dd2dd1fb3a4..7d6c692bf82 100644 --- a/jetty-server/pom.xml +++ b/jetty-server/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-server diff --git a/jetty-servlet/pom.xml b/jetty-servlet/pom.xml index 6280c65d32d..a9d1938e861 100644 --- a/jetty-servlet/pom.xml +++ b/jetty-servlet/pom.xml @@ -3,7 +3,7 @@ jetty-project org.eclipse.jetty - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-servlet diff --git a/jetty-servlets/pom.xml b/jetty-servlets/pom.xml index 56e9a8a5e91..093c2cbe2ef 100644 --- a/jetty-servlets/pom.xml +++ b/jetty-servlets/pom.xml @@ -3,7 +3,7 @@ jetty-project org.eclipse.jetty - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-servlets diff --git a/jetty-start/pom.xml b/jetty-start/pom.xml index 5edab24bfc0..27b583c8551 100644 --- a/jetty-start/pom.xml +++ b/jetty-start/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-start diff --git a/jetty-util/pom.xml b/jetty-util/pom.xml index e17138337b5..864d26de187 100644 --- a/jetty-util/pom.xml +++ b/jetty-util/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-util diff --git a/jetty-webapp-verifier/.gitignore b/jetty-webapp-verifier/.gitignore new file mode 100644 index 00000000000..9c65b190a85 --- /dev/null +++ b/jetty-webapp-verifier/.gitignore @@ -0,0 +1,9 @@ +target/ +.classpath +.project +.settings +*.swp +*.patch +*.diff +*.log +cobertura.ser diff --git a/jetty-webapp-verifier/pom.xml b/jetty-webapp-verifier/pom.xml new file mode 100644 index 00000000000..93caf632458 --- /dev/null +++ b/jetty-webapp-verifier/pom.xml @@ -0,0 +1,111 @@ + + 4.0.0 + + org.eclipse.jetty + jetty-project + 7.0.1-SNAPSHOT + + org.eclipse.jetty + jetty-webapp-verifier + Jetty :: Webapp Verifier Tool + jar + + target/war-files + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + generate-resources + + copy + + + + + org.eclipse.jetty.tests + test-webapp-logging-java + ${project.version} + war + ${war.file.repo} + test-webapp-logging-java.war + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + package + + single + + + + config.xml + + + + + + + + + + org.eclipse.jetty + jetty-xml + ${version} + + + junit + junit + test + + + + asm + asm + 3.1 + true + + + asm + asm-tree + 3.1 + true + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + org.apache.maven.plugins + maven-jxr-plugin + + + org.codehaus.mojo + cobertura-maven-plugin + + + + diff --git a/jetty-webapp-verifier/src/main/config/etc/jetty-waver-default-ruleset.xml b/jetty-webapp-verifier/src/main/config/etc/jetty-waver-default-ruleset.xml new file mode 100644 index 00000000000..fe7e5ccfa3d --- /dev/null +++ b/jetty-webapp-verifier/src/main/config/etc/jetty-waver-default-ruleset.xml @@ -0,0 +1,32 @@ + + + + + + + + + + /WEB-INF/web.xml + + + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/AbstractArchiveScanningRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/AbstractArchiveScanningRule.java new file mode 100644 index 00000000000..4cbc5708098 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/AbstractArchiveScanningRule.java @@ -0,0 +1,94 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.io.File; +import java.util.Enumeration; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * AbstractArchiveScanningRule for Rules that scan the archive contents. + */ +public abstract class AbstractArchiveScanningRule extends AbstractRule +{ + public abstract String getDescription(); + + public abstract String getName(); + + @Override + public void visitWebInfLibJar(String path, File archive, JarFile jar) + { + scanClassesInArchive(path,jar); + } + + @Override + public void visitWebInfLibZip(String path, File archive, ZipFile zip) + { + scanClassesInArchive(path,zip); + } + + private String asClassname(String path) + { + StringBuffer name = new StringBuffer(); + for (char c : path.toCharArray()) + { + if (c == '/') + { + name.append("."); + } + else + { + name.append(c); + } + } + if (name.toString().endsWith(".class")) + { + name.delete(name.length() - 6,name.length() - 1); + } + return name.toString(); + } + + private void scanClassesInArchive(String path, ZipFile zip) + { + String className; + Enumeration entries = zip.entries(); + while (entries.hasMoreElements()) + { + ZipEntry entry = entries.nextElement(); + if (entry.getName().endsWith(".class")) + { + className = asClassname(entry.getName()); + visitArchiveClass(path + "!/" + entry.getName(),className,zip,entry); + } + else + { + visitArchiveResource(path + "!/" + entry.getName(),zip,entry); + } + } + } + + public void visitArchiveResource(String path, ZipFile zip, ZipEntry entry) + { + /* override to do something with */ + } + + public void visitArchiveClass(String path, String className, ZipFile archive, ZipEntry archiveEntry) + { + /* override to do something with */ + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/AbstractRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/AbstractRule.java new file mode 100644 index 00000000000..c8a52952e8b --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/AbstractRule.java @@ -0,0 +1,215 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.io.File; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; + +public abstract class AbstractRule implements Rule +{ + private ViolationListener violationListener; + private File rootDir; + + protected void error(String path, String detail) + { + Violation violation = new Violation(Severity.ERROR,path,detail); + violation.setVerifierInfo(this); + violationListener.reportViolation(violation); + } + + protected void exception(String path, String detail, Throwable t) + { + Violation violation = new Violation(Severity.ERROR,path,detail,t); + violation.setVerifierInfo(this); + violationListener.reportViolation(violation); + } + + protected String getWebappRelativePath(File dir) + { + if (rootDir == null) + { + throw new RuntimeException("rootDir is not initialized, can't get relative path. " + + "Did you overide .visitWebappStart() and not call super.visitWebappStart()?"); + } + return rootDir.toURI().relativize(dir.toURI()).toASCIIString(); + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#setViolationListener(ViolationListener) + */ + public void setViolationListener(ViolationListener listener) + { + this.violationListener = listener; + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#initialize() + */ + public void initialize() throws Throwable + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitDirectoryEnd(java.lang.String, java.io.File) + */ + public void visitDirectoryEnd(String path, File dir) + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitDirectoryStart(java.lang.String, java.io.File) + */ + public void visitDirectoryStart(String path, File dir) + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitFile(java.lang.String, java.io.File, java.io.File) + */ + public void visitFile(String path, File dir, File file) + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebappEnd(java.lang.String, java.io.File) + */ + public void visitWebappEnd(String path, File dir) + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * NOTE: be sure to call super.{@link #visitWebappStart(String, File)} in your overriden method. + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebappStart(java.lang.String, java.io.File) + */ + public void visitWebappStart(String path, File dir) + { + if (path.equals(ROOT_PATH)) + { + rootDir = new File(path); + } + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfClass(java.lang.String, java.lang.String, + * java.io.File) + */ + public void visitWebInfClass(String path, String className, File classFile) + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfClassesEnd(java.lang.String, java.io.File) + */ + public void visitWebInfClassesEnd(String path, File dir) + { + // TODO Auto-generated method stub + + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfClassesStart(java.lang.String, java.io.File) + */ + public void visitWebInfClassesStart(String path, File dir) + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfClassResource(java.lang.String, java.lang.String, + * java.io.File) + */ + public void visitWebInfClassResource(String path, String resourcePath, File resourceFile) + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfLibEnd(java.lang.String, java.io.File) + */ + public void visitWebInfLibEnd(String path, File dir) + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfLibJar(String, File, JarFile) + */ + public void visitWebInfLibJar(String path, File archive, JarFile jar) + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfLibStart(java.lang.String, java.io.File) + */ + public void visitWebInfLibStart(String path, File dir) + { + /* override to implement */ + } + + /** + * {@inheritDoc} + * + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfLibZip(String, File, ZipFile) + */ + public void visitWebInfLibZip(String path, File archive, ZipFile zip) + { + /* override to implement */ + } + + protected void warning(String path, String detail) + { + Violation violation = new Violation(Severity.WARNING,path,detail); + violation.setVerifierInfo(this); + violationListener.reportViolation(violation); + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Rule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Rule.java new file mode 100644 index 00000000000..a21b9ad9b4b --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Rule.java @@ -0,0 +1,222 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.io.File; +import java.net.URLClassLoader; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; + +/** + *

+ * Rule is the interface that the {@link WebappVerifier} uses to notify Rule implementations of events in the Iteration + * of a Webapp contents. + *

+ * + *

+ * The visitor pattern used here has the following order .. + *

+ * + *
+ *  1) [1] {@link #visitWebappStart(String, File)}
+ *  Iterate Contents:
+ *     2) [1..n] {@link #visitDirectoryStart(String, File)}
+ *     3) [0..n] {@link #visitFile(String, File, File)}
+ *     4) [1..n] {@link #visitDirectoryEnd(String, File)}
+ *  Iterate WEB-INF/classes:
+ *     5) [0..1] {@link #visitWebInfClassesStart(String, File)}
+ *     6) [0..n] {@link #visitWebInfClass(String, String, File)}
+ *     7) [0..n] {@link #visitWebInfClassResource(String, String, File)}
+ *     8) [0..1] {@link #visitWebInfClassesEnd(String, File)}
+ *  Iterate WEB-INF/lib:
+ *     9) [0..1] {@link #visitWebInfLibStart(String, File)}
+ *    10) [0..n] {@link #visitWebInfLibJar(String, File, JarFile)}
+ *    11) [0..n] {@link #visitWebInfLibZip(String, File, ZipFile)}
+ *    12) [0..1] {@link #visitWebInfLibEnd(String, File)}
+ *  13) [1] {@link #visitWebappEnd(String, File)}
+ * 
+ */ +public interface Rule +{ + public static final String ROOT_PATH = ""; + + /** + * A short name for the rule. + */ + public String getName(); + + /** + * A Description of the purpose of the rule. What does it check for? Why? + */ + public String getDescription(); + + /** + * Initialization logic for the rule, exceptions from initialization will be logged as a {@link Severity#ERROR} + * level {@link Violation} with the {@link Violation#getThrowable()} set. + * + * If you want more meaningful violation messages than default, be sure to capture your own initialization related + * failures and report them to the {@link ViolationListener} at a {@link Severity#ERROR} level. + */ + public void initialize() throws Throwable; + + /** + * Set the listener to report violations back to. + */ + public void setViolationListener(ViolationListener listener); + + /** + * The iteration of the webapp has begun. + * + * @param path + * the war relative path to this directory. + * @param dir + * the real File System directory to the webapp work directory + */ + public void visitWebappStart(String path, File dir); + + /** + * A visit of a directory has begun. + * + * @param path + * the war relative path to this directory. + * @param dir + * the real File System directory object for this directory. + */ + public void visitDirectoryStart(String path, File dir); + + /** + * A visit of a file. + * + * @param path + * the war relative path to this file. + * @param dir + * the real File System directory object for this file. This is the same directory as seen in + * {@link #visitDirectoryStart(String, File)} and {@link #visitDirectoryEnd(String, File)} + * @param file + * the real File System {@link File} object to this file + */ + public void visitFile(String path, File dir, File file); + + /** + * A visit of a directory has ended. + * + * @param path + * the war relative path to this directory. + * @param dir + * the real File System directory. + */ + public void visitDirectoryEnd(String path, File dir); + + /** + * The visit to WEB-INF/classes is starting + * + * @param path + * the war relative path to the WEB-INF/classes dir. (Note: Will always be "WEB-INF/classes") + * @param dir + * the real File System directory. + */ + public void visitWebInfClassesStart(String path, File dir); + + /** + * A visit of a Class found in WEB-INF/classes. + * + * @param path + * the war relative path to this directory. + * @param className + * the full classname of the class found. TODO: Base this off of class bytecode? + * @param classFile + * the real File System directory object for this directory. + */ + public void visitWebInfClass(String path, String className, File classFile); + + /** + * A visit of a Resource available in "WEB-INF/classes" which is not a Class (such as an XML file or a properties + * file) + * + * @param path + * the war relative path to this directory. + * @param resourcePath + * the full resourcePath to the file found. Returned in a format that is compatible to + * {@link URLClassLoader#findResource(String)} call. + * @param resourceFile + * the real File System directory object for this directory. + */ + public void visitWebInfClassResource(String path, String resourcePath, File resourceFile); + + /** + * The visit to WEB-INF/classes has ended + * + * @param path + * the war relative path to the WEB-INF/classes dir. (Note: Will always be "WEB-INF/classes") + * @param dir + * the real File System directory. + */ + public void visitWebInfClassesEnd(String path, File dir); + + /** + * The visit to WEB-INF/lib is starting. + * + * @param path + * the war relative path to the WEB-INF/lib dir. (Note: Will always be "WEB-INF/lib") + * @param dir + * the real File System directory. + */ + public void visitWebInfLibStart(String path, File dir); + + /** + * A visit to a JAR archive in the WEB-INF/lib directory. + * + * @param path + * the war relative path to the JAR archive in the WEB-INF/lib dir. + * @param archive + * the real File System file. + * @param jar + * the {@link JarFile} + */ + public void visitWebInfLibJar(String path, File archive, JarFile jar); + + /** + * A visit to an archive in the WEB-INF/lib directory has begun. + * + * @param path + * the war relative path to the archive in the WEB-INF/lib dir. + * @param archive + * the real File System file. + * @param zip + * the {@link ZipFile} + */ + public void visitWebInfLibZip(String path, File archive, ZipFile zip); + + /** + * The visit to WEB-INF/lib has ended. + * + * @param path + * the war relative path to the WEB-INF/lib dir. (Note: Will always be "WEB-INF/lib") + * @param dir + * the real File System directory. + */ + public void visitWebInfLibEnd(String path, File dir); + + /** + * The iteration of the webapp has ended. + * + * @param path + * the war relative path to this directory. + * @param dir + * the real File System directory to the webapp work directory + */ + public void visitWebappEnd(String path, File dir); +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/RuleSet.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/RuleSet.java new file mode 100644 index 00000000000..5dfd32e8d07 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/RuleSet.java @@ -0,0 +1,89 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.io.File; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jetty.xml.XmlConfiguration; + +/** + * RuleSet holds the set of configured {@link Rule}s that the WebappVerifier will use. + */ +public class RuleSet +{ + private String name; + private List rules = new ArrayList(); + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public List getRules() + { + return rules; + } + + public void setRules(List rules) + { + this.rules = rules; + } + + public void setRules(Rule[] ruleArray) + { + this.rules.clear(); + this.rules.addAll(Arrays.asList(ruleArray)); + } + + public void addRule(Rule rule) + { + this.rules.add(rule); + } + + public WebappVerifier createWebappVerifier(URI webappURI) + { + WebappVerifier webappVerifier = new WebappVerifier(webappURI); + webappVerifier.setRules(rules); + return webappVerifier; + } + + public static RuleSet load(URL configuration) throws Exception + { + XmlConfiguration xml; + xml = new XmlConfiguration(configuration); + return (RuleSet)xml.configure(); + } + + public static RuleSet load(URI configuration) throws Exception + { + return load(configuration.toURL()); + } + + public static RuleSet load(File configuration) throws Exception + { + return load(configuration.toURL()); + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Severity.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Severity.java new file mode 100644 index 00000000000..8435c5c05b4 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Severity.java @@ -0,0 +1,39 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +public enum Severity +{ + WARNING, ERROR; + + public static Severity parse(String value) + { + if (value == null) + { + return null; + } + + for (Severity sev : Severity.values()) + { + if (sev.name().equalsIgnoreCase(value)) + { + return sev; + } + } + + return null; + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Violation.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Violation.java new file mode 100644 index 00000000000..66be3fa299f --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/Violation.java @@ -0,0 +1,186 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +public class Violation +{ + private String path; + + private Severity severity; + + private String detail; + + private Throwable throwable; + + private String ruleId; + + private Class ruleClass; + + public Violation(Severity severity, String path, String detail) + { + this.severity = severity; + this.path = path; + this.detail = detail; + } + + public Violation(Severity severity, String path, String detail, Rule verifier) + { + this.severity = severity; + this.path = path; + this.detail = detail; + setVerifierInfo(verifier); + } + + public Violation(Severity severity, String path, String detail, Throwable throwable) + { + this.severity = severity; + this.path = path; + this.detail = detail; + this.throwable = throwable; + } + + public void setVerifierInfo(Rule verifier) + { + this.ruleId = verifier.getName(); + this.ruleClass = verifier.getClass(); + } + + @Override + public String toString() + { + StringBuffer msg = new StringBuffer(); + msg.append("Violation["); + msg.append("severity=").append(severity.name()); + msg.append(",path=").append(path); + msg.append(",detail=").append(detail); + if (ruleId != null) + { + msg.append(",verifierId=").append(ruleId); + } + if (ruleClass != null) + { + msg.append(",verifierClass=").append(ruleClass.getName()); + } + if (throwable != null) + { + msg.append(",throwable=").append(throwable.getClass().getName()); + } + msg.append("]"); + return msg.toString(); + } + + public String toDelimString() + { + StringBuffer msg = new StringBuffer(); + msg.append(severity.name()); + msg.append("|").append(path); + msg.append("|").append(detail); + return msg.toString(); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((detail == null)?0:detail.hashCode()); + result = prime * result + ((path == null)?0:path.hashCode()); + result = prime * result + ((severity == null)?0:severity.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + Violation other = (Violation)obj; + if (detail == null) + { + if (other.detail != null) + { + return false; + } + } + else if (!detail.equals(other.detail)) + { + return false; + } + if (path == null) + { + if (other.path != null) + { + return false; + } + } + else if (!path.equals(other.path)) + { + return false; + } + if (severity == null) + { + if (other.severity != null) + { + return false; + } + } + else if (!severity.equals(other.severity)) + { + return false; + } + return true; + } + + public Class getRuleClass() + { + return ruleClass; + } + + public String getRuleId() + { + return ruleId; + } + + public String getDetail() + { + return detail; + } + + public String getPath() + { + return path; + } + + public Severity getSeverity() + { + return severity; + } + + public Throwable getThrowable() + { + return throwable; + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/ViolationComparator.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/ViolationComparator.java new file mode 100644 index 00000000000..24ea663f227 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/ViolationComparator.java @@ -0,0 +1,49 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.text.CollationKey; +import java.text.Collator; +import java.util.Comparator; + +public class ViolationComparator implements Comparator +{ + private static ViolationComparator INSTANCE = new ViolationComparator(); + + public static ViolationComparator getInstance() + { + return INSTANCE; + } + + private Collator collator = Collator.getInstance(); + + public int compare(Violation o1, Violation o2) + { + CollationKey pathKey1 = collator.getCollationKey(o1.getPath()); + CollationKey pathKey2 = collator.getCollationKey(o2.getPath()); + + int diff = pathKey1.compareTo(pathKey2); + if (diff != 0) + { + // different paths. + return diff; + } + + CollationKey detailKey1 = collator.getCollationKey(o1.getDetail()); + CollationKey detailKey2 = collator.getCollationKey(o2.getDetail()); + return detailKey1.compareTo(detailKey2); + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/ViolationListener.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/ViolationListener.java new file mode 100644 index 00000000000..e2ab668ecae --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/ViolationListener.java @@ -0,0 +1,21 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +public interface ViolationListener +{ + void reportViolation(Violation violation); +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/WebappVerifier.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/WebappVerifier.java new file mode 100644 index 00000000000..25044c18912 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/WebappVerifier.java @@ -0,0 +1,570 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; + +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.resource.JarResource; +import org.eclipse.jetty.util.resource.Resource; + +/** + * The Webapp Verifier is a component that can be configured to run and arbitrary number of {@link Rule}s that analyze + * the contents of a war file and report rule violations. + */ +public class WebappVerifier implements ViolationListener +{ + /** + *

+ * Represents the source webappURI. + *

+ *

+ * Can be http, file, jar, etc ... + *

+ *

+ * Verification does not occur directly against this URI. + *

+ */ + private URI _webappURI; + + /** + * Represents the local webapp file directory, often times points to the working (unpacked) webapp directory. + * + * NOTE: if _webappURI is a "file://" access URI, and points to a directory, then the _webappDir will point to the + * the same place, otherwise it will point to the webapp directory. + */ + private File _webappDir; + private File _workdir; + private List _rules; + private Map> _violations; + + /** + * Instantiate a WebappVerifier, against the specific webappURI, using the default workdir. + * + * @param webappURI + * the webappURI to verify + */ + public WebappVerifier(URI webappURI) + { + this._webappURI = webappURI; + this._workdir = new File(System.getProperty("java.io.tmpdir"),"jetty-waver"); + this._rules = new ArrayList(); + this._violations = new HashMap>(); + } + + public void addRule(Rule rule) + { + _rules.add(rule); + try + { + rule.setViolationListener(this); + rule.initialize(); + } + catch (Throwable t) + { + // Capture any errors out of initialize or setViolationListener() that might occur. + String msg = String.format("Unable to add rule [%s]: %s",rule.getName(),t.getMessage()); + reportException(Rule.ROOT_PATH,msg,rule,t); + } + } + + private String cleanFilename(URI uri) + { + // Need a filename to store this download to. + String destname = uri.getPath(); + int idx = destname.lastIndexOf('/'); + if (idx > 0) + { + destname = destname.substring(idx); + } + destname = destname.trim().toLowerCase(); + + if (destname.length() <= 0) + { + // whoops, there's nothing left. + // could be caused by urls that point to paths. + destname = new SimpleDateFormat("yyyy-MM-dd_hh-mm-ss").format(new Date()); + } + + // Neuter illegal characters + char cleaned[] = new char[destname.length()]; + for (int i = 0; i < destname.length(); i++) + { + char c = destname.charAt(i); + if (c == '|' || c == '/' || c == '\\' || c == '*' || c == '?' || c == ':' || c == '#') + { + cleaned[i] = '_'; + } + else + { + cleaned[i] = c; + } + } + + destname = new String(cleaned); + + if (!destname.endsWith(".war")) + { + destname += ".war"; + } + + return destname; + } + + private File download(URI uri) throws MalformedURLException, IOException + { + // Establish destfile + File destfile = new File(_workdir,cleanFilename(uri)); + + InputStream in = null; + FileOutputStream out = null; + try + { + in = uri.toURL().openStream(); + out = new FileOutputStream(destfile); + IO.copy(in,out); + } + finally + { + IO.close(in); + } + return destfile; + } + + private File establishLocalWebappDir() throws URISyntaxException, IOException + { + if ("file".equals(_webappURI.getScheme())) + { + File path = new File(_webappURI); + if (path.isDirectory()) + { + return path; + } + return unpack(path); + } + + File downloadedFile = download(_webappURI); + return unpack(downloadedFile); + } + + public List getRules() + { + return _rules; + } + + public Collection getViolations() + { + // TODO: Icky! I need a better way of getting the list of raw + // violations, complete, without path mapping in place. + // Yet, I need path mapping as well, right? + List violations = new ArrayList(); + for (List pathviol : _violations.values()) + { + violations.addAll(pathviol); + } + return violations; + } + + public File getWebappDir() + { + return _webappDir; + } + + private String getWebappRelativePath(File dir) + { + return _webappDir.toURI().relativize(dir.toURI()).toASCIIString(); + } + + public File getWorkDir() + { + return _workdir; + } + + /** + * Tests a filesystem path for webapp expected files, like "WEB-INF/web.xml" + */ + private boolean isValidWebapp(File path) + { + File webXml = new File(path,"WEB-INF" + File.separator + "web.xml"); + if (!webXml.exists()) + { + reportViolation(Severity.ERROR,Rule.ROOT_PATH,"Missing WEB-INF/web.xml"); + return false; + } + + if (!webXml.isFile()) + { + reportViolation(Severity.ERROR,Rule.ROOT_PATH,"The WEB-INF/web.xml is not a File"); + return false; + } + + return true; + } + + private void reportException(String path, String detail, Rule rule, Throwable t) + { + Violation viol = new Violation(Severity.ERROR,path,detail,t); + viol.setVerifierInfo(rule); + reportViolation(viol); + } + + public void reportViolation(Severity error, String path, String detail) + { + reportViolation(new Violation(error,path,detail)); + } + + public void reportViolation(Violation violation) + { + List pathviol = _violations.get(violation.getPath()); + if (pathviol == null) + { + pathviol = new ArrayList(); + } + pathviol.add(violation); + _violations.put(violation.getPath(),pathviol); + } + + public void setRules(Collection rules) + { + this._rules.clear(); + // Add each rule separately, to establish initialization & listeners + for (Rule verifier : rules) + { + addRule(verifier); + } + } + + public void setWorkDir(File workDir) + { + this._workdir = workDir; + } + + private File unpack(File path) throws URISyntaxException, IOException + { + String destname = path.getName().substring(0,path.getName().length() - 4); + File destDir = new File(_workdir,destname); + URI warURI = new URI("jar",path.toURI() + "!/",null); + JarResource warResource = (JarResource)Resource.newResource(warURI); + warResource.extract(destDir,false); + return destDir; + } + + public void visitAll() + { + try + { + _webappDir = establishLocalWebappDir(); + + // Issue start. + for (Rule rule : _rules) + { + rule.visitWebappStart(Rule.ROOT_PATH,_webappDir); + } + + if (isValidWebapp(_webappDir)) + { + // Iterate through content + visitContents(); + // Iterate through WEB-INF/classes + visitWebInfClasses(); + // Iterate through WEB-INF/lib + visitWebInfLib(); + } + + // Issue end. + for (Rule rule : _rules) + { + rule.visitWebappEnd(Rule.ROOT_PATH,_webappDir); + } + } + catch (IOException e) + { + reportViolation(new Violation(Severity.ERROR,Rule.ROOT_PATH,e.getMessage(),e)); + } + catch (URISyntaxException e) + { + reportViolation(new Violation(Severity.ERROR,Rule.ROOT_PATH,e.getMessage(),e)); + } + } + + private void visitWebInfClasses() + { + File classesDir = new File(_webappDir,"WEB-INF" + File.separator + "classes"); + if (!classesDir.exists()) + { + // skip this path. + return; + } + + String classesPath = getWebappRelativePath(classesDir); + + if (!classesDir.isDirectory()) + { + reportViolation(Severity.ERROR,classesPath,"WEB-INF/classes is not a Directory?"); + return; + } + + // Issue start. + for (Rule rule : _rules) + { + rule.visitWebInfClassesStart(classesPath,classesDir); + } + + visitClassesDir(classesDir,classesDir); + + // Issue end. + for (Rule rule : _rules) + { + rule.visitWebInfClassesEnd(classesPath,classesDir); + } + } + + private void visitClassesDir(File classesRoot, File classesDir) + { + File files[] = classesDir.listFiles(); + for (File file : files) + { + if (file.isFile()) + { + if (file.getName().endsWith(".class")) + { + visitClass(classesRoot,file); + } + else + { + visitClassResource(classesRoot,file); + } + } + else if (file.isDirectory()) + { + // recurse + visitClassesDir(classesRoot,file); + } + } + } + + private void visitClassResource(File classesRoot, File file) + { + String path = getWebappRelativePath(file); + String resourcePath = classesRoot.toURI().relativize(file.toURI()).toASCIIString(); + for (Rule rule : _rules) + { + rule.visitWebInfClassResource(path,resourcePath,file); + } + } + + private void visitClass(File classesRoot, File file) + { + String path = getWebappRelativePath(file); + String className = classesRoot.toURI().relativize(file.toURI()).toASCIIString(); + className = className.replace("/","."); + if (className.endsWith(".class")) + { + className = className.substring(0,className.length() - 6); + } + for (Rule rule : _rules) + { + rule.visitWebInfClass(path,className,file); + } + } + + private void visitWebInfLib() + { + File libDir = new File(_webappDir,"WEB-INF" + File.separator + "lib"); + if (!libDir.exists()) + { + // skip this path. + return; + } + + String libPath = getWebappRelativePath(libDir); + + if (!libDir.isDirectory()) + { + reportViolation(Severity.ERROR,libPath,"WEB-INF/lib is not a Directory?"); + return; + } + + // Issue start. + for (Rule rule : _rules) + { + rule.visitWebInfLibStart(libPath,libDir); + } + + // Iterator through contents of WEB-INF/lib + File archives[] = libDir.listFiles(); + for (File archive : archives) + { + if (!archive.isFile()) + { + reportViolation(Severity.WARNING,Rule.ROOT_PATH,"Found non-file in WEB-INF/lib. Remove it, " + + "as it cannot be accessed by the Servlet container or the Webapp: " + archive); + continue; + } + + if (archive.getName().toLowerCase().endsWith(".jar")) + { + visitWebInfLibJar(libPath,archive); + continue; + } + + if (archive.getName().toLowerCase().endsWith(".zip")) + { + visitWebInfLibZip(libPath,archive); + continue; + } + + reportViolation(Severity.WARNING,Rule.ROOT_PATH,"Found non-archive in WEB-INF/lib. Remove it, " + + "as it cannot be accessed by the Servlet container or the Webapp: " + archive); + } + + // Issue end. + for (Rule rule : _rules) + { + rule.visitWebInfLibEnd(libPath,libDir); + } + } + + private void visitWebInfLibJar(String libPath, File archive) + { + String jarPath = libPath + archive.getName(); + + // Issue visit on Jar + for (Rule rule : _rules) + { + JarFile jar = null; + try + { + jar = new JarFile(archive); + rule.visitWebInfLibJar(jarPath,archive,jar); + } + catch (Throwable t) + { + reportViolation(new Violation(Severity.ERROR,jarPath,t.getMessage(),t)); + } + finally + { + if (jar != null) + { + try + { + jar.close(); + } + catch (IOException ignore) + { + /* ignore */ + } + } + } + } + } + + private void visitWebInfLibZip(String libPath, File archive) + { + String zipPath = libPath + archive.getName(); + + // Issue visit on Zip + for (Rule rule : _rules) + { + ZipFile zip = null; + try + { + zip = new ZipFile(archive); + rule.visitWebInfLibZip(zipPath,archive,zip); + } + catch (Throwable t) + { + reportViolation(new Violation(Severity.ERROR,zipPath,t.getMessage(),t)); + } + finally + { + if (zip != null) + { + try + { + zip.close(); + } + catch (IOException ignore) + { + /* ignore */ + } + } + } + } + } + + private void visitContents() + { + visitDirectoryRecursively(_webappDir); + } + + private void visitDirectoryRecursively(File dir) + { + String path = getWebappRelativePath(dir); + + // Start Dir + for (Rule rule : this._rules) + { + rule.visitDirectoryStart(path,dir); + } + + File entries[] = dir.listFiles(); + + // Individual Files + for (File file : entries) + { + if (file.isFile()) + { + String filepath = path + file.getName(); + for (Rule rule : this._rules) + { + rule.visitFile(filepath,dir,file); + } + } + } + + // Sub dirs + for (File file : entries) + { + if (file.isDirectory()) + { + visitDirectoryRecursively(file); + } + } + + // End Dir + for (Rule rule : this._rules) + { + rule.visitDirectoryEnd(path,dir); + } + } + +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ForbiddenClassesRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ForbiddenClassesRule.java new file mode 100644 index 00000000000..6e845725c10 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ForbiddenClassesRule.java @@ -0,0 +1,90 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.eclipse.jetty.webapp.verifier.AbstractArchiveScanningRule; + +/** + * ForbiddenClassesVerifier checks the various classes available to the Webapp to ensure that they do not contain and + * forbidden classes. + */ +public class ForbiddenClassesRule extends AbstractArchiveScanningRule +{ + private Map classPatterns = new HashMap(); + + public void addClassPattern(String classPattern) + { + StringBuffer regex = new StringBuffer(); + for (char c : classPattern.toCharArray()) + { + if (c == '.') + { + regex.append("\\."); + } + else if (c == '*') + { + regex.append(".*"); + } + else + { + regex.append(c); + } + } + classPatterns.put(classPattern,Pattern.compile(regex.toString())); + } + + @Override + public String getDescription() + { + return "Ensures that forbidden packages are not present in the war file"; + } + + @Override + public String getName() + { + return "forbidden-class"; + } + + private void validateClassname(String path, String className) + { + for (Map.Entry pattern : this.classPatterns.entrySet()) + { + if (pattern.getValue().matcher(className).matches()) + { + error(path,"Class forbidden by pattern: " + pattern.getKey()); + } + } + } + + @Override + public void visitWebInfClass(String path, String className, File classFile) + { + validateClassname(path,className); + } + + @Override + public void visitArchiveClass(String path, String className, ZipFile archive, ZipEntry archiveEntry) + { + validateClassname(path,className); + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ForbiddenContentsRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ForbiddenContentsRule.java new file mode 100644 index 00000000000..c3d2fdedb8a --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ForbiddenContentsRule.java @@ -0,0 +1,58 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jetty.webapp.verifier.AbstractRule; +import org.eclipse.jetty.webapp.verifier.support.PathGlob; + +/** + * ForbiddenContentsVerifier ensures that content matching a pattern does not exist in the webapp. + */ +public class ForbiddenContentsRule extends AbstractRule +{ + private List _patterns = new ArrayList(); + + public void addPattern(String pattern) + { + _patterns.add(pattern); + } + + public String getDescription() + { + return "Checks for forbidden content"; + } + + public String getName() + { + return "forbidden-content"; + } + + @Override + public void visitFile(String path, File dir, File file) + { + for (String pattern : _patterns) + { + if (PathGlob.match(pattern,path)) + { + error(path,"Forbidden content detected"); + } + } + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JarSignatureRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JarSignatureRule.java new file mode 100644 index 00000000000..91fc2122082 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JarSignatureRule.java @@ -0,0 +1,231 @@ +// ======================================================================== +// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.webapp.verifier.AbstractRule; + +/** + * Signed Jar Verifier + */ +public class JarSignatureRule extends AbstractRule +{ + private String _keystoreLocation = System.getProperty("java.home") + "/lib/security/cacerts"; + private String _type = "JKS"; // default + private String _alias = "verisignclass3ca"; // default + private KeyStore _keystore; + + private static X509Certificate[] _trustedCertificates; + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.webapp.verifier.AbstractRule#getDescription() + */ + public String getDescription() + { + return "verifies that the given keystore contains the certificates required for all jar files present"; + } + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.webapp.verifier.AbstractRule#getName() + */ + public String getName() + { + return "jar-signature"; + } + + /* ------------------------------------------------------------ */ + /** + * @param jar + * @return + */ + private List resolveJar(JarFile jar) + { + List entries = new ArrayList(); + + Enumeration e = jar.entries(); + + while (e.hasMoreElements()) + { + JarEntry jarEntry = e.nextElement(); + try + { + entries.add(jarEntry); // for further verification + IO.toString(jar.getInputStream(jar.getEntry(jarEntry.getName()))); + } + catch (IOException e1) + { + throw new SecurityException(e1); + } + } + + return entries; + } + + /* ------------------------------------------------------------ */ + /** + * Set the _keystore. + * + * @param keystore + * the _keystore to set + */ + public void setKeystoreLocation( String keyStoreLocation ) + { + _keystoreLocation = keyStoreLocation; + } + + @Override + public void initialize() + { + try + { + _keystore = KeyStore.getInstance(_type); + + InputStream istream = new File( _keystoreLocation ).toURL().openStream(); + + _keystore.load(istream,null); + + _trustedCertificates = new X509Certificate[] + { (X509Certificate)_keystore.getCertificate(_alias) }; + + } + catch (Throwable t) + { + exception(_keystoreLocation, t.getMessage(), t); + } + } + + public void setType(String type) + { + _type = type; + } + + /** + * @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfLibJar(java.lang.String, java.io.File, java.util.jar.JarFile) + */ + @Override + public void visitWebInfLibJar(String path, File archive, JarFile jar) + { + + try + { + if (jar.getManifest() == null) + { + error(jar.toString(),"missing manifest.mf, can not be signed"); + } + + List entries = resolveJar(jar); + + for (JarEntry jarEntry : entries) + { + if (!jarEntry.isDirectory() && !jarEntry.getName().startsWith("META-INF")) + { + Certificate[] certs = jarEntry.getCertificates(); + + if (certs == null || certs.length == 0) + { + error(jarEntry.getName(),"entry has not been signed"); + } + else + { + X509Certificate[] chainRoots = getChainRoots(certs); + boolean signed = false; + + for (int i = 0; i < chainRoots.length; i++) + { + if (isTrusted(chainRoots[i])) + { + signed = true; + break; + } + } + if (!signed) + { + error(jarEntry.getName(),"Untrusted provider's JAR"); + } + } + } + } + } + catch (Exception e) + { + exception(jar.getName(), e.getMessage(), e); + } + } + + private boolean isTrusted(X509Certificate certificate) + { + for (int i = 0; i < _trustedCertificates.length; i++) + { + if (certificate.getSubjectDN().equals(_trustedCertificates[i].getSubjectDN())) + { + if (certificate.equals(_trustedCertificates[i])) + { + return true; + } + } + } + + for (int i = 0; i < _trustedCertificates.length; i++) + { + if (certificate.getIssuerDN().equals(_trustedCertificates[i].getSubjectDN())) + { + try + { + certificate.verify(_trustedCertificates[i].getPublicKey()); + return true; + } + catch (Exception e) + { + } + } + } + return false; + } + + /** + * Returns a array of certificates with the root certificate of each chain + * + * @param certificates an array of X509 certificate's + * @return an array of X509 certificate's with the root certificate of each chain + */ + private X509Certificate[] getChainRoots(Certificate[] certificates) + { + List chainRoots = new ArrayList(); + + for (int i = 0; i < certificates.length - 1; i++) + { + if (!((X509Certificate)certificates[i + 1]).getSubjectDN().equals(((X509Certificate)certificates[i]).getIssuerDN())) + { + chainRoots.add((X509Certificate)certificates[i]); + } + } + + chainRoots.add((X509Certificate)certificates[certificates.length - 1]); + + return chainRoots.toArray(new X509Certificate[chainRoots.size()]); + } + +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JavaSupportLevelRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JavaSupportLevelRule.java new file mode 100644 index 00000000000..cf93c409385 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JavaSupportLevelRule.java @@ -0,0 +1,166 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; +import java.io.IOException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.eclipse.jetty.webapp.verifier.AbstractArchiveScanningRule; +import org.eclipse.jetty.webapp.verifier.rules.asm.ASMUtil; +import org.eclipse.jetty.webapp.verifier.rules.asm.AbstractClassVisitor; + +/** + * Ensure all compiled classes within webapp are within the supported JVM range. + */ +public class JavaSupportLevelRule extends AbstractArchiveScanningRule +{ + class ClassVersionVisitor extends AbstractClassVisitor + { + private double classVersion = -1; + + public double getClassVersion() + { + return classVersion; + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) + { + this.classVersion = getJavaClassVersion(version); + } + + private double getJavaClassVersion(int version) + { + int major = version & 0xFFFF; + int minor = version >>> 16; + + // Java Versions to Class Version (major.minor) + // Java 1.6 = 50.0 + // Java 1.5 = 49.0 + // Java 1.4 = 48.0 + // Java 1.3 = 47.0 + // Java 1.2 = 46.0 + // Java 1.1 = 45.3 + + // TODO: check these since they are > instead of >= + if (major >= 50) + { + return 1.6; + } + else if (major >= 49) + { + return 1.5; + } + else if (major >= 48) + { + return 1.4; + } + else if (major >= 47) + { + return 1.3; + } + else if (major >= 46) + { + return 1.2; + } + else if (major >= 45) + { + if (minor >= 3) + { + return 1.1; + } + return 1.0; + } + + return 0.0; + } + + public void reset() + { + this.classVersion = (-1); + } + } + + private double supportedVersion = 1.5; + private ClassVersionVisitor visitor; + + @Override + public String getDescription() + { + return "Ensure all compiled classes within webapp are within the supported JVM"; + } + + @Override + public String getName() + { + return "java-support-level"; + } + + public double getSupportedVersion() + { + return supportedVersion; + } + + public void setSupportedVersion(double supportedVersion) + { + this.supportedVersion = supportedVersion; + } + + @Override + public void visitWebappStart(String path, File dir) + { + visitor = new ClassVersionVisitor(); + } + + + @Override + public void visitWebInfClass(String path, String className, File classFile) + { + try + { + visitor.reset(); + ASMUtil.visitClassFile(classFile,visitor,0); + if (visitor.classVersion > supportedVersion) + { + error(path,"Class is compiled for java version [" + visitor.classVersion + "] which is over supported java version [" + supportedVersion + "]"); + } + } + catch (IOException e) + { + exception(path,"Unable to read class",e); + } + } + + @Override + public void visitArchiveClass(String path, String className, ZipFile archive, ZipEntry archiveEntry) + { + try + { + visitor.reset(); + ASMUtil.visitClass(archive.getInputStream(archiveEntry),visitor,0); + if (visitor.classVersion > supportedVersion) + { + error(path,"Class is compiled for java version [" + visitor.classVersion + "] which is over supported java version [" + supportedVersion + "]"); + } + } + catch (IOException e) + { + exception(path,"Unable to read class",e); + } + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JspPrecompileRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JspPrecompileRule.java new file mode 100644 index 00000000000..73bfb552a43 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JspPrecompileRule.java @@ -0,0 +1,43 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; + +import org.eclipse.jetty.webapp.verifier.AbstractRule; + +/** + * Perform a JSP pre-compile to ensure all JSPs are valid. + */ +public class JspPrecompileRule extends AbstractRule +{ + public String getDescription() + { + return "Perform JSP precompile to ensure all jsps are valid"; + } + + public String getName() + { + return "jsp-precompile"; + } + + @Override + public void visitWebappStart(String path, File dir) + { + // TODO: implement rule. + error(path,"Rule [" + getClass().getName() + "] not yet implemented"); + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JspSupportLevelRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JspSupportLevelRule.java new file mode 100644 index 00000000000..15181ade9b4 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/JspSupportLevelRule.java @@ -0,0 +1,43 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; + +import org.eclipse.jetty.webapp.verifier.AbstractRule; + +/** + * Ensure any included JSPs are supported by the Container. + */ +public class JspSupportLevelRule extends AbstractRule +{ + public String getDescription() + { + return "Ensure include JSP are supported by the Container"; + } + + public String getName() + { + return "jsp-support-level"; + } + + @Override + public void visitWebappStart(String path, File dir) + { + // TODO: implement rule. + error(path,"Rule [" + getClass().getName() + "] not yet implemented"); + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoJspRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoJspRule.java new file mode 100644 index 00000000000..d296f39a916 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoJspRule.java @@ -0,0 +1,46 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; + +import org.eclipse.jetty.webapp.verifier.AbstractRule; + +/** + * Prevent inclusion of *.jsp in webapp. + */ +public class NoJspRule extends AbstractRule +{ + public String getDescription() + { + return "Prevent inclusion of JSPs in webapp"; + } + + public String getName() + { + return "no-jsp"; + } + + @Override + public void visitFile(String path, File dir, File file) + { + String name = file.getName().toLowerCase(); + if (name.endsWith(".jsp") || name.endsWith(".jspf")) + { + error(path,"No JSP's are allowed"); + } + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoNativeRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoNativeRule.java new file mode 100644 index 00000000000..ee6f1176f87 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoNativeRule.java @@ -0,0 +1,68 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.eclipse.jetty.webapp.verifier.AbstractArchiveScanningRule; +import org.eclipse.jetty.webapp.verifier.support.PathGlob; + +/** + * Prevent use of native code in webapp. + */ +public class NoNativeRule extends AbstractArchiveScanningRule +{ + private String[] nativePatterns = + { "*.so", "*.so.*", "*.o", "*.dll", "*.com", "*.exe" }; + + @Override + public String getDescription() + { + return "Prevent use of native code in webapp"; + } + + @Override + public String getName() + { + return "no-native"; + } + + @Override + public void visitFile(String path, File dir, File file) + { + for (String pattern : nativePatterns) + { + if (PathGlob.match(pattern,path)) + { + error(path,"Native code is forbidden"); + } + } + } + + @Override + public void visitArchiveResource(String path, ZipFile zip, ZipEntry entry) + { + for (String pattern : nativePatterns) + { + if (PathGlob.match(pattern,entry.getName())) + { + error(path,"Native code is forbidden"); + } + } + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoScriptingRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoScriptingRule.java new file mode 100644 index 00000000000..2cbfd45efa0 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoScriptingRule.java @@ -0,0 +1,235 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.eclipse.jetty.webapp.verifier.AbstractRule; + +/** + * NoScriptingRule ensure that no scripting languages are used in the webapp. + * + * Checks for actual script files in webapp filesystem, and existance of popular scripting language libraries as well. + */ +public class NoScriptingRule extends AbstractRule +{ + class Forbidden + { + public String key; + public String msg; + + public Forbidden(String key, String msg) + { + super(); + this.key = key; + this.msg = msg; + } + } + + private boolean allowJRuby = false; + private boolean allowBeanshell = false; + private boolean allowGroovy = false; + private boolean allowJython = false; + private boolean allowShell = false; + private List forbiddenFileExtensions = new ArrayList(); + private List forbiddenClassIds = new ArrayList(); + + public boolean isAllowShell() + { + return allowShell; + } + + public void setAllowShell(boolean allowShell) + { + this.allowShell = allowShell; + } + + public boolean isAllowJRuby() + { + return allowJRuby; + } + + public void setAllowJRuby(boolean allowJruby) + { + this.allowJRuby = allowJruby; + } + + public boolean isAllowBeanshell() + { + return allowBeanshell; + } + + public void setAllowBeanshell(boolean allowBeanshell) + { + this.allowBeanshell = allowBeanshell; + } + + public boolean isAllowGroovy() + { + return allowGroovy; + } + + public void setAllowGroovy(boolean allowGroovy) + { + this.allowGroovy = allowGroovy; + } + + public boolean isAllowJython() + { + return allowJython; + } + + public void setAllowJython(boolean allowJython) + { + this.allowJython = allowJython; + } + + public String getDescription() + { + return "Do not allow scripting languages in webapp"; + } + + public String getName() + { + return "forbidden-scripting"; + } + + @Override + public void initialize() throws Throwable + { + forbiddenFileExtensions.clear(); + forbiddenClassIds.clear(); + if (!allowJRuby) + { + String msg = "JRuby scripting not allowed"; + forbiddenFileExtensions.add(new Forbidden(".rb",msg)); + forbiddenFileExtensions.add(new Forbidden(".rhtml",msg)); + msg = "JRuby dependencies are not allowed"; + forbiddenClassIds.add(new Forbidden(".jruby.",msg)); + } + + if (!allowJython) + { + String msg = "Jython and Python scripting not allowed"; + forbiddenFileExtensions.add(new Forbidden(".py",msg)); + forbiddenFileExtensions.add(new Forbidden(".pyc",msg)); + msg = "Jython dependencies are not allowed"; + forbiddenClassIds.add(new Forbidden("org.python.",msg)); + } + + if (!allowGroovy) + { + String msg = "Groovy scripting not allowed"; + forbiddenFileExtensions.add(new Forbidden(".groovy",msg)); + msg = "Groovy dependencies are not allowed"; + forbiddenClassIds.add(new Forbidden(".groovy.",msg)); + } + + if (!allowShell) + { + String msg = "Shell scripting not allowed"; + forbiddenFileExtensions.add(new Forbidden(".sh",msg)); + forbiddenFileExtensions.add(new Forbidden(".bat",msg)); + forbiddenFileExtensions.add(new Forbidden(".cmd",msg)); + forbiddenFileExtensions.add(new Forbidden(".vbs",msg)); + } + } + + @Override + public void visitFile(String path, File dir, File file) + { + String name = file.getName().toLowerCase(); + for (Forbidden forbidden : forbiddenFileExtensions) + { + if (name.endsWith(forbidden.key)) + { + error(path,forbidden.msg); + } + } + } + + @Override + public void visitWebInfClass(String path, String className, File classFile) + { + validateClassname(path,className); + } + + private void validateClassname(String path, String className) + { + for (Forbidden forbidden : forbiddenClassIds) + { + if (className.contains(forbidden.key)) + { + error(path,forbidden.msg); + } + } + } + + @Override + public void visitWebInfClassResource(String path, String resourcePath, File resourceFile) + { + super.visitWebInfClassResource(path,resourcePath,resourceFile); + } + + @Override + public void visitWebInfLibJar(String path, File archive, JarFile jar) + { + iterateArchive(path,archive,jar); + } + + private void iterateArchive(String path, File archive, ZipFile zip) + { + try + { + Enumeration entries = zip.entries(); + while (entries.hasMoreElements()) + { + ZipEntry entry = entries.nextElement(); + if (entry.getName().endsWith(".class")) + { + checkArchiveClassname(path,archive,entry.getName()); + } + } + } + catch (Throwable t) + { + exception(path,"Unable to iterate archive: Contents invalid?: " + t.getMessage(),t); + } + } + + private void checkArchiveClassname(String path, File archive, String name) + { + String className = name.replace("/","."); + if (className.endsWith(".class")) + { + className = className.substring(0,className.length() - 6); + } + + validateClassname(path + "!/" + name,className); + } + + @Override + public void visitWebInfLibZip(String path, File archive, ZipFile zip) + { + iterateArchive(path,archive,zip); + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceControlRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceControlRule.java new file mode 100644 index 00000000000..2b07684f3c8 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceControlRule.java @@ -0,0 +1,151 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.eclipse.jetty.webapp.verifier.AbstractArchiveScanningRule; + +/** + * Prevent inclusion of Source Control files & directories that might reveal hostnames, userids, and passwords to the + * source control. (CVS, .svn/, .git/) + */ +public class NoSourceControlRule extends AbstractArchiveScanningRule +{ + class ScmName + { + String scm; + String name; + + public ScmName(String scm, String name) + { + this.scm = scm; + this.name = name; + } + } + + private static List scmDirNames = new ArrayList(); + private static List scmFileNames = new ArrayList(); + + public NoSourceControlRule() + { + super(); + + // The order of patterns is most likely to least likely + + scmDirNames.add(new ScmName("Subversion",".svn")); // Standard Unix format + scmDirNames.add(new ScmName("Subversion","_svn")); // Alternate Windows format + scmDirNames.add(new ScmName("CVS","CVS")); + scmFileNames.add(new ScmName("CVS",".cvsignore")); + scmDirNames.add(new ScmName("Git",".git")); + scmFileNames.add(new ScmName("Git",".gitignore")); + scmDirNames.add(new ScmName("RCS","RCS")); + scmDirNames.add(new ScmName("SCCS","SCCS")); + scmFileNames.add(new ScmName("Visual SourceSafe","vssver.scc")); + scmDirNames.add(new ScmName("Arch",".arch-ids")); + scmDirNames.add(new ScmName("Bazaar",".bzr")); + scmFileNames.add(new ScmName("SurroundSCM",".MySCMServerInfo")); + scmDirNames.add(new ScmName("Mercurial",".hg")); + scmDirNames.add(new ScmName("BitKeeper","BitKeeper")); + scmDirNames.add(new ScmName("BitKeeper","ChangeSet")); + scmDirNames.add(new ScmName("Darcs","_darcs")); + scmDirNames.add(new ScmName("Darcs",".darcsrepo")); + scmFileNames.add(new ScmName("Darcs",".darcs-temp-mail")); + } + + @Override + public String getDescription() + { + return "Prevent inclusion of source control files in webapp"; + } + + @Override + public String getName() + { + return "no-source-control"; + } + + @Override + public void visitDirectoryStart(String path, File dir) + { + for (ScmName scmName : scmDirNames) + { + if (dir.getName().equalsIgnoreCase(scmName.name)) + { + error(path,scmName.scm + " Source Control directories are not allowed"); + } + } + } + + @Override + public void visitFile(String path, File dir, File file) + { + for (ScmName scmName : scmFileNames) + { + if (file.getName().equalsIgnoreCase(scmName.name)) + { + error(path,scmName.scm + " Source Control file are not allowed"); + } + } + } + + @Override + public void visitArchiveResource(String path, ZipFile zip, ZipEntry entry) + { + String basename = toBaseName(entry); + + if (entry.isDirectory()) + { + for (ScmName scmName : scmDirNames) + { + if (basename.equalsIgnoreCase(scmName.name)) + { + error(path,scmName.scm + " Source Control directories are not allowed"); + } + } + } + else + { + for (ScmName scmName : scmFileNames) + { + if (basename.equalsIgnoreCase(scmName.name)) + { + error(path,scmName.scm + " Source Control file are not allowed"); + } + } + } + } + + private String toBaseName(ZipEntry entry) + { + String name =entry.getName(); + if (name.endsWith("/")) + { + name = name.substring(0,name.length() - 1); + } + + int idx = name.lastIndexOf('/'); + if (idx >= 0) + { + return name.substring(idx + 1); + } + return name; + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceRule.java new file mode 100644 index 00000000000..48f2f0c5e07 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceRule.java @@ -0,0 +1,70 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.eclipse.jetty.webapp.verifier.AbstractArchiveScanningRule; +import org.eclipse.jetty.webapp.verifier.support.PathGlob; + +/** + *

+ * Prevent inclusion of source files in webapp. (*.java) + *

+ */ +public class NoSourceRule extends AbstractArchiveScanningRule +{ + private String[] sourcePatterns = + { "*.java" }; + + @Override + public String getDescription() + { + return "Prevent inclusion of source files in webapp"; + } + + @Override + public String getName() + { + return "no-source"; + } + + @Override + public void visitFile(String path, File dir, File file) + { + for (String pattern : sourcePatterns) + { + if (PathGlob.match(pattern,path)) + { + error(path,"Source code is forbidden"); + } + } + } + + @Override + public void visitArchiveResource(String path, ZipFile zip, ZipEntry entry) + { + for (String pattern : sourcePatterns) + { + if (PathGlob.match(pattern,entry.getName())) + { + error(path,"Source code is forbidden"); + } + } + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/RequiredContentsRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/RequiredContentsRule.java new file mode 100644 index 00000000000..75efa42adcf --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/RequiredContentsRule.java @@ -0,0 +1,64 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jetty.webapp.verifier.AbstractRule; + +/** + * ForbiddenContentsVerifier ensures that content matching a pattern does not exist in the webapp. + */ +public class RequiredContentsRule extends AbstractRule +{ + private List _paths = new ArrayList(); + + public void addPath(String path) + { + _paths.add(path); + } + + public String getDescription() + { + return "Ensures that requred content is present"; + } + + public String getName() + { + return "required-content"; + } + + @Override + public void visitDirectoryEnd(String path, File dir) + { + if (path.equals(ROOT_PATH)) + { + File root = new File(path); + + for (String expectedPath : _paths) + { + File file = new File(root,expectedPath); + if (!file.exists()) + { + error(getWebappRelativePath(file),"Required content not found"); + } + } + } + } + +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/SaneArchiveRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/SaneArchiveRule.java new file mode 100644 index 00000000000..56a0ce22cb5 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/SaneArchiveRule.java @@ -0,0 +1,59 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; + +import org.eclipse.jetty.webapp.verifier.AbstractRule; + +/** + *

+ * Sanity check of archive (both war itself, as well as libs) to ensure that various entries within are sane. + *

+ * + *

+ * Example checks: + *

+ * + *
    + *
  1. Entries cannot contain references to parent "../../my_file.txt"
  2. + *
  3. Cannot contain multiple entries of the same name with different case. + *
      + *
    • /index.jsp
    • + *
    • /Index.jsp
    • + *
    + *
  4. + *
+ */ +public class SaneArchiveRule extends AbstractRule +{ + public String getDescription() + { + return "Basic archive (jar & war) sanity checks"; + } + + public String getName() + { + return "sane-archive"; + } + + @Override + public void visitWebappStart(String path, File dir) + { + // TODO: implement rule. + error(path,"Rule [" + getClass().getName() + "] not yet implemented"); + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ServletSupportLevelRule.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ServletSupportLevelRule.java new file mode 100644 index 00000000000..29c95312b3a --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/ServletSupportLevelRule.java @@ -0,0 +1,374 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.eclipse.jetty.webapp.verifier.AbstractRule; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * Ensure declared servlet level (servlet spec version) in webapp conforms to supported level. + */ +public class ServletSupportLevelRule extends AbstractRule +{ + private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance"; + + class ServletId + { + String version; + String name; + String type; + + public ServletId(String version, String type, String name) + { + super(); + this.version = version; + this.type = type; + this.name = name; + } + } + + private String supportedVersion = "2.5"; + private String fileSep = System.getProperty("file.separator","/"); + private List dtdPublicIds = new ArrayList(); + private List dtdSystemIds = new ArrayList(); + private List nsIds = new ArrayList(); + private List schemaIds = new ArrayList(); + private String validVersions[] = + { "2.5", "2.4", "2.3", "2.2" }; + + public ServletSupportLevelRule() + { + // Servlet 2.5 + schemaIds.add(new ServletId("2.5","Schema","http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd")); + nsIds.add(new ServletId("2.5","XML Namespace","http://java.sun.com/xml/ns/javaee")); + + // Servlet 2.4 + schemaIds.add(new ServletId("2.4","Schema","http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd")); + nsIds.add(new ServletId("2.4","XML Namespace","http://java.sun.com/xml/ns/j2ee")); + + // Servlet 2.3 + dtdPublicIds.add(new ServletId("2.3","DOCTYPE Public ID","-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN")); + dtdSystemIds.add(new ServletId("2.3","DOCTYPE System ID","http://java.sun.com/dtd/web-app_2_3.dtd")); + + // Servlet 2.2 + dtdPublicIds.add(new ServletId("2.2","DOCTYPE Public ID","-//Sun Microsystems, Inc.//DTD WebApplication 2.2//EN")); + dtdSystemIds.add(new ServletId("2.2","DOCTYPE System ID","http://java.sun.com/j2ee/dtds/web-app_2.2.dtd")); + } + + public String getDescription() + { + return "Ensure webapp works within supported servlet spec"; + } + + public String getName() + { + return "servlet-support-level"; + } + + public String getSupportedVersion() + { + return supportedVersion; + } + + public void setSupportedVersion(String supportedLevel) + { + this.supportedVersion = supportedLevel; + } + + @Override + public void visitWebappStart(String path, File dir) + { + super.visitWebappStart(path,dir); + + File webXmlFile = new File(dir,"WEB-INF/web.xml".replaceAll("/",fileSep)); + String webxmlpath = getWebappRelativePath(webXmlFile); + + if (!webXmlFile.exists()) + { + error(webxmlpath,"web.xml does not exist"); + return; + } + + // Using JAXP to parse the web.xml (SAX pls) + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setValidating(false); + factory.setNamespaceAware(true); + + try + { + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(webXmlFile); + + List detectedIds = collectServletIds(webxmlpath,doc); + Set versions = new TreeSet(); + for (ServletId id : detectedIds) + { + versions.add(id.version); + } + + if (versions.size() > 1) + { + String msg = String.format("Found %d versions defined [%s], expected 1",versions.size(),join(versions,", ")); + error(webxmlpath,msg); + for (ServletId id : detectedIds) + { + reportConflicting(webxmlpath,id,detectedIds); + } + } + + reportOverVersion(webxmlpath,detectedIds); + } + catch (ParserConfigurationException e) + { + exception(webxmlpath,"[internal] Unable to establish XML parser",e); + } + catch (SAXException e) + { + exception(webxmlpath,"Unable to parse web.xml",e); + } + catch (IOException e) + { + exception(webxmlpath,"Unable to parse web.xml",e); + } + } + + private void reportOverVersion(String webxmlpath, List detectedIds) + { + double supportedVer = Double.parseDouble(this.supportedVersion); + + for (ServletId id : detectedIds) + { + try + { + double detectedVersion = Double.parseDouble(id.version); + if (detectedVersion > supportedVer) + { + String msg = String.format("Specified servlet version %s of %s is over the configured supported servlet version %s",id.version,id.type, + supportedVersion); + error(webxmlpath,msg); + } + } + catch (NumberFormatException e) + { + error(webxmlpath,String.format("Unable to parse version [%s] of %s, not a double",id.version,id.type)); + } + } + + } + + private void reportConflicting(String webxmlpath, ServletId mainId, List otherIds) + { + for (ServletId id : otherIds) + { + if (id.version.equals(mainId.version) == false) + { + String msg = String.format("version %s of %s conflicts with version %s of %s",mainId.version,mainId.type,id.version,id.type); + error(webxmlpath,msg); + } + } + } + + private String join(Collection coll, String delim) + { + StringBuffer msg = new StringBuffer(); + + Iterator it = coll.iterator(); + while (it.hasNext()) + { + msg.append(String.valueOf(it.next())); + if (it.hasNext()) + { + msg.append(delim); + } + } + + return msg.toString(); + } + + private List collectServletIds(String webxmlpath, Document doc) + { + List ids = new ArrayList(); + + // Check for DOCTYPE defined ids. + DocumentType doctype = doc.getDoctype(); + if (doctype != null) + { + if ("web-app".equals(doctype.getName())) + { + boolean valid = false; + for (ServletId id : dtdPublicIds) + { + if (id.name.equals(doctype.getPublicId())) + { + ids.add(id); + valid = true; + } + } + + if (!valid) + { + error(webxmlpath,"Invalid DOCTYPE public ID: " + doctype.getPublicId()); + } + + valid = false; + for (ServletId id : dtdSystemIds) + { + if (id.name.equals(doctype.getSystemId())) + { + ids.add(id); + valid = true; + } + } + + if (!valid) + { + error(webxmlpath,"Invalid DOCTYPE system ID: " + doctype.getSystemId()); + } + } + else + { + error(webxmlpath,"Invalid DOCTYPE detected, expected 'web-app', but found '" + doctype.getName() + "' instaed."); + } + } + + // Check for Root Element Namespace ids. + Element root = doc.getDocumentElement(); + + if ("web-app".equals(root.getTagName())) + { + String actualXmlNs = root.getAttribute("xmlns"); + String actualXsi = root.getAttribute("xmlns:xsi"); + String actualSchema = root.getAttribute("xsi:schemaLocation"); + String actualVersion = root.getAttribute("version"); + + if (hasAnyValue(actualXmlNs,actualXsi,actualSchema,actualVersion)) + { + if ((actualXmlNs == null) || (actualXmlNs == "")) + { + error(webxmlpath,"Attribute must exist with a valid value"); + } + else + { + boolean valid = false; + for (ServletId id : nsIds) + { + if (id.name.equals(actualXmlNs)) + { + ids.add(id); + valid = true; + } + } + + if (!valid) + { + String msg = String.format("Invalid xmlns value for ",actualXmlNs); + error(webxmlpath,msg); + } + } + + if ((actualXsi == null) || (actualXsi == "")) + { + error(webxmlpath,"Attribute must exist with a valid value"); + } + else if (!XSI_NS.equals(actualXsi)) + { + String msg = String.format("Attribute mismatch expecting but found ",XSI_NS,actualXsi); + error(webxmlpath,msg); + } + + if ((actualSchema == null) || (actualSchema == "")) + { + error(webxmlpath,"Attribute must exist with a valid value"); + } + else + { + boolean valid = false; + for (ServletId id : schemaIds) + { + if (id.name.equals(actualSchema)) + { + ids.add(id); + valid = true; + } + } + + if (!valid) + { + String msg = String.format("Invalid schemaLocation value ",actualSchema); + error(webxmlpath,msg); + } + } + + if ((actualVersion == null) || (actualVersion == "")) + { + error(webxmlpath,"Attribute must exist with a valid value"); + } + else + { + boolean valid = false; + for (String version : validVersions) + { + if (version.equals(actualVersion)) + { + ids.add(new ServletId(version,"version attribute",null)); + valid = true; + } + } + + if (!valid) + { + String msg = String.format("Invalid version value ",actualVersion); + error(webxmlpath,msg); + } + } + } + } + else + { + error(webxmlpath,"Invalid web.xml, root element expectd to be , but was <" + root.getTagName() + ">"); + } + + return ids; + } + + private boolean hasAnyValue(String... values) + { + for (String value : values) + { + if ((value != null) && (value.length() > 0)) + { + return true; + } + } + return false; + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/asm/ASMUtil.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/asm/ASMUtil.java new file mode 100644 index 00000000000..9267c57ea7f --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/asm/ASMUtil.java @@ -0,0 +1,54 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules.asm; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.jetty.util.IO; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; + +/** + * Some simple utility methods for working with ASM in a common way. + */ +public class ASMUtil +{ + public static void visitClassFile(File classFile, ClassVisitor visitor, int flags) throws IOException + { + FileInputStream fin = null; + ClassReader creader = null; + + try + { + fin = new FileInputStream(classFile); + creader = new ClassReader(fin); + creader.accept(visitor,flags); + } + finally + { + IO.close(fin); + } + } + + public static void visitClass(InputStream stream, ClassVisitor visitor, int flags) throws IOException + { + ClassReader creader = new ClassReader(stream); + creader.accept(visitor,flags); + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/asm/AbstractClassVisitor.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/asm/AbstractClassVisitor.java new file mode 100644 index 00000000000..1ec62be77d1 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/rules/asm/AbstractClassVisitor.java @@ -0,0 +1,77 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules.asm; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; + +/** + * Abstact implementation of {@link ClassVisitor} to make asm use within Rules easier. + */ +public abstract class AbstractClassVisitor implements ClassVisitor +{ + + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) + { + /* Override Ready */ + } + + public AnnotationVisitor visitAnnotation(String desc, boolean visible) + { + /* Override Ready */ + return null; + } + + public void visitAttribute(Attribute attr) + { + /* Override Ready */ + } + + public void visitEnd() + { + /* Override Ready */ + } + + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) + { + /* Override Ready */ + return null; + } + + public void visitInnerClass(String name, String outerName, String innerName, int access) + { + /* Override Ready */ + } + + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) + { + /* Override Ready */ + return null; + } + + public void visitOuterClass(String owner, String name, String desc) + { + /* Override Ready */ + } + + public void visitSource(String source, String debug) + { + /* Override Ready */ + } +} diff --git a/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/support/PathGlob.java b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/support/PathGlob.java new file mode 100644 index 00000000000..12dd2e16369 --- /dev/null +++ b/jetty-webapp-verifier/src/main/java/org/eclipse/jetty/webapp/verifier/support/PathGlob.java @@ -0,0 +1,58 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.support; + +public class PathGlob +{ + /** + * @return true if match. + */ + public static boolean match(String pathSpec, String path) throws IllegalArgumentException + { + return match(pathSpec,path,false); + } + + /** + * @return true if match. + */ + public static boolean match(String pathSpec, String path, boolean noDefault) throws IllegalArgumentException + { + char c = pathSpec.charAt(0); + if (c == '/') + { + if (!noDefault && pathSpec.length() == 1 || pathSpec.equals(path)) + return true; + + if (isPathWildcardMatch(pathSpec,path)) + return true; + } + else if (c == '*') + return path.regionMatches(path.length() - pathSpec.length() + 1,pathSpec,1,pathSpec.length() - 1); + return false; + } + + private static boolean isPathWildcardMatch(String pathSpec, String path) + { + // For a spec of "/foo/*" match "/foo" , "/foo/..." but not "/foobar" + int cpl = pathSpec.length() - 2; + if (pathSpec.endsWith("/*") && path.regionMatches(0,pathSpec,0,cpl)) + { + if (path.length() == cpl || '/' == path.charAt(cpl)) + return true; + } + return false; + } +} diff --git a/jetty-webapp-verifier/src/test/artifacts/.gitignore b/jetty-webapp-verifier/src/test/artifacts/.gitignore new file mode 100644 index 00000000000..bf5aabfefa2 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/.gitignore @@ -0,0 +1,11 @@ +target/ +.classpath +.project +.settings/ +*.tar.gz +*.zip +bsh* +jruby* +jython* +groovy* +*.swp diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/pom.xml new file mode 100644 index 00000000000..3d7601f2e1b --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-groovy-lib + jar + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Groovy Lib + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory new file mode 100644 index 00000000000..8af8bb9660d --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory @@ -0,0 +1 @@ +org.codehaus.groovy.jsr223.GroovyScriptEngineFactory \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/src/main/resources/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/src/main/resources/README.txt new file mode 100644 index 00000000000..906d0a4f50f --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-lib/src/main/resources/README.txt @@ -0,0 +1,4 @@ +This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +It is neither a valid JAR file, nor contains valid Groovy implementations, +in either scripting, source or binary form. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/pom.xml new file mode 100644 index 00000000000..82ecbe4dad0 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/pom.xml @@ -0,0 +1,22 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-groovy-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Groovy Webapp + + + junit + junit + 3.8.1 + test + + + org.eclipse.jetty.tests + dummy-groovy-lib + 1.0-SNAPSHOT + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/README.txt new file mode 100644 index 00000000000..f27b3191d90 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/README.txt @@ -0,0 +1,4 @@ +This is a webapp is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +It is neither a valid WAR file, nor contains valid Groovy implementations, +in either scripting, source or binary form. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..9f88c1f9632 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/dummy.groovy b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/dummy.groovy new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/other/lib.groovy b/jetty-webapp-verifier/src/test/artifacts/dummy-groovy-webapp/src/main/webapp/other/lib.groovy new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/pom.xml new file mode 100644 index 00000000000..302fcaf410b --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-java11-lib + jar + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Java1.1 Lib + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.1 + + + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyLib.java b/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyLib.java new file mode 100644 index 00000000000..d9a8203d145 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyLib.java @@ -0,0 +1,27 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.testcase.verifier; + +/** + * Dummy class for testcase purposes. + */ +public class DummyLib +{ + public void dummyTestClassNotIntendedForUse() + { + /* not intended for use - only used for test case purposes */ + } +} diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/src/main/resources/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/src/main/resources/README.txt new file mode 100644 index 00000000000..62c883903b9 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java11-lib/src/main/resources/README.txt @@ -0,0 +1,3 @@ +This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/pom.xml new file mode 100644 index 00000000000..c2b6cc3872d --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-java12-lib + jar + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Java1.2 Lib + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.2 + + + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyUpdatedLib.java b/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyUpdatedLib.java new file mode 100644 index 00000000000..30e35fa1e6e --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyUpdatedLib.java @@ -0,0 +1,27 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.testcase.verifier; + +/** + * Dummy class for testcase purposes. + */ +public class DummyUpdatedLib +{ + public void dummyTestClassNotIntendedForUse() + { + /* not intended for use - only used for test case purposes */ + } +} diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/src/main/resources/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/src/main/resources/README.txt new file mode 100644 index 00000000000..62c883903b9 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java12-lib/src/main/resources/README.txt @@ -0,0 +1,3 @@ +This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/pom.xml new file mode 100644 index 00000000000..29683ed739e --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-java13-lib + jar + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Java1.3 Lib + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.3 + + + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyCurrentLib.java b/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyCurrentLib.java new file mode 100644 index 00000000000..25f060c490d --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyCurrentLib.java @@ -0,0 +1,27 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.testcase.verifier; + +/** + * Dummy class for testcase purposes. + */ +public class DummyCurrentLib +{ + public void dummyTestClassNotIntendedForUse() + { + /* not intended for use - only used for test case purposes */ + } +} diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/src/main/resources/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/src/main/resources/README.txt new file mode 100644 index 00000000000..62c883903b9 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java13-lib/src/main/resources/README.txt @@ -0,0 +1,3 @@ +This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/pom.xml new file mode 100644 index 00000000000..f469224ddb7 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-java14-lib + jar + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Java1.4 Lib + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.4 + + + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyFreshLib.java b/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyFreshLib.java new file mode 100644 index 00000000000..b93f2cfd982 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyFreshLib.java @@ -0,0 +1,27 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.testcase.verifier; + +/** + * Dummy class for testcase purposes. + */ +public class DummyFreshLib +{ + public void dummyTestClassNotIntendedForUse() + { + /* not intended for use - only used for test case purposes */ + } +} diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/src/main/resources/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/src/main/resources/README.txt new file mode 100644 index 00000000000..62c883903b9 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java14-lib/src/main/resources/README.txt @@ -0,0 +1,3 @@ +This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/pom.xml new file mode 100644 index 00000000000..e12af4a27c4 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-java15-lib + jar + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Java1.5 Lib + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + + + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyLatestLib.java b/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyLatestLib.java new file mode 100644 index 00000000000..be05acc114a --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyLatestLib.java @@ -0,0 +1,27 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.testcase.verifier; + +/** + * Dummy class for testcase purposes. + */ +public class DummyLatestLib +{ + public void dummyTestClassNotIntendedForUse() + { + /* not intended for use - only used for test case purposes */ + } +} diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/src/main/resources/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/src/main/resources/README.txt new file mode 100644 index 00000000000..62c883903b9 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java15-lib/src/main/resources/README.txt @@ -0,0 +1,3 @@ +This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/pom.xml new file mode 100644 index 00000000000..6ff141d7504 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-java16-lib + jar + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Java1.6 Lib + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + + + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyModernLib.java b/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyModernLib.java new file mode 100644 index 00000000000..1e4c0352dcd --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/src/main/java/org/eclipse/jetty/testcase/verifier/DummyModernLib.java @@ -0,0 +1,27 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.testcase.verifier; + +/** + * Dummy class for testcase purposes. + */ +public class DummyModernLib +{ + public void dummyTestClassNotIntendedForUse() + { + /* not intended for use - only used for test case purposes */ + } +} diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/src/main/resources/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/src/main/resources/README.txt new file mode 100644 index 00000000000..62c883903b9 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-java16-lib/src/main/resources/README.txt @@ -0,0 +1,3 @@ +This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/pom.xml new file mode 100644 index 00000000000..c38b9b4035a --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/pom.xml @@ -0,0 +1,84 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-javaversions-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Java Versions Webapp + + + org.eclipse.jetty.tests + dummy-java11-lib + 1.0-SNAPSHOT + + + org.eclipse.jetty.tests + dummy-java12-lib + 1.0-SNAPSHOT + + + org.eclipse.jetty.tests + dummy-java13-lib + 1.0-SNAPSHOT + + + org.eclipse.jetty.tests + dummy-java14-lib + 1.0-SNAPSHOT + + + org.eclipse.jetty.tests + dummy-java15-lib + 1.0-SNAPSHOT + + + org.eclipse.jetty.tests + dummy-java16-lib + 1.0-SNAPSHOT + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + explode-jars-to-classes + process-resources + + unpack-dependencies + + + **/*.class + ${project.build.directory}/${project.artifactId}-${project.version}/WEB-INF/classes + + + + + + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/src/main/webapp/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/src/main/webapp/README.txt new file mode 100644 index 00000000000..ba2e2233228 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/src/main/webapp/README.txt @@ -0,0 +1,4 @@ +This is a webapp is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +It is neither a valid WAR file, nor contains valid JRuby implementations, +in either scripting, source or binary form. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..9f88c1f9632 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-javaversions-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/pom.xml new file mode 100644 index 00000000000..6fec6b3db33 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-jruby-lib + jar + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy JRuby Lib + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/src/main/resources/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/src/main/resources/README.txt new file mode 100644 index 00000000000..73178116f20 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/src/main/resources/README.txt @@ -0,0 +1,4 @@ +This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +It is neither a valid JAR file, nor contains valid JRuby implementations, +in either scripting, source or binary form. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/src/main/resources/builtin/javasupport.rb b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-lib/src/main/resources/builtin/javasupport.rb new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/pom.xml new file mode 100644 index 00000000000..1f04225a007 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/pom.xml @@ -0,0 +1,22 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-jruby-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy JRuby Webapp + + + junit + junit + 3.8.1 + test + + + org.eclipse.jetty.tests + dummy-jruby-lib + 1.0-SNAPSHOT + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/README.txt new file mode 100644 index 00000000000..ba2e2233228 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/README.txt @@ -0,0 +1,4 @@ +This is a webapp is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +It is neither a valid WAR file, nor contains valid JRuby implementations, +in either scripting, source or binary form. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..9f88c1f9632 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/example.rb b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/example.rb new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/other/lib.rb b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/other/lib.rb new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/output.rhtml b/jetty-webapp-verifier/src/test/artifacts/dummy-jruby-webapp/src/main/webapp/output.rhtml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/pom.xml new file mode 100644 index 00000000000..28076c9057d --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-jython-lib + jar + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Jython Lib + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/Version.java b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/Version.java new file mode 100644 index 00000000000..bf6af0b796b --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/Version.java @@ -0,0 +1,28 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== + +package org.python; + +/** + * Dummy class for testcase purposes. + */ +public class Version +{ + public void dummyTestClassNotIntendedForUse() + { + /* not intended for use - only used for test case purposes */ + } +} diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/core/JythonInitializer.java b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/core/JythonInitializer.java new file mode 100644 index 00000000000..c9f720aa1d1 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/core/JythonInitializer.java @@ -0,0 +1,28 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== + +package org.python.core; + +/** + * Dummy class for testcase purposes. + */ +public class JythonInitializer +{ + public void dummyTestClassNotIntendedForUse() + { + /* not intended for use - only used for test case purposes */ + } +} diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/util/Generic.java b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/util/Generic.java new file mode 100644 index 00000000000..b692781f8e6 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/java/org/python/util/Generic.java @@ -0,0 +1,28 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== + +package org.python.util; + +/** + * Dummy class for testcase purposes. + */ +public class Generic +{ + public void dummyTestClassNotIntendedForUse() + { + /* not intended for use - only used for test case purposes */ + } +} diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/resources/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/resources/README.txt new file mode 100644 index 00000000000..bc6accef097 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-lib/src/main/resources/README.txt @@ -0,0 +1,4 @@ +This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +It is neither a valid JAR file, nor contains valid Jython implementations, +in either scripting, source or binary form. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/pom.xml new file mode 100644 index 00000000000..c37cae0b537 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/pom.xml @@ -0,0 +1,22 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-jython-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Jython Webapp + + + junit + junit + 3.8.1 + test + + + org.eclipse.jetty.tests + dummy-jython-lib + 1.0-SNAPSHOT + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/README.txt new file mode 100644 index 00000000000..ba2e2233228 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/README.txt @@ -0,0 +1,4 @@ +This is a webapp is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +It is neither a valid WAR file, nor contains valid JRuby implementations, +in either scripting, source or binary form. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..9f88c1f9632 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/dummy.py b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/dummy.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/dummy.pyc b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/dummy.pyc new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/other/lib.py b/jetty-webapp-verifier/src/test/artifacts/dummy-jython-webapp/src/main/webapp/other/lib.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/pom.xml new file mode 100644 index 00000000000..af7f08ef7c0 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-nativeaccess-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Native Access Webapp + + + junit + junit + 3.8.1 + test + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/README.txt new file mode 100644 index 00000000000..ba2e2233228 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/README.txt @@ -0,0 +1,4 @@ +This is a webapp is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +It is neither a valid WAR file, nor contains valid JRuby implementations, +in either scripting, source or binary form. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..9f88c1f9632 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/dummy.exe b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/dummy.exe new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/dummy.o b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/dummy.o new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/dummy.so b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/dummy.so new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/executable b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/executable new file mode 100755 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.dll b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.dll new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.o b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.o new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so.0.5.7 b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so.0.5.7 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so.1 b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so.1 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so.5 b/jetty-webapp-verifier/src/test/artifacts/dummy-nativeaccess-webapp/src/main/webapp/other/lib.so.5 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/pom.xml new file mode 100644 index 00000000000..992cccb5e29 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/pom.xml @@ -0,0 +1,84 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-scm-lib + pom + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy SCM Lib + + + + org.apache.maven.plugins + maven-antrun-plugin + + + create-scm-files + generate-resources + + run + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-scm-lib + package + + attach-artifact + + + + + ${project.build.directory}/${project.artifactId}-${project.version}.jar + jar + + + + + + + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/src/main/resources/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/src/main/resources/README.txt new file mode 100644 index 00000000000..62c883903b9 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-lib/src/main/resources/README.txt @@ -0,0 +1,3 @@ +This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/pom.xml new file mode 100644 index 00000000000..f2a20367d62 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/pom.xml @@ -0,0 +1,116 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-scm-webapp + pom + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy SCM Webapp + + + org.eclipse.jetty.tests + dummy-scm-lib + 1.0-SNAPSHOT + + + + ${project.build.directory}/generated-webapp + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + create-scm-files + generate-resources + + run + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + create-war + package + + run + + + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-deps + process-resources + + copy-dependencies + + + ${war_work_dir}/WEB-INF/lib + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-scm-lib + process-resources + + attach-artifact + + + + + ${project.build.directory}/${project.artifactId}-${project.version}.war + war + + + + + + + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/src/main/webapp/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/src/main/webapp/README.txt new file mode 100644 index 00000000000..ba2e2233228 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/src/main/webapp/README.txt @@ -0,0 +1,4 @@ +This is a webapp is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +It is neither a valid WAR file, nor contains valid JRuby implementations, +in either scripting, source or binary form. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..9f88c1f9632 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-scm-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/pom.xml new file mode 100644 index 00000000000..fb11c34596d --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-servlet23-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Servlet 2.3 Webapp + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..8e33e5df0f9 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet23-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Web Application with Servlet 2.3 + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/pom.xml new file mode 100644 index 00000000000..124277c0623 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-servlet24-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Servlet 2.4 Webapp + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..84d45f90325 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet24-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,10 @@ + + + + + Web Application for Servlet 2.4 + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/pom.xml new file mode 100644 index 00000000000..53f45ba3b9c --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-servlet25-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Servlet 2.5 Webapp + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..d06d132c1c6 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servlet25-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,9 @@ + + + + Web Application for Servlet 2.5 + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/pom.xml new file mode 100644 index 00000000000..60dd7e54cf4 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-servletmixed1-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Servlet Mixed 2.3+2.4 Webapp + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..7380f0f453e --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed1-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,9 @@ + + + + + Web Application with Mixed Servlet 2.3+2.4 + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/pom.xml new file mode 100644 index 00000000000..28905a1b9f1 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-servletmixed2-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Servlet Mixed 2.3+2.5 Webapp + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..655af0b40d0 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-servletmixed2-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,8 @@ + + + + + Web Application with Mixed Servlet 2.3+2.5 + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/.gitignore b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/.gitignore new file mode 100644 index 00000000000..8baee4f43cf --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/.gitignore @@ -0,0 +1,8 @@ +target/ +.classpath +.project +.settings +*.swp +*.log +*.patch +*.diff diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/pom.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/pom.xml new file mode 100644 index 00000000000..419a4ce698f --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + org.eclipse.jetty.tests + dummy-shellscripts-webapp + war + 1.0-SNAPSHOT + Jetty :: Webapp Verifier :: Dummy Shellscripts Webapp + + + junit + junit + 3.8.1 + test + + + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/README.txt b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/README.txt new file mode 100644 index 00000000000..f9b06ce72d7 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/README.txt @@ -0,0 +1,4 @@ +This is a webapp is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/ + +It is neither a valid WAR file, nor contains valid Shell Script implementations, +in either scripting, source or binary form. diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..9f88c1f9632 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.bat b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.bat new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.cmd b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.cmd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.sh b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.sh new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.vbs b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/dummy.vbs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.bat b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.bat new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.cmd b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.cmd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.sh b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.sh new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.vbs b/jetty-webapp-verifier/src/test/artifacts/dummy-shellscripts-webapp/src/main/webapp/other/lib.vbs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jetty-webapp-verifier/src/test/artifacts/pom.xml b/jetty-webapp-verifier/src/test/artifacts/pom.xml new file mode 100644 index 00000000000..2378b4f5d16 --- /dev/null +++ b/jetty-webapp-verifier/src/test/artifacts/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + org.eclipse.jetty + jetty-project + 7.0.0.RC3-SNAPSHOT + + org.eclipse.jetty.tests + jetty-webapp-verifier-artifacts + Jetty :: Webapp Verifier :: Artifacts Parent + pom + + dummy-jruby-lib + dummy-jython-lib + dummy-groovy-lib + dummy-jruby-webapp + dummy-jython-webapp + dummy-groovy-webapp + dummy-shellscripts-webapp + dummy-nativeaccess-webapp + dummy-java11-lib + dummy-java12-lib + dummy-java13-lib + dummy-java14-lib + dummy-java15-lib + dummy-java16-lib + dummy-javaversions-webapp + dummy-scm-lib + dummy-scm-webapp + dummy-servlet23-webapp + dummy-servlet24-webapp + dummy-servlet25-webapp + dummy-servletmixed1-webapp + dummy-servletmixed2-webapp + + diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/AbstractTestWebappVerifier.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/AbstractTestWebappVerifier.java new file mode 100644 index 00000000000..a3dec9785d8 --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/AbstractTestWebappVerifier.java @@ -0,0 +1,46 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.io.File; +import junit.framework.TestCase; + +import org.eclipse.jetty.util.IO; + +public class AbstractTestWebappVerifier extends TestCase +{ + protected File getTestWorkDir() + { + File workDir = MavenTestingUtils.toTargetFile("test-work-dir"); + if (!workDir.exists()) + { + workDir.mkdirs(); + } + File testSpecificDir = new File(workDir,this.getClass().getSimpleName() + "_" + getName()); + if (testSpecificDir.exists()) + { + IO.delete(testSpecificDir); + } + testSpecificDir.mkdirs(); + return testSpecificDir; + } + + protected RuleSet loadRuleSet(String name) throws Exception + { + File xmlFile = MavenTestingUtils.getTestResourceFile(name); + return RuleSet.load(xmlFile.toURL()); + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/CountingRule.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/CountingRule.java new file mode 100644 index 00000000000..a9f055a691d --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/CountingRule.java @@ -0,0 +1,126 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.io.File; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; + +public class CountingRule extends AbstractRule +{ + public int countWebappStart = 0; + public int countDirStart = 0; + public int countFile = 0; + public int countDirEnd = 0; + public int countWebInfClassesStart = 0; + public int countWebInfClass = 0; + public int countWebInfClassResource = 0; + public int countWebInfClassesEnd = 0; + public int countWebInfLibStart = 0; + public int countWebInfLibJar = 0; + public int countWebInfLibZip = 0; + public int countWebInfLibEnd = 0; + public int countWebappEnd = 0; + + public String getDescription() + { + return "TestCase only rule, that counts hits to visitors"; + } + + public String getName() + { + return "test-counting"; + } + + @Override + public void visitDirectoryEnd(String path, File dir) + { + countDirEnd++; + } + + @Override + public void visitDirectoryStart(String path, File dir) + { + countDirStart++; + } + + @Override + public void visitFile(String path, File dir, File file) + { + countFile++; + } + + @Override + public void visitWebappEnd(String path, File dir) + { + countWebappEnd++; + } + + @Override + public void visitWebappStart(String path, File dir) + { + super.visitWebappStart(path,dir); + countWebappStart++; + } + + @Override + public void visitWebInfClass(String path, String className, File classFile) + { + countWebInfClass++; + } + + @Override + public void visitWebInfClassesEnd(String path, File dir) + { + countWebInfClassesEnd++; + } + + @Override + public void visitWebInfClassesStart(String path, File dir) + { + countWebInfClassesStart++; + } + + @Override + public void visitWebInfClassResource(String path, String resourcePath, File resourceFile) + { + countWebInfClassResource++; + } + + @Override + public void visitWebInfLibEnd(String path, File dir) + { + countWebInfLibEnd++; + } + + @Override + public void visitWebInfLibJar(String path, File archive, JarFile jar) + { + countWebInfLibJar++; + } + + @Override + public void visitWebInfLibStart(String path, File dir) + { + countWebInfLibStart++; + } + + @Override + public void visitWebInfLibZip(String path, File archive, ZipFile zip) + { + countWebInfLibZip++; + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/MavenTestingUtils.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/MavenTestingUtils.java new file mode 100644 index 00000000000..6691f717e43 --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/MavenTestingUtils.java @@ -0,0 +1,166 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +import org.eclipse.jetty.util.IO; + +/** + * Common utility methods for working with JUnit tests cases in a maven friendly way. + */ +public class MavenTestingUtils +{ + private static File basedir; + private static File testResourcesDir; + private static File targetDir; + + public static File getBasedir() + { + if (basedir == null) + { + String cwd = System.getProperty("basedir"); + + if (cwd == null) + { + cwd = System.getProperty("user.dir"); + } + + basedir = new File(cwd); + } + + return basedir; + } + + /** + * Get the directory to the /target directory for this project. + * + * @return the directory path to the target directory. + */ + public static File getTargetDir() + { + if (targetDir == null) + { + targetDir = new File(basedir,"target"); + PathAssert.assertDirExists("Target Dir",targetDir); + } + return targetDir; + } + + /** + * Get a file from the src/test/resource directory. + * + * @param name + * the name of the path to get (it must exist as a file) + * @return the file in src/test/resource + */ + public static File getTestResourceFile(String name) + { + File file = new File(getTestResourcesDir(),name); + PathAssert.assertFileExists("Test Resource File",file); + return file; + } + + /** + * Get a dir from the src/test/resource directory. + * + * @param name + * the name of the path to get (it must exist as a dir) + * @return the dir in src/test/resource + */ + public static File getTestResourceDir(String name) + { + File dir = new File(getTestResourcesDir(),name); + PathAssert.assertDirExists("Test Resource Dir",dir); + return dir; + } + + /** + * Get a path resource (File or Dir) from the src/test/resource directory. + * + * @param name + * the name of the path to get (it must exist) + * @return the path in src/test/resource + */ + public static File getTestResourcePath(String name) + { + File path = new File(getTestResourcesDir(),name); + PathAssert.assertExists("Test Resource Path",path); + return path; + } + + /** + * Get the directory to the src/test/resource directory + * + * @return the directory {@link File} to the src/test/resources directory + */ + public static File getTestResourcesDir() + { + if (testResourcesDir == null) + { + testResourcesDir = new File(basedir,"src/test/resources".replace("/",File.separator)); + PathAssert.assertDirExists("Test Resources Dir",testResourcesDir); + } + return testResourcesDir; + } + + /** + * Create a {@link File} object for a path in the /target directory. + * + * @param path + * the path desired, no validation of existence is performed. + * @return the File to the path. + */ + public static File toTargetFile(String path) + { + return new File(getTargetDir(),path.replace("/",File.separator)); + } + + /** + * Read the contents of a file into a String and return it. + * + * @param file + * the file to read. + * @return the contents of the file. + * @throws IOException + * if unable to read the file. + */ + public static String readToString(File file) throws IOException + { + FileReader reader = null; + try + { + reader = new FileReader(file); + return IO.toString(reader); + } + finally + { + IO.close(reader); + } + } + + public static File toTargetTestingDir() + { + File dir = new File(getTargetDir(),"testing"); + if (!dir.exists()) + { + dir.mkdirs(); + } + return dir; + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/PathAssert.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/PathAssert.java new file mode 100644 index 00000000000..ff3012bc930 --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/PathAssert.java @@ -0,0 +1,40 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.io.File; + +import junit.framework.Assert; + +public class PathAssert +{ + public static void assertDirExists(String msg, File path) + { + assertExists(msg,path); + Assert.assertTrue(msg + " path should be a Dir : " + path.getAbsolutePath(),path.isDirectory()); + } + + public static void assertFileExists(String msg, File path) + { + assertExists(msg,path); + Assert.assertTrue(msg + " path should be a File : " + path.getAbsolutePath(),path.isFile()); + } + + public static void assertExists(String msg, File path) + { + Assert.assertTrue(msg + " path should exist: " + path.getAbsolutePath(),path.exists()); + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleAssert.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleAssert.java new file mode 100644 index 00000000000..5b9f25ba33f --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleAssert.java @@ -0,0 +1,184 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import junit.framework.Assert; + +import org.eclipse.jetty.util.IO; + +/** + * Rule based assertions. + */ +public class RuleAssert +{ + private static Pattern expectedViolationPattern; + + /** + *

+ * Perform a static Rule assertion. + *

+ * + *

+ * You will need the following files. + *

+ * + *
    + *
  1. src/test/resources/${prefix}.setup.txt - contains 1 line, which is the src/test/resources + * relative path to the webapp you want to test, (it can be a WAR file, or an exploded webapp directory
  2. + * + *
  3. src/test/resources/${prefix}.config.xml - contains an XMLConfiguration suitable XML file for + * loading into a RuleSet. Represents the configuration that will be used for this test.
  4. + * + *
  5. src/test/resources/${prefix}.expectations.txt - contains a list of expected Violations (1 + * violation per line), with the expected values pipe "|" delimited. Example: pattern is + * "${severity}|${path}|${detail}", where a representative line + * "ERROR|/WEB-INF|Missing required web.xml" would mean a violation of type {@link Severity#ERROR}, + * with path "/WEB-INF", and detail "Missing required web.xml"
  6. + *
+ * + * @param prefix + * the prefix of the integration files in src/test/resources that you want to use. + * @throws Exception + */ + public static void assertIntegration(String prefix) throws Exception + { + // Load the 3 integration files. + File setupFile = MavenTestingUtils.getTestResourceFile(prefix + ".setup.txt"); + File configFile = MavenTestingUtils.getTestResourceFile(prefix + ".config.xml"); + File expectationFile = MavenTestingUtils.getTestResourceFile(prefix + ".expectations.txt"); + + // Establish Webapp to use + String webappName = MavenTestingUtils.readToString(setupFile).trim(); + File webappPath = MavenTestingUtils.getTestResourcePath(webappName); + URI webappURI = webappPath.toURI(); + + // Load RuleSet configuration + RuleSet ruleset = RuleSet.load(configFile); + + // Run Verification + WebappVerifier verifier = ruleset.createWebappVerifier(webappURI); + verifier.setWorkDir(MavenTestingUtils.toTargetTestingDir()); + verifier.visitAll(); + + // Compare violations + assertViolations(loadExpectedViolations(expectationFile),verifier.getViolations()); + } + + public static void assertViolations(Collection expectedColl, Collection actualColl) + { + List actualViolations = new ArrayList(actualColl); + List expectedViolations = new ArrayList(expectedColl); + + Collections.sort(actualViolations,ViolationComparator.getInstance()); + Collections.sort(expectedViolations,ViolationComparator.getInstance()); + + // Compare expected vs actual + if (expectedViolations.size() != actualViolations.size()) + { + dumpViolations("Expected",expectedViolations); + dumpViolations("Actual",actualViolations); + Assert.assertEquals("Violation count",expectedViolations.size(),actualViolations.size()); + } + + for (int i = 0, n = expectedViolations.size(); i < n; i++) + { + Violation expected = expectedViolations.get(i); + Violation actual = actualViolations.get(i); + + Assert.assertEquals("Violation[" + i + "].path",expected.getPath(),actual.getPath()); + Assert.assertEquals("Violation[" + i + "].detail",expected.getDetail(),actual.getDetail()); + Assert.assertEquals("Violation[" + i + "].severity",expected.getSeverity(),actual.getSeverity()); + // TODO: add check on Violation.throwable + // TODO: add check on Violation.verifierId + // TODO: add check on Violation.verifierClass + } + } + + public static void dumpViolations(String msg, Collection violations) + { + System.out.println(); + System.out.printf("/* Violations Dump: %s */%n",msg); + for (Violation violation : violations) + { + System.out.println(violation.toDelimString()); + } + } + + public static Collection loadExpectedViolations(File expectationFile) throws IOException + { + FileReader reader = null; + BufferedReader buf = null; + try + { + List ret = new ArrayList(); + reader = new FileReader(expectationFile); + buf = new BufferedReader(reader); + + String line; + + while ((line = buf.readLine()) != null) + { + if (line.charAt(0) == '#') + { + // a comment. + continue; + } + + // Parse line + Violation violation = parseViolation(line); + + Assert.assertNotNull("Unable to parse expected violation line: " + line,violation); + + // Add to list + ret.add(violation); + } + + return ret; + } + finally + { + IO.close(buf); + IO.close(reader); + } + } + + protected static Violation parseViolation(String line) + { + expectedViolationPattern = Pattern.compile("^([^|]*)\\|([^|]*)\\|(.*)$"); + Matcher mat = expectedViolationPattern.matcher(line); + if (mat.matches()) + { + Severity severity = Severity.parse(mat.group(1)); + String path = mat.group(2); + String detail = mat.group(3); + return new Violation(severity,path,detail); + } + else + return null; + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleAssertTest.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleAssertTest.java new file mode 100644 index 00000000000..cc3d837bb18 --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleAssertTest.java @@ -0,0 +1,33 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import junit.framework.TestCase; + +public class RuleAssertTest extends TestCase +{ + public void testParseLine() + { + Violation v; + + v = RuleAssert.parseViolation("ERROR|/WEB-INF|Missing web.xml"); + + assertNotNull("Verifier should not be null",v); + assertEquals("Verifier.severity",Severity.ERROR,v.getSeverity()); + assertEquals("Verifier.path","/WEB-INF",v.getPath()); + assertEquals("Verifier.detail","Missing web.xml",v.getDetail()); + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleSetTest.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleSetTest.java new file mode 100644 index 00000000000..5c19012f12f --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/RuleSetTest.java @@ -0,0 +1,36 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import org.eclipse.jetty.webapp.verifier.rules.ForbiddenContentsRule; +import org.eclipse.jetty.webapp.verifier.rules.RequiredContentsRule; + +public class RuleSetTest extends AbstractTestWebappVerifier +{ + public void testLoad() throws Exception + { + RuleSet suite = loadRuleSet("basic-ruleset.xml"); + assertNotNull("Should have a valid RuleSet.",suite); + + assertNotNull("verifier list should not be null",suite.getRules()); + assertEquals("Should have 2 verifier",2,suite.getRules().size()); + + Rule verifier = suite.getRules().get(0); + assertEquals("Verifier[0]",ForbiddenContentsRule.class.getName(),verifier.getClass().getName()); + verifier = suite.getRules().get(1); + assertEquals("Verifier[1]",RequiredContentsRule.class.getName(),verifier.getClass().getName()); + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/WebappVerifierTest.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/WebappVerifierTest.java new file mode 100644 index 00000000000..a5301492a31 --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/WebappVerifierTest.java @@ -0,0 +1,63 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier; + +import java.util.Collection; + +public class WebappVerifierTest extends AbstractTestWebappVerifier +{ + public void testVerifierVisitation() throws Exception + { + CountingRule counts = new CountingRule(); + + // Create Webapp Specific Verifier from Verifier Suite + WebappVerifier verifier = new WebappVerifier(MavenTestingUtils.toTargetFile("war-files/test-webapp-logging-java.war").toURI()); + verifier.addRule(counts); + verifier.setWorkDir(getTestWorkDir()); + + // Run the verification. + verifier.visitAll(); + + // Collect the violations + Collection violations = verifier.getViolations(); + assertNotNull("Should never have a null set of Violations",violations); + assertEquals("No violations caused",0,violations.size()); + + // Ensure each visitor was visited according to real contents of WAR + assertEquals("Counts.webappStart",1,counts.countWebappStart); + assertEquals("Counts.countWebappEnd",1,counts.countWebappEnd); + + // Visits in Directory + assertEquals("Counts.countDirStart",12,counts.countDirStart); + assertEquals("Counts.countFile",6,counts.countFile); + assertEquals("Counts.countDirEnd",12,counts.countDirEnd); + assertEquals("Counts.countDir (Start == End)",counts.countDirStart,counts.countDirEnd); + + // Visits in WEB-INF/classes + assertEquals("Counts.countWebInfClassesStart",1,counts.countWebInfClassesStart); + assertEquals("Counts.countWebInfClass",1,counts.countWebInfClass); + assertEquals("Counts.countWebInfClassResource",1,counts.countWebInfClassResource); + assertEquals("Counts.countWebInfClassesEnd",1,counts.countWebInfClassesEnd); + assertEquals("Counts.countWebInfClasses (Start == End)",counts.countWebInfClassesStart,counts.countWebInfClassesEnd); + + // Visits in WEB-INF/lib + assertEquals("Counts.countWebInfLibStart",0,counts.countWebInfLibStart); + assertEquals("Counts.countWebInfLibJar",0,counts.countWebInfLibJar); + assertEquals("Counts.countWebInfLibZip",0,counts.countWebInfLibZip); + assertEquals("Counts.countWebInfLibEnd",0,counts.countWebInfLibEnd); + assertEquals("Counts.countWebInfLib (Start == End)",counts.countWebInfLibStart,counts.countWebInfLibEnd); + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/JarSignatureRuleTest.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/JarSignatureRuleTest.java new file mode 100644 index 00000000000..10917769d99 --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/JarSignatureRuleTest.java @@ -0,0 +1,39 @@ +// ======================================================================== +// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import org.eclipse.jetty.webapp.verifier.AbstractTestWebappVerifier; +import org.eclipse.jetty.webapp.verifier.MavenTestingUtils; +import org.eclipse.jetty.webapp.verifier.WebappVerifier; +import org.eclipse.jetty.webapp.verifier.rules.JarSignatureRule; + +/** + * Tests against {@link JarSignatureRule} + */ +public class JarSignatureRuleTest extends AbstractTestWebappVerifier +{ + public void testSimpleVerify() throws Exception + { + JarSignatureRule signed = new JarSignatureRule(); + + // Create Webapp Specific Verifier from Verifier Suite + WebappVerifier verifier = new WebappVerifier(MavenTestingUtils.toTargetFile("test-classes/webapps/signed-jar-test-webapp.war").toURI()); + verifier.addRule( signed ); + verifier.setWorkDir( getTestWorkDir() ); + + // Run the verification. + verifier.visitAll(); + + assertTrue( verifier.getViolations().size() == 0 ); + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/JavaSupportLevelRuleTest.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/JavaSupportLevelRuleTest.java new file mode 100644 index 00000000000..bf1561b6483 --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/JavaSupportLevelRuleTest.java @@ -0,0 +1,18 @@ +package org.eclipse.jetty.webapp.verifier.rules; + +import org.eclipse.jetty.webapp.verifier.RuleAssert; + +import junit.framework.TestCase; + +public class JavaSupportLevelRuleTest extends TestCase +{ + public void testJava15() throws Exception + { + RuleAssert.assertIntegration("java_level_1.5"); + } + + public void testJava14() throws Exception + { + RuleAssert.assertIntegration("java_level_1.4"); + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoNativeRuleTest.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoNativeRuleTest.java new file mode 100644 index 00000000000..f082411392e --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoNativeRuleTest.java @@ -0,0 +1,13 @@ +package org.eclipse.jetty.webapp.verifier.rules; + +import org.eclipse.jetty.webapp.verifier.RuleAssert; + +import junit.framework.TestCase; + +public class NoNativeRuleTest extends TestCase +{ + public void testNoNative() throws Exception + { + RuleAssert.assertIntegration("no_native"); + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoScriptingRuleTest.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoScriptingRuleTest.java new file mode 100644 index 00000000000..c6c8bf32ec6 --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoScriptingRuleTest.java @@ -0,0 +1,42 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import org.eclipse.jetty.webapp.verifier.AbstractTestWebappVerifier; +import org.eclipse.jetty.webapp.verifier.RuleAssert; + +public class NoScriptingRuleTest extends AbstractTestWebappVerifier +{ + public void testJRubyConfiguration() throws Exception + { + RuleAssert.assertIntegration("no_scripting_jruby"); + } + + public void testJythonConfiguration() throws Exception + { + RuleAssert.assertIntegration("no_scripting_jython"); + } + + public void testGroovyConfiguration() throws Exception + { + RuleAssert.assertIntegration("no_scripting_groovy"); + } + + public void testShellConfiguration() throws Exception + { + RuleAssert.assertIntegration("no_scripting_shell"); + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceControlRuleTest.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceControlRuleTest.java new file mode 100644 index 00000000000..f1716cbf59d --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/NoSourceControlRuleTest.java @@ -0,0 +1,31 @@ +// ======================================================================== +// Copyright (c) Webtide LLC +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.apache.org/licenses/LICENSE-2.0.txt +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp.verifier.rules; + +import org.eclipse.jetty.webapp.verifier.RuleAssert; + +import junit.framework.TestCase; + +/** + * NoSourceControlRuleTest + */ +public class NoSourceControlRuleTest extends TestCase +{ + public void testNoScm() throws Exception + { + RuleAssert.assertIntegration("no_scm"); + } +} diff --git a/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/ServletSupportLevelRuleTest.java b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/ServletSupportLevelRuleTest.java new file mode 100644 index 00000000000..756a45aac0b --- /dev/null +++ b/jetty-webapp-verifier/src/test/java/org/eclipse/jetty/webapp/verifier/rules/ServletSupportLevelRuleTest.java @@ -0,0 +1,33 @@ +package org.eclipse.jetty.webapp.verifier.rules; + +import org.eclipse.jetty.webapp.verifier.RuleAssert; + +import junit.framework.TestCase; + +public class ServletSupportLevelRuleTest extends TestCase +{ + public void testServlet23Rule() throws Exception + { + RuleAssert.assertIntegration("servlet_level_2.3"); + } + + public void testServlet24Rule() throws Exception + { + RuleAssert.assertIntegration("servlet_level_2.4"); + } + + public void testServlet25Rule() throws Exception + { + RuleAssert.assertIntegration("servlet_level_2.5"); + } + + public void testServletMixed23n24Rule() throws Exception + { + RuleAssert.assertIntegration("servlet_level_mixed_2.3_2.4"); + } + + public void testServletMixed23n25Rule() throws Exception + { + RuleAssert.assertIntegration("servlet_level_mixed_2.3_2.5"); + } +} diff --git a/jetty-webapp-verifier/src/test/resources/basic-ruleset.xml b/jetty-webapp-verifier/src/test/resources/basic-ruleset.xml new file mode 100644 index 00000000000..2ac16f95f35 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/basic-ruleset.xml @@ -0,0 +1,23 @@ + + + + + + + + + *.jsp + + + + + + + /copyright.jsp + + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/content-verifier/WEB-INF/web.xml b/jetty-webapp-verifier/src/test/resources/content-verifier/WEB-INF/web.xml new file mode 100644 index 00000000000..12bbf745ce3 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/content-verifier/WEB-INF/web.xml @@ -0,0 +1 @@ + diff --git a/jetty-webapp-verifier/src/test/resources/java_level_1.4.config.xml b/jetty-webapp-verifier/src/test/resources/java_level_1.4.config.xml new file mode 100644 index 00000000000..aa26dd24aa7 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/java_level_1.4.config.xml @@ -0,0 +1,14 @@ + + + + + + + + 1.4 + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/java_level_1.4.expectations.txt b/jetty-webapp-verifier/src/test/resources/java_level_1.4.expectations.txt new file mode 100644 index 00000000000..432b2441296 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/java_level_1.4.expectations.txt @@ -0,0 +1,4 @@ +ERROR|WEB-INF/classes/org/eclipse/jetty/testcase/verifier/DummyLatestLib.class|Class is compiled for java version [1.5] which is over supported java version [1.4] +ERROR|WEB-INF/classes/org/eclipse/jetty/testcase/verifier/DummyModernLib.class|Class is compiled for java version [1.6] which is over supported java version [1.4] +ERROR|WEB-INF/lib/dummy-java15-lib-1.0-SNAPSHOT.jar!/org/eclipse/jetty/testcase/verifier/DummyLatestLib.class|Class is compiled for java version [1.5] which is over supported java version [1.4] +ERROR|WEB-INF/lib/dummy-java16-lib-1.0-SNAPSHOT.jar!/org/eclipse/jetty/testcase/verifier/DummyModernLib.class|Class is compiled for java version [1.6] which is over supported java version [1.4] diff --git a/jetty-webapp-verifier/src/test/resources/java_level_1.4.setup.txt b/jetty-webapp-verifier/src/test/resources/java_level_1.4.setup.txt new file mode 100644 index 00000000000..db98daf3ecf --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/java_level_1.4.setup.txt @@ -0,0 +1 @@ +webapps/dummy-javaversions-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/java_level_1.5.config.xml b/jetty-webapp-verifier/src/test/resources/java_level_1.5.config.xml new file mode 100644 index 00000000000..5f80d29608c --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/java_level_1.5.config.xml @@ -0,0 +1,14 @@ + + + + + + + + 1.5 + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/java_level_1.5.expectations.txt b/jetty-webapp-verifier/src/test/resources/java_level_1.5.expectations.txt new file mode 100644 index 00000000000..c119c45715c --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/java_level_1.5.expectations.txt @@ -0,0 +1,2 @@ +ERROR|WEB-INF/classes/org/eclipse/jetty/testcase/verifier/DummyModernLib.class|Class is compiled for java version [1.6] which is over supported java version [1.5] +ERROR|WEB-INF/lib/dummy-java16-lib-1.0-SNAPSHOT.jar!/org/eclipse/jetty/testcase/verifier/DummyModernLib.class|Class is compiled for java version [1.6] which is over supported java version [1.5] diff --git a/jetty-webapp-verifier/src/test/resources/java_level_1.5.setup.txt b/jetty-webapp-verifier/src/test/resources/java_level_1.5.setup.txt new file mode 100644 index 00000000000..db98daf3ecf --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/java_level_1.5.setup.txt @@ -0,0 +1 @@ +webapps/dummy-javaversions-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_native.config.xml b/jetty-webapp-verifier/src/test/resources/no_native.config.xml new file mode 100644 index 00000000000..47d49fc9c70 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_native.config.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_native.expectations.txt b/jetty-webapp-verifier/src/test/resources/no_native.expectations.txt new file mode 100644 index 00000000000..b187c8eeab7 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_native.expectations.txt @@ -0,0 +1,6 @@ +ERROR|dummy.exe|Native code is forbidden +ERROR|dummy.o|Native code is forbidden +ERROR|dummy.so|Native code is forbidden +ERROR|other/lib.dll|Native code is forbidden +ERROR|other/lib.o|Native code is forbidden +ERROR|other/lib.so|Native code is forbidden diff --git a/jetty-webapp-verifier/src/test/resources/no_native.setup.txt b/jetty-webapp-verifier/src/test/resources/no_native.setup.txt new file mode 100644 index 00000000000..543f1ae3740 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_native.setup.txt @@ -0,0 +1 @@ +webapps/dummy-nativeaccess-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scm.config.xml b/jetty-webapp-verifier/src/test/resources/no_scm.config.xml new file mode 100644 index 00000000000..af006caf35e --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scm.config.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scm.expectations.txt b/jetty-webapp-verifier/src/test/resources/no_scm.expectations.txt new file mode 100644 index 00000000000..0b0f2c893b6 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scm.expectations.txt @@ -0,0 +1,36 @@ +ERROR|_darcs/|Darcs Source Control directories are not allowed +ERROR|_svn/|Subversion Source Control directories are not allowed +ERROR|.arch-ids/|Arch Source Control directories are not allowed +ERROR|.bzr/|Bazaar Source Control directories are not allowed +ERROR|.cvsignore|CVS Source Control file are not allowed +ERROR|.darcsrepo/|Darcs Source Control directories are not allowed +ERROR|.darcs-temp-mail|Darcs Source Control file are not allowed +ERROR|.git/|Git Source Control directories are not allowed +ERROR|.gitignore|Git Source Control file are not allowed +ERROR|.hg/|Mercurial Source Control directories are not allowed +ERROR|.MySCMServerInfo|SurroundSCM Source Control file are not allowed +ERROR|.svn/|Subversion Source Control directories are not allowed +ERROR|BitKeeper/|BitKeeper Source Control directories are not allowed +ERROR|ChangeSet/|BitKeeper Source Control directories are not allowed +ERROR|CVS/|CVS Source Control directories are not allowed +ERROR|RCS/|RCS Source Control directories are not allowed +ERROR|SCCS/|SCCS Source Control directories are not allowed +ERROR|vssver.scc|Visual SourceSafe Source Control file are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/_darcs/|Darcs Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/_svn/|Subversion Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/.arch-ids/|Arch Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/.bzr/|Bazaar Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/.cvsignore|CVS Source Control file are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/.darcsrepo/|Darcs Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/.darcs-temp-mail|Darcs Source Control file are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/.git/|Git Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/.gitignore|Git Source Control file are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/.hg/|Mercurial Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/.MySCMServerInfo|SurroundSCM Source Control file are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/.svn/|Subversion Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/BitKeeper/|BitKeeper Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/ChangeSet/|BitKeeper Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/CVS/|CVS Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/RCS/|RCS Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/SCCS/|SCCS Source Control directories are not allowed +ERROR|WEB-INF/lib/dummy-scm-lib-1.0-SNAPSHOT.jar!/vssver.scc|Visual SourceSafe Source Control file are not allowed diff --git a/jetty-webapp-verifier/src/test/resources/no_scm.setup.txt b/jetty-webapp-verifier/src/test/resources/no_scm.setup.txt new file mode 100644 index 00000000000..bc01807d23c --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scm.setup.txt @@ -0,0 +1 @@ +webapps/dummy-scm-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_groovy.config.xml b/jetty-webapp-verifier/src/test/resources/no_scripting_groovy.config.xml new file mode 100644 index 00000000000..4986faf70b1 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_groovy.config.xml @@ -0,0 +1,14 @@ + + + + + + + + false + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_groovy.expectations.txt b/jetty-webapp-verifier/src/test/resources/no_scripting_groovy.expectations.txt new file mode 100644 index 00000000000..5a86d668a6d --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_groovy.expectations.txt @@ -0,0 +1,4 @@ +ERROR|dummy.groovy|Groovy scripting not allowed +ERROR|other/lib.groovy|Groovy scripting not allowed +ERROR|WEB-INF/lib/dummy-groovy-lib-1.0-SNAPSHOT.jar!/org/codehaus/groovy/GroovyException.class|Groovy dependencies are not allowed +ERROR|WEB-INF/lib/dummy-groovy-lib-1.0-SNAPSHOT.jar!/org/codehaus/groovy/jsr223/GroovyScriptEngineFactory.class|Groovy dependencies are not allowed diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_groovy.setup.txt b/jetty-webapp-verifier/src/test/resources/no_scripting_groovy.setup.txt new file mode 100644 index 00000000000..f631249a77d --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_groovy.setup.txt @@ -0,0 +1 @@ +webapps/dummy-groovy-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_jruby.config.xml b/jetty-webapp-verifier/src/test/resources/no_scripting_jruby.config.xml new file mode 100644 index 00000000000..882f5c2a308 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_jruby.config.xml @@ -0,0 +1,14 @@ + + + + + + + + false + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_jruby.expectations.txt b/jetty-webapp-verifier/src/test/resources/no_scripting_jruby.expectations.txt new file mode 100644 index 00000000000..92678886a36 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_jruby.expectations.txt @@ -0,0 +1,6 @@ +ERROR|example.rb|JRuby scripting not allowed +ERROR|other/lib.rb|JRuby scripting not allowed +ERROR|output.rhtml|JRuby scripting not allowed +ERROR|WEB-INF/lib/dummy-jruby-lib-1.0-SNAPSHOT.jar!/org/jruby/javasupport/JavaArray.class|JRuby dependencies are not allowed +ERROR|WEB-INF/lib/dummy-jruby-lib-1.0-SNAPSHOT.jar!/org/jruby/Ruby.class|JRuby dependencies are not allowed +ERROR|WEB-INF/lib/dummy-jruby-lib-1.0-SNAPSHOT.jar!/org/jruby/runtime/RubyEvent.class|JRuby dependencies are not allowed \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_jruby.setup.txt b/jetty-webapp-verifier/src/test/resources/no_scripting_jruby.setup.txt new file mode 100644 index 00000000000..793c6a4e9e6 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_jruby.setup.txt @@ -0,0 +1 @@ +webapps/dummy-jruby-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_jython.config.xml b/jetty-webapp-verifier/src/test/resources/no_scripting_jython.config.xml new file mode 100644 index 00000000000..83d5aad8b6b --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_jython.config.xml @@ -0,0 +1,14 @@ + + + + + + + + false + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_jython.expectations.txt b/jetty-webapp-verifier/src/test/resources/no_scripting_jython.expectations.txt new file mode 100644 index 00000000000..c6823a168a6 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_jython.expectations.txt @@ -0,0 +1,6 @@ +ERROR|dummy.py|Jython and Python scripting not allowed +ERROR|dummy.pyc|Jython and Python scripting not allowed +ERROR|other/lib.py|Jython and Python scripting not allowed +ERROR|WEB-INF/lib/dummy-jython-lib-1.0-SNAPSHOT.jar!/org/python/util/Generic.class|Jython dependencies are not allowed +ERROR|WEB-INF/lib/dummy-jython-lib-1.0-SNAPSHOT.jar!/org/python/Version.class|Jython dependencies are not allowed +ERROR|WEB-INF/lib/dummy-jython-lib-1.0-SNAPSHOT.jar!/org/python/core/JythonInitializer.class|Jython dependencies are not allowed diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_jython.setup.txt b/jetty-webapp-verifier/src/test/resources/no_scripting_jython.setup.txt new file mode 100644 index 00000000000..4b20b76b0d6 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_jython.setup.txt @@ -0,0 +1 @@ +webapps/dummy-jython-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_shell.config.xml b/jetty-webapp-verifier/src/test/resources/no_scripting_shell.config.xml new file mode 100644 index 00000000000..f97ea8bcdf1 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_shell.config.xml @@ -0,0 +1,14 @@ + + + + + + + + false + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_shell.expectations.txt b/jetty-webapp-verifier/src/test/resources/no_scripting_shell.expectations.txt new file mode 100644 index 00000000000..462b265c087 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_shell.expectations.txt @@ -0,0 +1,8 @@ +ERROR|dummy.bat|Shell scripting not allowed +ERROR|dummy.cmd|Shell scripting not allowed +ERROR|dummy.sh|Shell scripting not allowed +ERROR|dummy.vbs|Shell scripting not allowed +ERROR|other/lib.bat|Shell scripting not allowed +ERROR|other/lib.cmd|Shell scripting not allowed +ERROR|other/lib.sh|Shell scripting not allowed +ERROR|other/lib.vbs|Shell scripting not allowed diff --git a/jetty-webapp-verifier/src/test/resources/no_scripting_shell.setup.txt b/jetty-webapp-verifier/src/test/resources/no_scripting_shell.setup.txt new file mode 100644 index 00000000000..e180fb91db1 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/no_scripting_shell.setup.txt @@ -0,0 +1 @@ +webapps/dummy-shellscripts-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_2.3.config.xml b/jetty-webapp-verifier/src/test/resources/servlet_level_2.3.config.xml new file mode 100644 index 00000000000..91b35b25245 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_2.3.config.xml @@ -0,0 +1,14 @@ + + + + + + + + 2.1 + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_2.3.expectations.txt b/jetty-webapp-verifier/src/test/resources/servlet_level_2.3.expectations.txt new file mode 100644 index 00000000000..20af16893fc --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_2.3.expectations.txt @@ -0,0 +1,2 @@ +ERROR|target/testing/dummy-servlet23-webapp/WEB-INF/web.xml|Specified servlet version 2.3 of DOCTYPE Public ID is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servlet23-webapp/WEB-INF/web.xml|Specified servlet version 2.3 of DOCTYPE System ID is over the configured supported servlet version 2.1 diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_2.3.setup.txt b/jetty-webapp-verifier/src/test/resources/servlet_level_2.3.setup.txt new file mode 100644 index 00000000000..97453d84b28 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_2.3.setup.txt @@ -0,0 +1 @@ +webapps/dummy-servlet23-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_2.4.config.xml b/jetty-webapp-verifier/src/test/resources/servlet_level_2.4.config.xml new file mode 100644 index 00000000000..91b35b25245 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_2.4.config.xml @@ -0,0 +1,14 @@ + + + + + + + + 2.1 + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_2.4.expectations.txt b/jetty-webapp-verifier/src/test/resources/servlet_level_2.4.expectations.txt new file mode 100644 index 00000000000..07a9e3f6661 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_2.4.expectations.txt @@ -0,0 +1,3 @@ +ERROR|target/testing/dummy-servlet24-webapp/WEB-INF/web.xml|Specified servlet version 2.4 of Schema is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servlet24-webapp/WEB-INF/web.xml|Specified servlet version 2.4 of version attribute is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servlet24-webapp/WEB-INF/web.xml|Specified servlet version 2.4 of XML Namespace is over the configured supported servlet version 2.1 diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_2.4.setup.txt b/jetty-webapp-verifier/src/test/resources/servlet_level_2.4.setup.txt new file mode 100644 index 00000000000..5996e9b7e24 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_2.4.setup.txt @@ -0,0 +1 @@ +webapps/dummy-servlet24-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_2.5.config.xml b/jetty-webapp-verifier/src/test/resources/servlet_level_2.5.config.xml new file mode 100644 index 00000000000..196f3e72336 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_2.5.config.xml @@ -0,0 +1,14 @@ + + + + + + + + 2.4 + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_2.5.expectations.txt b/jetty-webapp-verifier/src/test/resources/servlet_level_2.5.expectations.txt new file mode 100644 index 00000000000..78fa619543c --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_2.5.expectations.txt @@ -0,0 +1,3 @@ +ERROR|target/testing/dummy-servlet25-webapp/WEB-INF/web.xml|Specified servlet version 2.5 of Schema is over the configured supported servlet version 2.4 +ERROR|target/testing/dummy-servlet25-webapp/WEB-INF/web.xml|Specified servlet version 2.5 of version attribute is over the configured supported servlet version 2.4 +ERROR|target/testing/dummy-servlet25-webapp/WEB-INF/web.xml|Specified servlet version 2.5 of XML Namespace is over the configured supported servlet version 2.4 diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_2.5.setup.txt b/jetty-webapp-verifier/src/test/resources/servlet_level_2.5.setup.txt new file mode 100644 index 00000000000..66caaf0dfe0 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_2.5.setup.txt @@ -0,0 +1 @@ +webapps/dummy-servlet25-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.config.xml b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.config.xml new file mode 100644 index 00000000000..91b35b25245 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.config.xml @@ -0,0 +1,14 @@ + + + + + + + + 2.1 + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.expectations.txt b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.expectations.txt new file mode 100644 index 00000000000..a9da5ebb15f --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.expectations.txt @@ -0,0 +1,14 @@ +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|Found 2 versions defined [2.3, 2.4], expected 1 +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|Invalid schemaLocation value +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|Specified servlet version 2.3 of DOCTYPE Public ID is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|Specified servlet version 2.3 of DOCTYPE System ID is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|Specified servlet version 2.4 of version attribute is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|Specified servlet version 2.4 of XML Namespace is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|version 2.3 of DOCTYPE Public ID conflicts with version 2.4 of version attribute +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|version 2.3 of DOCTYPE Public ID conflicts with version 2.4 of XML Namespace +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|version 2.3 of DOCTYPE System ID conflicts with version 2.4 of version attribute +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|version 2.3 of DOCTYPE System ID conflicts with version 2.4 of XML Namespace +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|version 2.4 of version attribute conflicts with version 2.3 of DOCTYPE Public ID +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|version 2.4 of version attribute conflicts with version 2.3 of DOCTYPE System ID +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|version 2.4 of XML Namespace conflicts with version 2.3 of DOCTYPE Public ID +ERROR|target/testing/dummy-servletmixed1-webapp/WEB-INF/web.xml|version 2.4 of XML Namespace conflicts with version 2.3 of DOCTYPE System ID diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.setup.txt b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.setup.txt new file mode 100644 index 00000000000..b473c59a4e4 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.4.setup.txt @@ -0,0 +1 @@ +webapps/dummy-servletmixed1-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.config.xml b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.config.xml new file mode 100644 index 00000000000..91b35b25245 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.config.xml @@ -0,0 +1,14 @@ + + + + + + + + 2.1 + + + + + \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.expectations.txt b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.expectations.txt new file mode 100644 index 00000000000..d2326c321ca --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.expectations.txt @@ -0,0 +1,15 @@ +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|Attribute must exist with a valid value +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|Attribute must exist with a valid value +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|Found 2 versions defined [2.3, 2.5], expected 1 +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|Specified servlet version 2.3 of DOCTYPE Public ID is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|Specified servlet version 2.3 of DOCTYPE System ID is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|Specified servlet version 2.5 of version attribute is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|Specified servlet version 2.5 of XML Namespace is over the configured supported servlet version 2.1 +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|version 2.3 of DOCTYPE Public ID conflicts with version 2.5 of version attribute +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|version 2.3 of DOCTYPE Public ID conflicts with version 2.5 of XML Namespace +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|version 2.3 of DOCTYPE System ID conflicts with version 2.5 of version attribute +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|version 2.3 of DOCTYPE System ID conflicts with version 2.5 of XML Namespace +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|version 2.5 of version attribute conflicts with version 2.3 of DOCTYPE Public ID +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|version 2.5 of version attribute conflicts with version 2.3 of DOCTYPE System ID +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|version 2.5 of XML Namespace conflicts with version 2.3 of DOCTYPE Public ID +ERROR|target/testing/dummy-servletmixed2-webapp/WEB-INF/web.xml|version 2.5 of XML Namespace conflicts with version 2.3 of DOCTYPE System ID diff --git a/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.setup.txt b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.setup.txt new file mode 100644 index 00000000000..da6d2ca5075 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/servlet_level_mixed_2.3_2.5.setup.txt @@ -0,0 +1 @@ +webapps/dummy-servletmixed2-webapp.war \ No newline at end of file diff --git a/jetty-webapp-verifier/src/test/resources/webapps/README.txt b/jetty-webapp-verifier/src/test/resources/webapps/README.txt new file mode 100644 index 00000000000..a46c58ef038 --- /dev/null +++ b/jetty-webapp-verifier/src/test/resources/webapps/README.txt @@ -0,0 +1,10 @@ +There are a number of Webapps in this directory. + +Not all of them are valid. +But all of them are created by the jetty project. + +The non-eclipse names present in the various webapps, for classes, packages, etc. +Are used for testcase reasons, and are all dummy implementations. + +See the /jetty-webapp-verifier-examples/ project tree in source control for the +projects that built these webapps, and their respective WEB-INF/lib jars. diff --git a/jetty-webapp-verifier/src/test/resources/webapps/dummy-groovy-webapp.war b/jetty-webapp-verifier/src/test/resources/webapps/dummy-groovy-webapp.war new file mode 100644 index 0000000000000000000000000000000000000000..96f1eaec36501d3e0a43303b917668bfb5c605f4 GIT binary patch literal 5519 zcmbtY2Q-{p*H&UON|4dT)mxO&f@q1}d+&X8MsJBbqC{^&M2iR^IzfaeqfIcn;EL!( z5G5i?Nc=O&74DUM>-*QY*E;jQYu^2wz4zJYoLw|kurJ_Ypy`1XzS#GdzkhI1Pc=DR zDQ+coc^=Kb*?<^nC^iHjQPvLiIS4gK&$6jWsVm9L>F9#h$76CNmR6Tyt6sVNNMmv$pYGBw@HxN zpHN?v1-z8u^F{|z6Y2HDNu*{KDK3d0?E(QG?@EgK*JGUMbzXfSN-qOB>3?W{o{QiN zmy4tIPdm?Z5})C;ak299f_VK0ZUBlK>g@pW{K@lU<-++C3rA2Ziw(lS;65`WTDGl^ zt7`zay(bjv8^DeFgPRY`%dMj>rKzK+p$m4h@+>pJ7f*Jjn@;R266wv2tk8_@)6^zR zdR}?=-3K;70k4dzvcZy28PP}gM05kihNUjc1o$MzN~@qudqqjp~d)D@$sOUf#VDkbzN1^H9`I;ZM#QCGFU)yL?^Z5aA4X<3ZJSs&$4`t1#UUSFeozmT|= zn>dZ{#>LX)S=KdNDjR|oKiexF{sLf-d{0A=m0h0mHOL>%vx^`&+@^S#cQJ>KCspkZ zwA((M=Id;W&XG(=s*&y0u9Y0*0P&04eDn_9(Ra4+(xGI`8FV7SFS7YGu9{Y+NEZ(I z%Jzk7l7#@R2jgO6mocS-_Y*!03&=5a3?8_Fgmk*;NBqJP(?5|S2h5R0+mfJkhRR*1 zl5IChIK3twaf7s*=fVv1fg(sGmP!#{E=f9)Kz=((VRx@=_K^B%LRCKFc#rK>k$Rr7 zua^5x{R|VrWUeH}F&RGVmEVve_g4bfTp0(jRQ7@|}-o8Fo~$7|PiuhzP7E z1K5ADsFkbHBIy-xqu7*p(}}gxt?4$=j$^e!ju{1Xf+jkXK}Sx_`?i9)7uW-?MAm+S zraNk7EA7B}Sy@v+l*$N@k}9=?lkv2Ux<3s))VmqcdOz4SQtCsD0`I#CnI4*~IsUQ! zV854tJ?!K6Wr51Du!+McLe)ZcD{mm}Wh~seRtH_)a4zmIM(}wwI=+1wuC`LiO)Zvd z)(zCBVwDVv%F9Z74>CQv#U|H)EJ;blTV0&48}6JMFe)yuaQtxNI0G`x-|3rfADGNP zTw4Y6jEB?_#BsJXEyy$8Sb49TLaDwb^rYZssB~Mx-Z(86o&+^*V^ts4#v|QCTbZwB zIiiU*61?VbYOn7&%g`o3h;gL>4uKlGSEQj9Q7kjhTv@6<+-iVO5Q*HpbfMk{QL<*8 z%rWzXBW*9Cwu}#;~by==Nre3tRnXa@rP; zTKDW%N0Ba5xmaGfpB)nKeobqufo#Pemh|~2tm4&q3aS$|8aBdKg4UW|?uBel`KWW! zM8R(MD6Oj7J!WPVdNG`7lx84W$Zn=LVqOBD$lu;s7-RMQmbzqwq*{(xiSAie*KMCR zVH9#Pnj4*btMyc=B)3ADbNa^f+@^*CKoZ}o2mgYs8_p8}uMw+p-|Bc_VF@Bzy7xC; z4taaq>UE~iHC~CY7(e9H0su7XZUQKrGdH(|Utc>4n>QYjP9q@9<}Wk-i&&Cdq3o5u zH+RB@0C!Z$G>HlGoid(p96c4;ww0S}bNfYFNHGO!H(B2HWH#!|pn@kliZZZd^}D7- zip!w&?A*1Dtn$~-5MvdqgN(~w8ucQiIr~dS#sseXVvea|-)O(7_*Kl*YDUFqnG8Go z8<=7T{srG_>WW){fpu_W-V_79WpwSQ{0u;aWLVw{<8S2Oin%m_y`?&xTlG!!XpI5c-BP@b zz#pgTp0do0Z6ePNnhp{@dXn17mu+GkTbl8f2YfXJXVghF>@D+pjTp~DYBqF8jYj@8 zAAZDwSGgUe-p9p%;(Fe4f)I|7i3W$qMUmH%{vV_1V(zekqgC;632YLzq-fMHs=^+2K*dt2!?SL1bR|m87&Unp6{Z+PU#pPDysi-^S$c>w#!F2`rgTY3y~qdS zK1hI{qeyr<+M0v5uC`VXHtdpcbs(=0(41tpY+xsRV>sH0t7hAbM9ZR({DIMyg6ZVJ zi#kUL5mSRYZE_IMqeu7i0Y2&5KT8M38Q4blI#w>yz2vkaj}RRFM8?Qlu>cj+^c)h^ zQZW+WEL6BU7<4hSn#n6bSf&9(-ICDzC$}oHI4$sh{ac3Ig;TXXA_5PI|GRcqRPEj`)IG$h{CXbng zx}_;kzh&MFG-#q`&f6plFm%`2sFa1cgrs09Om=!y8)oeGUr!&M$8W>Q94Aw)LL2B_qL4OiorX2;R zLv1)}edb&9NeH>HD9GGq3nRGRXA1&5?3Y{G-wEx^yb7mmCJ{hR4?Oe-uSp1eG#m6| z0@EiNXHg*!9FTTCh8Aj4-DRo`4-JYo~1DOwXe6G z?C>fNyCSrl>)4w5!U2vNoZ#52%SDBEMkX9KViwjvbUQrM zVCzoK5s-X3Hat0FI|+PmKlPn>-ni*{fIQC|p5E;;BYbeYB{ZW}jOExOy9c*U@^-Y& zW&hk@4ZkM^&tTXm`7013)B{hfS+fK)50w>;qXyBL?9dNl4fc0+F^fauh4PZh?j1y% zj0;kD8-!Snh7U$)s;m@uFk40=EUjZ;78KeJX#&0J?Lr44C7XJf(9y8B#!t%+WzsJL zr8|(evrjv(znBOZeaW37ui4SqKUYAlShij>Yfc1Uq-G*7v}7>ZTqpe4ZIRW`t;x5; z-qfM@F_M5L(%sCg&OFhL|aZuR!t7E9ArlX6D@5%i+v(J|qXt)2Yx?HV%A#Oh_i1W;B=b53N_F#yOi=(?2 z1ndOy_6`7hL%h8IQ>lXX(!V7BZjyggD5y^A!XiR_A0RIhyl0&(Som>^>E9%~u3E(ypB_ zS~I>ghr1hIepIQDs&K8e>(6eR1<6)1Xk89VVjQ_MmSFxAl)T%t zCHlg2pU8e);t+L7VPcVD|Gw*iG8IL{80%8#=g+fo3j1{z1kH@5{5$_RmuGq+r!$;C z%jkZ^4?+uWLA{=KFMh8s`fB+>Xw(ww^#t{!oAG-j`ab?aXe1Hp%$^`myBohpqx&1D zXbBYhq}y?V`E|eJ1eJfs>Wswys{3)ec)t#or&Gi5PmTFIbe;wODl(mdHBd|X?>Kc9 z{i`^2iiV-kr%~%H?pHzK6sLUYpCRHDd48v$L&Oh4d(Iby{JBL>0>+6G&V$ig^AwzS z9{jtz|37JT+BZaN^!~q}^w$C9MEhTdloS2)??@4zGyQkk|4Pu`0p`>&;P)Qrzi+)$ jd4#Al^RK1;|H?bP12t7}z8@lD)I}410Rv;_`+@vF<3wNX literal 0 HcmV?d00001 diff --git a/jetty-webapp-verifier/src/test/resources/webapps/dummy-javaversions-webapp.war b/jetty-webapp-verifier/src/test/resources/webapps/dummy-javaversions-webapp.war new file mode 100644 index 0000000000000000000000000000000000000000..967fd373ee2404828155203085e301bd72b4add2 GIT binary patch literal 16665 zcmd^nbzGHOw=PObh_py3or~_2?(Xg`VbQ6G(x6g;gmiaHNrQBEcQ;5a?!vtlH+$>( z&i%eW?z!jX_p;Ux<``qnu_ogg<9X*mRss?V9^(3P_C(?Q_U6xT_rR}GLW+CEV}Z+TXe1baLYG)#;!1Xub*-{S3-QB*WafP2cDOT5dU9h|MyXdKaH|9 z)Bmx~zmI(I(?|nLJs{8s_?yw!UiohQ`)C_Glix_-{zAgYz|!m)(C9akg#U%4xskoS z%WveV{v~;PBcQ#3-ft(u^xsqDXk=$*Y-VKlV`^{^%kC(ger8_eN6-)u!3Yo#fS)v8 ze>{c`R#q+mb3I2rdIkXa2LO5+I)H*SpR9tYj3SM>o*lxjvGJTf#0wKspIP z!$TZS%NNT}UQ)Fn$78NJ$8jbu|yV@!9quM4yjWSHUgN& z*hEW&zuNbjd<=@REgX3v@|Ks=rhAftPL9~|GCcO)DDD+CAdge8RADRy1vZ zovnkrmG`x?I`DGgT|fjO;LgRw@v@9~9cQA~fYe)^4_0hTAUel5^a68PEea9znF0BnF5WtIdJamJ zTnAsWEKZ_GdJy&|>l=-zXo{Jro`tmrV=Ex(8@mW@Nvcti#b`Z@b7izpY3=vLyn`(C z*gQvLf?dUUj5KZ`ms93|hn1^#w0*|ydZEGj zAmoin^Q(PxhIb5s3L8-qYcNgA)}8U6>P=!CK7qVfdaSK#-nzYJC!6o^EJKQ22}Uh8 z+S-=_74D4`8-DSOuG!D!HD~jZ3w9oYT+D^le`ES4J2@~vTU$)Xe;r$-mJ|{t5}~Za zgbp}4Wi>fW1*rDcT6lSU@p@9{*w|_QzNS<(6XTRt(8^I-EH)={Yy0A4FayPyMc6 zH??q-Jw^*AL0eZ5CV89TY`OVoT`MUs)7!M?#Iil<=B2eR+SHg?3#plrW#koG6%i#> zTzl*LbE1dGIsi7pvz~t?8`iW11)e~1}j@EYlzkL!Y6%YnHI=lzR2vR(O6ek9`mWc zx(;vR)I<8nMMK#}DPQd!v<&~q7gkoBN9>N0@s3vBt;A|bZ8e#f(dxR) znf~CAk5rU++p5ZR zc#$W{!^m=>8!cJ~FWtHd*RrR;`Iy>Bjy6mt4P-;Y#p2|0M(TR3&cR_*Lrx!6++!lH ze?%;{-D8#Tl8995z@?g?{Znh#$=6}0b1vjs`Ti}gLvJd_;+!CvB+=;_ml0!`I`ggL zW5J62S33tlTzvk=Tpe1~sIIING(5}>)0)CB?aH9=3xUBS0G>RFSanbVX$q^OgF}1$ zVZa(Jso@td)q-@!IewYxiLMp3w0yOcqn0B#(jL+Tsv$kn^i40zu3~GAK4RvHnw5Fq z@l1pTi7pzQK}oL$FQ&$Yr=vU0*_B=oWe-BR8mHuCBl-}VtkGNa_~bnK%;m(4&FObC zUut&2qaq?Zo_pDQZWG2)%kS%VOu!oBG_hWwICZ$wU)672ob#&Gx#^KFHQ{x>H&?_c z+viJq^%d&i-pGs=C4%{<6wCP%A+j-%9T82r*^Q0IG{;`N^iuPa3!O7}=RFbI*(Q?%FI$LPlZn*Y=lWsj3+V3q2TDM9Sn7!W=iXg7pP>= z6{Mh$;1DY1f2B6&D|F_C%pq*beF-bnDgbjBfKo0^fF3s)G)g5td6p`7s9`V^s%SgU zA`0F75%mIwKqT4g{7B+^iahhO^bHYlGFHCSLmmp$FMd)UTDoAw~Gxlk^<7k<~+2r{}I z)(7(`?P&2!=O0PHANV238PK^8#t;AB;|KF^@nhu|_;Kg|0sMH*d4(Nwp!S@tj$G?; zIXr$wz~EwRr}w-f7v-y7MdQ@SaK(8!+F&IQF>_lnJ3{S1#a#<<#`Q(ALlVFr7!pXm z^~pU55pm=BsJAGZrZ^Bt<$=nF$`dW-+RpCZ+^hiUUW3f(*I8L>xl|Z56dK~F;%*#* z(!LY3z0|hHJZH6K_+i9~nXEraC-y2ue(%L)>pYPYvnDUkTZs>H(N~+ZwP)Pt4*?-* z%#o&U7+yW_GWu34nXgQj(MFQi!$zZ@di_ zYcp@if+vH-iOR#3weYxRo%dP$ABy|#OF^2{g0^}V`-J1iC;jz4!X7)737VH~> zV@r=DGxRQmnCF#{-<0F~@g?!)h0xUIxsqUzWSQWe#vlr+(u~q1)OXrCmD_6Mm+Znj z1|yFj;MjSMeVFp+e8z0l-)ZkeA3yTJ&Uljxmn;m(`X%MiDR}KfM=BBf{si6>a%Ijt z>3LMpmr_l_!@VJFV1U+D{5{S3BZiYnO{u(fA3kSfJs>g}m~1K<MzGiRY={}tH?^mc#pz^HU}n#Bg#n+hR*75*fHSZiwJe>J~Hf5-WTn5 z=0E)=VoN_HB(NweZU_NHm`hW zo`@OPiGf6e2E4%1)(h^(=+PCATrC%;VsHkM?v#zPfLiQM7ut2ox>b3d8W!(&FLtBR zYVXohpX~OrC9J10p1!@w=xpE3S?l2b?0`F^$PQD?Ek z_;6Nn{jz1$FmW8bAKaJix(DH%8)?%iG_h{Qv`gdl+&v&sNv))>Y>bA0Hv*tI;3o&aP1pDaNj0D(*n_IP~)N`(6$@1e0_Uw z?$jtZCRA2nC9 z*XXrC^#RCtwjIIO4mO9*&j4@0qvZxX?*9xPkG_FNP#Ygr>Vrt3V!7F&q%-5fV(?C@G%fST$&!e%=|D1k$s^Wpr*XlhZEUG62@5$r~*e>AiGW- z)+XbM`O!U(_#&6#7X6)c%q6sDM^eL%J;A8g@h+a~u1m+AJ_60YxCS}zNQ@M7x~qC7 zx5%m{cfZatp2X{Xs@q|TI&4Kykd7J(>|sA|UOVwcfY$+SC3x{gaT@k5MN~Nt7*QKx zW&%cnR*>iySb#&4=wCh*r|V6xpA4X~;CRe@JWh&d!r_)$>`**-T?tM`(07+ zx!icnpZt%hJz!=#yD!>KnXZcunaAb&4wB8E1yfL&WMFirr)5;nh$n~ zQ%f*04Rp0j@{7-EWJBkk4-P3CL!g~#k;1^Z!Ak<#dWN#wy4H|5;+)!^>h?HU#W~@` zRRJ{jBb~>r=VnpiYXDY*?Q16$+#)r$S7+taxKwG%ah|~KuFBfw%mKxobyfG>7~6~a znv6_%5w18jrBCu%m67XOZR2ZCsBJ6e1LhW&n+}U6CRhgTHczbx%AGI!V#)zPO?TpI zt;xv_Y--K0SjwZIFynxWP~EGj!Fl`U*3D#fobyG{$1TZbM%p^_Zr5r{7s8hs6`6Iz zk<2Q^D_ab)Z%7|aI-1HWI&?5)T0&CseTc?R?@(kp;AZsjbbke(pK>*yrzt>zHnG9! zm0bv5C4BEl+wd~NaZG)_Kxoi&qIBd?ChDZqe9)<6SE{acj^MB!SQWVZGQO)Q&_*hu zJgRS&aRTx!quU28clU5N$Dx-3bt;Bdb;|omtyeGAlc$VoU~MCkLN-WtCdK1+Drp)@ z55-NUm#{J!g>oA6RL3q<&$`XW1Jg3rT7@vL&T|*5uar8AmUVfNqVqnVB4u|RM=5%k z2zNb|TNgW7e_n0;#4(u;6(L|BK|W9%Oe(m@VB0a{_|ZWy&V<4OQSI#@5#U+cwNcL- z&{cOf2{+Y7>`ZjFOt!L6?}hnF)>}$kN(@6y0%N;@4QGOmd*W+t!W88g=`5+4CRmAAzQ%vz2?qL0@m(Ar#n2>SC|9WfKR+wM7{6R? zp>pUNO1@FTt{~0ASqZHRau9bqIlP;+ixUoEp1Wa_1>lJFWh~htSdCPL826o9|`K-Hs-TqzEz< z+{-sLb<`9KHC^{fqTWAT?gRV)jwyf#Dy$(ZovVd5u+6wY}rX&t=69BADKoq4M$uJ%AuWM z4f&~XKb>}c0^<);$?@syr}YTM@QirdMGJ-pdX>6W?l6q4Q&TNgHT?}#qs%;}JvMEZ zMmCOQ+nP^hn1f5XfAa#d|2in7|r&nVKiJP(NL&H{^@du{8tIaasN%?LTmq zHRCSL;T*7u5nr+nOSFC16dKD8yk_rriFvLeBRmCGO3ZZ@{30&)12Rzmgp9#&kTK*& z1)Zyd8(m9__daQdfu3$uLD!tmGf!K{TH2;}ty%!)t{YEafJfb&i+Zsr`{5A($n$$t z)>8v9TnjJ6ru-QaAJ^HOGBXM0PI@j+MLXG06EYCdPMhg#F6OpVJ*rL$}B<6^pO zYT)mRn_5+rixunj*l8GO_!pJzs~%6)A#ZMbcFJdy(d2>zN!Db2S3!^?y)_6nJd*(C(N`ZfwOxipSGoUsytz#CcLedf`i+biF)@xQ?L&%sK&A1Sx zz&xBYx*lI>M>L^7_Y$0*ELC9DNLQ%JjwCyny%RSXE=$H%scqu&Vs#7X2^UpCW8K3l zp5c)-rJj^m!wKW1<O<+bB7}`E|m~6&6{dBDv#QePjEB+R8uZdB=U{{s=m=`-yuUx zZeZ#Ijb}z&1zoM;&c2Y814?Z&Ha;xBSF1)BsPVZvgBA7u1!5L)%!|?B1~zK)FSMcn z%63V>GI#0Q?6IfM=e(`l=U%d-6)|fe<8!H%@tr`|N$d^YFBPMwzB(E591b}nZs4pu zGU#BBCd$3cD%SQJNUnq9V~)b zvU_Ts-uioAp>X;5@Rl!>@2fBFIMJCuPL_P*MGplj1A=NlAm%s0p3KHH)!L z^YfK=YNvhi1eY~+hTW(QjslaXFcPA7n7q{F`zZQRKYMM(pSE|okc|U7)vwmRvKEf8 zj=D|R_GubwgL+wVskf%n-HvTfu-WXgbco}4TxVB(5Y7eEgBvuawJt^vo|7EO1}?zo zxu{TvDw+X!3=HGQT{uLnEQVnZq8KLypr=q(cx+rZ4REs13?tLp(ehZNBx&`T&-*go zZ$z9s7Y%PSsg9<$)^D$ERt>KTif81j*cSN2znLjaJs+;qbFQ=QL=L zFS()9Fc(+Wl@^x|VYE6Sg;lqltTNrAU-4?@kY*~+tnQ)3$A74^R97+ooMVM_1)4Tr z7e4?wTCSY153N|K)d)1ZrN9q61Hx^rS(xlJ6H}KpwNR$?O0H?sLn&{Q#LMOA>j z*;mF>8&G@eZry~nSov61lg=60B&3beBu7sW8qGriXJ=~KTpOX|Iu?_(g)+Jm%aec_ zhII#8(X2Y$bUT$Gy_Qa=N*egwkZJL!Ml4-^+da%sthNdpe0kBAx?T$|+ zT~xOQCmvzresX{5z1?ZxPu4-=YI0;WlN-mCJ|SGb(2I~a+Ev8B<4@>vvaI!i`!cI^ zVghXdL$D?xVPW^d*|Va~W~#)KVym;v%!6fyN8!aJyMA#N)z*8qQ;n%h$QEgbEqQq~ z?C-VdFF*T8o+2Y0+mmXpw!2lixMZ3ywZFlc+M$t1u|&y^H}U)eY8~d zUdVDf=(%T(Ed|D`$$SkpcE*J}$FpHRL54I3jX6}>KF;{^jkQ`R_=&X|XMg(*9k=ilftENX$!I#X&wjUS7lWD{%Y0{beWJnQ$rVSH-Fz)k~s@r6^h^_&2em~zjP%WwlwQ)OrMQ9_6pnw!VVni0J3 zj8*JJ@nsj7u}Z}W0(zPdCpgx6Rm?SPe;k$?(WvFFW?S-JWRjlKK`5ovkB6__-lTU0 zrI9F^9DJe5&YP0q^t8^>m+a_wiS=mFQ6P+5tVRl;WBjn3j#W5*X*wA9=8FeIv~dEY zW_tOBmVR2AiKnsu+=9eOQ<_7$XDRI@S*S!$K&W436L4J0i{Ji4Z!*Yz7HXgL9mUkwP6$H=Ev2j?; zyI9|5?c|m1j3+fOe>hTm$m~;>AzZzFXMY%yUX-bAsIPfMDL*Ai@F<8#C+r1W2lT`e z<9qh)Z5Hc|2u$tzygfcQPl0V(w_;9P*t|5!nCNYqmIGIX?w~l|1w*@S;plKs9{nXK zn}VrPuPXVRAWErUOtV3!GE%~ar~^KgMBbRw>cUN0hu}xZ z$9YKEJeI1~SI1Xh7*!m_V~15Pmx2BD3WoW+DN4K#ZPTed7bRmps7A*4lA&Z7P{O2< zbDIYAL#C5+%LY)k82CZ&y-s=lF3DP1Uo9!o-&)!jRen7r6SX97-m``p?|sqlYLCL* z9OJiktJ$ye?w~18eo8-bZh;K@gl5Fg>p8P;Y3iq5dD&UTxHGLPDC+yDhGX`jU3>S+ zd1Vw~K#06~0G7tI*lTK_vxk!C(8sNX$U~#e^q#u0$PcO>R|{1l7*>u0Rc_6dKJbi2 zWYT*|CK=DV#xL6`cKbrau82mjNFqw|b|+6vYkV|Arp9AfCTvZD(ZEnz zr-eS#tcip!D(7lN?19|&*wBh5FO+t!#`$s5;stE2WOs)-GLu)oxgFDV>CpvO?yCq9 zk39Potw_;(>=fAv4r9ly{Z7Lkj4{+JRjgWI=&%Jt#}pVk)>RCvXrxV5udKZM$7F;D zFB%UkjBN4VjQs6sIfYH0G31@s2&JB{k*!HC)H4c`XU)f&tPq+=#7m((l#GkeFF|E2 zwX#zh*2XbDwy$LZHX15(U0o6OF>^Sp7;WGOv_RfU*-45#cqJ9N80<$o>oYoMbyR*e zUWc~Qhd|q&4l|GYLRmfb#ten5-JDc;Ae&E1RpvF%5-?n41}1qJV4WEm{OK0*I0?W- zP%aT9q_`CP!0Q^CS1(9{$xk0-8aJEJBLp;`W9vFRvBu*f=fG$9IO1R70H3(JXxyYN zGCxckoHX+&+cSj&t(=dN942Cx6)y9>kRVi2Fc)b?+l7-=%kfc+xG~-DjZfgO6EMloaV#=zB4^~;jV-#%#@&agejE^GsT`67_ zPmKjpQl< z(d*b}?qmb<`x(GL9{)e&GK5390|8M8zQul8&(EjuzMrZ4<7C{AlWji^qzPUhGZS#I zvoo@`mo(F-`6e4DD<#qR6g_q%Ex5%rd$l>x`2ceAHTS5?HLF-OSe`1j^@wJZ+hz#UooioZ1?R2%|aP9 z`0!=G#}B$Rxl$%~GH~i)cUY2^n(wl%y%$kJ5!TCG@m`SRR-%??F{VINA&tbOQO$;J zR@WSHsYNu;t)xo~pn-!G6OhVfXfsrj5(g?gq(PN#Nv+M_gxJZ;ap*J{lAO4VcozBP z)#2Pn5w@#VWVl9BKEtB-ffM9Qqq7h2s^XUIpGuYFUOHMC()Mz?+~F?o$;-WroNSEA z1w}z@>{^mp=5(e5T67jb$V9n8p4sCUP=EEic|+6Kf5h)f&kXhKjSPS5_fN2UDbAVK zelM%Bd1o^9CbVb_{j8Yl9{$B05VFu@pRG7<9r(kn9-x&mXN^sK%PXm zT=1s~w-q*kU5|}PkLLQ~i;Jca!G=Gg!p0`F5b;3tVAk+VnnApxSOp?HHx_QHxm=Ox z==%sd%@|SjO2b@y3=3NgqcQVOeyMY8vU3=7V&jZJ*gAcOaM9{3jh zclNuKjiHg9^$)j4{Mhcf!=~Bu-?qCZc@2d&B{aeC%hD66{Tz*cL6#5vUXf(=FL^&d zCaD#q2p~J5YwWCzhTXYbI6``gJYh9hIK-d+iYC!TPkw>s-cj4ZsFIO%4NWTw;zMk?1OEymb23#?I-L{+Zeic$~f7@D4{Wtk|wY{`1}5Cx@WA zgkAuGV$wk7CnOVGcHAV=bP63LMHU1WAqqWI>)7h&@!30(y2T791*EH9NV<4ddJQd< z?&@Y2NZVI%{gkUJ3Lg^w>hwM+U%>tUgwrL#TOD{4V{V+D363#;Ivw36AWEDM?nrmb zBaCa~wR@Yf#%j+#vGXqM*W{)ta-qFNeB<{nHp}(3Ue&dC*qV)>v#@+xb?77e8kMEE z9MH?d7W<%@FM=TvEAyR5F`+Scq^)&aZicua&s%l&ODor9xgno}jDCfBvAlS5Ol+Lu z2d^!{M5$JChFrgmd%aJLz0g;D|)9?>XB`$p8}TX{WG>9TJS zSPHSaqG4-a)O@|$OAvc`#gn)LFG$moSrN=AjdSP4A5>uTMi z73gWOt=p{swe-0XROCI2j$Pa2J=ThIBGC@rQOjJfyMOh$e$L7wJlN;4;G6&7+2}uQ z@eb)mx(Ab115o_p2&h;zemFg6kWV!OC<%m?o~})aMb4A^zgfH=DpnpVIDL`Yef~AAg^_$hn5+9?wj_A1cI2%C^U<$KL$HVVMM@zyx zIvT`%(WeQvJDWJ%OwK|PE@VOAGfRv&M`c&5LX9;4ARZ~fu+H}uWkgCXPd`HQ39jKb z&q7uG85!*xA8#~&KjP`lY7Vz_G`7*vGov_ZGQJ**1dKOwdR?HWG?JLUp zPY+8oL1cgRv^^0{G7{L!+2C8`-|@7toe|LVCwKn|p!udjW$@b7eyqHomAELc1IpmH zfMUtIDB#HY7ySGqpmbN4Z=Sbq;5=uvJU2Dy5SVFv-diRAs%XULc&;zJ7d!GE+F2r{ zv*r@YhJO&l%BGJIb#dl(95-(5jv&zVNsYf3!gyq;nqs*nugby_DGkO?k!JNtMVDG! zGnNBcp(vlr6c$n%*3K0Ah5l*G$UvVkxy;8wI6E^@5g{%qF|Zfw32Al&koLVKu~%-K zda@@%q=C^Df$|}M`@MEo@(Gw3_?rbQ;m;&Ps#?DVap0&$r&bO-V(nd3-<|gbg_H?Q zkGulicmql(VWi9t&~7{)4o<=fg;E_-z@ENN!mhh9 z9Hd}@Q#R#m$4tRY4&U7up-=qZ$q-r3lnCwXwjTpIZ3QERlce3QPOL6X`vybLiz^4= zHB#`W?nlEh`fu*mcNs#d)A@f@P)ZFKXFxa?O+_#`+E5a*jiBvEU9oLjE!VDS-I&y! zeTANbK-V2$j1#&$Yu~wI#tXiGUCB)|0XXpk zn%P(b0pO%p@7c2-bA*Gi2Y0(XWq1pEdl#Hdg4va8guS((U(NB?>Yv$IU8mMVN*&e{ zbPuXms1%daA&8fVx9WAFOGE=m+Ym(i4l#QdThgffp~OyK5MF7^zsnV|B!+(XGBh?$ ztD9PdDl0hVj#D3l1n}I5&Otg9u6-2Ou9Im&;qw>CwyiD<_ImmdSPWoEiCv>MHKwzz z=6=Y$v#6(z*7Rvp5J9v?tKI#VFUj|@i8LCb0vO4ZKmi*`T0y8!55j!E60}HA!T8sC z8;d_ZLkKz=3M+yj!J~ddDvWWaNnDEv6EALcr{{AehNEs=s-YB|p>eFc;pAyDd6DHS zW6SM)nryX_=kxk&!1=%F?i4gC!4oi2}#w_Cep#Fqgt*gKw7 z!UZJtk$%;TA++@`wdbUU5)h8Mp7@tD5Bg4i~3dR6uCHccP*Dut>pq18ob;HkD4ZELn?rQA|77jWVK9UOHqIMeG&f4Mg zvzK@SU?x{NO^!u>&FzGCvB(AR@k(tJu=A6knr?fvS*$c?KPR2K#|t!4Zf~tSO2CUk z4r=Du7mSe|I3^qXcm&1$_Pp3;_2P_ktfbIOtY<-*H{8;t1anjpcP#|>@_BFe>$m47 z2}KR_l3jxc3aTtnQUpV~vdr&nxO^qy6s2JNoN#NOb#a{MrdcPaJvM8O_icc2?^<=J zLo4)nL%CK(V?pR)utVpC!oMLjJ{}xCC^3*6F|auM_$DS@_k!(;m`izsw|fxymibR@ z`)77G&y4Ks&5VG6&O&fu`2eDqTgP_Rk}j1H12@*vx8&7V$aHO?Ofk`J^s8FDPrTa0 zZ&RO3q9MYXN*W5K#l3P&;8Xhe<&)x3AyA!%uGPesx^CPLhseXb~$A3y4K+k=*sxN{dB^4HC8;5CD< z2M}A=G3Dm3{zmMdo8hhpUtcLN{u0oBYK^mO=HJ=9Zgabl=KcriKbqctZU4IM?M8#m zFEo5F*nc;d>o&L>O_~3NrteL0zn&S@cXi*kz}mm0?+2CeyNO=6$^CI%yPN@xEVo^L z?X>Sp{uM`YW8t6M=DyoVdExVuh3oBb15CeYqPwm7c1OjH>L&1Z{XY3ys{gsa;ywZ$GfVQSFHHOV$7U`2M!)+mCW? zRF@O{QuRMS*!fxYKQVnbst>@C>btN19*P1q{@xiVsKda?yCRxYHv|2x2@i06>hAOgBxN0udUwV7;am= zU02^&jivc_tbXTBZ`-?FUEbJ(q5C)N{k7Ko+2}tNST{zU>3=S_Zsh(B&DX`uAJ=u< z7G(G-C-`34{2EQJbAcOS+rJC{s*L#EjQGCm{032F|GLr}2>5&H^L-8fT>N~unDPRH z@ox_J)f#?n?$1)_W|45;{tvP;ppD*+92Z2%Aa1qV(C&%q`jApQ?& CAz?HC literal 0 HcmV?d00001 diff --git a/jetty-webapp-verifier/src/test/resources/webapps/dummy-jruby-webapp.war b/jetty-webapp-verifier/src/test/resources/webapps/dummy-jruby-webapp.war new file mode 100644 index 0000000000000000000000000000000000000000..6704458065c3188f43dc7d5e63f32cd9c4578f08 GIT binary patch literal 5210 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 literal 0 HcmV?d00001 diff --git a/jetty-webapp-verifier/src/test/resources/webapps/dummy-nativeaccess-webapp.war b/jetty-webapp-verifier/src/test/resources/webapps/dummy-nativeaccess-webapp.war new file mode 100644 index 0000000000000000000000000000000000000000..81fa93c36d8c31827e36e3c0d6baf69dc9338d9e GIT binary patch literal 3561 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 JQ(P5x@4v!Apw0jQ literal 0 HcmV?d00001 diff --git a/jetty-webapp-verifier/src/test/resources/webapps/dummy-servlet23-webapp.war b/jetty-webapp-verifier/src/test/resources/webapps/dummy-servlet23-webapp.war new file mode 100644 index 0000000000000000000000000000000000000000..ffd51fba646c1ff7901dcf1aee23975b4e487efc GIT binary patch literal 2118 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 R4P-hO5Q;K0Fa)xKcmUkhofZH9 literal 0 HcmV?d00001 diff --git a/jetty-webapp-verifier/src/test/resources/webapps/dummy-servlet25-webapp.war b/jetty-webapp-verifier/src/test/resources/webapps/dummy-servlet25-webapp.war new file mode 100644 index 0000000000000000000000000000000000000000..ba56dfb49dd533e2d05fde5cc2f304c15e4356f7 GIT binary patch literal 2173 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 literal 0 HcmV?d00001 diff --git a/jetty-webapp-verifier/src/test/resources/webapps/dummy-shellscripts-webapp.war b/jetty-webapp-verifier/src/test/resources/webapps/dummy-shellscripts-webapp.war new file mode 100644 index 0000000000000000000000000000000000000000..fa7ffa3a581def7b6c6450eddef1ebd1985daad4 GIT binary patch literal 3343 zcmWIWW@h1H0D&2a+}2RsgZ*3~+9=KSU$gDb`lo)+nNojal9t?R_W{$xqm6fx}s zDiu5DbO#B02L+eR)mkee!!0z~I7qZc_;k=`pp2JsvDbk|kv}_c&fF<5Q6zT#l$;44 z)2i4$wmDc=>|}ts3)A@=KzD_^I-$58Q?C!PRgu z7!+}VgN+F&2LhmAODWCGt<+1-O<{&Rkb|MQkjr{sz-q?DKn2%-B?4lGYi(yPeL ziS0ej)odW*^8II5^mSA5lJKU4tF0H>1H50ZI--)$bu1yNyFOk#C}Xy6&@QcRYBcUHV=e;^GYA z4NgidAzm?>lP|?_TQ|%$sJ(YLQa9T=Pf3<3ffB$NmbMW^5^y1atIh|}@*i+PW zREiW__D>MZIH)6}=k@k?+{BGCLZNnkubzYi-g&yZj%4_vEZ>`7C(M z`r?~Q^*QOA#MXAoe5&M~7Ivy(L-|Ub8xQrp)eq)rP5dLqtGK(W%t}t8HfHrBq9O_{ zh|pscl!YKk89CfBvjr$6!%K?X#In>pc>cgttd6NTzbIWVH904^oY(iD6+hjN2Yi0TVlkzUe zP1tdCzy0m~YXk0HVSga@byLtYvs=-tgPl~e9TS&H-e+Dnds5Cd?M(+b{T4O)R4doL zSogZXoc~Vgq%$XuXU*L0bTVmSPimKQN$Z5w9=;Q%o2G|dc_sh&LcEK>qq2>@+c@9( z3Z~|{$-JuK2M({RV_Y>m-cP07H0CvN^pS{jggZDZS{`xn%2Z=NdY_vp{lyvg?K z;x#kf*+eH#u&s92@V!_)qwx+~lKO&=mz>WpS;ue}C@61fb$LpQ+`dRgsSw64Zi6@p z@8ymXcb^o59P-l>xU~51xg#Zy8Dhg`JeIbZog;Fo?YfjveUew(_Xll0Z+jj+xG^{X z$D*58%@HLLsODN^c5YDU_S5TB+kXlrdnOe+yY9lbq3ou-;jW2wVV-TdF zYhkffHi!EcbKrV2A>SRlBmVs6%CEV}8?K^l;k4g5**qrnnre%cZvxMZPgNFk7iL;( zbU#{Trc#!;wny*Nx5)jsf3FS}ZWWPF7R|V1Q6Vn*wMS{USW055=bhtxMN|gpDsqGg zn3)+=LO=k>;{8A-tVYA93smVs07%zUAQPqwQ3d1nET|HO0FZ8BV3vhd$uK?GD`l9j zC5`4lJ@6_T;ZW>VG(uYfP#esl&Y6!r!FZSk)kFL$B~awId8H zX^aGFL#ZqAX$94lFtDVt4Ml5l20oprmTp4P39KZD*LojCE1Fla)v5^h@-QRUvB*~9 z580bQeUOkvb1AwuL}CRccP18?HsqkeOyZ!*4FW*PO$(?CqpE|YJ50@>JcZC4j;R@U z)rZ?qa0UmP3UbjL;tj=D6~e5;UKzrCv83@gHLQbHjmU9~tqe!lx(k@;(SjXU$l>-R a$W}y&9^lOiE=fdyJ(vJi28NaFAnO2jDS37P literal 0 HcmV?d00001 diff --git a/jetty-webapp-verifier/src/test/resources/webapps/signed-jar-test-webapp.war b/jetty-webapp-verifier/src/test/resources/webapps/signed-jar-test-webapp.war new file mode 100644 index 0000000000000000000000000000000000000000..4cce7a8a2059f52f7cdd8bf4a296ae35ed79a095 GIT binary patch literal 110306 zcmZ^}Q>-vRv!=Uj+qP}nwr$(Sw`|+CZQHhO>->9Xa%N^H)7^FVRQi2yI+f~DkOl@p z0f6|=#xMfo2KYY~BmfA2tf-10t)!e7{qH0I05E`pG&sb65kUV7Q}}--qx^^X|C40} zEy_#d|90_T zdeudR{@cX=rZWEr1@nJUHkL;8|J&IAB#Hh9>1^ucW@G9?Yv^D}%S6XYE6PY`W$0Ag zVH{7fmD;M^YPOmYaU;lyU5r~^anAsvB~Vi@OZ) z1_&s?VV$pFM;7#cpA7{70YGCRRZw%HlhJcykW->j;UtwyqtPBR06+!Sm82-LMK3$z z-htzI><3RJgUr=6^MHsbqXNR&V*UiAF_WNq)n|&TTW!Umv|ltK6E!o}%^deU*>?VJ zkKm)}rxnQJ@1C#c6ML6Q?b(pu?X-N%TiF9YPEX54DK$XT^EYvcGVLf_&6n#jysZP! zUG#~4VZBmUxKW9>reXkJHt0TKb?_<~9DgFZx)QK+EjbJ9vK~>^T2u zfb04D@Lh6j42JFNv`7wYRvGg1hV?;LPi(7aMO$iW&i=M7$KES^&DHN7@W)Zl-k!`H zhY%+JFEIV;e7Mz|F zoI*3tOHSxfvYIAm=x8n3qY@2`$1fZ?&78C+qqaNrAtzPNh#-PLR1zR;`7gVpdnw7- zs+*M9+$x-!NabtLYuh;ZESH1Z{!`mvMv4o)C0<#S3N#ZHERPsb%cqRS)y)=3hd}p-^ng!?EDD!%PzmL!nLx zz;k^s-je#xE!Aj~e(Q52P(;YGo{Z@VVCgC2(*#)#Mh?90H!BUTz^m)icuNBAj z*0*kN^Hp|1HbiVD!tW^TW!tp~t|~b%DhPyS*8(d6GB3HP7ysVmg?2H z)4jQz17mlS6C9&0nb9l{7)rz>n}+UnMrp@Q^!=CWo=@S`x4@}V=~PK+R^?tLS5v#4 z@0&(}$@BE#ZcEAT1ywiREe3-*$SEJC0)jbC#EF`Ui1lpg?~1EN8ums;RghhSZQxEC zM!jcr+6%aLuExP*dKz{=qd(6#YOIVmupqkW#Mln3?8 zNIpVkK?v+1VYKHK4hB4|2$qq};&4wT?(>hwpX7vz<5?;Oi&{mZf)gjMXdB0vR zD{i837UoIcsqO;(uou*GX^|(UAxlTLi+QSpwkH~#iJ#F#v#K>g>Dj{bCFD0mw!; zlTv{0sYl6f=aEt?|S2r~mDtS%p$6RfLyLQ3R%;;_{0px9b@{B!UQlF=p z<6bQ579Dl44$*DXJl$C%x%RFGHQb-bGU4Dss|M|(G8q6C&~>)R>u0tCk#)0IgJt^=UGd7`^386+61s~C19$o;)JsZN*4u$OK1+8qt_N_o0TCd#Lz-c$Kk#i(f0mj7foJVuQ zU3~JLkag;abIT8chE~v$q-OddmJt=}P5_cRYdZ0)uz4)B9pu$+UpI%n9IAi~$q*eA z5M<`XsZiL}^A?CgJL#FxC+;gd6awslB!dsK0zQhEb)mEP*Lnz79a&=Y(%KSXy`7ULFrY91^hO)y+p+^+C+*dS1V+n_KT?Z23$!&r31D`ofSva=s zx|O6w7crpQ^rD=n!D&lMb8{EpLn9yV9ds5VHy_yDljDObBWvL$8d5(=JdzmFjWZ#4 zo7T>UAM^4Nf2p#;$&kjjTy)wDOvYZ1OJ5t?Jg>mxRl$b2<;qrn8w6#t3M(cI3=b@J zv|_UoSI4zMH&IUeru~APnVN;otzKyJ+D_kV_^RS2EJ1#5c)UgXL0g%DV*5Gv#HRE? zL9L^5K#`jSOO)*E)ub8Pe;bC^dOMMjcYocZ1*yFfgk=zG4i=Yvx|m&-PwwDfxEvSd7InT7Ca~e0}(e zLT91FeZHlv+%UycJAK~Ue>ThnYyOIFE9Bh}3Pr_qirp0aR!!_Z+Y4yjT}qz{8cNY3usd zww(I#!Kp2brme0L5)w;a)sAQx;IBEfgKsMC;qQl+efckm+qogxgSt#Z2}EsKy}8?k z`PTsrUAh?bnU%Fo@mbt$UFiokJMnuWEXGs)wZh?wWMFj1A5mL+nYN^t`=SAa?R}ZF zRO|tVlC?c-l6sl5g700WTq!7N?i9pY){6;@6(j4cMsJRu8*J%42FBU7)huq8$@gGmzF6#* zJq>ZHN%1Pap?T`D9>Xa4sXC)~p|2=P>LA+R5ASD7Q;=`T1$uO+sc1eXql#C@Uw2DB zq+NyP?nwLsoV){2whygYU~ubuHC+_jHSgv+E@SjbPAw(Vs^u#5k?B}a_=}P^Y;=Dq zKU$d}X-46eFE-7p`CT26yL8KY&5-YG)JZ5Ko#d~CXb62OYO9rC5N(9MAdf2=$nnLL zEU@LY&Zr8uYyjZ=Y@cJI=*0ZYk2I@4TXuzmX^W||A$X1b$LBM61`f2!4N6+*dFOyQ z!Bi!haQg`F*>D6?@gTdRNPSUNq>{XK?obtW6O%(Nf=w(e_!>OUpp0(kDIR<2)u9sKt#GN@zhBx}X^fgi=9)%sJ)nsI# zUI0(G1tHNq=0)?qei8hk{saZk=@vuAr{@LFmb4S+u$44XIGI@u*TdojX>p^Hvu|uo zFuL@^gLNP+UHsEC3(`)irGfoeL#5J_ijuTPm@Z5#!{(7YV5<+0Q9~T!9W`prR6{gb z&*@1HVQs(=#dIu*L`kmc<<$lgfvJ{3n_v>J9G|Atx|vzzEO~%u;pb7j4ZJ6yeh~W) zq3Nj|c`7Egx@>SkfwFP=B!TCpjnh+x!1ZiXi7IDcfw?26y2i;F8-A#}WAR}uuD54U zdgfV^Q#OitK2Z`k+;((MWZL>zy&=`;EJVb<<|HYa4K9zTK^IrAVEC>mHB!}@;Lo)>nmmvNkEYxK-)bykV%YJK zpM9IEg{i1nd5I&EP7PnGp$H|+0WCTrS@Lra<@)k*Ms9i$1lYruer4MU2lp8qmGmdu+yEb&!7`08Q+Slr^=DW!kgnpj8{tt;y z>O>+X+E~!kEx5Jx1zv{+jJ1ZQ>F*|t4_P^=coAsQPB+aEylC!W7n@LN#+QJ9g3OFt zd3+vbxf@PkL(-#I&Knfr`Jss)qM}X^18GHhrLWv~Z{h8ohOc?cpRay=0Hz#>f?r9nHA9*2~N3d?X7QJneWEk(xIs0 zg)CK5uFtlJ7cSZE-eQ(YyD%-_Q{YGPO$YvQAdQW;N|BpuCx$F;jm@(@h{$KPAy{x5 z^WaB%bB(Y888XW&Kaw^ip)JMPZHJ}(gAl~QMdtLovrxp^`Dz{%Z`zrxN~xP@u|M~h zz{i;0eR2CwBa1z{FNv@GFKAo5Jdz-qKE*nL<87&R_dExS3nbm2NOV6B_vF9$C4y6KZv;f7J}+A0i>YQ zGi^ryb)WlZQPw}{%xA~1^Mu#=2%H~n!?Ozze1u;{Rs|@64=(~YehCa+Y#xxE-Dt+q zu3dg^kicP5PKQqM3xK)xPaNQu%0tJA)6dH0v%@VpymvZXj}_kmLJ3o7TBjOlEPj0e z7z$i58kd3-6+>blFG5RM#Le@y&RBNLkI)|#hOT$b zRK%fS?qR8Z)$p^`&QwIVP1NN+E=j0$Eq+@ABw((AVYQaJ{kKjXi|I$;>@(A-b`R_H23sQpg%%7WK z(VKA`8y`j%zRyTXJT5Nj@a|T!ut{cJ46u7e?57Ndn|=Tw8K*a4mWI-kl+QJ7;atuA zAm(0;mmGf71w53w4c5l;e_Y$I63ro-S-t6i`^!i~VmPir!oX2x2;;bxpbI%F;GKe? zG^4%pz`$gO3=2V!djeDgxQWG!ywF~si;0nFDCp#7wbO2_n%9U;@~PvA#_VwEi(PW#a;Y$Oy6=fzdV9zbs#CwOhB)AiEAo zb*@o4GwW#f#1*c~uHKdQ$el5wWhWgT!DZ^3Q%S(0cQKk@RxbOnEU_N#2|cH^cgl#t z#LFgc6QgiYHBBsUpySo@<{W42R2!ntd4!kZ54pCJ7CAS2u3UO;vu?O-ENgADRXNsIEMMk#mMqz}shN{Zi@a`5{pQaTvEz?gb`zJlP}KH@uJD_;q+zgSL-L$x^##5kf@hj^%tv z=wFslA>!@&`EBO!3}Ju|Qik5vK)G%@N#%Z!;Iz-Asf76sfQnUe!Xxsi@q>n@AKTqP zmwK?ip_72E5w#H|LbcW>)sLKQu(c8oNu;4tmFXE*-VA|1bt+hR;PvxylxmVPRvg$u zc%TneR{PiMf|MdN=;{?FcQ}iHl$!mMcjvxXo!fUQl3{YX>Aq7@8Ea|CRL`ad)57U! zI|%9;y-8+8wx`0M`ZBC5`eZx%kfqD=R<=_hw3wI3`cYYtdsmxhko=S&@*NvxsJP(MxL9bPCC;+q{NPy3Deywd70M$Qg&?S^JB_s=KK**I6>4 zL<|9wid~}YeI7MysXRK)N_oA>rU#+rCeO32+$Tw{=5CEwkQ~nqSYB+|vtr3Ne+~s# z5y_rjI4y~V=2w}WRC1Re7h!lRfpM(gyM(b1YlVygc2HN(V>Vk(`PDp1a34saG(d!5 zxl`N5<`hh*Y-!N#S-@>B*Pq6PR$lWm2`l&!Dpi6C$vkP)0-2$Q%JfVG-rWkw8d4`P z(baY6A_5tdaX6mo{gNh@D9Vs!kA(No7(1-8p!y8r1_EmPOKCFWs@KDc9kPQ5h>`NS zkaq<$?~6EVe;vl9rDkrcaH~j0zUr48(mSW*N=Y|!?a7%Hp;ig($DbmYYRKBAb*$%Q z4&PEEuCr?V?AUM53a=dw%ZESo7N(Z|*;r-F;{MI0w^&+oX}px^3%eRe1#K)&b1LSN zP7#J+OyG4zcdCY=Z#oR6x<$z^H|H1TT)lATlhMM(cb!3PONw*J^WIQ9saVV?I2d5x zdpTw{m?Z`Z^PtUE!Yrc8T-^NynN`OBC+Nrubbdk1V(DjuH{V#-TU*h7_!L^c&RbT_nowU}Ir{^@hh(9up-*9HbstYpu+oxw z&>k(p;X*aGp$qL9t$7EX_H?berdgRk8!7w#cB-SK_6+$fygAe0{ z@E;u|#Iw3vO_;7qZ?~2-Z2b~+4FBkOENd0T^3mDyKV$t0BmD0Wb@Gt+FynokP9Y`7 z^5%|o3s^Q?y-r?Z6N$nanLtT2Jg{8yOb|5T>{ zfWL|F@yh~#=T81$vcI}s@Rg0RrNPaWxum(7O*tYVJvp_wI5kC~HZv$KU$iN)Dgpi( zyNIhGF*)1FL^CTjE4f^Vugvl*3x~NrLvXI`g8yM;X%Ky)ib#;KfmjX4*cvX*X5{1p~8IW)9XC?>h?nh5X9-mz99&1NQ2TmLI#`d#}So76FtR)aTw)66Yij{E$^~A zk0M?{a!u41$^9{poqgr5)x_?JhH)?Vhh4E2YIb-H4G9iUd%F+{FJ&B=ivS%xMJiOE z8B439C2jU6I3>Y`z5R@w zk;*)~%S@p{6UhySk!6b(NaIweQcWw%nqWDP62GJkvTD{j1He^JKRk%r4&A@bRU<+D zdc9v!NtZH$gEssZ3o{%HGz{f7P`oX53#(BVGKL`YL4Wd>>|hTNV@)j9IjPJ=#YRv{ zwx2&Qhae+5OKer5(P*l|MEWCW+(567+6g{Uh&xzku@NDa1K?(GxPo~}r@=^=1>=-T zq1AV@4vvgmfy`y;k20Us@}5R6E+)flb$S$dZuWHKFkrbKP(cf8r9!1k^|lJJ1)VIt zQXumcKzEicPf+R?7g~A~oi$C@GoPtYN&yHH+HL+~wVnT!VjRAMppm((x5o7jE4~MR zyrF<1^pVwGfkTe+Wx#-#sj^{{aATVwTiIyCUCSHF*RyR_xOF-V*3p|VOf-j%(o#=R z!zUp;7485_T4&+9b^}a+n?&>L72Y%Ap9>JhMr>At^;AisX{_~{0rp!#SCAih40HqV z;i34RR)-Owy?pYWrC-|T(U(0J7N$(To>|?JqA(AReTxO34eF1P24WTJwXUmhGIvMt zQ(P(9WMoBNE*8BUSQ19JR^4rYPAf$+vWSG-1=1E3!!sJnn-3QC*_bJg-9d%ZrNg){ zLj>z*u6HgZa;E(YB`-CX#eenm zvs{vRcDi|VrTnuq4T6#UF&-^^U?O zJkZuAULOG`(dU@C(~1Kfi=Ju%A-y^IxcEJ7Gbb{Zu*<9s;0ZqwVKHu<-q@3h(f;$F z+N`zlq(ME9eNJg^<%gzm$L9v{F`&kSpE!4~m5Oa3S#U#nWfnB!q4>nCmG)^B|MtG; zWCTACbF;}b6i=of#~!S_6&PFoJd6H`mtSm%v&ucyL;0L<6t0zX;9Cah!?3wLe<}XQ zz1=gg3=kG*&-)@}O-N2@;~HlaftX@@DjKOohBRgA)U`g-n^u|8BmzbAne9#Tl1@;j z6a8?Sio?QMVMEggH6F^9En|s;%Z(3)gi3T03(w3Nnp1aeOwViG+qOlMX!|C&bjsLH z;RUy2s$g%$ti5WXr#=hTFStEr=ky=0mm#lugYO28qv5 zkfKIReThUDuBH=*CGUWJ{U;+=PjsnB#MDda(${uYw&8i#tDfTL zgibN`8dR;m7Z1GnH)Sn09XPr@x=>!D-N?+oyF7YT7tamaHG}@frRyBNJ{Ppj>}cOr zy&G9)4^V;qrQLUPVfb80XD6$xrTyYYl@`x-&csLMRX*;HZ_iFn-mB%0%USXYd0ubp z-Oz!)A)$WFxs|F_yC-n=buV~z2L5;xfj{{al68U;^Q&Y~mQ_+#xj0>W{wiS$3r2?u zQ8{l-IfnRU(N)2{rFNsWi}9`}@@Xo!M3tBvv|3dx^b0^w&9KdB@1&{0gQmxHF^0P9 zwe>vqRFT5e=bE>xQFwKiya1&@Va^>gj-$>f&0n&w>j{T)_{m|wx=S-bL5HPxj4cus z^m-=JniQWH5oUOBl1>R(yp)g?sKKq}V%#&}73Avv`cTk;nzj()s=$FUrRy{8?GKyU zoxP4l?Z=YnqjJ5QA;;x0<$9ZwhXpW4DuEpMG}6u8Pd|gMh@JUWH^2>b~d` zT0~|1*H#Wfv<8%t-E%Ya33uYCKyqf6?n|_}HS4QKm=^7!wB2v*Ur|S_NzcwRW)()G z$e0nG$<=&~uufx1D}Pm20!!uD%YO>l-9+s7VFv`Adk6UH+$&szDH2pH$$N?E6#@~; z^h}??40g}Oyc-3vGWjcJUiCK-`fu}Cm|kFMM%b05G2nZg22V^l)OzhNDDY%+j3k`; zpL7$;5r1;VCdq}$|nSq-qD zeJL%g)%@F-g_Gb6~Wx z{UCS|H;kIc-oFD%`JO2IpD4X3Nd@x&+`tU*v4A$V6y2!Eta2EzH;jaWwx7TR?La(B zGXoi3Awb)KIM2by=Xful;6_NMM`zED6fY6Z_n*NAB+wvkw;TaALv-tN{5vEyK~Q|d z?K-X_R4Z`zjDCn7#46f~+66Z+UH;jNz<`|9!1Vx3v}wT;%P|T;w7!o70t@TwJ^={s zrMw$Fu&lAlL8K7$#cQP+N(z^z*SZ7T&b$1Ihk+-lN%$AxSi7CM7>%9wB%PP_%Ua1| z{HmQNM}fH#yZ?%d08rh()J%YF zHf{jgJ$VG&K+Z&)5_{eiX#auV#zKfYPzrfDN4lj?P()hikWg_^w;8jx> zuqfOC`Aa(kBIN`ZG(jssSyiwi6>tSMrPbjO_cwG_SwKjtlKBaDK2$wqD3WX8M=dZL znnXfmZm=11+i-T2<7mg0?$FW1j)Z%t)T=~eg?uldoMI|0S7c?!1xkPBd`8nG(|b!6 z2)KW*OZi~d5(MR0a8Qe(G}{1wW{a_OeY;H{Vf|fB9YIV^83r?j zR1=U<0g}6ZDheGs{bE1ttM}Eg+&@Jq+dy=&@M|dUTnOffqzs+jb*%}^jF&YWoGd)K zGBaI}Wvi&5PKd}r2E_+t6a+)K0L&to<_|=f2C$6#-gl^?-f83*o!VY})fyZREj;tp zNwe5EorPF}!^_&v`=Eu$IhYoP_@JKc)DOeQ*ovkAT zzV8HJ;!^AE4M{BI?2XZUi$zC_O|&;r&H`K5IloWuZz&OM@%OWH`N~Y)V}d!$F$9VP z3OcTfEvNmUPt}m&SSH~c@c>}VqK4w9Z0Kn(rUcQ+ywe?enM$i z`}C|kUz5NFi%S0d7qAByL1guqbz+cF-$WOd(6-1c`h2Ef1MiepoP+M5deb) zA_~}l9sA!g`^@?42_y@03q%GzK{H35Q5$5Rv!hC~4`;2Ummi}cuYHEc-dzHvmLA&LS036ZEHMZ# zbfHOh`y3InB)JSS)!ur*l|^hwNNG9h*EtwgPN$zUsg+;gpnFZeW!| zds1?epH`y=8LX1`b<1D2ww+e)Z)cxZkYuML$vxYy$C0c9(;tVHJnHpS@_|jhXOWoL zN@Do2w4m=~K9BaI4N+nIv?l}eA*HxUCn`@chMc~!sM{_kLto-0xbYy-h^?xh^hQCN zPB>PO!IP+-6e1352LolYiY2?d?+LJfybQu=X6i+|Fi*98M+)lU8TUyDC{MwK8Y9o)^~Aefac;2PiK-Q)09DB3N} zLz7_ZZ0aIl05_lH|G0A*(ZI-Ih6t)Hbxaa2X_$e1ZeowTV+8%Qxx-Z-vZ)GP3;5t0 z?fv35F;OmWU1VHI7{zTur|NfbhQP0=+HxlTIqI@E7_AC*6n7K~C54;wU0O8o3P*zc zzR6^inHW5pm5^BJu(p1*OHdl)WH_E`fyPoJIJL(;yXep#=i*rh18{Tkse3Bw$YJIh zHY7fTvnV0EAdS(1%PpnLidoqR{C{l}>xNE(h>CfWklk9KvGSqcdHIIWYOwZkW)J{#=de z6S&%tE!NEM3 zo<^2^@hrUxvUZ8d;^e1*f^SdEDDPi_Gwk03(dvj$-u6z8O zg*vGgX02#U|Ka+5ZK!ByYfG%QN7rj%BPUO5kGunG#n0mRv!w-a4UIRzPuPF5Wa3P? zTy)nq|m%Q4*!n0T{+`dEZTOZtU>-Q#C7wb!ob}T!1|Mdch-~D>3 zE*;2vMw`M3n4ssh>5V3Ob_b5ZneY)RpJaHcyp*Sn?mh>?!}^!jwh*1UQoGie;cVZN z(iGON2t7>(Ikw&+r|+ImU*%B*{;MwC1ga>QCPwLrag09eUdxN%6qa^_p z!~>&lH5)C=voyB_oXrjU`c0D*Cx8@WZ z-T0&9Pf(=I?hBj}0>>9|p<2p%R9uZjV-H=zCUgXkoC#v5z}IVO-Dg9^0B|rau|O{m zf}CtP40q*&hD(xKZ=S&zz_qYlPSAomqkWsJMR6q|tq^eMCf+}VIZKLbdGAmUdqDL|4``&$pZR$F^v?L9L=&W^+ z9oP+{r%;3&Ug4|Yvc;?BR}ZFhZ!dHJ(3s%6$hDY>a4Q)NhSiJ&XS3m(EM1eG`UDRD zw?b5;)n5b9#%Ja4gjB*kIwHgbdAh>DkK}=SvL(|~W;};m$yVOB@l>tcs-93L49(eW zd;3yS6%vh{xWZ}FHofMV=`lbuWVN`g(jfI{J)1u64Q%wIOyFYK`T?xJ<0!lcL*%6s zh;n81wg1c=fg#_Ov^DL?^PKL{2DB~%{k!k1DdMl}+HIrH*xw?&+4~VHD|&Ah(`-he z(g3r@K^#1Vu0W7J_FAf>as~C2 zEUHTJg!I2bl%PiQ=_vqq?a`n*q7o1fKxwBQy*j|la&R_|v*Qnd=7{MdmYR4}0(Jlp zG7c`H_is5S4=;(&a@|CdAY|dQi)m#TigU7A+NAT(4%n0fNE#`af^;#mL=K){uAW$b z@RVOuj}P4+=;6HP!#i&s&7dWOvF8hGsyiLlVBpOM_y1A&L3xClMgG&>>2eq+SJbr4 zMJ3Byj}j1d$A0H>_W2ePe3pO#EL?i}m}EX{_!&)A>Zd4G8WcSKG$rdEACBn2qlzbk zd0^VQd5&FsH9YwWEmjh%3L|@9Idp}Q2K+2LZ0N$@t6N8F2jP^yauJL~-k(q|{aj3d=!~I;q*%8{0%(}X9;mtw@(Qn~XIfiq?!N#5`pvEP z{s&BN2rVq#^%pSuW70PX4h9AWGfEDImUj5$O+{`QApv94=T)wFY&|)qzU$9=X+cS0 zd6^^*15>{%G%Hc}pGRAAW)d=yBVD9Wr#!8wBs;8I6r|50Eh!zbLkCYHz7z4xiYPwv2o3RYS2apTY zFDzG03Qnc67;)ac(H;zdB8&`7EFftg0{OOn97{$t91=(ore9N>t+PEJT!J`KkFj0*fQv}!GB8)Hk9_UIKYiwads z;)Bj4eq!CZ^h?buqE2!%^Frw3Aohtti2_}c+F4`n(bFYjV1>yHNtjn;CNB^g8q?`C z&1amMU?=`!f}xW+J9F0ca-?nO{Jx@aa&RQ>_Dl9Q!gQlNQGm08oJf;3+BNS5A(Rh_ zD5R1Wx=GR~z+28;){_L>MwEmTjj(h)}^$Frs%PKde7MG=N2@ViJKUdw>*}NmB`BPaXCT z`H|ZK6syEp(&xobukRe2;D?x88C<9_GxL+U?85Zt$k^a@p$%Vl-8h?||;^^V;|d zLvFo$go?TPiv7ybVpo{JH&*HEEV}~q26Ry>yAFjg;f(r(idYr}Xc1*}bgHO*P3_0f z95M!Tc;Y0-TuqE+A@jxng1v24tjnIK81^tqFq@xn(!%tbkfPz5~W)KK-8JdVf zN}RJL|7R6y?!G)`*|iN zBlKW8y&_z*#gd_R{Q1Yjt?s2`6?wCED^biT+GKo z6=>oC?7r29$KthD&~#*p)A$!NddKsyDd?)8ilneH>(7yeXuckrEc?XicM)l;#9@^o z=tJhn^ngeR%A#AjpQ2%76BJV|afEc%L;ii>|NF)P{sbtcpu&gs+Dmn(f_`^_eivSF zg(jHtdw?t^iPeTYN|Z3cOYiQl1`Ly%`4BZ)bP~x?0VQr0)J7-}ZxYt_b0#|3gGp3n zmdgH6&9!5uxnCSfXcYmbqnqY_$pwyE=ItMpT!%<7^c3RvSbrpIL~bT&`4|pO`~9== zDVItq$iYlpSvY{b<1^^a1pE6gu zhrwbGxzv7Nsv3wQ+`Fw^` z_K9$<*8W#m|8?Y_q`nC_!Hr^hX=mqmI0}gT3Oil@&cf%`cNReFr92nmknj4;dC^#B z3PISTyL*$bLfVtbO!J5KuGcP>S=-okvZ$F$)-)eP|^& z1TmuINF!yC>WnED;o#a#EP2i$Qe!-?Oo_JU&pBg$k##_##95pLj3LDYN84tAT zII7f}-j(0wX(scgQ1?Tc6ZF-}xDSmzi#cPvw?FmBzD0vQnW*5`NduWhs`u&l&5pyU_|=8C}^``yu8=C1jsFDC*-x zYN~V|B1XuX3e>n9SFQoP6Dhg<2(6t}{X-To$$Zio^|`UPA`c80_K=1kUFlHKbm-yt zLe!EW5;|rZ%y*S~E3^w!mXM)Y2FF1__V^Pkd*Sr>4*qTSn%BwvT4Jg)<508q)1WZ? z8i$K0q8Ybtg00|duWyn&J~`MiUEg^3Butpn+^B3L7&7PIOGnzonl|Qd38J+BhhJiB z`d(LJ-1ne<(YEUiooB`px2Ke$9lv&2-8ID&+T#%5`zE_>p2#H~g1cYSY{DyC(L zwbs$qmGNP>R@>PKER*3u^>A-&&>vW{>WmZ+FZCywovoBWxSd$)m+O?Dy^u0XooNl6 zM*-kfUX|&$Jye=lV(J0Xmm}!9p}_eA1KP`xh+ z%u0?#Yk#C8wK{mk`rN$8!Z>JPT3=Y4JueMz#P;Vr6I#&y^juK+sg~nLn)8XITl$dL zYah&k1DkVfeij2@1qyvqr^tPJ08*T~oGm1^Xcj;PC{;u^AesF|al%2-3EVBaCeeOi z6Gfzdv$4EGZ33wSZhJsaEPyA7G2}ai!MNVaHHMr@tB(pd1?+YZX~0bYr98q_!Zz20 zs)VX|467*e8%gpSAnt%F-b$~V0Gz|pP;=HUJw|aVER&5RU1ZHNkex=7UY;Z7;}Vx4 zm0zbYeB$!5Bar%zsMbqv=f11*eB_69S`qG-I8YuVXvhTkl5;)8O2q^RHMK?sm*uvZ zT}=bm(B=1&&qu9uIW#h>>uoc*+)zW!eh%pM;}Wp^X>)>5eKV7d`m{w$YIaPC8_nsX z%7ODSOb8~&%Kh9^`PLysdRy40z^$z--7be$&bNx}Lh4j0n_4&41 zWpa6Lb$Lx>ba8EPZe;V|-=n*It-lLrSnTdAT5ZK?Q73peQGR8nfq`lz0O2*3K4nEz zq1E`}xpM{c-oPN0#P+yfC$)9!ohEAvW>ZRsZ-ku&9XK1eW{OBS@!4N_Tf7H>rPVugdw_hxm!kd7DK*&r1=&(7k2TF*sLg zHl@w^X|enwghEIn5$G7@K5hiOG0~a(+B^LO^PeZD>`czqg0#0+tcI*F9oowyIul;U&{6x-dBR^>%sx~x=leLn-RAwTyMe8@i~;|I`0O4g*txQ zI3WMXv;U01kbjwiqbUlShMt1*0uo#p*DnpOExQ+o6XO3#<_apcOh|@KP;L{Rj(+vm zK?!dPGg080r!wp7=|Q_L-Hijiw+bDf=E^&n*jQ)J?*lLWqBoWX*-Cwfzp!9=E{eJ*9K*_&w(wI%x^SET1p?EpMvlmBypW(EM*E`}{3;ip=Pi3*w8;t`bMdx`9vxTSDcnI!CUe|Se3LG4PDZz@T}P4on4Tr^MG!` zgid%0O2uAsSByOwZ4|1(DgLGX*s0gp*Xm`iOeI_EUQz3Gs~Zv|_VxJS(#61-;^_!` zf}y^MB$8EgWk??P*FlrrT;U9emmt0}x=xf5dQSLIg_jFxEpF>-8*Oi(#&E=X!Q{|DXH?r;}w959~Y1df%z9n=4NAKSe z{|_l|9US-4WD8o%%*@ncW|k~ww3wNhnVFfHnVFfHnc0$Tv9!K-zuBFcw{z#c*@%jc z?vDPWEA!OJ%u|^^W`xkK&{o$>HF3dU6j-ngtpnEh`I7T#HS+E^0MZYQSHrixwzj@K zDjuL;l_!{6{-@u9IM-I)Fw#Z>`aR_r)kAorrRMSyK_X_5Y!Vt^=^w|5yB5@0+MsKR zm>u{)q>@R!@mj(W);B;sK{df$DV91$63&f>AG`G2avUh9`lO$+=x2ClX*sY$?;tZ`-Q{P`qhS(to0W2bJ=mB}yV7d3oud^c< zj#rS=v@lm*BZ^d72)D#vqU%&lLN9Bm;!mS}pluGppy;8`KBQ#@e4WQjl@qn?$$+@_W|Ww z`6kfEU03)mZ%I9rYiP8xhHm^##N4mK;yr&h&-af+O!42C=ifozJ6=j|K;Tc*B5abc zqy#=785xo37mtQv$7T~z6T!g#ZJoUrw?KX^@cg5L*j``jtuU%}aU?iHmMPZrCjEA1 z+RLZA8-!yNDA0vghzJ696NQeztqZaZ_j~@4)VRDZ$V$p;fyWTiT7{HZ;(3J?h539&+~^1!UB)a_Y}6brna)Zt*}V`H z3Qvx4+PB&bJZ9X}-vJ#d+E-^WGFAGEpu*b%aM4cd`QV}RD8GIXgvaepo8re3XwwrG zGe&r^V|LbyA8K8_FUs;)PwE-%I#2_{!(58UiG^Rx%Pm+bvE;Rhbgpn~=l`m>?`*=B zi3NN=(H3oosoF^OsY4 zA9-vA{y4-A_@A5t_-~x@AED|U+X?-LibQYCSg>h_Mg~+xa8`E~ARq&R^#~3LaZ=z& z4dwZ#2N3QGhpJ*_txg8g+aXRq+jhQ1&67423_<4_jieWir#}V#hM=uR$HVrvuS5G2 zN~FyYEV?5(k%dl!V+x`(POXfKne`{B@=w_)lI=5a(3{;)AFDrdUMS!0yp$n7`Y&`3 zjdNjJgKlh>$C{z~$vI1q=$rNd`5^#EpPy#qBuVlR5u~ZZRva;VP=A>swJ%Ab@y|wK z{t=&~|CK33-3*QGoXl-){w+`4mBkiB9qHY#?L$`pZStkr+BfKs!R{{K4>7YA@&Fon z^Ov>DbZ%YOu2S0&J1cAo4;g~_bAT;)Ow+#AuSq+cWHO(=pJYDVJ>B5`_guc7FNBYi51{znC_k z%rMVQpDe)GG^FC=YttUQe6Pw58=2MZ^I&qMVr@Thjy)b>Qp zLI8O5u@T5HC2y5O=yGKm?jKuk*TMyQ2%-k_xg2Rv)cfNd#H%prcq4e+%{{8%Ke+6(qagUgf2uw-_z45%&*GQ4=Hf?76DCaRmr%Ofa_ z$5cg-(0I()-pJld?)Hq_$WmW&O?U-g;#^vKZSwiv44aJR%bx#2Huz=Kg}!zv)!7W{ zD;iQe{yqz~7>w1Emv6-tt^(q0g3={;{REpjKdviPsnEDZ)mpu#a_$kWdZ zAj9>S&$pm3B&E3U20-qB`TY7~;BeRtw4T591lbnkY^Ebd!(@8xzI@(rn$F+y_xga` z!O8%6nzw78SOdA5n>KEm|zbb`|du7N+unA_X!FL6agu{$XYhqQU<2 zaun=JAg2I(3`YF&Uc(WIJ_bNZ!n@4a!mxP+vI?9M!m|}ud{&BzeKN8}98KvZ$o&K}` zlQq>))KEvigy~R11PQ~S%TRw}Q_gF!?o}g32LRCsUKFE+G7PN|B7iH8zEE5F*Uf+$BItbr$&61bY@#>xeL|%UM4ehk%vLXCCmd< zwE34QEk(hL>vl<@B8}-}+f&7j>5Y>T-tz|nLYEn%V?*GVC#;tuI~r3kMK!cloH!cf z#vsi_#hJ(%tJNrtt&c@2`Wi5%mDUZ9#?(9|rw$sDvB}75CbdV^O-MOQj_Y0NORM+i zh*FauoZDJVPL=#QG8W&F#vGhBBli~!I24wWk)*(N7hch0^O?E%jVC(B&jZRz*b~{$ zPBe>92IH-*=j0CHYn_>8mg|bJ+`D~sm>poHsAg!GXTz=J$e$&>TBnxAIIIazxPH3R_!&rIXA~hL5@^jiW-V-Rnuu*g@4)JKUx^_bLVfa?alm7i}W5E z=DRScZH~BXSRKCsJ#%$+su}eg1P@i@#w|I3i>h!#`32C(FAIa5j{rv-jSxaBP#A`{ zLM|jnD-GfZF(J}W&JxiIV$m^ojqWrC=IBY|z{HRxfe`+VuZ(f87yN?Gp z*jBIyTN3Oh7xsfFL1+ppABM4Zk7h>=QCK5P6PhYDxD7DGO0jWsSahq32v+1REFcR(#*gTax;BXz|>RAA+H+u!n=Mcz1#hW~m2be$9Xv2EyQR$&ILRl1 z!#f0qfE?fy2=AR-M7+n=H{MxBuj1*>0IP!S)f?U6Yr$Q|te%A%&He%Ud^TGk1bp|R z(%PKrP-oQWBq)5Y;W|3TSo0HiyiSHdzAe2F?A<$>8Io{`vo`76OYwE{tkW94D^d2! zgThnG_iWPwysN6~wW$iL0nr-UV6h@)Nwp~OE3OKjCkD04JFIFQjh%+bc}2j8wMBhn zm`wje`Z#nJH#DI zK(8ZES%cHgV~Dj)^74=g}Ut1q;!8hlF~#eNn*194{y+G_`NTTqQ%wIb4G zi^d6YcMJNp54;oJ08!k>1?&pHI%Jq8kwQkFFfYOB0>@2QVe3cA)deATP z>%8oeae4o$L-{fmr)LkUND@|&#K=q7Q53$V*+YToKn;?!5bbVS57xOlmGlTi`4Faf zwOM$I>sbxf*_?=XpjMl^<(`j?$0zdc`}56gyaWHJqL zQlbR~sCWG`) zvp>ax1xjV}awAUCU5D^_`MaQ2_NGDB_)|l+*XnyJY?^W*;qVi|T=Gu5wWWs6nHj~Ot6p~?@061{lLN?gMG?GFGa+(2t-+UCq!mLDp?iuoeEiP~JVAe-_M;P@MeM$nhSJh}CvtfLPB?}mP4zj)F=@Ht4U`i25pz)9+IJ{SYUH#R&AY}8jc90a z!u}i2q&@^A#5k6htZ2Ta*av-)B;;BC(g2u8GpfvFF^@5^4L!CMs+6v_P}u?VN{@-} zQ@@2ez1O%L8IW}_)#c^Z=>@Yyknn`qKirub8WLV;&Nf3wOV8vltR=G78C4z>)_9{w z=(j0KWxuCkMJn>Jk~O={h#cutAgtco@glI(tXZ&dm-n)dk3%^){aWrRc{nd|5N#A3 z4c{@FYM3U0VN-G^=GnCY8%N|!oHkY}=jA05Q7bXafI7Gc$u#F-&L`c>J}q$kM3!)K zjj>auz9wf@c~_wt@gMR7e1OPEcKt2Z>S&q9qFH5&8@y?oBNme?-70E2R~ z$2~hLdJoY_$j{B`;p+z{kQVp`O)sRhZ`}rQ6sycRz&%8RJdxd{K+~`DU4g;`4ZkwG zVO+(Z0(x~Xf56$%VR0{|zmnV$4f~YI26LD!u=Q-2;wO1~qIv)Xw3_s=wYt0;SPq~n zo&+Xm+=Qyb>H<}|#W+xOeDR5l7h`W&_b@#HPRjnN zhj~GQiB~ZA`YE`}Vmt2Y=geT|(fUPT-xMj-l_FB8{si^;w6?#ndzhWiC|HNH=yWob z?s&_&cz(M22H~fTinTCWa~pvI-aRZjZQ~dMn;&u=3_8u-Y09smjsM6)SLNZ`bAUi} z8^KHj+=>P5vvb&^M>!Hs5`97q!+X{U8(t$^)#ls@Tb|>zoPRFPcvR7ld%W&5*^%#-+y9vln|{D~K8ms#zb@X;Rjsm`r#v&kwHOPT}RF@X)Pu5W=c^YD4Q*rUyh2E0M)7FxSpQ^TCZ&j-g zQKKbh#CQX9Bkmbu)r|rU-)qMkL(GZwC`W#l4+*V+pOKgpqMx&arm?-qCF(e{wdFC` z(Ebq-kiM!D@2kpM>41P8?YU%{+kvkK9;&VsRWXFgC{GzkbwM2;V_uOW-a&zu@QHm* z!GP1Q34n=X(v^36Wt67AS5C+D7Bm_tQ?U`T|8%u?Hu@Q&Snd0_{!t}@;FI|$v#k4{ z$wU9y@&AiF1P`Qu7(Dx|`IUbU3=LhQQ=FF|F8;WBBcfU}d~-F@NX6q9itM^7=fvVj zzB`qbICbsQ4vd*EXl4;Vw>va|GHVz+_v%M>i}3%-Lr#CmL#niF-2WyIEe3(4zs1}2 z5$VUt&HxS=7-=kiEs^CK#2DSP`QCCo^Qn@>DLA7@(ATvKAZs2{gv>4eQ+Nm4UyEVcmZG8MN6Oyv^2TnazdU<+ zgVY5Q3!lj|vs{J|&7Z8WvO{pST4)a*2wx(&3=_O|iK!2bba*!oV=dr0=K;K>7Lyl& z*sCHL9fZGQ+G7Ec8ZnTP zqzx*fGSX~Hg|IcQbQdp1uCfN^KHX++btz62P}*)!PY4(ywwYxb-XHw!?Z=}LwTIR zLS;XI2`eCfrj=cNBUtt+(()7y0_vY&ZiqEJjQjQ!oPUL=CG0sPs;1>Uygva+eH%yd zi=y{&zrKf1{qk?ZOBm9U3Hswy*?+|Se+lU!bK=)Mf9MgLEvB_*bnUfBnQ8Mz!OgNm1 z1*g97S^Jbkk(I-=s)%jPbDI6D3VK>=I=Vi*=??M+L9=+0iee>Dq;{uzB-uu6_Sj{C zrXeH5g~gmaX3D^suv6r}t1YpaD_dAe*U#7UcABXLz|lh&4i%N_X<@OeuS@!}8F~^! zdinT_xOAWKK=Pi?egq=GGh}74Y**}~mAXOf(8>v`&fJ~`GvkQhWJ7pO%COT%u!g3r zNaHkqUukMAJQX{MD7Z*(Db^R;_851tTn2QLO8(Lk-D-KUK^p{^iczB}l!$N~Z@`k# z94v9(I`uHnMl^kyuuU6lLzfeGS@F5Cq1xzLy)+mqSJJdi-#44H!Bu|NyKp#}G!iTN zL6y#wcftUeuK|?|=idj+9!jLy{jZ^}#Pv*pJCWD21?Z3YR%y=fgh-Yt=Hu<9Y#6DI z>Kqk9<*8qspMD=-aB?bix+`%Mpe~`)mRv@{uPhuF|(-JLz zZ_X1P>+x9hT_!R3A-r(-DKF<>JC(V}4|4DpVO|YdT-^BjHNms1P<)AD-*4%gN8wM;TNN zffeQkcfQgeW2)+7#M6eg#8N$Mi(v_Isv3gAn`A67q?bKc4_xG8W2zd&!qa5v01mZd z3kPXS84}Er+sEqai!oB3){LZKbZNu?i6hFrhUSlVTQICb@ex#SAu+|I~>)| zAP}{VCNZ~PtDpV^3?FeT8h2FtTplnS0c^O%i3CMWxTQSs`~JNrj(g^~;O|Jcq8NBN zeRge1E4d)oAG?OHo#59@yKWn$^B|#d-wR_sd8fh|rXCB3Tomm3IQGE+Ej-D?BBWhT zB!3nUAm1+3@Mutn3f^{)amP~7F^-+ss2uzUw71&~MWF@UIDC*sqV#V}TMOh>Wf8ju zqBIZD>AeZqngsuikghcSHi@}y^r>9s1>Fwe*-pj+{2eR?4!*iGAM8>`IW}a?O|Hj%_<-W- z=*pZ{m?lV{EGITW=< zm3EUa1*SQ6X>I!$)WDSvkzwc2^Yp}auB3UZ2*Wm7W-CRexhEzg%tG$wWZrk;^#{z` zR<>Ql4V$7Som>i(XEuN+0(G$1huaFj>8oAn)^zGD-ueCfZ=&*R-2%w-z}l3z7#df3 zs#fZn%AEwP830zx%efN6R)VB>rZUsqZhTtLyZD7vHKHRa$bP(4RChC9+;|n)7~5!b zD6M6tlEq~h_1KRWuUjfC)nUdZqYwzmkQolNl&S-2vcc1yRnz}_SR>WT&DQWwzOIb; zPs~m7Uo*F(ovn?d@xPia6eeYX1re)|P|?s(e}1r$yV-YpCYlKe1t1lMw>n$vO)*KC zm_)ytm$E3aQQpqJ!+M~PL5xkdN+KSbkTo(+$hRJ%ErV+2 z-%hxj&c4$t8nh`KR*;GF71WsZqN6OFE;2aH-ZM?id$}kVyFrIPNz z#Z;xbZd37FjIL6yZh4QOVuy&VVIA5mOOqv@U{lFcNkV7Hdd(N>5~1Kjee5Lf&3OG=nH+Ri$ex&TuW1 zT^YAO6EI?L0t?oaI3$sjFm|W~-N-R%m!qGv4?HLu0v6(mwPV;eWS7409U>Y+4NJh_ zCGM@*z*c6N@F^zT&8#yoV_&_kh4DM0WhOf%zNN;ZWyX@815f9tk`*fBN>z(ChMJS` zoG3J@Rz3aC@$TkF=+7 zo3I-qNzf_cpnH@-jvJi;G)x=y6DdT@J}RN97kalxTA${QglIeXcWD0n_p#FG$-ROi z1#T#OIJDi=_Ji@M8$dijMx9KnK#0x|xtY)Xhpx^_s#x%oETsaxX|ejw7Mp759Et2i zH8;!7HHq{~5LJ}EEV81Zdyr|@8+p1N4mC75efPTSd6BRA1@{EBejA#RSun#^iEb1z z#hF+){)`HY1MgN~Bwr3gWl3v2ZqtPnc5g)81tPMdG~L2mGvWR!iw}yR+tvdg-tkBD zo^>zWFCX&znAO09p2DARkP@|Su0>*0T8g6mu^@5_2$XbN^*qP{f$XbYhSFkXM zu=SC&faeAw;RZn=0ZEmz5LB>mFp#i-CJDq0Vd9Nr6j14ZDHa_sw@K$Lw~B(Lft`Xy z>>KKXCtt@@7u5QDvJ6%~3ES<@A5Hr9f7S}EV)N&txs|?wmGOVN0Z&$*l|xZL{M@lQ zUmy??)ugE|7F}|oT4}_l|Adw>Od^J`k$O`^-?VP*M5O!v!5qe4KtYGUw3g<^kkkEk zi)pHp+944BlgZX(XX?qD*|w42*Y^#6k81+hqrIWvDn#Hh<$CSY8c2{zFx*Y^74H1T zrHDSRWG~$CTEk^@<7zC#>UUNOMOT!OvmjttMP8DXH4I~ zd;p?BnfR@TwZHloea$}JJ=RWsL0GS`C%6Il0Wh;Oc#ShnskY^F&2^J4^wi4eM1JP* zYp=8Xj}9;7mIk^wtVG@YNUL@Sz^Q}#aZ=|`(&c;KBno@*c+!M4aRcbngt_>beVUWC zqqU<$@qOazYuQ?|bNkzg9_q{#dQIR(=goKo*N)5u?L)jfK2Mp-Mw@oFQ9-7iv+Fh) z_uUghZX458b!l1Hfw&G)ga*rhWK>k|y00v$8v%IgGluxKf|n{*=9br&VhOP(+_s)W-% zfkP?bFGtDSr_b*CzOumMdIQn%qb~O5uJ%kN<;&aMhjSu>nV9j z0Wv9~ym_8A;%QPe7iW)3789l-Us-3mlpRxbULvXTb3*)rHW0&20@ zYuz;0`}g|W=I)MTg6?Pg8;alXvueK)7#eg1sxoz2zFtWHC-ey*tyHfkAS@snxd{G8CjIJFj20Se=OYkr#?oTA845+|veQOmdXzb5mFb6GmNBlqw?%yB&a_mz zZXFv%B27L;cpOcw)z&fKTvjw%s5c$%E>;# zIm*Zhrg6Fo&D4-*c3&(Ij;#?qVaoi>F-ux_D(Z4vOZh@G`7W#jU*QJH8o8SsAI9dB zlmZ~mL&z@qi(6R-D|@Sej2;hQ%+ zNW0#>09``VsZmw@Jf&fE6gk$VQB`Wa;K&0q`q1ZWQB|J8Iui8_$B$-pd(Clmyv#Ch zCk_%eea|x|jcuV?7KDt4aKHtA%l+#3qHOI5Fny=mo(6*0tuh=+=wpp<`Y0HJ1+QLt zn0^X$b|kHvv?#42;G)fJzaTm?TZ@IH+5lxjS-C)K_|Q#c7+?lKCoDWLzf%1PjgefZ z9Hd{VK0WM0m(s8B6BJze^<_;dLL2kQfF7gPu|77Ey=`rFI8zIE@1Pp7!=57uzY7C+ zP>^m1E4#Vs?^wT)wF7>RD@^uP?#`C2jcEONf ztZ1u<#m<2=X%rTF&8i~v2VQ%r6pEZ+sSTFbEw=D=0T@mc=^zjEEFn>hMA?W{k$CU- z-ekTqNc)2zS+5A^($19*%j`}?lA(>0n{qsZ<=}4Y+L*}8LFEPNcrtgixRU-@WG*cD z-I13%ThP(LPbAo2lGdNgoK7MvUzBvYqa|VJh!Y!Os>DggNVJqm!$>mdlGY+hK}_5Q z$6N?>*?dXL#1RaXHNuzGF9>@`IinAGYVHcOI~Pr+ ztPRdw7shdyXbN@_Uqq?Q=+Xxov_gz|fPK0q=D}TsE6fs=#Y*_+@Y4`NLtV;5_(~ah zu$(5xVh=?USBR{+cGeddAS4C(_Kj!0$P4Pf{|HiWgtx(j!gD8#ri)v!GeS-MZdZXh zc`JW6%0W}?PE)*gW#B%6GFfgwbRR`QVj6)N&&A_!HOxZ)T^1E&T~y$e;u~`D zY%+xpx)P6H7Nv<%FGXB&j!G6?%|Y7faccKD?w@zqD)!z101a)fR8L?mI&gW>=|WSz82uc|Z2!f-jZF#%JK{`_Tv=aqXt;qiM^9GtOQ+ zW*3C+O~|Lw)}Q0v{i=R9&YfWsZbrM(LM$+XyH`9Uf(9-`ufe@1Cn{$}ThokkS#yO2 z<*s+fPaK|7bGmLk8{#L>y`O*Qm??crRes>#zP-c!pS30a9n8f4y!?mpnQCm+gK?7~AN;iy@aEz9N+R}kmrEAwRs0dR2GHFI{wA<@_w zELQV#HTlBAr6F{1+t|M?)=Kl$gtZ1`uy<J;wUwCnB9!n*K5u6rrl%ctu1kIz0;eOXqy3@ z1l+{SI0j9|O+SpQKjPUM>F0A9UWvEEmA42#Tq3A9wilN- zdYpGtRw&b{V@8;MV2C?tO3k*!n6TUQl4#n1;r9Qo8H(SUa~yQJYEM_a>mcEnue`yH zg;S+bR(RT1c9|O^KWGw!Uoz#Tk_c$Hi6u+4{_Zk&HHk=UVw+FT#$#19_EezGg~yG{ z9*TgHA^m(Xu1>B*C2!8$#Tg1<{;jG4ztEy`a*c--MKKL)tt7D}ZEP5>Y?6s|$-JOU z;BC?&JFYd6Cy? zlJXu>O^TlI!y;1TP25Rr&aXfkId*mkN_%&mG;k@2{$xf4OxV`bgwUZ)e5M*hQf{7v z>zR`1HAFNZbFM{`m8eXK%|yD0e6Q#VqqSLjJoZ-d_Fm1$wES|huxeM zKF=7Ae+HaT9SzvW=Mf@*wDUT`Ya_8Im8?Oktw_`LcLe=d-I#Zvv{82^kfKG_>3*{#x0Dy0%9byV{v=JWnp~d8wWPGfHBcc(!C`1Q zg5JT#8YfS1rY(;rBEf6?$mPzzWnwxJ=dwAv*oD59uXgORtk#m@+KDU$5}9_RF%ON~ z+!c0)FR-bMF9;ga28kp`;C}7e)@GvByMLi%7|>agad2D@2AVNPR`+4lGD*uwU>v4~ zS+lWWdxMwLYYLZ{OH7>UrZ+DFZ!?B+=<%X-XEnL?R2 zG!#lHD}Bpa!x62L~uzB59u@;NG^SNW$J;8SCm5zV#inMND20POm} z0Wc%9T?8-eR~+m|#Tz2PTpNk*g0ui$7%UT*^iXhm3D3gu)d3Sd6E3?+LLMc%NM?4I za3+dS-if3nKeJELcklpo1x+j>`ZxfQL`Y2soUUGTQ6TQRJ@BoR^ERunB6;zs*DGN~ zX1l7QT%#vQE~HZ;TYH&HWxDm3gp0%L_33;rf-fySgGz5U1x=NPdw&MhF>X$YMGB`O z26gmBG@h_k=d@=q9B<*#U1lu9d!6^t7$0(qyOJ3FcSSMm-UWLQpK6l8 zuOqD9`Je9Zs-w-%*)bo|JAq#d_TRp$4;c~@p9%0f?|QjxMsA%+e?s61KNrSyJ0bM* zk*_j`GoBkGn+~+1;+o#`5k=fZ#Yv;`G>z>VGerZ$8*gcWBOq!83yx@0VAqJ z3vzvOB=TnIi?k|(hKzA+a?1}l*)nMW@N>&t8Y;wH6{WG_21QOD>?Nlz`Y*7@dLT{t8Rq>~_T?)a= z`!441yELTSlD@6ZE-j=9A*N6{{Yr?>rW?Q9*CH^8L=x!e7ZNldj*t^tkH?2eZD$iF z#e2Bq;1h7C6HODgQYcaryQt*o$X+UV+`-3b-5tQ*y)eU8pN-;XSJhXm6c5hK5O2Im zm*Yv#&a3%|G;UABiA9%8sSuzO%WOdIoV%pu5LQX@-R|+^`%+t-Sq}pwn?HaQ2(tLe zTiD!)`wJNDml>0SCx=Xha_sdfF-4&yS~(YnG#<=Y_cG8OqM!71AHX&E5h~&D4l{&bOUT zyZBpIGOc4fFWs|#@pwUIk3pEzBJfVi?YD35qa1AfzQ`C$J1gkjMu`W*B00$u50VF* z=$E9~R?Az@I;&B-k^o$Z0YcxN_D$uX56-&xcIdrKJ?TC2BRD2R2u`3tR1CgZo_Bt2 zZ@fK&dFwpFd-p_oed4~nyWhXS96f9wJ*4ii=054nox0!7otloHIvzdzSx;l97=P9- zSuR;GTNd^g+Ydv}PD^~mO9D}IyPp#C^>2dpKB#;PQQ_3F{nR&=HCQM(vSBl99y%NN zKA_9{i;pL;xiMKipF}+Cdr;IwvB-ShiY#JbhP?Gea-K(g>~$6wOo;S`{?Ab8;c9h4 zT@iI|aF@fEYot2@m2N1!2disjK9}GfP>%H=UnY0~+csmJ=c%1b&=<14Vui^1&@ZU= zUP}h;L1U%jbS12|6*c%MYH@GZlHFqEPk>*1#X2e%ta9G*r8~7t5GG*6rM+P_V^w__ z;Jih#;VFArjP>W3W?P5lPa75ODHEsVPwNhp6qPMJ+!U7V5JP90PZ1$~G_#Cn`F(}* zfy1QkvHDn2pL!C)dZ_tIZU#?K^O(?4;U#&YV`*#B47o5cvcWG}X%_<~vccta(vJGC z%4r7!5nAdm%4sJ9?{rmGfT_&D;6Q(QJ*}(R+ACiXxcX$ugvtC#G|FTZ$cf}MvPwp^ z6}=uPY^x;8dCJv7?Uh69b|BB=;;`|_xCA&3fwe#fl9(}>XTL6J zg2d=HQJWFQ^`P1b6Wml<4(isutgVRKN$clyt6_p87oy|k0+H{c#a1ZP#+~Z)+(XL^ zN=_4&L-^}t3k_mhl&REa#;jo zK|<8MVFH4;=ab1DYjT$6EG|rx*gUe50gaS6OOa=^Q|<9BO{)nU5;_TIbu7<9J@)q5 zeT-V;TloHsZe4=YWGRl=2OF^V5?~)zU5;rqij6(3-+ zW7;;QoruokQoGnLIE1lHdm*2Vi4FXX?rUXh_Jy4CE^3=gj&qmEMA@2{f&>ev#$~RU zLx-D`C0V|3h_DC68=DceJK>E7&$8sGgWYm^xtV@@c8Fe5+G7FArrO)$PXZ`(O}PBX zPSZ{BS*sp#+-?vLXPGp*Z-r&GP$_?Eb27GPlQ*}=+>kSR`$yTSD)`yoS%}x1MY6RK zDu)Gf2{5`bpi(rQ54fE#Yc~pBq{y%uhrhYFzsE;|nx2@u#1yb2FFmlVMinq4(@ZWt zMj05As^^rhvqmuV&ZDc_vdjuUqnE0MJB9KP-AdF4?*JJeuq)}9iq(a!*$O0=G79JP z+_An0XQl8D6yA?M$9O@_POjc1c;VGf=bz5cv^}HGw^)w4xv0uyb!h@*`IeZoKbdrCGoHa#eAo zm_U;)Rk6@F{Qcg5=%zSZ$t;=EN%X_KpH<|rR_mbJ7H;y*<#YhAijRt}limY5Rzb=< zkGS_e%6MIvjbOSrBr+gqg5T~l@AHsk8c1iG0MKkq(TQvWN{_yCeP1QvK)Q~TKAsAE|NCO}R z!Ma}pJh^i)XZ<58@GZkIU3$YV8{msY&e_QOe2kF2c@?!?AM+U z?r6>7(!IsbCUkq>5+IfkY8Cwo_+0S|cP@0en6&37-H;GK1{(k82Mcp5tJUIg%4Q->3N@u5{` zY7ZKyvvpUxN7O7rwT9{2%llm!)~yyFom1Xo3^J837M+7tpScXzmq}l&aWJw>)@g3+ zv>NJQz)Ja_D?bd_v#_Q}j@7xWZ=)AfCZF9pXaNgD4IyL75F(9A;#S)K*%X!T63nb# zqCQ(NTIx z&XBxo(p?Agw`SaWjC~-*z6cKvhuWij`8kV|JN|-|!taqAjiG@cB;V7DFqTk4XwPh( zov=n8x-RcMo@=Ibd6%LIk%Cq5cB>x>%zr8X!f7z^2}4*yeuk~so_8__u`U>Ta|wGC z$<-#tJe|LZk5aPZgA9@Ch|3BkW(`=5qwa|73_6aRTZzw?e;3aGv4t>MP76mAb#%8#U}O4TEf1JB#em3P(xO^rQ_|WzzKLo9v@Ad))kwT$ z`>Ld~5fUO+hu7nAEzxI5iQnz+aMaLNr`zN4LWRGl^#}0u6e?YBHv7ZL+fEOAdf{d=HtjpgKfKiVEqK#<44>Zx9I++O>w-K|0++v8t?#CGKlR; zyKNP!1FcI=e_zk^q$oaU%jwAhrG4^mU0xm2xj=9*%>h_Rmu&~ks15(A^rvo(LLJ!e zPVfr&uPOxl!WGLZll6>Bi|~}mS(Ii@$olZN5{MvnezOl6Iv8F-u??&ZSb=tkiEww#<)I!jeCTL5Jip zi#@fHHQIn_HE&D;K z6Svz6U`J4;1zD2bCQc=2Q2KsIGG|(z3R2w6o0<}v8<;?}03MH2e`W|M1{iben6`L{A zgU^oMJ9yz_;lR~7;RNnXuN)86OAYnGHBch$Rztc+FDheaG(aFZAfXMfl73g3;MYs7 zqWRrrKiuo%YoVzaFGh6#Cq$WSDP8G9D^vF3JRjJ;BRO7zZ&Hvxp1wBudnIYq8Dy>` z=t>P~)&de=B2>2IfXfluC&FJW1(d64{T=k%x3_;(s%ic=SnA)m%OxkT>)^1Xj<7<7 zg8(55i3=?ju~tLLRf@zEWIDc56e%{ z4W_@j#k$5AoFAF4g!!8-23X;UX$T&RsW|cqg8=|4NCj}5Esd&yCFZ9|E-Gc?33cE9 zzeszhC{Y$ATeNJgvTfU|Y}>YN+qP}nwr$&0t8Cn}caL{RpYGSEU-$dXkv};D86zU* z46rRnX|ntFP~%@O+~>vVI5#JO0Ucqt@8Hz;dHB}J<4)M^V&CTX#_5~#;hw^a$2NOP zPF#D!SLPl8SN08pWC$doqAL7Qksn~00hb41CSjjBd5B3IGNF-Z${aAPB`F}?2bs`t zvX+85DhLAdLidC-{G(j+Opyzy9Q-q34oh5m(fu)g$JLJy3Fn|dPir~YswTk==FRMa zHKX+tsGT~N64GPE5gkxGh$`<{T)R302|Av6>^bKr?(fWMXQx6QjSpOrgcFE+;l)wd zi<1wJMPKXJsl1ix`D6=E3)5IvMHzSQb&fO@S+nlM_F{D1@XY`^L{Qp|QJY1la!8Sc zbx;G-i_<{n;-j*i`9F0iMy>W77j~3vj75Liq+YU>W?T;QL#^~h_=}f3`{qu~$6;92 zs#mLBJga{lCeyc6ife^cKD8yzJdF;bN2)B0&TDigD`8dJ?4n0%HoN?OKJX|+T1}X9 zeD=&HbtuWn_!B#hr(12K(irWcBG#iExtb`_8O%u8s%~9vbeyex)VGVSuDNcrwQe;c zz9L(Q=DNCBO-swr?fGq!P-O}o=M4?sXxGxFtFfUwQJt_*SOLO{O)#joh2 zAkEqldbg-d7B22X{1$$MJ3dR?8}})3k2TaL;E-$-LoCTC>kxg!Io?V9C%#Me9&kLA z7%$#S>K<~ulsGruOXePQJe62C-b?x(cD$8%H~v%R9(+8P*f;)D`d&8Vce=i;@!BHB zGfaoQ2s>Bo9$B`C=3{LSi&5`W2L>DU5wickzMqb4$dk#~q|lAjxaM z*`4+ywI;AN0)7qo=-MIoXohDNR#kOR&qm~IV@!l&_bZTPdD`_b+MPD$>boaVPvK47 zzwt~>t+mMm{*l|5{^h3Eel#&dn(^#AulQoqjwVZ z7_vPdO`Y#&*RH!ZIiDXNcmT9{B?Reo)7F+^H0v?fbe3}xkFELpL)jU(tKPlxzjk!A zUo{KX?XpYe=q*$#scJrgrSH&(D@*8Bg4I!U=vTsFBP3&X-LYG>M%k=O*U!b&35eB6 z0zwK0>bEM^5S2HPQhW_7tDfDR-$mxgM!6VXOf9?BWxQ-|(uFr^QfjKVTZIN&wM7Tj zZ@P7@z$_`BtFKE;SuwLVroPQz#zG8=(4YsUuL49bYK+0kiCr?SdJS(7O@}TCpGt%; zEucy}PTXlf#_UG{8@ebyy;Bw)R~;fesZaAGY~QO%4PDPIzkg>Q2t|HzHkqzy5=I-E zOBLNIVUDt3Q%P=KlqgcEc+I+4q_P}M{HlbZ^b>iIFZ_i&w{#GvDA;)xJ?nk3_M$pJuD2&slymIFbM{?j{ZQsh>hbO{B(b2Nj7ir59|>63AU+!VoD*UE8Q-qHf?GXqfZzi+qhGGt=uD(bd6o!zlVBq-X^W9`Ap z8=9RSv3XBzzgzE~9;)*n z%Ct=qOt%ydW{hn7mKdCf#HELT&j?f>W8Lke4L9BD%-XUqPSWc=qHePe$%46~5oeSy z*yi1lJhI}y9z_cjvX#@V-<8lWkBEu~f8j9n#NLsX$;H4NoFSJUuH#i);e~zanXzt% zYrD+mpqk0@D!x358vHQFd8^!%kEGgQf5c3Dr?2(GOqcus$6qB{Zz-+AhkuztxCk_e z9k9slpfrL}^j;sGDRw+KJ7d>?p^i}y{39mCFVb)E^eGVm7e zs!|50eKi8PbjV5DhduaPQFWIPJ-M;`-t*et^PBUT&5ubcKSOLNDOJmw=GB!Q%@0|8 zMQ6j(IYLJZsWMz5L7-##7nK%qXykM*XmQMC$nOf)%7&>nX@BF9j-`{O2Qf^9L93Dcmo2XK8F^<$JlD}n!lUl9Bk?U1&Di=}T@uya zdukPp#jU08y+O*K?G&J&{xBKu=RywHYj1gfXLS&`caeNcN)Rc>8gPtaWs^UiDZDWg z)rG?j>2eHu_9OSPhtfp84bkb19&k3Go)S>g>ZQtp-#I^<)S24HGZ;IrwWtln{&Io+ zKvhLobV1>zQ9)O12{Ml~HcCTyopyoh<@tNrmV_kWu^12l!0caAB3b`iv-2A|nY-x! zwQ~C(=#g>VP(b`JL1f?AzQJL7w#Ctwwj^b05KsXtml#gQ9LKD9;B%H*4u%`2IIFLq&>(z2h&p|Cc;Tmj51| z|97hNU*HVzAq1U%M*f%?TbD+g+7{=jK?DSRrBi!2=n$`i+-9I!ZN+dH+;2wGS66S(>a7d_O zambF}ON>gT5CW!4*D#ilvkcvjdBsbrwjhskHZ972j_&6l zGj2gX{*c5r(EGo$N)hIwZp3xU2ZH-oc#78(YpH@~q3&o*EzOryf->v;g%igbrP%O4 zQ26~Xar)0n0{;;w0dpH8a~sotN1e`2n6_E`OIeSZ*G6%%WIq>73=1`yA`O-b0UCif zvJ3)LI5;~oYN1@Kvzg4_bq~}HCa#RKeh<)%d?-C!+#CrJQaHW+e-zF+K?g8&B+|q?Kw{|ra_W&a=_q<+-NUR&Q z5^Z|}{SlGav>khMl4>K$japRw!_JLcd)dDuJ-dc3cy$iE7q#@7%L&_=*w4m}tmhz$ z+xy$Fg0Au9NoOO9Rk+1E?t`I7Sj8OP@@a2J9oND_4|Mj-L1-U*GuN?J9Jf-tJIUIP zt?>%qmm}EPYSu(Mo4N|$ezT@8i#Sl{!>pP8su!LLKnzPJMUOCguR?lNpS+CmQZ*UImhgW8#vY?%jKtwyTHPjyyRw;q%LFG*9 z{N0VmQeWY&xx`5XLc?)BB#(DgcvvWj@Ni4F*)nNjPdepeT9cIw8xzqXmFRC6f^d7QY;ojf07tR$VNmZL}>;B3Z};&RD9m%hzljQ5z8{riB)BPg?B;xFF}? zZiQa2e5Yw~n~mBr+C2t$BJK$XWPM#)V~0&?qie2yu9Z>Y+8?vj_DS{+?Vnr^^P1Yq zyax`cPh)yQO_}ExGBw-)_nZAAAo^j?kFFC2sd)b0r;Dm*f0C<} z{!6=4_z!-Q+$9>24~Yl~rQQL0D<-SRVZfQdV9y>%$kIxa;=$|!N;vf42A;7OleL-| zko5b8tEb0~)W_Gu9poMi7tBgAOpyf>J8(X(5cVX!9{D+`R6&nkSxi^`C=!Xc&u>)! zjz7^tx(rtrpUI&Xn`3iKODHBQxxv=OMH25M^NzUq}(K^Ah@15V; zXXVeoHsk%08(0QRpk=j|PcyntrfnsS zOTlc0Y`lX0Wta*72tt8>7{%dVk{JJG$L(*!{8!=%5p+W`y?h3T8=CKZ0(A&it44D{ zabq{=kE_(50K5`gWqL%cj{95b?MyGDPhfgctoc}%T9rbjp3OVM*bw(yS;@wUWYib<4oZ@$tX9@Z#k(Uh-ihV&X@4O2l!}R&><1(as!bx_~a-y&xv)<|z2$W_3GL^xcJCy7hvVR|QxQ&YW zOTQE1e<<|*f5A|8GPiR4e~2H@u1cyH+on3Mj2QSJq{adXK=)#d1d0Zdg8=dag;Ci- zaRBk6By5S9MgvAScBgP5Erizf5}LyE6=wBf&GMQw$k}oWK+PH(3#l5-)$hPdH61CE ztM}?#r!z-@>0&DqJ&rRkoTpc|xqoJ;@Upnz_eei?U|X?-ZKj+KMc9CBmfGqy_^46q zR8@j$+NTq^K(LedE1K5{vT)24C|y}YXo4$yzEe;-Q|GymVW8Sng%9h6rmXUem2C*o zY0oaAo2<=Y*>+nz1=$;P`dS+0^;TxYayw*UN0x!z6v!gG>gloQ2i=7;OZ(dKoQ z)eNDKMV^AnM-a<5o4=UNnaw>HEx1YO6`7(o(sVK}mSG)R^UI@}U(8@A^Q@%EIu4v( z>~@NZ6)fP<7Te5>yHXfiTS98pMH~FB=XI)iPd7_2K9~#DyFIoCz8rd1_RTMq6{S1! zt><6NAaSQxB*8^%%}GJC9P(s_%3?{v45{afVXZDm?dpXXtwoqAP1VDO9`)Q7-~G!{ zm<>6bp+%cCk;R;ZNJ1V*s&OjB9 zSSJVLTaO&{M_W{^DsdTqokW>yHYeq<7Ho)_e;JloIY57}Wf!txl}Xp@*-uv`vy?@j z$+P4<8T~#{$L-G&t)t-zF%~{6EdK(EtZ|7K55S^u=;1hlNRmEiO%^?rdH$Wyc~f6~ zZLjWtW*oadY3v(;j!N7FxYz+G?cwSw!KglesJ%(u!j)hV_2NLLOjKO&2UAzV;h^z= z`rEihQ97BWVI^}hqu#ejB&JAM(^J8e6`rJhsm%4xD7bytM=>#!2;gz1n@n)ilIDmd z*vO?Kaa8hnM+^`iV|;snR2xd+d}e7Z#Kbo0myIGGN5F6EA$PI~)a8y>o@C1xo^e&d z?OMH<0Ar{NWG}V;X($`{I<5X{s0)-TIRu3|g?>sQDUSqj}9;vfiiS2|VUj zhwC9}5lc3<-F1=b$Omnwf(y*i_~{32YjNDs&(oT8g^BsXn({0I?;qKiit*MgzEwHn z*Y~PS>b7T2Ea^R8?;HWCdS+Nfer|C7oCNpzurD2Iet)#fqBPK0G-dKf1KKVf5Qgc< z>$DqTEE6~R5MUi8v3h{q=L10n>I8#&WUQh#!H8^j^5Nf%yWKioFfZfl1azOTQOGZz z4Dh*61&FzcA%hAperVEeW07yK0ch3i2gBE|27u28lDI;5Vc^;dX0H**yLWk5yH9zl zw1%$@$hye~mI_{q5s3=iq{D}}kK(;NUfL11k__a-FGX$(fo)AAcd!&abi<0ckB8t2 zpJRa_xG4ug$g*yEhiRdu@A=53Q1L_Z6fu%_G!(eUr3TeIB)tZfPeKz)NTj^(=5L$U z*(uCTWfLbf^xjR!OA{3kQ(;4h8ZG9wEGFP%y2~vJe}*&2P_FfcjNny4c&xdYD2Po zOy@6PW@udBv|5l1F+OEFXOsIKC1($&;|^TkwPN6UnF1S$I9;Q4$M=Q}&FV-~X$um4 z^MQQ(-9<+o!-TIUfAherlF4JoA?23VT*ryR=(yAIRqt-IhMB{iqt`k16Z^yHSm1Rn zs5@F92k{s{I82Ecw9f^e6U#t0qpSs5C=|pPsqup`CjemS=Yf*)@K3>B4Qjs9tDgX6=VSd6fDOQKd z^M@;}$|j%Aa$agCz}0?_8qyt3SjY}8r}PE7Yd!KxHdRiN`SOlYz9VY$mhz!%T&mWP zX-BW6HGGY0>Xp|1J23c#cBeN-thTkT+8`%0tUAyz?v97BIo&fENuSFwdn);a+WcH0 z>lam3FI!n73B6!6lqgzS-CuBOo zheiJhB=wQ6-%qiBfjh=$lQ)92{{^F{XnJKJU0&H4HKS;kq|-X)T`AP zMqKT&>GevceU9H{oHR@UzFZFM0Ta7e53g?oR>+!KYr>Ypmb8KCzRj@J1n>Qt?*Pna zda76KURSK<9h%2?GVv#tH;>-Yu6Ttn{e3R+Re)k z{;t?SOJc>b7bTp>tN|Eg&qS%p4B6qH4CiShWNpAlRVh9{M*>kxmN?>rD?7gj{p!$8 zX{;hop4Mo%5^ta`B(wc1Xm2RC&-kBKA~_-kNaW3G|BY6Vqo$HHdRRO`es}pv$f*hn z7xl@8`*ed>`Bxxe0!U5#OqxKn4d4b(hGDhJG9n6m)Bze){SdV%#Ci~v0x;-d1rQ;c zlt}!R2;()9i#ei;cmyhHZkw4LEKM8LGo zTYJ$^t*WeHDpNZRR(pn;@KuKKKUIM}(Yq3}|E75|!7$AI0|5ZQ`0IZrknwjp z^h+^xJD8>Z-N(RoiA<+dbliMkTKS;!qrm$!^86B2d8o- z?LqSUk0o~qhKk1`W0Os>=0`9Xkf$VzT1D0$W=+v~^oB*XCGSwbB2;1I{Fl3l_GV$> z4ngBUgH{oVl0XQqUnzxu#%CQsSpC3a0l!rA26q7JXi2MvZ6awDrls#a%m}bN%8E(D zLGgAN1wyyj9lKzoAF8-55|KL*PZUJt2e(E)q=jRWuisI*h(!{+U>L=!w8_&0`X>^K z5M$p4k!?s@UGv7VNA(w90#brsWcR@G<3yXr>~eVr+f}2vU$bQrN*ku&)At!@e)JuOe2v)6es*g5$pFat9qLM z9(i5ke*!;I+jfH<`7iKA=OU#I{OfB|%F$pJSTLbcAS*pk(vJ|TI9*J*imWz#ckKl_ z3#6+<;s|}aX5D8)J-cOQzX0_rCc01FRtC)2y`b+<^%WYDc;YwKGR%XZmB*vhYmNdf zW)zdanDUU8^nS|V$h==eHsU};b`W&hptlF*Uyesn8&pw{t>6{Z%U}?LvDWPT{ah(h zP}_o(P>T1YN+4KTH%S-#51W%RfrYDShyaPi#Ve-|EBmejonJOJG-JR6J8FKftUV{q zfERRIfj#J5gvS3wRPm0fDC9BZ-FXhPko4>TQ;lm(tQe`)VJ3m4SQar=W<6;*P8#ok zJCYkgPqfu%)KYmWb$b>n`H!NN`A7-4BJv|R?=KQV75GH9!yQZxQ-)lQJ8(cA_QmSe z2b~jUf!fzWm^%X|-h%aj>{r2yH5ZDxsam9hsvpQ@r;#i2g^M`lrjXbTzjaPv}>ey{gMZ9rwp;axO_lw6x>(?ld5>6EsO}HR7Ovb%KI;vbPr334$5^y_VAD6d zPq!c+5G5B-9WLT5+--I)=m^y%=+D@?`Ou!g(W(rl-#H6FlII6hJ)y)z?MBC< zS!`VpZ+z+~Wi9+laa|`f3R@$ZP(6X@!5V%^h)Qm*k~LpTGqs)=fvq7@!lvc0QDheo zu;ZFkd}B{bSE6+KQd(yV%3N6-DfDuF36fapS0eZaM1wshx6qn9t->jT2t3u^3pDrZ zHFs%b)q;b!AbEm2uv0_mXRtD7u=+bNMIMWW2R7@?k@q>*q3MV|Jo#1j3%G6!VZ^c44lCuyPyli52o0NBP=^%N@zTKA4;7#oB)5#o2`V}{EBVU%;Z z0>46~;j$2E8FoqEuO_}(W#=N;-FZ%0|4145o!1}{9E+|mt?(;n$l$fW1(0Gvm3X)n zM$x`e5LkbuxU+#Hg)$I*GIPf>rAsHuK*!Z`l>l>HO z7JH`X7mVG z8TA7xsf0t~&S^A;d;0QdiXQ%~F&Jq;9yi1}t)aZsa_v$>WY7;alRE}zkrAfyu9vz_ zB`DY*7U-~~VGrV-+8Ho*V$TKwR9_Qo@QP_s%I_(3keq`nsUjVDQ{oGk4cP6zE`NCM z0yuRUN5qD5`{;EV*M{QZY*;(HA|!Vd(i;ZRoRl$cXblUTY^f=WD?=z$Ux0hjty$6L zmEq2bl=f8n{t#NfdI$s zf^qgfb^4OM$G^5PE%UQfG(ZR<^6f}y+srlPbDG*C+s8fU^FaB6;t%*f2W&{;I5}?i zI&c8*UylDn2UL^u5692`|LyqybhL6hN#1so6=8Juivn(D63i$jMXjNW5MJk?Y6FI= zE(sMB2EEBCp?#uAM8UaHf7e@7AttfrMlja^y@`0|>(5JXp_j`FSEDXKTl{q4!SYI< zF#-(1CZQB&%Azc#WTPq6zD!GjUWnvf63Zb6R5a)u93}l|mCY&kPX0m?P--B6PaWWw zP36xa7TrC$=32cd!UA7qyi!|8!Yafo$LI(ETHK_zq9dt8&~G+P)$&CQw`BP2h%Iyx z$S4KO4yxQxAST(f=SG&2x8nnY-d*^#L0mCq?Ij*H-Km7kbMEYKp)*-?_yUn?{(W5< zRU@wlh$@1nENh516VEs(wc@zvsHQW|VOX?fjZEmAmp9U?N6Lm&u{raHH;ZN4_gyF248$HG!0AJ#VO-H^9 z9OZ%8=muJd8i8wklx$CwTrWFu%xBQGh zZT6^ktLx zBEK@-?~ajR{a&y~<}d?C{?K;Cd1c(UR|t+A`c&U{bI8R8M@t?}DqtslxA!fchO_m0 zVmU>@Jk@EH7PKb&W7~MO6Z_a|{yhDbD*8Q_OXa0D(-YcgIde<=;CLi*u{iY-`RFXr zx~u2omOKXfg@n#6?#-1g-FR*Z`1AK3qjiV*CNwYr06fJ1Vi+J}D`0En{-4i)L@R3k zt%fAyD!FO>i`?OtP?;Eoa;Kl$;DsQhSt1ysgct;T2Tf>$$vVk3#R2av?<=s^9jGn3 z^y4<3p}|2QyhWB{2Mw!$0b6!DQ>txGdgI6OOQ zg`5Rbs;UaRri;}o>I*t&L(lvdUsyL`?G2Zf5w7M3Dlk!yT7FwghHlS~9fhu%5royr zm@eUwf_G+q<5hb=XF=a~#G3xu;j+cZGb3%S+Q80f%%51Lwz1`Hnovce2DFVyqc-x2 z7ES%LaN`~_t65`orJasC9LMCW>!nx$bK?Uv&e+Cd@D7$Jt#?yT0Qrr&g4FqQL8#IBY@9hDq+YK}*6ww|3M zpw_xqYe_g>3eBMK`E)_w2w;NjqX=|m_1KfuX|QWtFoMC0CdGS3`@L=oCb}28cJ43Z ziJxS5V_7+Fh^^=yzoPXa#?c8OB;q6XsY?vPh;aHzv{DWt{6QGOXa|xEHu~6W77|dq zXgVfkJQyqn9ELlNm(H!4bO1N>RQp}t9K2hHDlJvSb-cBg@rB0UD!v; z4%xl2Fz+JtfnZwCkn=|4q>`nZ#KF&Hn@Ln!bl|2ADYVt+l4b@`x1Y#?C9Feg|Sx?P-JBDl+#0sFZE!v1_5mNmc zLdF;DGOgMRK?WX~UvlKuosjPOJhgnI*9Dv752L+F(v_Q{{{9)Yn8V1<{Nrcz@-HWe z|5>p6--XG4*z{Gg^h6Ry_F>CpWmeCV%iBug3PObx6SfIZ;8P$BPSKQ4B3W;NJ}14h zX`_fJfS3@LS3(e$M+W_sqyQc3^W^>t{f&kh1bGmF_x|^)NHV^ZD|v z3xK-U1H!?>Mq!uPmyI}ZN9?OqI|sY1Ly_;&ZGF1Q^1!Fkc=|^fz6_BVldySC@P@^L zbTMo4dXWWku)JHOx%nw0V}8m&x4c@8%Y3bPR;)vlg=RX1o-muqN|~)nLDhL9AKElb zQb1c|w#m|ksogvzdm)OpQ*(fPTI`fjBQs@Qn#S7JTGHLxB*lPyL&&#$`dQ7iMbEjG z*2(2QYp|2KbIoQob}q~CtTUZZX|ctm=2*UCUby}2eu%-Kuj$w>CuAj#AX&0f-6FQg z#j<|}?aF0yX(`9xkBeff`$C!x%c+Nl)8-0elhlm0z${5ZwIzIUb652#3?!1I3Y&Cz z9=B0qIhOH8I?1KVAmz~mN8*{Jq#c9oFB|pcGYR5G^=irKmdzyFRMBfc(aW6fBss{& zbtiItl;gNFQgdRhceBMRubDct<3=xRwiA_8#!&E6Lyf#$fYhvIm=P_F0eXRE^qeh2 zdGUde4MCpe5Okr8A{eFgj5rmkE=d-+MO7VvF~ST?NhU^1X{OPMBNuTdV$ezfsFYr0 z>RRL~C<^-Jyf41p<1aqzRiC|@1dF!mW^y&;CXxUM^`y$W?dryH)FTIfV=ZUCY1A`G zPB9L4a%6=5C5RGX`riQ$1hjs8OaO!G3ccCS{gp6N4@bGWD=+rUW#nxvl1BO592CN z?rW0P9Dc5*o+o2;cTQi~-{mRMqcK4*>(u)f*DCaQ##nI^0>WXGAt=gB)%xn<^r4JE zr6H))rs{(9Nd!?ik)`@%Koik3ZW&z>xC2#@xhLzA^od<4&|_3ls`SG4SwJVzNex>A zPV*?k2&cU=0yv#0(I@lrB>Nqlmh(`yVK@hMLcHaxMnB|e7`mo!;Rfyh)~saj zw@cs`x&<5zbz)^%{Guf25Sd&wuZW1G(dbb)yTwdjfVDQvH;py1k$<^0XVVaK$+Wom zyhbm)ZVyObSvgmSRWwhh5M$;?C#a$L>I`bDI*<-VwXNXnE?ra%hH>95UQroa0*scR@(UT}NIGmRQ=YCh93$yK%@iy=`SiBL z40%>(GAI#5S+EVQlQTgB)`AcC9Kd3?2-7D9nd+d2I#?%-HEM~yWbNIw&LJ# zt+PQ08-1az6`gWp?^kJ8hbgT8F zcJuvzdK)Hpl5t+N)xG7I(Yoie+=Q5^`8vpeT9#>S-(*0OY5}ha5jxyIQ=cPMr%Sz4 zMc7pM*n2$&Iq(oY=k|FGpV*$eJPp ztS#nir%LqV5jb0O$aWAsg0t5LeexG*-$y!cCIRzl9cHvUwkO$wsg^{bo?LCqRDlF& zXtOjeg~||rOkeM1ZboNyb}9w;q9JtNEh!#C-pC!?N}mr+)&@PV>$?i+rEXb4Q?Iye zyH@cu8{7%uZ?+ea-Cn(qX*Q!pQ>LXQeLZ}dh_@_tHZ%d7q6zVAG~R!p*Wg_Ra=zTj z{94x6;hp`BTDy&0@dQgisGiwui{C@4*3{}6Y}}HaeIdGpjbY(;AbH&nzZ}Q7^sz~r z)n1Kd6e_VW|Li|Zc=0$LH+D>^T^}_%l||i|epDq~=MvOEManP#TPM|cem!;x3;3^mY>R{|>>+E1?>`133Ev0B^W^AobYvg3KtZD7I$%^>x^^Ibt09&onV9@HiDk05S zb6t`lp0%V>b1j+{K&?Zba2!c8{W`i!y8{@|aHYkiNWzo?L0#9m=3Unb;QMO8PJG(v z*f1t}zuDP(#HrJOQay46Ok?T5O}gs5KIE*}aN)OiD(IL<%8)*zu0j?Wlx%o!#g6&) zKD}-h1l*6mYRaqI#YI9!r-R+gjuA~un+v({5-E&G#!O=SkhUV86FuHg6M1LWq*EKa zvWtCud<{`9!VY12WTrDaZufez2X6E@N#(*uy8C^(OGZX^Bzb?#QN50S`ep-ygoBre zwi~nm!`mAwBJGsE8nrZ8bl@ z(Lnx?yvH?*uAiBP!lFz1J#{jNLpP&JrG_QY$kESI(aNVa2g6YYc2rV6?weU5a$=}a z|BqVNvP(D7V;mHbIuH9TAW_9A+PadoI+4(rxR6Q(h1tZQJra?*&R-|M++;oVoD+bj zwaYkX6xLMhj41v&<(Q?t(43JBlxmuDhqTRvL{S55U9O;LgqMYiiN3L-y<9DNYv9VD zsVuC`pn#GPl*S+WjA|(fpp=bzdNl~OZbUd;jyWqU_B@=`)E;U{0z-QspJL7_Ik3f0 zWrcZsfd+~gEMK8ULXERkE&m<^Q@H^sd!_}HoX6NhI6fUc2s8xC3rt{1L9r=GWb~vA zYB0{}B#{9yG@k`VUHql3Elb+8HxYMTX|Ubqy`J6?2uR3h^SVbFEu}MJ4w7CK8@^K6bmAZcNk?L0JQmoTrHJ z*Y_!Nur5HsZ9B2=}3zpsWi{Gn;R0t#>U`nE`C~ zwl+kx)U5rwvfGo~;l~NLwLFUWx};oXcsq0HacJKym@=0gQhIdy6`?+R&dwjd=gy;3 zmb{N#WE%fl@h3$^C^ZnvZr@sYE8r1qXup&v;Yad z#Ps4opkP>sQo!Wl{0RAU%JK6`a`mJ*dkg8mXdGQsHbHbmW^+&H6ht_M5P|Wz4lIjX zxZq9fVEpRKpbcD_C5<3l?CXfu1Or9dl*y^rM!Ff-fMhUC(zuM$<`&mb& zrDOfpa~c`j54URwC_P+Ud^ov4ds*w*-DB`$YXbNC>I~4^R}c#Ls6oyJ#8=bDP)|IH zm;k?V$+wH#KhK%S&LPw^6n$YCSclxvOAi*yj{j6@&WXX3X2*FhAmR4+Qo^UX@dR$; z-GCu9zQapn0aTpb#)1)A)s?<^C!YWD)&kr8oFy2kkc&IJttzwYvH4g~1&2e>0`x4sWK#o`9jJa$Zp zctYdAq}J)F$+|`e_`b%B)7{+JjCAc|rA7;Vfdn)u#&Qe^-n_4!kbZ+_BDLT)bD~cW zPYC*z?rpH3Upgl#(4HnzYvAfT3lNpjDbD<-2=62ty94pLm(W`&b)z)7Bd)FFn5L4> znX`|#J62VZZ#A6l>fyW--nJC&RIIcDZYGq=Cle>L20T27*XGoVSK7CeoorsvIST^( zq&=MX78k}}ehzs6X``rFpFAiBsZXtFk8ia=?)DUlfE*v**05s(UmPMJ1m*1{bO=`@@evbljPS*}>LMVJ`LUP2g?l5(gC$*nA$1eJ z%yvEXzIt>xGod_qgmc4RaF1Yx8Q5V|v>(oRxO$DJfR^0 z0N#4;jxYk^A zBo~)NNKJ+@v56bZGG8tCPi%lY>)LJ=c>A{!A~M{wPg??|&}{aB3S31bby!ctZ6N{S z^8B7V+f&iX87*1y_S5^p49kjST7ea}tJJJkg8*vu(-xrp?#t?kW}W`v&|~HjJ7^vEPIx7G>Y5 z`mpIQF4;?Y3Sqvw({vM_z2sz59Qs>6Zhw7@tVP+EK`7Kp;Go<&1Y~M6_#Ioe0Dz~T zTyDk_c~VFaGwzNdBNNCl>gHZR#JM1~9+0A7ux{OLS|Y@CuP+0<@cy@f!x#Va*SasH z%@4nW4WKNUF3I`_yNv|ZvHuW#r%~(Ykvo)|-QDLuTEncw=VYXk2Ju8h$&Zch!2}xNe-+4N1(AeTMGs^vWA|1oi@Nt*)p9 zI`NyNrFZGDMT(p8Bw{x zsY$lJ8L-WM+-pabzfy`o7Yk|@!OZ3LE_+>Ef3I_;nR0`jTBU95j$65{SueoXUso+{)E~*>iN=LvxoY+L`nMZUPDFRX?ehK5m*-!zG0ko zAPnDHkqVvalPx8%>_0;ibFNVZLCOWHx`DglohwnU6}43qaqm*K1h|k3@yc>{e|Ocq@%VmTrGMc zdLIjUxNM(!2XPvLQ`?11GN=@zyLzBJZI5q%fQhUdYBctzRqqM4$|BwX6;9{rQr68j z#$l5O0xD_p!`5Z*}H*>xdUe$RPF;aJ=3^9A+P>5B{#Qvs#T~Fvjk}~jP2rj z;Wx{{GoH!$pp)IC)6UUMZV34b8=;*SkIT~gKL*}%QbEMy2H>vfFk;bVXJFbbi5ZjX=* z`e;)<7UO@pS{pwfr}rI)*K}eBEOaUh4)na29Nq^fdwI6IBD}wj4oJf@cA8f?ZBMRr znseWLDf)qqvhz)-;W+fWCY^?1C0t5S#H6PBwa_f}MxY>ABLbi}jq z4;``Hl77`{*Cj0x6g@swPk#Q?DQy+&oh>%jpm~@R(Agl}3+2SW%j&CXdssP6+KzLl zYZm!X4|<&op1dNLFC|Z_xX`xShM$n_G~|*DmE<9~KlywB_|me1M%C|f$gvBy*u=+uD+q7Q~v)GsXj{3<5j#q+C5~zFIvEk(glG9q$2o1Qp7*e> z{Y=a!dkmtUk8_-gir=a-an!>h;#%j;T$JxMiE2P6o$8!>S>PzJ_pD zlxVWE&ASN!oSX@84|TTP-4@iU<_U36z32bM6Y6_;QhH2Hz`sdH5VqXw#mki~y{n7p z&A-}pLI6)du)m}G)1*(sSc3W6YxTuU@s3Ss+gxB!M>`9aKW+c+W!IO@%iiIWkp2D2 zA_zys#diK}x&P;Hx{2?+(Mc~n06-tl|F$Dwr0=BfCr}rQ^ zN&F0eqa@p0FgD*mn~}tbtm+4sE$wC#w2e4Kx{PM)C`K#jcI zkYU%t3q`}fPle$Wi`IDoG|j=LNH)i`aFl>rc#Hrc+*sh)Gk=v_v{o3%6U8@#M8bd{ zUyK2oU(Bn%-ekyY_<(N=r6M|}Uagv?toz8m0aYHYc?9O4mKifb#kxR_zI|`F-T^jj zxKt@5!!qP(3LAK7fdsgOE-v23vbr!dGxN)5*LY;DCPI~Mecfgx?9_)z?N6SH+;)UIfwZVvCv-plu-q%R{DZ0YSMQ0#1CzZt7X&fW#iBU$d=>b%h$ zSd3Ucrcanb170+85Fz|nzWSpPn4H}lXZWiC^)S#ZiK=GHL7f5@u4F`X*eF(f932uf z9Un#h8icg~c{y%{=luDn+g-PK_#;~yY*Yzv&IrBm78|v@-wXAM-46h8NI}dmS%-T% z(SBf%^-G()z-PFd4%cnZ5BM8f+urW>?%wv!z|C5`+aKGWz$2zZD!@TO5Z#jmQi;-d zVbVRkDakkU*4KQ_XEK-4hlH<{otGUG`h0PEKq2}3VWA~q{zh0aA&Me_5ep4L{T;~Qb@@y~ z__^Kzq{PS_ULk6Ng&0o}#)CwIe52SJ=$&CR>K{S>hq7}B@&#zNeA~8d+tzK{wr%~} zxNY6GZQHhO+qUL=^I~FlZ(_EYk&9Yn#P7tZIz>#8nV$#gZ$ry!|9IqJzh>mA8L}C& zCBt?Tg;E|*u6!ykej%AsbizoZEK@WCo2yDYJrJmwU=XqJpW(?g?7w*0ziQCD3>s(5 z!8u-4np_N24{FCl3`#8z5p7%co;YS=CshCuS=#AR&2f6N;RVX5v=z+>IJu84s?$+Y z^Y{T8i{=bA)U;hKud7+}!+BSU>QIxzF%fQyQtP?tgKaj~#o)35#`4AC_%t!#X@Npb zjH|RIO|vMnM*gUA6NA$0z3|FO8S&yTno8bsIF<sA z2Jc}6_3DjMmWZR&b|gwP--49q(45B_mE0+maZ7589b|jeX!AgSY0G8FA><+jU>rZ~ zR72)pRc#%3xU~X4CqC<9*A}~}I?CN#X7vtEpJ&TGprh{+ zi%zLVcl_$cD$FD75a|;l%Eki-I+fsyOk6}6Zb}DJ3nLH$C>E@7@o?>~ zY8AWxSj#Autt?$&FD%OqMQ&C`VncNhC=T}@%-;47&&;^STE&41fpueZcH;gF3QJ{h z-StV@r2Vlhc`osY3|tZ{4+uXpX0_L$(iYSjxW9vr$k%ec(05X!a%$S|IB&9zB1|bj z0}@>#DPIp!PLN(~N#1TcZmHY6G9m20-@IB?9YnN?#+EwX!yA^E|BvN)%Ol_mbQ$zITg!*#L(b*5{1b^{%efu5RQh%S3o1k)7!4 zG{*&Y>53^H^RMgE@T&!FNwNQ#IOmZFX*AeI4#21Z!7glxNXy*Es|WB z@`c^^p1t3>qH?Y*1ALd28CjVmyeAGKu2;+IdE-_5CFxr`QX9%jh6 zC@>_hSrs^&2|!?Hn{QYx5|LfenRcE2d!oCs)mH4rO__*%opdmID}2A z+rWvX)Km0KqsY}b!A%9zz$v_M@I<5dMfqPXVI}5)<^kMtd7ORa?wzoQ(3R1AwxMi} z0-0h;{N|dR{URfv1TzdGhjAgWAJn_z2>)Z!EH~-9XAMcRB2X@ z#FKWnroBu~PBQZ_tW?rwiB8_uCS9M;Pw zM~fvy9Ed~)YjK7B#xy)0&`cG3CQUC=(E%l{@nChYW8A5nkjNB|IWtc?ucI4h6^j$( zPQ$+aV-iA^ccw07p;sjul9Ueed$@UeyOYcsjX+bXYD0GQL&wAfDsB6l+&1x`aDYb? zs)S}TYD98?CLrsD)t(i?JpwrzdVM-D$xLCj_(SQ2H z8)3$k9pmFb5ZmTJs}3~2rA}G_^QEO171oju9+PAmhFN1Fkgj&rS-nrlNOe&QCH!17 zWwC)Dh~cNg$kaj{YFRWRY;0!RnuM-n4(V49ZTM=~(bLThJ%nwIXp&NtwRK;o?{xgk zG5|CTgK$BN2Au0-ly3&O-U1eR#*pjq4h|wcM5E2RiLL2i?pF;#Ql1i!|C9)d=3ynR zn_l1lZyP3{nhCu-IDw1cd8jgY{=N*6>BrgkBiw^fe%JtEr&o}Rn_mDY!sB*$zcXod zv~=`Ves2}m$?-wse)KSD6+jHEG8fa8bIj$3Wg4yd51FAXpMVvJ4B@NV+!-%-)Fe%V zCp{dMngTl>5ZT0>^v9RLM?VFtgVGlCN z0NPj#Rr4>u|Us8XlNp7Sx5rd5KUZORpHoGGT@f24;RxwfY!Y z!Xbzwqq!FZm^NL-ULw*f$-Oamk7OfRCY>1BGFA$53y!VE0T%=;aKNgag^~Wyp%=;t zpvc3Rf4$4GtS9a%c5@Z`uhkV|_?k*qY?2q5p1eaES^+2zU3|L@6f_eUmZ4_b*F=10 zjr8FII3%*w_=%i&8B-GVz2}c<8rH48NU)WBF!9)s@CZ?Dz*%vFjq`<``CdNFIGH(YDZIdy$I$`8UmoX;Gj1t*XL^i2tHAo(L-wkO535mQVM z^6>mnfJ2UQ3TXGpDb$>}J^{R=FDxz5M+S%E&MDD5zOG0@J``>KF^&frcluh7Am2`ZE(gyxjS8Q zSCWW+4H(h{X)E$2*c;d+Q{GGBQu; zQX+V-op7y*&FQCZ7K0k*V~McniB+!@vUT*tKV-9q|2jeWLYm^t(r}yl1k%i{H1zt0 zB!!LEJBwS8>)RTDj8aTtGw2*{xbnOqx}blIPcVsF=eOe8bF!CV2XH5NQ|SSJ46+f8;fAs?zP_b%mT4yw zxn={H-bvvEGf(sQ!j!mzA8xyhdW7{{hLK4MlsK13@B9Eye#b8wtqFJ=p=_2`*mpHe zCB)npu$Byi+YY_o+jA=yZoIOMT{{k}Bhr;Opc}{)=-v5?^%x51P}{Mvqym|VKpRKhR6$(?XP95VGKTPMmG-DxAD~UwN7cz z&4vBDR-jT2CPeacCE2ugj6TH>$>J;50TAxkf693Ebc*jpFLihI-xXwb*t^OJ}0*7#pDp?R%o5z&drI5TUoJ634} zcOyZeIsSzW6tnCifK`D?7LaK@d9{hBkdt#PS!n=5-8! z1&CLg%cACV;7>oM;qoAXbnlIYO1q>zql`CKKjsa!@q%eG#0cwF3NgL^=QIq1rt(dT zNmdHB_{FGo!3-^{CWdEk@!?Z2-+BP}+%aA^44TH6d_%BCX-aQiSI_?t_Q}JS8RF3? zY*xu2MHqpYgNg=ZUv74HTmAR6p4aB5Gy}v2zSAqbeM_2_`PKpu7JaQJ%tTYmTbi_0 z64v5un}}p1XZ*4rMiX9ZGwSsOG7^EzY$hyRRXnL`LRyRd%Shg0C@VQ&}Q=wCgraZ{f} zV@)svr4$TSox+f=VW6GURp&~Fk4bbsYrW6uO+99LZYT}+9_sh!^*h`|Ad+iV<&eiM zBZY7lLMqE|1B<^CNDqf?SMP&$gee7hXKqz!Sy8wIv4x~!_UJ($X*-EOJF<{apSVY9 zlR(8{4Y>1_7Q%c^*1}v-y-5Bvl4=(XMa|+2tH9|~X!;IaePCmxiHuU+8KMDyX zxnp|l#!=2<%_SoT5#@|Nv^G`Q2CGXHzv$hB(gV9?$ZQ7bmdp8xRNql1Mx;>WTYN?FFqQR-+jJTBqAIs3DBK!v7Nae^|2}KpNsecW8q$3&|9qG?)CBY+!t$xao zG;bJVaV@}W;~xPphuxDk){GT}S*e4CIRw6Cs@2~aFg0xtbi6VY=m|&FU^w&fDK1n+ z8&XS|Q+NVQwJ8ZJopiURtA}np3$G^5CUAJSV8gKw`}`?FV7g-s!H3;C=8EgvDBczE zu1Ui1xTtyTk%m}cHBi+^R+j|1Vx@i= ztc`>~o=oC$;Gl8y58eLxQ#t0?!P6|Ub~f}b<%X%^Enhw9qYYr2e(&H640MDhpA zp{$#N>}@s<@@ObAsLs`MN^a3vVSp-51@`rHAAJLzj9b;b0BH%D5bc2eA3MLU96b7R z9X@V*YPT+!vI0CKP^vFiQmP#%NhCKRvvq4jZK5hR{G#lWa!vF~BWmq$=`e1sZDro( zf*gpr;?Y{{KG8>IhiuMbE}T5|()%pjVwSM4$wiek)|Dq=^RoAWtjv}&sJ;PHZ|qYo zYeebG3P_F-MTmh>q>Ic)bUX3+v*@2O7@%|L$xid;Jxy9FPnscZRBCz&=#2iN0~?o# z;4{J(oT>(X%+OEG%TdRKVD#yZ0Qz^lkG@g1NE_e%gfeh~TrE*r$Njf|n`F-&+3x4a zY(nBn1PXlwM70R%%p2|2e{0_PqRp0(%kqbVehH)^5jqGpww(cUYm+SEm{gZc8{31V zVhfhl1(5p975u4lhXs}J@v2FYT51e2w=XLb#mh9`E3cL6IM?OVkp7L@RzzFj?pDte zy7G-8E9f$idDx?jk;h5ubel%(m;Y$3l4J#*N4~x>0Sjg+i(2)Xzf*%uQUXhcT2i)% z{hN#a0$PKSHu&oNB6KCGpbPF1Es$ia%VA3{!Nv-e+_{wF#)hQU++|aXjv=KQjWja| znuq@yZC|Gz1V?c{nn}`?yd5UrXkb(ZS!KC_AtsZC{dDRTJGQ8Zu(u!kE9qqDdS75L zLaY4wyMTb93#Tu|eNoo$@D&^{a^nKa6*Bg^rZe)oq#EjgCoXOMQpPAm`$Px)>;`-W zrDJB#NOTKsmq)r)d7m^KhAZ5qG^zv}{HE1t4i9QIHB^Qon-gT!tE8J6jrAzXDDw?) zKlEe<-2>kaK;4W`2naYqh?S2mWB?5{GgrgvPyFE!w5{lUc+4?V;}r=_`hiHJrz0Rk z!iPrHJ%}WQ0$PC^BvnUNcJN65A3v7r7`pw*O8C4JsO}(hV9r&UtCCuxnW- z<)gNW5ct<4e)+U@hWpKMYWAuY#4Pm`OQ^kjhY%@iZ8)n^F+sJ-|36 z`;9&FKnVlKjiHJmCXHwk4yjmu7%LDaj2BVeLL3QOKZQsjRiarvhIP;12mGlnc<5cX ztuUNl;BqzW)0g*PS0Uhg)Kqk=qyJ5piR0fiV9@QqXwOEfOTklYL=547s`s9kvffOoAQP_e62o6mk z;WtEfo8aXx>#4P46s;0JJ9&BgXJTbaz5tJ|A0bu!ky^|^?s+$sqn6ALg_0NfWySfL zMt!DJimQ0j`Po7Y4$*c%uzHdQ?%j=C@Gb}?7lCjZDWm5df?fFOT)~>_D@4b$fbezV z7knY?o&K$j5e_u{2})4cD0FClyb`TQrLryWN%_IPc@LVo*o~7k6q_E^mlZ#i>n%pb%Z4sdA zpi{8GwI7abkYs|gn}LCY@RvQ1I7llS;pbpRX@63UeyG##rA+e_$bNy)U&2(cUD^mX z#HSATIbTvH@QVprYPqhL*klud(G~aLB(CmfC*0sq#ezgJ&VO*IMZpSf8F~c$NSQj$ z!wKVhP6ZCBcf1-}*z|XkBjenxHL%uF-hKv|!5K15X2b4wack%mM`tAGJzsAa@GvW` zXF%%II1}GiOg(9%T6KeRD%(w_4!>!xXEqpH`JrQK?u$i5MZ2GLI(Prt)PGL5G;UP2 zb;8F4p{1ly4!iM$?IiX!eBkHyWx}~x--KU+;Yf6g@PP4%cN{gg^w~t1NR)e1R38SL zoTQdrli$1)BP`&ZeI`A*y=Go+I|Riwj_=HscPNqfBIPzzg!~B~#g!RG!Y(e z_KoPDUjChjP@FlYX+W7=2-uur<_w&+-q-iy%RLoSHFU4{9X81>=mMfEkZt&*;edA2 zZ>ocwdvriES;*^UF2mehGJ=4M;6Q<;=6$*P`*CjY%lg^d`n$7J@Vg(Ebhdl)z z1!K)oeeaEIXgeJ)q7xC@I1am6unZRJjl&9gxVV6qPF7J=Q1Vv?hn40PDf6il-xh2_ zB`5r!a1=wP@q8gkOz$^i{DA-O=dD6842}M8XFV*YijW9SzjnGjnj{QP9>z2sxa*_T?;CPHV=bCX034ydDnVK{mcb9B(7b> zX*TGfHfTG?W>R z2mUKTMWD&Syu-Az{T}tQo}vs=(^E+-0Uqzo#ZcW9l$F_L>NFi@DcopA=SLCFFc0QG z4gN1zO$i9zh$RuTc>U@t(w+83JYE7Fdv)umrCwZl<9tPE+D`BUUsMl7mjAeBi}i#^qFRChwn8vWt1+^3JR^a3+H}YPKQ~oS@SEjxeoQ8e7~%U{j#x<+#kMFmz?<>N2@6JycfSwHz32{ zOri&~ICaaT!VN*w`r?$n{mAP8s@o}}lvx(jR--9z021AEk$wrIVz!Zj5I>;^S6ce{RJeCOgP+S zARm5^Of`~Cl}rp9SbkFUPoPDYQwry{6iPJQ_>AHfPE)5^S^DX~6FYW?F2F{|sm5h+ z#ZGzB32m*6T&zzA$R|`&QYWEQO<7JF!bJ5<`PLf(Ws7NVeqmNlhVxpGnJxeBP8FV7 zVx*D7QIfj!2VrcZtxEl%wG&D!l26ykwexMNv`6baR?Ng7;J^($kLX^C%nHUU7t)hv@>a5zH7ZBg@)nTY)F3)Qtv$ zCaS`sUoF@>3q%gAFU83fr~sIJ82Cy5T<3xYGknT_Ww7C7nRCg=sTGqRS(c!qwtx&Q zLtiB$4ijwT$n{~7WuP;FgL5t9^1OF)CB$oFOO?ijnQRTZ30@96L1vhcG|g_$9Vk;% zD2{yN0#S9dsy$aBi)a~jmK=2-j=Docy2Qxwg?UDcxK8Blw3yCiS)Cn$8+l{Kf|s68 z#d-?M2x#)d`Xvfw9`3+lI<2hG2$@PO=LUG8mzRs9t(1shX|Qm|&iE?bYVUwr*cY%0 zmFUkF*B(ozP^(F83W8SJA@Mb)&v*`U_j|SafZjPu_wYM}YX(gc+EWgaTL$J=-TlZfzw4Ey{=u?Z z^9D7IcX9^~!|2?2o>yzY(^n@D1^(zdEe^2=geIioK*yA5XM;P899p9KZRwSQegtnB zPiRp20L%u*$G%t-3xs=!l;N$Qnhp}TX{qHF6$_l40nclh2eXZ^3oaUkY;KW5S-=_f zd@gKA@Rzg`d9mlr%26@AU9N;Uey#;L{ZQNsESyo7tN{s9kl=SJZX*lNBa=zWm10C< zWEE{Ie|Bl@P&ekbti;W>b8zDM4C7LbgC8~u==KbZLZ%lmBewcE+`c3MV;#U)S2LKP zhZRe4jR(t-gR|Gp*OLT=r?aoK-N=_2pehy)*S%qeoyAR;9Y#$x_wTK6(rGhfc|>^6lBRAnc{RZ2WOBn`Wc|!#RjZhmtZ%O3Epa@0Vk zaOvkA&{Up63Q!daRQ-mB-;Lo3&Ima;U*5gt1_?q!Dsz zG-8U(W;(3M665FKY9N3<&MlXe$~W z(N-Ur*bIrG9hoI569sq%<-?Kv6rSX77U^P7)XASo$7Hnwxs4YKpQ(t$zHYrKXwE7N z72OAxG5+^ToblhC+j+K^jfNjQw6=o}$P;LEpYM~f%O#G`=<&OeY8r|CS(zh3Z z^0tJXOyr@rSo2ur`M%LRHQU~bC)>L9kiwP74)w_av`p{BCW^>Qo(6Dt8>bDALMJfo zKCB5nZ7ZEv=8)JwHjlPC^$yH?qsu8Y0V`~WWDHaZ0VZfrHmGX>(5!M7+cb@9t%Z&D zjB212Gy$aVg^l-fZyJWywFU`v_82cUz8b%hL90f{v1O3ZtLl<9|!I2K*%8Ke>8FsI$i0NdjG6yI|gy^Qnr5u1#_ zWjzUlAr~gEl(A;idQYJW>IxYb~QLT`<1c=O+oOuyd?A1uV@E>9w{POnCNiEA>N zR1{KXB5X^ZUKD1XxB*p@e|A=5M=Ht2zb`qQaEDtFG+pq5`GpUyZ+ZCpnKPRZ5OAD) zR|r>6z-h*}sp`nOJy2?aI9gZlZ9D5K?>waP$m@|biT8O9GIo>6JK$-{-`CMWO{svT zQEe184TGLW8<)+!jX%8QO5U9L1=SwbtA5y*)iAgUunB5~@weUktQuTHw0OC`h8?#y zIGITpv^1W;s^3g;f8sZBCzU1tLw|~Dz!JF?!tTRQ-FmRiUo0>rBVISW>J?fHZl!1< zu#iHTQLHs~q(SoU*N|9#6OpesL$HjwAD-Zg4op`Fi-04wl>(0L^E@n<(**exH;x2^ zZeaH}BN7>mMix>s9t4>Xe&S_m$40R>)B#)-<`K^T3Tjq~2b>K-GTiMb<6OprLcVMe z^a8>xc@`2Y9prs3mSdnc`p)?Qfpo)$O_f!f>EpgQwCIH@*|{#jlAwWw{lAL=1Z+j% zk@{YUJ8Y!^BfvjV60P58BEssb-YR=#zzDfXQu(Oxnsv@yB^B|N^=;3UH-g4qAXEsUM%#B z#BJQ8h`SB|x9<#P{4M~fKY{IG{H*xZ@J<1@g#o_`fU&lkZ}uNCgs#@fgxMG8^oq0DKE)h>7~*QA(wVX1LcZh=Jm|i>F$|G&)3tx>*u?KDRRz^ z;%{K8EdE)e@vieWOfZ2fge|zFOm;d#^?^pI4z3fIb5jUbC$*=7L zoZDx zq$g5YCb{?QX4FTI;z6vKCAa&`k4y0SxA61Z==7cQ+b_I3C1R{uQma^#9n)6x4(tcJ z(yIBW*s!!>MnxZ({Kbqe+FMl*Iuo@HI@7S&@+4sdBcIdYa0>?CeqO)O?<=0oxu z@HLD|<(U(7l}Wr7-c)fo)fp$;Llw#h4$}xq+XqawO@6S=X6>{3U##l-(t83$?`V|{ z_qxxcTwCxcOy6N=wR-KSfQB|nF{QvfqUC}yvRTynos?6cj$u#;iVs0atBEbnE z2CwP<$MrRjSY5_IWRUFyzJ4?zdJ?h-cZ1XF0a>dUa;9iurAR`f#uJxS-t*txC)k$q zMeYc-Rou9Z7rrj~@v1MK;d!bHShK_gl8xa7 zLn5zhR0;(_n%~A}9SpEO{#aU+6O3Z0f zV6p?`h=qv9s1>;BhlF-&=smT@i)K962dVNyiZ5vXCKE_NLjZ{W>TIEfCuU3~RmqEM z66#uux&aNs$OIL~3*!I-d!d_ipMJX2j4#u19@SqS>`@Gah#aY6Pf@0R$WA5UY&oNZ zQK{@mlko{N9*VeoogWM7uuVflf|WX zn93|+3VqLq%5(~r)eQy+*gf2nSx9;W{sL(?;X$9-_~Rz5I|r<(_JEe?@E(eX(g*Xw zm2%)1fM%u9D%Rt)T$%l(8ek&~28T-ZnsFdZ7+@O}N`(pyN-*-gj;M+=o+&8wGq3NJ zG>f#H#y5g~2V!}AdBwe?*mz5toayM&Rhymakds14$Pcaj2ql-`f_uSeL+=6xG6p2@|9^27aM*$Xuz8dl|Z4&qA{jhE*=u{LW|xf_BtJikv6*( zB>yjxM1?lP@Iew73rFan%=t_LOIus93bN9vUQ77AIztqP98wkQJ&b9%Tm0qhA;1G5 zaV55Lo^3LSBAGi!t(ikxCS<^zjM@WPMKhP%Tp_bX8&ol7N5)as>BecRbO|Fq0gT_D zag&+!Xyote&I6^230iZ`(~GF~^cQeKE^K?(brxKLk6#y4%oJkA(Ij3;w*f`kpD7F- zLc^=nHW4H!8GmNg*nHp&d5sXTimnK6o+nR9J36M+a5t_t#9{6(P3i0hN+dL!-wO7)E*Z9U=6jN+Fnzati`ypKytJ?@iw0v&8viVmyiT52gMPf#JvU$ z%YO-fXVp96WUGdf$k#M~e)Rf0-~X=}w5}ir2q`_-g8drw#tyEjW#;8(b#DC+*M|({ z1A-`c3PcGFC@M+yR1HGbxq3(7aqqYL+n(fm7crk{a4pktlX|>@dYUs=2%+89LF$UE zApqx-(OM-N+cs23+IEO8RG{eR8Dzqqf)vDE*q8GUII6{BKw%2~P!tRnCa7>2}HVodhOtv|9f_h@5>Qo=y`52np8u2po{s#W`)^K!t!E()tswiLLL zq2CI-%GOwYzC2^b{=LJ5Vf?)oXDAHzPvV?V{S1}rp-fqbLAR%O&A3A|=0ev{<-Hu% zh7fFNFdno^d#_Gj!mT*A9+~*DChR}rRV`I(h%MWr{Q^@L9B}9;Q5$j=A}1&naL(XG z5)J`kN{hCUFg1{M+Ryb#!6_*nI@RbxZXQrD>sN!^ zOp+%Ys2D8%nPhIzY2LN42_E}?8@rCz@bVJjBXO--;DsKip<(MMfd;qoo#$P=Ey1HI z?^Ty9W~3f1eC$j>!YSMbOA%%q|qJ4CTdn<$x`#7CF;Qx3rkhF{Cuv1dJ zGV1oDm_O&Ety6^R_oRYGanW#DQqlE8@4zFt-X9aR4>vavwt|2Ld=+PZiGXs4sC4eu%P(eB>nDk!RsZeqceWE^e?uMtpUNU zo_J6yko%ogWX0?v>@t&Pa9e6k(1{9yBSk_F1gnS+zdwr>z^SU2H*70?I7*Y4?!P&J zLRT`#hr@*goDa-X&0LP1NEJ$5Xx1;9Nj~H}yWUZ$4%>@1rmYkk z)Wb(x8GA1VxjC5%@v~bs_&hH6%pl(sriL&p5 zMFq!0?T!~YIo{3dqhikpK((|e492Kmcu_6yw<(XO=31Yn`hG59l|J9FJf!sfEBJz< z88AnGj4Qe03cHNSShiK+i1GqJ593B^8>_b0ZpZ_iSq#_#k;4e!C`zFc!(& z1&FMV0;^93^ z?)Ws+TgdkOOi$asW$h_p+X8(3O8ynSev1JpVH-Yg48N?sR8d6^avwyIHbzd#Fw=}J zK+?>rE3*mHjsHfTncwu9(MSvgO^XL9Vl^I{&;MNCvi5o2d2jS0v#}FViQSCnu(mO0 z5I>yO>#~N_^3d7M+J0)V4P0tKUWdo;R|c1XLyL6=2CT2z%?@sT;N$ETKehy6y*sZx z;Pl~(Bd$EQ-2UMH2?ce~_F3#5Eb-6J`AU2he)YfUIQ$+?@i73Axt*SNxZb&0pg23w z-ci)`qlS|im@K~Bg&Z81#@)Bk2OpeBncTbF0vVjpd+l580NMd0B8v-yV(LAPaBg_5 ziZ&A-6xx4avB4Ae3DZ32BNSADp1{ry+og;eepWGk?=7SplY+I1Yv z@_U(aqS%MO+j%;+*WGukUfX)5(R%qQl`YZv#DMDe^}l~Ny-&50wnqR0a^U-)#4OkU zmzXuNwKB7J{Xd#^TU*Cta|GFs!hbjgQ12tDnD{tHm7t=X8d5{gU7$Luz(Z>&B?94Y zL`M|){rqjt2qY=e!eG9klAARI=5Ar$`+m|gHru;Z4Bd&|9-GW}b`8PHPhnbCpgDu! zor*~r-23Y1wf+6h7%ZIH9VJTK{8uwylNr#Xn?5qKIxRIeC4S zFEnlyWv1jt)#HLm%`(%3(N(j+KN09-Z*-U>=nZqgCaA>GPm7IF_xsG5BN2v5Ro4_$ z21CPm&XHbK>mtXw>u8CdXv0NmlyoVc@!G7;%!l0B;MR?11hXgLDzFiUGlz5m|6qAW zj)rs!sx=Ey!@r88J;Fwu@L>Qij8Qn7uV1lu$>vg1W>gm@YB&MIl$4@+n0S-z+z={@CoCgT3>*u&UP`8)gZswyP;JZ{itn~( zvmCyVdMs1G(+>385>(`_T3cpsSDLMe>`i!;aZ z3$Ai8$*u5z>=}TxbsKgp2S$mj|Aq;Dn`3N&#sgy*Y!2qf;a))_G@g+rv%#Ky!~ zuuSSXeH2cXgwlEn1M4(QVQG|7CnKsNPDFH9NYId>?ARA}CV6gAI4QuKO<%94S>EpE z`a1s4{m=GL)ukKnQE|{It5Vj3swJ0{>Zko1J)$c$Xq_=sf@pa-r;kXRoy52RzvmXh z+PmSRnDM|J7_ci@NtbM7@J?zXrI5UsJv?I;uZDWEGeD2D{OUy?R5chY^)F=bm5r$O zBa^a`lsE1y_UC9+Z%@&nF8$DRGR8ao+^PmK9(`2hcI7q@uN&lm$J)$}qlZV^ z6{rFlE_vuhqbP`MU~ty=+hAq32EZL#Hb^O86`Iw$X%nUZ6v(*EXRaoFx?Lg*gG5S9 zvyYH&5`9gNZgrSE3uK+l8F{8yddYU2Bww@*!zoge^L(NZNvLZx^S=Jm$3Nsc0WPyL+`d zzUWqm#9OFlJhT-|2;hh{4;}y-ylWrLoGAAJt#pM1C88nFZb@RUzJQJM#&F`qW#Oa* z3@<}_$?<5Zmb3@xf~g)oA(<)9d6J{gv+ZK&YYSNV6LcYym9_|WrHXy3<%nC-@qH9! z18nA~tQwXAuFF6jT2jKbcU!*KH~h&rX_DM|t%@5!bV$B)eBWya9L7*UqlF6U;6s)i zTzmfyjH7?D5O}?{szPShDR_ood~>c3rIwGhVnV(tAZN&fdQrDnqLX2~T=LKK-FfQ} z(tA{n2i-oeICqB1(`Y5wK_xRe;@r@aQhk0&C9Xh(Qa^nYlQ%d*ptVxg9bYp}9G8!Pl#F2*_IH!>A?a0Qy+i^=H!l zj~0zmVQdL1T?UT2b@G-nnKMWIFjiI^ODLTKa&AHDxw{a|jDURX4)%8$?igpfn|Kgf zK{LoC%%Wu!yzsU>`S=mm--^lUjX;o0hx@q1_~>XXH{LPj%n}UFMwFvZ5&$?;{Jy2Gpo3h}wT(oPHXBlu^z+7RNg}*jP zrSP%>ya>yxQhsB9@C<;g&I-Nywz~p1BrRiZZ|clE*`9Xzh|vUmPyDc=wohqC-w>yv&XGa?#8)3-)uj!x z!rPg9unKCtDyNoM7D}F@cfN+3K74Spfj4aLF%i4llTQs$TkzO3`nF^T)m(Yw9#>+G z^^OgBa`#=rU3o56g4Or0{a~3y&xl^W0+s)gj>}{}MjnUV)F~+UvvOYI9H{uW>M9q) zJRiPlQNOk1!u|&};qR8BeE@kk&&$fey$$mCT7rz-5U7H|M`w})wS~UtLvV!9&}}Kt zk) zrri_|an4#V+fWlbgPM1v)?;DYjr$hHqFWn*kj8a*W(Nx|p^^3kihYCy1AvFwJumY_ zUW&ap{g)yULvzS64E)##Z&>&wInBFDQox`AhZQ_w zN`dV^+oN*aDbkbWM_%e$)1=h2b47g=8QMi!wc;k4lpp|0EIv8thhzP@Bpt!{@$vf`aq@2jyjyY4 zgLU%8bj;{`+eBjvdokHb$DgYP@E&cWpuhG*_MyMg$+T*or<^ihDSKV}9(jFzX5T&m z#T&iivO2bwe_HL|t~r^H@Mw#B25d*7QK9THV2Mou?`A<`Xe2mG%w=tX7Ck&*Z?LR7 z5|>}Mtmea^eOZMs4eV?!F@Y|OMs4doTFPJ8(04LE_yZ6so2_R%=&&0}M(k!dW!quN zaY8M9Knpg)49&}-B?^Xu9E@j^=E*^4A{sQb`3PDa<}KE(nS~sb7XVm5r@tv_*1h^Z zPhAgLmjU6s0|@~Z+e7JZ-aB?#^tQ7d38cug?a7-2W?y^H&4DWl`8pI6N~|o|(vS;0 zL%r=kxNnlL{2XwhEjlLHm{0Jbr6ovwz%ElUP$!)I7L|#+Iy~&Rxle zKA+tk$jo%Bok;xY)tqRYeT6?oQJO33+&gdWerIb9dw6hb9WS9-A5f(h_h8L;!jVq= zYFv4Di6%uo7p|L7ipT%6D?Ji7oRD>tQ@Q9VyZ&Fg?Ro9D1MkpY``jKHuUoqOyjwjm z0ockdJoot9uhj$ak_}!C2UE_VY~m*54w;rqPRlDBhxdJA8;27Uca?Ib2kV9mo=fWU z1dGlBmC?(t&8r&b&S_aO0!%g;*VNy#S;vve^V*qv`*>e+Wn@7)eaiX(VFtp#9 zDyf4}nNh}%W`n-s4$=BC|7`QwFw?iD1gs|;<&tlIW%`z%&A%7T*f~~YuHe_L2MbOs zWD8Q{kNw*)>q(}6OT%;jJ7+Q@s$j_w76_=3_J5*y(*KF#T^tQq44D24*pIb!TyR^_ z{Yw16Cj^FW?nuUStP1M0X&SPWB&7IL_|7w7Z-U6S$m<~7#hH71cDdUer4roD{>bw_ zleI(-_qPL1gFpp8f83QKaF4rMPP~3CUDq%t&{~$vU%Gx@K9=t`e_k08a<)GnhA>^4 z<3Yei1aD_EO9ZgvQYVis-%U-oZGC+`J=uOnXHzx0YW?R>-2#^8tgBBy{)DTmdsnDo zzmAnSc`tBSn`qdyyqduh3Jsd_hh>f|Gb>d#_fK7Y~Obd zB6Ga&%%7dr9^8$;oo(LlCkgTGNa3e+X59?(HwZR9Pn@rJA=fR{w^_%$X<^QMBs(k( zAP$96OMu>Q?;MkGgdHJGcy6FdzZ22Ungpn>y|(wBLb$C=M>Z`RH;Dz5y$NIRz{VE`^i zw{6?DZQHhO+qP}nwr#&{+jj3aGZ$NXIkmsyJV{O^nrT_b#LXkI8w%9If;j0RHCIyT zHR14P62~+!`7x~IP+M3AdLP%xS9PNvNF1$u^-4ZZ-~0UPO1VwJ9=n=vEwX}RbzTZpVn$@FAUGy5e? zv_McLnveo6gk;peo`odWNj`eqwz?$xTss3nLT&G-&-ODZ9*8QESg_vUsWrfQFDY=> zSo5jEN%o{YxopxJW(bXfUh=dyU2UX%q#`JkWRPh4$g^rumCewnx7torO!DkLVBAI# z-=fv~0rx#k0G(rx@)H&BKkwf>|FYETD2Q+mJ{3d#4 z3d8>0!}!t=F+xPekch7pBv0)akKpiH>%dm`K`%Qit?YlcVNKR+T8>pndwq##o(!O#lHsNx42bGJz?(mR`^D=}u`2t%+YMPQy>=`OwWqcNt!=~OT z#B^UUc!X1Z=hhI@VOfy?PLKku$SFMo*f^$Vk-It%XExjB3fslUzj{zo-K>VA z&8cIjMdTC{0=w&wcrogN)8~b_ve~`2Eu7woE^=-6!7V5C$V%5{YFIUF+<0g1tlrTb zb$j#aM;K(wQiCLvWUHdcr2kL=`}TTZ!a*G4-uHTF2q63Pq0HsjC$Bokk_O0aMR`Aa zO3XmkgZH|+?TXQAt!J{4l?zb*a{it|6IMz-H7nq;t4zUiKBV#;1d^B)+kCowWz^qP z<0AY3)$j1uX2*CSjCb(UIzo(&XxvaJTsf;NbGaY2gJEyjT|eBrczhH`!cKZGSk}yPVp2-S}Leu6~(0 zslpZmyQjddR~?|_CT*s7>f=1$hDh4$$0UH51L{x`q&#EQ){3JGYf67TO-Iw^Fug9u zPh#-BC-%q)5X$@sBxB}PzzR)^xd@a2^=V~#(Y1soQ?V)c6S3#Hfn(N!Zyc7;xvP#B zm%HrcaDp~)N>vnZiK2>wZ$3E&mTjrMy#|!KqjTz3i01o@$d}wQ%&OdVMKRgw{V|~{ zQXOrS>}ijxSHa#MsLjdxS|$He-$S!&#-9eVdKR0sR+Hbi9IMlF7c6C`~IR*QjctS%~XX6@5DF#Aq5@w7yCN0ys z5^M+e6p!aX{7qrfgco1Vq9CMLq18Q(lIr5YOS-ZFBkJn;Lj87?<}%6l5lNKAeH>s) z0Mn&n6$X?zd<4z&o7lBGh3NjrlT}jd5==#fR+S-L{4>N)a_RhlG3NCEPF9KWoEs!o z29J_IBZFHMagvdUx8$`6pV-tFHA#oy&EX0VE0|cu4N_*4rBYG++Y`8mDducXCrV?U zqu&*}4R7Rh8fbVGD72Rl?t(#0g=gml7cav+71UT}=#yz`fVcF;#wNv+Tkw-?yJi`) zbg!CgwC6CiN2MSrt40N@^SxdP)95XDH3>VX>wY%&<)>ahPlcmBbj&g`i#fk!mu;Ap zQPMT|1S168+1dc7S5<4+KjBIy?MzmepCuie=&6 z%?{X9_2eu~i6`kQ3z%@JfMh*&oaoTow;5!&-%^3YCU@66w!^(3KkB8D^O)Sudc&d{;$s1*2S*fEx!H`#n)(B z_4X_qCJ46dAy>^3k52-bJN#Klz^SA?_ZA6tymvvB{b)3!P(j)lz|NonlM zAa4vD>o$j5=>hiA9pX;jt2wIpEB^S?o4eKcz~%ck(BuH?PQTFbxU- zfS>e#xAXn~V6KO)&Hubw{ZE&=&L31t=kx}rbW`%QtkwD}M;lZ5S}Su}lFrEj?`<<97B@TieHpszm*me_GtSgCO+ubBKf9Wyo{NY0SKrbMSIZZ)h0byV| z3u%)9!=6p@n_11-3vN>+NZ!ZP)+RWlab98}KN({>2{MWZgP<2pQAiw6mc)<|(!C)P zBR?EPr=e3p7^Bc7!C^7tVD}QZ75+K0$7QF>NO}eRFSbPHH7gc7JG-m?h1Qv6KcXeq zB8PP@%ly_X)_F9}-C+cjpwg%Gm=Z$^H<=&MCWs%pOUyU+kn-W1GSr@A+~#hHOjAd{ zY{(!?Nr=ouiYv2b(9|UuS~mzl8b0z}hpd)ud=H;p`{owGk#P0Xe6&06lQ&_FQs4|K~@FisS96{nuIarQ80;6&#e5Uy?OuMug_OH?YGD8m+ix0=2?U5 z7$omoxXNtZTT4Py|3~F5U)n#umR5d*yJQOAMJzI&RIx17xF$Z{Ev_zU4>09&aJBfa zY@*^{jla;fjK>Rs9icSw3mkaN9d_jGdsub2E@@>qHC{CwNnpSI@S zr>~n-ubOnvIg9OZ)S?jmo0Yz=@9T@?#i#Ty(%yK{feg`^ZmznYt@nHAWC2ijG^r2beGPzs>q+nmXYEtM3KBErG9|AQ$*|+{et~P8xlY zrfrBN`7aeB1E3;I-MC0G7l`Cfum+A&UjAs3$DgFZ;{fWgEQqxVI7ws^O&tV0qZpO< zcg7G0R9HCFb}!6Fg5kiNw~&C|k%8zyaF*fOLc1epaCZP?x_#w!^)G24MZ{rgDZ(C! zrVnJ0?{uezSnk!^G{c|!LlDS!gt3+E6s$rF2K-|USZZZ{w1$ZQF&GcD(1D*&Fr*`T zhSddipUQS(&H#BC48QF<1|x7LtYqtF%R_KL`Bd>>XUTDh1Ux4y6!<%+EInmnP*^Ae zpCCM%v<7I5jsXLR-4-}2E-EJ4Av;kuF#1)s{N)YDU+# zXKQz}RTpCr{z2Z%IF76 z5_v1c-m*k?^X(uvp)wPgez>H*pEJc9-c8u95vf~g_UVS$?=4=MN~Da3B^Dh(*v{MDk|uG+wC{0DN-)`Rb!$9J^aE!R zGz_$e8PN;Yvqh@HB=KXh(T4vZod?kRyfmezjYxy`LA5R_ox573OY=SVU#0Vd@zXZ3 zX@9I>i{3716w~Z2O^T%pFF%qrVqB$07|m((nQY^(`(u<%-zN%}D#EZ*G{*YbF_B6# zVHlL*KnYxae7Lioe;x8kk%R7_Z1kZ!kfo(cUI50jlRgUOzi=GglQYE;`-Fs71u!wv zesWoP!A8EK`m?e+S2P*of=`qUxga=Xx$S^Vk5>-|%+|H2)Me<(xb!Ur!5N9PCh5)K zAp(2ap(=O}5Hn-yVfcZjoGlNsPviK~{nuDqrw|4He`Gb{3_F`WKF*KdqwaqjRRF*2 z&WYd`cXZm&$%#V)tY#z$?Xv;=(TekgxNeqJ(1VXEh%z5oZ+HsqjaBo_mO+NSHC1~Y zzgI`KV6`%#qYU5$rx4r=GM9B4**{%FewNzS6r%NjsSKBZRAlQWy8D(pYvd0MTA`znF^7H`>HD zHv#pB-d&os3K41=JOEN{ulhPc^4839#mLLrzRMD_#TJ-K&M8-H*z5c2ifi_x)uIr* z(q4Wk%3mVwfT}YdE0|YumSuB8Z5FR}a955apVUQO?r)wGW9vx1^cBBp0!|Y{3|dyH zE}bbp9WbUM-qN)QuDB&bBu42Smhoy{IMrWD{u{6LH`j-Yvrw}5JeVWH_|$1{4aEg; zA2iVlpnx#wR7*vOiT)gO#{uO)^vM-Ta8kXDB<@B4@?F{X@*6~T!C*b><{|f;2pgCG zvQb#J)j*4d%j&8IHVgP@tQ2vYpcXjO3CM3AXd{g5iOZY9r>_kT7M)^8g$`k{>i5xR zaIEq%t>I4daDat1hKm=nT6d{cIA;af$Sp1dR00{+)TPISmI{{xl$Ax~xXU|XT;0ca z(H-Lg)ijGshndIYXS|a)P~u8_ok8eByK8cvq{Hd*ySJlfN2%hUHzKN-|NcWA@@JkW zAVmi;|0rO+G??78ij?O-ohdi>KGG-E%IA7(OcE)_59SgXpg%^M~euN z*sayTSMQU^A#(9iiKHiAh%#kZIiStT`FkQ(Pfba!A2`U-%ivnjA}^|PJ4sGf*XxK) zimbAUr{+ogkxh*ns^nx`z$jma+xCj7r-NV%vgpewcZ)l_phW60dk1N?N>Mt% zM)8sVISkLHclLfVucN1BhH5%1Y%gYd1j5cVxRZi1bx1RILcHdh`5P-`Xj4A{f*9=E!vTbOKr>e36 zMaXTFKB-0~R7GP8?YCmPPQx~von5lA*5*>K&Pw_%I>^s9@H&P{ESffA>4I{U6Fn$* zxvL`(?(YdDQ0ElRAFIu;td@EDRzDB9SYADmJQ0`PgG-a&)8ruACmj&!sA|hsOy5t!R#PW zPdS|939GO7O5GTekzl^BqojewI{QtCnM@7SD9DYW_Daz|!}4leXAYFLeb9n`Pipo@ zn9Peo=(iWBBr^mgzAyAOjeG8g^9(>BodWHCQ4Z%f?9*xj0hAsUxyNy>M{o9V0y&lu zYeJ!29^$i6KDQP4Ar2odxmr^f2iKyY$~~%cOa*qAIaR>-nC~i?T-wH8v^SiZ@XV<)t^RTi1rU#X zdtLt-8Zg0ZGrpalR~RF~(Nqg~W(|FgYwPj-D$KEjKe!{HO)1$g6GfJ_tvMw>$af9h zN@?4kWh^dpM+4|O3)QFE1kI1a(&JaZ;oL?PjcAK9-`DzLtf0DZejTVAYKh8C4yf$O6~Ic+oJ zsOP}t4$tSnon?49YIEjnNX+^Um|`>nRE=C81zHbk=JeB<$OHqnt&x!x`;3RB^hK}m z8dc0aTm@HZou2O@8n=N}j|1I+so+|kx@B&KMaN)OR8N@_7~W}5ypfiER3;#Ux?jyx zld3vaHVI>SZ}%|ZR$C0fLIdV~4WUBgVm7f<9s9)4jrJSeFDaV(CFG-)rNKRQM-P9m z3^YysmcDpI;9Tg@l~V_FHr?tY4ftSns3dxJJpA`)y#kEtsTeE(z^c&yZVmGPsxo&| zBU(d;{|X?O{=3u~TlYWG>=Cyg=!{QAjOVNl^b*_;&ZAlJ~5HTr30c09} zy6Ymoe+N_`fJCA*_ez?|p>gAmexU!`n#u5+Y5@t*7t!Uinm~G^siVUxg0y3_CT=v!_lAJTq-H<*76!^? z{{xZ@eR6SKcjnQOxEToov%=DrWH?UVk|-L;G8$&$Uj!>c zW(2WStcoyJ_)|P51m{kyr=bd*hR-U8rsigVDLz06sgfU~_T%VdP=78h`ZVMIyK&>^ z&Fym3AEUQN#!emD6KTKq{@txzJzDkX4()f>Y4g_nH-Ge2HDfvfC5ITFDd!Tr$QXqv zW}#5+iw4jF$Gv;vq-;+t`+#~^^@!YKu2+g@R9oWYHv)RaG|)sefHV^RVUkS6ITNdC z@??F?PY_?=>wgY9Bt+bFhz*9P*tt&NVQdvqCh4V!KC!0FBZu%4_-4kyjoPh8fhb>p zrhm>}oz-ttGuhL)NZRcm z8TbG!QvoW{AjqrD5v~p22>69B{}jlKs@y^dIV29q*(8rTr@@{i0L3U>5V?HqxOiXqdCmi~t@66H-Ej?lqjVK&KP{X7a@m$Vh5FfQp|ca+S3HB}JUp@dWuk z=*z<)L6V7(zF>MoLWB=FIUfi2?a}OR#z-Ve3I(mNlW@bc($%VZOdK;7exLjzWM(e+L;J-}d~TGw#Z> z<7kU5>B#QH100g8ProI^9I}GA4{(tIAF;uj&^S{w>dwTJ+4JzcJpcDh^SdNjdKObr zmvD>t#Z1npV#NZDl^3k1*Fm?x9I}K8x=jLFYQ~95Qs-$ z$OIB&LzZi-V7Q?*k!W_@7^k6>4$nPsQtLd8dc5OtATN+80%3i?Inc9dz9e@FVVr5cezS(J_VraY(^4ja2gIR-Y<^fgQNxEkMmsx{j$Q zOm-47I}zFOJ)%hcz5_pFro%+coC#h+&-m*1(a&Y`ybJL{SS@Q3HUsfIm3G;utzl)u zMu5UZJ5l6cwL7AdrqI8|MX9H6#2;ZbrnPRec%n)ZW?hz+Q@4=Ha(WRrS{DlcYs#0@QMZ-%W=`+0ND>Vb!%TZQ~(OafJPP!Nc_%PB!^pm>U)Hx z1TfK*nHAl$xOMKJvvsirZx#)s&NCD#g;|gqW<+R`KRDPIz`>*3E};()PoGL%0%XP% zQjLx#g^qn$Nta77_ZfZ&tlm0=i1oD!YkPyu&qi_rAXqqIdu^|k%F3B%50u*iT@Z^D z*Mk<37vv5s5d_tdoP=Gf^#p@Nmv{?X{L?_Vb7`=HH-clQ_mEnr><5u-9UBD4=9i) zIrn8TKC3aV4NgXGY!=Te!@uXamcj`f#uNNSkv1yH6-9O{)aSuIG^KMQ_G2M_ANw0e zOOC7^`uC;hB*Xq!%PYi+Jqy=kO)dobBjsicDj%T6+CV=O|6)^t*f%nX=no7MuwQ)@ zNlj!^gUK~#2E!c;K^_(W(7j`&6s;t|q{Ylk?`<=Qb8$Lglmj~O%NKc z=ekNuNzGnksO(Wf>0@g@MZQ#YTPd7NKSBcD!sJ#4qWJkw2Dd=bQ)vqR!xrZPNbz#QtYpdQjalOI3G^s8iP=2w>a%k7t2K72DT$ zT&5_WtlMc}CJ_w{JTEPz%f*QNPQ3`-GV1e&mY%YYa1^?4yA~h_iov ze6XEA&kYz)I%HiuY|47k5uGzUzFZ_cO4(BFZVL)!rainDYhIwwyB1!o(q+tlz?-@M z1hyY7t{`e$TGnO%?j;OFE}N4n*372x=UR)FNkMQLL_>Pzn|yVT)CYmBdX=2ZxVpObW7{!sYx+QLIukJpe@{M8G*d*KfiTiV>8S4|qt zxn6jLS;W?o__&FG45c5yYYq^0u~=Jt?zD40?FT0u5rSc3=A1aw*3jI=$zp}YXFHjF zhE0`Q59m{}fB6+tzt~<_9b|iJ!LpXY^qp*|*-C-nT}p^GBILsRf;NP7Hdmrh4O{6704+U1cQh_4 zpkjygL_^m~sC+P(3GQZa9w2-%iLAyt$2kJ0y0Ty54L5+jb!~Ycu?B>_g2ezI7=pX2qRAbUraLZF$N%ogFm;rw>~oH z?bM&%;G3~?<{2W4)}yKS4H&yKkpL>hOLiIikVT~~2V*;>#sy)jCr?@b?Ta(BAGLwQ z8JK|;zNMP2xeRU;;}7p@SygbDc4;4oJ2Iuqlfqf|mpb(Ri*_-$av|ZME8jNPLmm&Z zc|&Mtqv9SZ%>;yy*cr_mf)x^S{;LRg|HQ)w(ut(nKD``R#lmc0?pn*4C!%wK?~x#E zF(!tDtii~BHmysS$*2k4R-)P?Q>eo~B5|}+Xb#-Lzt*R-U(mh&im+3}XP7AvZgUcG zkg3{9J9^%MP{F3qmj2-j42eV^7A>^?>VP<5=A{s2*_>}oHT+cKoGzJoktk)px$C{P zUf!kqcHjr=F^i~8pVuW@odj}siLSzul?T1eLkI!N`Bggk6oqgKYBSTB7EzF2vFPk@ zwLz+pfZI*AMIMVi;)%ytcNa+rd7dp=Bt4x{nVL|Q(@?eq3qX1v>fiu5ZN>{GRthD{ zma;3D*8?JKlROd?t^Tg@giP<@Yxep?ys8=5jUw7jxK^>FL+d)pDJ7{XgLC8+L4b%< zcnja~&RSST^2@RMxR^?PRg65OZELY5yK42?i4DX%HKxUVe4x7_wuhu-8FIgI!oQ0h z+s&_E>(y&!G&h40l>MI5AOx}71BsoPxkTIBgLNp#{?J1OJ%#s=mnm=iObzy4a~Szl zNVZM^^n@(Ne7?G-0sdtvVjsau|NTlFc-QBhx|pdp-%u5{E7SpyOxiXv*H1>kj`=)S zE;gdEam@8*Me1#q)}}ily2hZFVL(+_*o__s>wTZ7yKgE!rFt}i=uhOfII5hXfDv!( z77$gUyFb|Jj%Mud(CW#jS4TH?bM$??e+arQqubq~5x7lue+pj}<-mtg&5vDqoJmJ; z1sC^jnW=d_G*f4M$mU_FjkVU*?v>s58z`@#PyA`-5xam^s!wi_>jJ~6w^8Lv42Mz5 z#k+w|M#pK=Fq-)zbNp;+x-CTFb`Xz&oQVjSVTQ6zd0Cxr^A)Q>@$PLhxsMvr6vz<_OY;s^iC??cO_{weL|+4BRRiJH_Lc^$hl0Gwe%W3;f6 zH{4&8S7w^`rWbPN18Emdg`*6!$(}t{Rtvv(s}57iTIU6ko))% z-d;nt{od(W`*ZMWb)foH`i2#9TCZ9-uFf5K$BeaYJ#E>vH~f=;?pYI#Sy_80&70qL zWLXyNA*>P-^P0p^iF)5HX(eVe+*+(`GUTo zm4|Y<3!PL#>R54p&&H#hZW2YRG?+*FMVPAhAOEb3&ONQXr9Of}dNrxAQNcmF=ad-D zs?m}>K~0F32R2A{KMEv&QQZrdcC8(n^qV`WV~EtZ*~0_g)Ni#uFT@XC-&^yWS3mxQ zH^(0QipMG+!0Ap8Jkb-L)!Q(uzRcUOXMEN?VCJ~r4-zxv3C&37QP#Zr*TJ^%sUK-K zcmc4MO)oN!e5P;h0{jJkGWO8A$BY}^0^jdtxJ}Q}CAhPE#auy=&nEn`Z_zW)1|Y-J zp3ozB~4gZXy> zZxv55CiB$g91ULN+Z_It608a8tx36EE3FbTt>BnXSbIT|1B0zN|bEEKE zKCpPmsBi!O@=6f3Ko8at001=j|Np%b=Ku0ac6hCwkH!-7dHaos{1es)D}76JP|c;a zbt1c`VMQs4OwIdsm`KD?dI$u73rNZykLtV6U|}StUQaIRR3D;73d+07_m-J`zQXO& z9~7C=H7U`1raWEgJ^g7<@8?PStMNn$Kf-;IX+=_xG5Ig#`Fi&6714O+N#>#Zrl2P| z^3OC?Nt$Ir^-G}$(5Ho_QfI1~#y>=)g82Hf;O4=<=_E<@NlLvS$^2!iyaSYX$VvTY zqU*om2qH&`1|vnMl41HZC|RI7QAUX-(->~Nv`MDFqR!$oX{NqRc7Q3ANsJ!{4V0)F zSjZ7RNcSwTc$`?#xxU2#f|Gl0dqE_~IgTaxdAuIb`$E&zji#G>4zrcK5>A$N>Zk=! z8nkMcMNFJ8CYqQ5==&@%K5CE{bPzCk`k%rb6&XDc|J?OeukhvM@$vD!gA#5|Mjuxe z+_-@J;>d&Ph+you%_?c6_ZR82O8~~^+H`6Fb2~EtlPWz%REtXsQNus*p$(kcuJ4uT zIRzfl#~!Bk!AQP<1GI^b#D5_1<>KDIeoZ(o0AljPmgUvkm4B80PRsc7;J}gnT!-iD z$Iyo_?yX?*`R;$;q5rNNd=?LoI6#*t%3TBBfs-Je6zLoUW1lfV6gcjkJJX(y=`w+J z|2Yw-CDA{DYno7CTWi)NA+0xoJfi`S%Bo3<5~;97UN+jj#q^4%a%PxZ z^ZhgVX39kO?4+gcq~i9;nDzdie}{;;Ggr+cGhZJ^P;b_j-Di z4c~hu>*b^I=a=OS99N|>eF$J_qJ&!Nnn2I?3|*mr`~XW0udb)&tY5L>$^@_ab~T71 zqkaa!!JBoo^#n?`Rp@!J)w1~_YA6F+B#&al>j)nOGO!QTM7432CM-YC^%L{8nfHqBKklNG-kke!mbo;Zx zNHJ1tB)D!+Uza7AFH2CM6R{r6%B}k^#2k0kZXLY@+n^rNqO>6 zZU*pX9{q0qq2FKih+Z^lX&(>{P%NQoz!LLsrg<9h@5eks#3xWnt3w?{qsn{K-zr8m=Z09D-2FhFl6HEn+@|=|(C! zBOEQhaI`-4J(a*}z{P-K(1;bqJjg+ZI-4Zw!#Aj^IZzz>gJ9XGwuPc@K1TPxzt)6Nem~H)O7}Mr2G#PN79$Xe zA?pVwBS_IK8HxjdZf>)ia)YVK2!KYJ4-x(H@bdfBi6QTGF)!%hWSw1|AC4XjeGTJn z9KDAh>tS%O-X08@X<&HzYSF=AFo*E=J{ypaErIMgi+M|6_ua?En-RxfBzTqug!vE} z>v4K;_JjO=!Ji)owp^dJ}mi3(cgm;pq}CV>to+*s!ZMI(-I)Ri~;KRTK?ns^*b5ci@8vpA65(< z2dp3eesP}|0d6AB|2jSleW2F=Tkp?!{vH7r%@vX7mI%y1ar)LaZQxSw3AW=Ok^F=_ zPI58Fn5y}i(!WCxn};z@D2BHwWgPkwMl5j!)p_lSsZAdb8oXm1nm)FA=XYR{v}qYn z*i0H`kW9Q_e~Dxz3i?E)iX@3oY6k+Cf+P1wj%UK3Ss&m)BCSgh)`WTC?ZMFKg=_}J zv=5%d@uZ_@q@2)i`hf`RH=s)xGJFkU6pLrZ0EDEkX|b|<{|L!;Cgb;YoN+SL5Vmul zCF4NADl+iuOvgL5q9d`E!MPzIq%n6R zHIj}j5{BR6BUink0*o#V5&>a1uG%6~QALdc3IO>)S?v`{g*K?vLEw5FRKk*!05hV+ zWu<_Hd(JOch~%%Rjv{MY$#2ty~zCx%YYaX@F?9T@UpKrgCqKNr^HAM1PPv!AzO!Ek>-9=du%2(yMCX^=4p z`RHJ$8V<&eWyJk=;s8+v|87ulkUhQENl`rjmiONde_mWUdwQ^%dHZo-KW@-*PQ@O^ zT_+BJl>j`fU%YQ-lR0$YV+e;+VfG3DJ+28*c-YuhR-|FRb*|Wo40Ha?arA9H(`u(qnr$dGI4*59PBF{@|1IRD;EV znmoFy(aO9-{QAF#GVuKP0Cv7$ACNQ8SAdbqZv?Y{MqD%jkoo$-7$TMCOsb%;2!2yd z$Pi-yoR!0?;~-BGYoJ&ixLP~WQJ2ISSNi$-&*i=>Ek=ejWFx5tdi%q~mnM*ud}jMx zczO|1=OEF+%5%_CXv3IzcY{^;;E8q=tm8U3I0z#-A)2ka)5NKr8H5@QfWZK_w8IoH zg`k$Hy277eYK2|%BT-Z2LaE#g$;%vR_aFj(V6%hbxOTaiej{&Eeo4xh*%As8;5)R^DGpf z%(G`irSy95V$fH_yC`;;tsjcjkpDPMc0H+LKX=cvT?WmRQirIhd}hup+9mRnmXd&x zKpAg!KyQ?jU<}~u@QZWuL6T|u>6T}m5yp_3u0xk)f54znP{SqbGz5B?8K6DWO|)`U z7ui!9;ndj7lKxTQYn;~Brh7Ky`ns1)l)B&!TSugOc7l3;i5ymEimahg+m8^`?zj$~ z4s-KOFVX?1&>$UH)P^G9M+*H@w4DuvkBl-hEw!F0a!G#15SVu2EiRCVj=0@#Z_$E; zoyWJPCZ^0022R{-gviq>HLFTFFbok9Gief6I&RR5wDOBb71BWx)jNj|ST%@o$b%9E zKVS+aIL&V-O?~%^kX2=db)Dpej1ANsi|DB*!MF~!Z({RG7qUbPt4qa;@zZGxt0kyJ zLSU=6xn9;d=97Y=!CIY=miYuYS8ATG1y-Yd&@CphC`kV3Z5!7URa>FXh}(yo5uuiy za;C=v@@Z63JuLBpL{)_r2L}6)PNW*w$M=ZK5hT|T}c#BXu zKgTJWcxdtF>&V1=>1ln6Rk2xQ`I7HbC6sR93!H76u=t>A<<1m-rD#ELek7dH29*(O z8D3fdpibaTv?6l?ihET5w6NA!9_A1^5BVkRyrf{zH8MDl0*dMZXN(L!@e9ZZLC(|q znCTh>Vb}}_+Z-L=r}VxyGDo2ISBH+(Q28etPyl^TAQK;C!~$Qx9ib5EsGt3>Awfo@ zM6a7*ojw}f;H%vl1Ex$3vx{neS*a7i)Z?#@8y9XyGDYH(OLG6f?oFY z@y3#&Y>puRmkq9SW4WOscti;jv>2M^Y9Y@?c0rSc?-qnGqoSw~hD?XxQ97XxmFtt$ zM*|(Qr^IP46S6NdIK}XzyE@B!rt7YEje*43!ISsr&^hp#XtIwDCKoQMrKsQyLS@3V zKUFpzWpy6_Jb%x5N)ZLTQ7p|@HHef+fm8cBTQYGGE-#AbTk=Z6kRhGe=v)BfwBQnz zx4jYn{c^tO-k1PN0+tOyc;f<7?#_wKXLY2;ef1{ei&p;Lt1UPm5x!29~L%kg$uv(RG5%N&1{KEvpiO@G@Urfl0k&J zRGkW@2qF$-D2aR1$(;zTy-3YbdSTmsH*2-o%A1%_Sfhux6+TF@ceip^hHe(0S7Xrr z1r2{f>E4WDM@^}S3a?-*!2ubGtq7UCOLflR!I~z-A~fL9djiLMbC?@}3x6C}&O{s? zl}P_;4t4KmkT{1=1x*WDAMosBNXldf#&=kfBkpY~EK{1VR<$6?l>nHv3j1LlXQu?> z(%9(o%M_WY2m{dS!*G2b+K-EE$;r(Wf5umhAtglXuy9mkJmM6&sbaYAL##K9#T{i3 zH~OVJtmS9U=`}xvfmGJ<=_x;%fm%CMM^Np>U#ugKR!yn^CDogxiZr4+W?jUvic=Q} zYwdnmY9h*3dJ;Gd^KiRlLX{ebbtk3fw!LBQ7r5(48N=q#=H?y(U&`K=XQJoOq1bIA zY_oN?kzPnN|NJ&)eniRqu|yl_1CinQ`5Y4tl2|f7(i~!6%Z89fK2^O@{?NLM*zXyg zrH_MA*WjkB0JxAsXIM#H+BqA2?INpv4s5@xx|TShuLeG=V#&gHMQ?ZPLu6y@!-T13 z*c!M{hDo0ca!D@vTwD0m(u7C&n(m9v;r8wO2|K7auO(M);+h)@suEEUL_+D@Wa1|KZ@&FT+Bi zyVK#~qdj|b(>hiBz&xQRp&y>5iET$S+y2|sQl_KW8o5ueJHjw`p zM5>!p8${d-?voh2p4#JNd{z17gz)5Em@R=Rna#elAYQ(UgesbL`|X6)B_U}f80e48 zod#6*Ucedt`^_xG2|#u|%!tGAzf^F`=rB)W3)B|d`5%C9VBYcBmYG}Pz*>u)jfIDp z>FLAldjlD02S3QUEC{R$Gp_O->~w~kJ&HvbChiwJ!S42(Ogu@W^Y!WB*zSsz&xdrN z!&#?j$y zqihoIiAJRwZ>1TD(|8+A3=_u0t9SXFl4j#FR*}1H>^P%wa4FfGye4+omz+>VK?Lpn z@b=veW(iO;U2RhMFM{WR=7bPkFaHWQZ7ew;SH6ezhrL0eeu$Jbu5`f(BCn~+KAT4X zWwF2yAX7Y!4+rC52Yx*Wi)+l#=aEQT_`}Bi0^2EVj6BFifYVV$&hCP*n1xq#?NUl-%6JelaDU zq~atY*3ICh!-h?y>+Xw7Hy*vn)dz>?e?0mxArxrvMem#1)k1pm=+AtE0qx~1HDai; zDCDJ8Yh~S~iDMac>G8po8#7nckl)K!FM2Ds55G5F{#g`w7(uL>T0!0N-On*?+77}^ zSMaKK@gJo&m;DO1IuynrLaD7QU*AXfz+%1m_2BrcEt63!8yGG;TEX6Xsx|n*Rjl~- z;VTFTdl&V#m*Fu5kn%XXcU*X?h7Vhzsf{zhlsu|)?zBlkUN=n^4z|ory{@}a&bX@V zfA!~tpPf4HtCII@yozvvhduMj*8TBZn{~pk1kJruL4Qxr9q284qY(`jBBgbd3bvs` zpM0%|Wy$RIAISbspP}SZY+p$;sIaxML{(eFfk#Q1zK*)zL>XmQy5m)!x=Dr!rYM%J z!^_T_$J*LkgNKYT;Gke*jz=<=xmR|TUb5#~?DhG(J+}Z!K(@a>J$ik-FJWsKw~Z`w zPCM<}OKn%9ej6A>4<$KD$70Jlz@_Z)uOs1Z?~xzUr7DWgE^Q|~d9ppLz`X!`TwGLU zyM&r5Q(*+*7T%+6BTt0gOJdLgc_6$Mr;5-QwwxtUKBGn1=DJ)+4VvQX2FYsUFt$1is(_N|8_D zvYKsIRfz?}6DMFXd^6Oo{i+G)4m;}2oRPU(p@VXv)ml_$NGKa~`b>YdUnZXa;U*e* z8&>6Qs-gx06RGAqnhh;ud4hRe1dG`A(KyVLRq&LoT17Pk>DC$24PNs2r_g>t6vXHw@AxO1u(XwtT)ir$T_ ztF{Y@OHv>nxF27+b_u>-z0V%IfQW3MYhp%dVaa~IJ&ECCZ+tSCxt06)ge-1ghZ5k) zxf%kW_bSHI|NO9{muDC8*n4+S48%KleY)ff&jY=I?W!t#IvITRd90^zdF4Q8DKa@PauT zOpaWNU@0%5zHp=9Uw)f>PrzC8pb+9etiUS4$RK%_kF2tnUOK>ZS+t>LP0>A34Vg#8 zQtn2Ogf_Kll1n zwr$(CZQHhO+qP{xd%ij666OllpRQWn^>j6PjrO4Nna8MP$klwOc0d&(_`2O^$rQ}8 zcVx{w63url>u9iQOLX2Q)-{l3S!IS*bulQ5I~$?F5&vfr!L0x5c%d%>E&k>8 zjqx*A??v%B$lTJUr9^G*x1t(8v=d^f8QeONPS<+1I^Hg#Masxs5KPvHj9M`dH{OK! zp&gBcLyqmjVCk)s)o^ja6a0psXq&;`UR9hrzPiaJiIlm%UmFrONi*UiO+tB8TFr?v z{QirU0QsKA8AzEvy`-$qj5AEzb$t9Bhca>AxrX}l$e$2N6#+L(UJw`X$dS?s$H{Tow z&haFgl?wB#@)h|Tf8k#XIlWq2OSn~TTBYpwG_--j4f{utqOR>-^{b-E<~F&-;zBQf zBZaumQUKxgu%~x=iid!ZQCFj>wh)*2U+EB{*?fA_C#9rwAPt;QY#iQ?$Wb@vjd7RAhT>#rZ-o2iWVJMJ9JwYsR`52X+hf>;j?Pm#4~u2l_e` z!&$*4t4hckXn)$g4vNXPece=4AnJ?&yIX@u-4>KpKdZ3iEA1xrk(rPl7ZbS}GSYRf z8>{f*#Y|atr4QjBu@Q1s96c-oJ=wZnPRu**yE?hUCm)IjBjHdHS61dBPLtD zrA7LezTSygSLwlXQb%lY*Kg`Q83j@^xn*XC;7D!-@79>>@&k;d2V}BLTOP`5`54!f zg=akG!MB{@e21!e#f6^FbJVrQ{>tj#fBbaN%aEOL+@@m;T|@Nep0_zfGS$}JE--g3 z@p|s_eMa(Lu zjG%+v7J^Y5vj&4N(#TVq6-7IDd2=8uZ$U9LK4N$N^EcdUCzv%+6UsL3XwZwWD5u*q z+>dzd7VD0`!v;F=Lw4GXyDiBM`#|)bF*1kh9-H<>U6d7=v5#7L6dt$2@6;H9O35T! zbn61+F1;{!d)@M9iw4HOpAtxC!IZTKXXKrF!oDrLmbKVgy$=DkXE+|wZn(znY`l6K zjfe-1EeRhbd`p=oY80;r^#!azs6WRD2#>mOZWnzQC;1TMK+`I3=d;|?Qcl-rF7LhS z?jK(>FQ@IW7J;76zvoM@mCtkdnx~xxz@(!~iY09dBb)lAsyZgr!gMv#h-+V|MLEUg z9(_BwlZ92A!(?Nlx-;T+HwSWw-m;fy*bJ;s5JNN=ovN)Tb*gppv_E}#v-Yu^@6I;L zl3=$Wm!y}Q+fs~Cw3#|upA_d8`}ML^W2$c*L&ICM^pojw8)83qxBrsuelRc5`!YR{VX2 zY-vaWyHApB+Oa&*55{hw>(C#CIEeE+hQ=kZw1!hf7s1QD?ZGU(43RBXlvJKwH-n}O zdr0F_U{ARfa*Rboagsuu{U{w1H-Uk>C zbh0k+jtpI9p94lu6jzE#udWM3-cx~==0t}gK^PZqBOjK$1b9ca!q1&L2z!mp+8~u! zjws3!SMFCBKDy!5i58I)w+i*jENYpiIug(=&HJ)QauOH0m`@^By?CRO;7)b1;lI>- zzf?Wt29JaMLa7K5p5G|kY)W5qo!lX0fU|>uFI1gJ-qCrUM5yU) zjIf-bhl?l{!olhEv3gh+#Nk8tQ|BB`+oI2XL1eyv3u$knQbjdV*dooT=%T4SgsmZF z3Z5+;Bj-k-mI@7prpA+Wp0 zXEOp+D_Lw6lz)q#r5W{*{nBc=^FHZlc2{mMb}W=`{Cqk@d7f`8)bRGTJ289xt3pN$ zg~N#@A?9zZTM#>#{@m0j2x7 za0X-p>Z0Y)+XMG5339lq;+A<1Z;AqM*YS?N2ft$#e#wTo!aUUOTjQMG{@mgl-ZgCV z+~y;H*(2V%Z81&jn!5I<_c(=O@ZmAbw^cXCIj=oj;|QPSy1~KRO>eNyZyPP~j%q73 znfcSx-Qt;Y;YOYDU{oNToZJJd9}bt|A5{=@PCP`5!ezGPj!4jI3qGj=`uNt z<%?UC`ZVkHtus-p;+PZI`ZC$Pg{!xE?c;c*a*iJ%;FK;_f3E+7_}`uj{I$bU5-|{v zP~iW)=K}bDa}7LJZd~FiiNSz^5?-K;O4fwrw-9gZ^WIa_Xt|*0US>7m)X7 zv>B#pzLOhMq;V9!=;TaYZ0uehc>{8}jijfv5*x%49$5{95lsNxGc4{%QvTC9#aRsQ zS>d<_mRab}hl!7K{qa(R;SEx>MpVK+xF(MNiPHl8G>Oju8Q?^|jNtI~ICadSpb%Wq zNi$zg=p(Fro!UkFzjNx2SWn8+Lnes%*++m`-OB_h=v4bbQa@QoR!FPPNEp0VJs^k# z?n@pZ@wfVjGF{KNf3vFd9tU;m*~YXO+kw+{AidN2`HYn#%rHOf`yFrv(} z-sZPU0Cnb;EG9lHA+c|}T$8D?pWl-clew~i*F@*lHK!{AV4k?SP#s*xXLnRFZK(W( zJCAe_gE5*@1_Sm0zEA3q!#=ykG!MV4yBV3d(%>M2}joUf)EHVu47=^#7+&aM^ z9#s17sQxG+QH&(WC@T^#n>)8puWoyKbi}SiCi@w0^>6(~+z2Sit!BGfPiZ^5r)2SmO^muvW+r`6cX_yx>p=Vdc8l1J{;eQt(R+mlj3aR z*9400aWO$bNIiyUAJc!(AS{SgiH~3x42sy#UDn$W@f%s<9|W?=9Ma2Y%OdzL>eqae z>jjd@@Lc_c#reOzUvHAe5b@pCvvxJ?=7ZLdNdST_;8C<9H;c(Y{)0}h{TOZnRY0Do&3W5Q{xK2A5S3N7oATFbO?{*GQ4F} zW(|p4jm<>?9)XrNh(fNeA)+SqQGsN+_8X#R2O&qGLAad2K%@Yo0N~FIo3m#1s!{;` z+Ce-c`mF$4FoYC-l3jdU^FxxRobmjQ1tVAntsIaqLU0!BP?A%Y;WEmZ{=%ChK7l_H0v!?J7OKkL<0w+k~0~eBdB@!6i_&LxbNUXOEB_G=~yhPVJ>MctMUqg z2h*uPTsmL^lnUIpTkxubun*{;u06qdp+~Ru5UI+}0v!-|M&3{t;9KZZw?CvXvIsh0 z*HKae<`G*KIbWvRd2!^SCfewNa--ivj>xdy9J;Pq7_%(a5ZIj(-^C*Q`c>>k>Q?yVP5tJ9qGf>A^8bi3O zCd57TdhA8Al`X-s)LS1`1Ad*rAe_w?Q8Q-rh!#{ENgGSf3qe$AuF$Na31RR3LV0YUP#?HdS)GryqTYrG(rhfB&fQ>{iNXmm!E;Rxl+P3dIDeoS?RgCm5?JLaCFzm5m>@-WLlV-6^WY!EkrRTmND^%^qu@Z#3!9)+`dyO6 z19_f2dvZPWVAz+H%nL@h)q;F?QxEfzF^ejE(nbnQcp>fpkOP$AYqlE8G?Z$1y2#WC z<*Dov=xLs^Nl@ld_QWeru=H0O-CobP5{S)Ep5L!qPg-%QvpElgnRg(W<3KoI9w89J zkUIGt)C8(kE|R^BFl8f=rJaqAX+)t%FoGD<1`9-4LivP6zV~|PM`z+ngS2S|;_5Xm zAbLI6*^61Rk%{!|KcuSlUIuY*^Kzv6SN;g|6hrP%rDC{`pSwQH7mOOnvg6@6jFto0 z6hO~*{#s%muJe%UArnQZ6jxaDq*~Xxv`J2&W=h)Q|Qk0lQ&H5Rv zCsfmA6d%-Sb(HP;R$iN(0Xd+d{g%oxdJ&8X!~BH66d(bhQ9&w1+ndw~x^b>9*qoWP zG<=l7gs8DSG=>t8C0md2>9t16*j%XQ1#^~a4-dj+sNAr$efAk%LE2s^fHvQ{C zIxJ!L4ga$4jny5ghdq%Qboqm+<5>TZi)?a}T>2}{HL4n+!)+ScfEX@`)AIMWSSrc7 z?V4(W18wQDq0LDaAoe5WK_?z9Eg3u*?}SHpT)oWhQ7MS}E;A7L>J$1gFI#dyd$x+1 zNI0$}0hHE7Z>FF;AgB+qped*^-jw{cSqs_A&vgu`(Y$ylO8&h#){;sD(Jy@nMU0`1 z!g(IOX3oe0A1ZpGiyzi^wyknf8&6&xCD+v`0%!euC4;#Wbgdv2f{f9tehl(6?MQN0Fl@^q*o<_krmg%RA$Lyya;;4bfr|7 zen*!$d1zPMF5XC;W(TQ*tX^h0wdNM4;l#YPphcuIM|@^4uFIIJbAQ4v{7@wwr<|ba zpbBF>s}QSHA*fd~gTLmkQVGs}@GZ;D@hgxeu09Tb~NL_+> zQxefN>6z6Y$Abd~G*}~j2xEVMCud(1M;?# zL|bHQeae=)B$EGB&}_X*0}rad{Ypcga--^KDB)W}SB6tD6fY$|L4Vb&#M0kyiCMAq z@$aDGR7OrQ1bX&h-UEH`9$JARln=?^5}3Odmf}yw%D+A0WkNyt=3UXm)dmYS7Uv+_ zsnAwk%X9{v)JAStzEBH=OHznHqPj9(6kC%n)*;txFT7bCj2037FJzhV*Hfdpb+Bm! zi**?h3WRPMtH>A!h=9u#D%RI72sa(z4!T!c1QLKpD-0>Frmf)}WG^+1J&MDGs(TwK zALMj^fAbm)mx9LivEu1^GcnAySOtls)IFixkTsbYNX#%DZ71D-t~5F~QA#ddFCv|B zThtT%>1DG9{m1bs-D?TIL_;SGS=h{4i>OKZ8KavysG}xZtZy=^hE81&tK(fL zga9aC+>=Jg5tPG%6_c9pNG;u7)q0f9dzw0u7F;RiCMmKOSjCVen3?K9#Pns8j!Dij z9|4n$dScRCj}OZJC=3p##=qFfye%-8TAETyW>$qoJybmT9|=y`MK3w%s<<24*H#+Z~l^p&4cq$1& ze-29n2(~VfyEJQ-jK(%qlCh;YZNoxx4663KK_a#hn|1B0UaHh>S&1_JpY!5+^J(Rg zA_gQ_xIYW~xk%?eh4F@>8Z+HNauGHK@uhS2<47(U#ht%J^rCdsF{3nCmz4?!((nhc z9SXWtn4g1lfgIQxhOybCCqdwG4V4FhV$_h_2UwBF0;xgU3|BPlqu{`9#(O)f3m$&w z5vs`88ed$iQi`-2KoIVMRE`hRUi$;rwa<0j_(lSBdCAh@Q4RGcf4omuWYDX^ELktZpWvH<^`FS8iiY&E|l;Bo2YclMlC_1X$MRHnlP%E9KZHvgU)VUS$l%Es_ zR0>$|PNnF`zS!OvvWcD|bS4Z;Az*oVV(_^RS@;sA6fJDIye9qq|M~SH z1TMVaGaP-(u$WlH*j-$N71@jX=jUUzU^Oy|{^Bb9N^B(X^O9|j4!8lSfIE^33gjZm zQKe=AVlIHtML?wX=f&}^PyMDs@a!l^-Dm)H3w|%JmjB96`v`8o&}INce6i+nB;l~2 z!*Z7KUvk!k(Fh=5Tj@?5MlP^w$_;>M#>Fb0FwB3k{xI#|hsyUW+nRqGyTQ{zY7Lu(BSun#SHdm> zlOH#qUyU_*?-ir(OEQng{qSpXBTYtPTxH(!CDx3lh0Lx((zF5c4(vNPxON+fW=j;aIx;wlC2K7Vb^d+`ej3k?BEB zahfcOqM79s9E;@~J%3Rv!kiup+s=J`VR*@T*>)MeM_m$SeQPnv#z5)f;NZdoZJ>og zHlc8d5|c?4{JcHpAT~S21~~_Rq&b`8LLM)Xvq_;i z%(0*`%2rEyHzPov9kx&CzQ)m`2Gl@1APdBW6B|}nlrHohh_>`vnbpchRkEb40>{gV zv#=!Gt}-hHZp@vZW6)3pC@Gy=#f32umxi0Y6gipL+f0>uDS`^Rt1~wBn17Z#rgIb0 zs4(ygLPLO@tOl>zRORd_Q5{~|xN5vugcLj+6D~?^yTNFdFq$C|(Yr7z-bD$zx>42P zBPh6(3d5SvQ!%44BX`o)vU9R<)gnXGGiI49&nYO?x)uQHNkL1415rhl-z=FY^S+i{Mz&@pbf#xjXc5bPrIxd)Cn+LS)(Rzlz9YXd?xHlxQ$vN9TQiZ(U*?q^?MV^va9%*$BJtX zkrCA{&g2xFCynykm3kBeAD_;CG)qDpWPYLEpx+-?d(SHJSaVfl3cDCO@JJc!ieeAi zRx}*T(q)LCf8%-wHs+=F?P0WC9vPW!0%T3`LT0j z=hp3^|2VL#_qBOGX3|@0ZJmBQ+cSRSx;m}q#O&Ic^qhWoARB(6SE&l6c^&@NlqF)z ztHt;U332WJoKdoAu`Oi%i4ep#2F)NG;DXWWq~f`3015YU7pkf6A#u4W*j691LUWw1 zfjRAY>xr$s6aHf7fjr!)TEiD+&9xN#O30l?2x@$q|yT4S61A1>8M!_P+!`UlFY$Is=p}cRVWgT>_j}-otU}zefvb}`x>+J z9+pPyQ!n5|`shK9awQD#bEX=aP5n2p`X zf}kc=8+>ZY=E{StNq6tUPvj3NrhskdPvONV2MfrkRrn}VWQEm8etKviqLwv%?! zqJ~y$jIgzM6IFm~z)f>zqq>UU_WY>{@z;s7Um0A!-a9eeHuDkACgfi8bsDi|5_|Q` zFaY)6Z01?zDZ?OmUxa!g+}Qf%=OXq_#7))qYZ>)Suau0UQe`x+wjkL{ zG7e*or)SDrvd4zX>5WrmgSKU{Jb?O*t;QSaDiHp@0W0GXkrd#k9Wbt)S{vj$@1a-+a(&UC+7IDfS& zvA53<-4pXng2O;z=y^LS|5|kX1CW;6q1msduuILahoGPivrF!B>dJVOzWJo@hjcG#)IWFD@fkqSN9n#o$N zh!NhtPCAh;oP9&56IBPl^YUR`r5R7)e-NNmwq(rLcm_I9x>8bWo1AZj=h||~?@6{O zZWoi6-WHKjD={vC)a}eJIy7D`ubY!>bV@JKu+WHY{NEB4P2mG#-53y16Hxni1@7eyfrv4GDU@(vQ_EX0v*NryE~BI*j+KQzt_ zbL%UFI}gFJL2d2g+npUDw;+fr8|i=VLrx_{Ox})1)-=wq=9yA~@V_GdUMrXhCw6!7mz-7RJ#;OmjjcE013wpv+1(-&#D_vL^G!KUJ|66o7ZJ`Z}-eGoxV~}Ro*=l1(lxM%29!o%xmLi-m378UMs&o z^D4NB3N59&8ki^7stf80xu)^Np)tu<(mD<6y~H`HgPNKTr8YHl@RZOddLTaR{uqraiWXd9hpN0_>aTQ8n2#2T7YjiBp!0`vFQybKh;Tohj0#2hbOTnd zKH|9+EKt6+kAXyDnKqhB^k-%)6Qmo~VG7;I8R7Yr>f)ynkwLpWIYK-ofxb_)kQ(69 zL#6jrzm($M*pM8~lINC8Zpiqt&h4HR)Q;>PyQ%g;`%66p!hTk^`m-Bm_cmwDltS0c zXjz69QwaLwqJx;6gO>yUu!ZMrh(H!n4AZe$3zA}tK`d@}h>df_omOvDXdjXY}iCeMn8 z+mGZZUYodOweKIFq_U6i!1Kk4xE$f- zAJ@DO)6UJ`KL@m_Uq8-ZLVgf+JBnqD-MtiZdT3z`*mFAX?w5kT@m6WhPca%@i?e=x zZ!bG6GAW#jK0QsJ%O|(EYuzr65vvC9A^d(l(e>yA0yAml?8&hc+uN+Nby4q7Q_{7(m5u51zPdQd@7V03)DIzZSRTdR+V4-jz)heiT z^b{07`HgkxBq}CE^RHr~QfsHQAWPqWP5wwf*uoyF9nP_0%_|=F`1YCVtT>kFdtBk( zgnnDY*Ejz7APW4{zh{qAE`_HGfitwVhYm|W09uhmj&DI!o2-r(BxS(=YQK2ZmQ7x&ecm1KDC*Br!e9E_MYJd^f`=WiOn6%-~^Q5|B zG`iVH$a%c~bN`Y@OMQDe6np9`dgX=N)=u^sq58B&jlG2&=91hKS>&zzo9E6~%R9Qh z;hVzeX|spIuhs8v71_xy-;$aEte}ni4*mD&I)Lkt|EDCi4!Ic*oczB2hb0oZmkTob;jABlmap zH*t2lS3f|-q8HixGrhWOPY{zQt&&1$iuHR4^I_Qjn2A4 z_v~dB_0Fffqwc<742Nb3XH{oI2QxD>{-}*XfGotB?NGD&+_SVYA7RX0_pD(-N%f*W zGzAD)E?t&h5NC34IPuYMhzikSqR63lHY{34WQcvpP|=BDS;pH7i%gU%aoi zg^wyDa{Us0Ooy&XBtL%UK@~J5(((iRARuPQUph5Il$k>4X_^cSZ~Ara9(0Ys?go?% z=0tHR=yMrhNnE<3Y<2O^By8N5uRJ`T&yO2s)3r!Q-RE3{+~;(0aw^BIsNJoqwI9A$ z-mo#-ljjaFMOuy^43v+;Gx>{ClEV2W3b|Z_e@Am>Y0uhmqzlATU0V8!orW;@> z%S1JN%EU+HKtr{=js2rtv*$lG7;^mP<{x}Z*)@LYrAZ)TH9w(wejd+qadyM)h_v5J zO?kZd{YQ@%`$=Zk6JtXZez?3J#lZk;pc3D5#NSy=pUF)b__;{Z$xW0?3-m}X`HHx-p{_~VEn zh-j5K73=%`&=drFtpe_6uUvb;Ve-enXU!apLp(ggmx|~QWvsmAt`Lr3>8d;!98qR{ z7F3LPUQ8kk(3fiOe#c*J{mhNXGgxhhK_L&6_G`^XvTsG;rP0w72eQoT(?D!v|rJ0_tw1ax6heOO>0SOu>@4H&{^K&As<{2#_t zHHd3t+NJb#s^~d#ZNrRB6NS1f)^&s!g~3x0ZvlKRsp93LXi{>cZ4g&@Mr|y4^x0U166pUgtl}{blRk-L{4H0 zK8~x0P@z3RgcMl50(%I)0&3mmH>Un(e7J*hV z9-rEzcLFq{xjF33qhe6;(O81(X4rDgfqza}aiBo*6E@C)82VA~A9rkoQMPhv_Dq_g z9c~;kkI|+UNYWX8TF7fyri1n+LPl=B(zeunPmyrh&Uz_HHN_GF%lJUC!aw-zQ}ks@`Rc6^0WH)_*=UIhn?TvmD1^DsqdV zC;8-a!1DvFhAzDe`+TOIhFO1)9t@f7i39XS)Lb|ZjFvH_)kHK*a}8vGq76N>C(T*oRhFIsd6h^}_4Br6xz( zPt)VSYN=@P8USwz&nJ$@V;tgIA1^tOKm$B{aM~b1g6p|_&G>wbyH-^D=$*Z_+UUb` zlT0RU7-;#5{zGVm3AkM)SJ@57G3AEu<2NqvF0q$yx)PK_>eDt3BQ3*rKxJJ~LQG7D zdAV(N7QfdmM&pb7DrWrJFT+bL{OzwKbnJPug z1&Tlg798vwJoguA;qjXCsJ|QB<#+24xwxT^t-;xKv&HQJySW`&%?t_fYu&dPq}Hcf z53C6=fbsP`xWw1pg%+_8EfHtsCwa*rAr7tV*8h23J%cMez9S@TT!v5#!J%{d7a_8L zsr%HD=Io*sF&A=UBMS)9o!(E<-!ZC=2mgvHWy}m z!fDd=P3Q!)%FY8dZ2!+LyH`ur zF5k{A)XpgWP31DoRcV_@>zSR&F(|6=t=%M>@wPshnfQ^qqKFQ^(L zxN(B2f^nbRpabWntLAbiAqcKAYk5*Y=Xf$7C;Pab*J7s$`8u-|Ht=HH@z1N}=^=V* z7t3p-R8L5iW`V5Q?Waifl_XtE$RYK+jo!8MAoUPoMGQ*TWzp2LD4q?b4%**NH1jg^ z%5*f1|W=5tuSup#=YMEnfu7olZ~UB*%VXQ z8WF(*X*`LQL&u2<*J!U&mWb|*;#_bJgQ=%PB|?eEX^d<@v~Nf%S9>}5c8ali?IT4} zGp60+815jXPjJcJy>UV_{Yb2~z-=5PmQ(ie0`!X@s;J5AC1WS)E&UXz(nf?s`~fgG zZ_)}^ z(G;tYh$0ms=V*;!BL!2Kz((Ob_zy;)(&5rK1Gya0guT#W2*0=qR;063Q5u#sZpw72 zLa2F6#LNbVNCP}fGH2IFyDQS570LT*-+IVoj16kkj#;Y{6iE2M1b}9uW%T{M0>dGb zuhce*go!W+&7mWNy>#Y@tgkAMfOJlOEU5mdl^aAlh#|B#bCaXlH7yUJRIVI4Bcvg8 z3%9c>r3f*}v$dfMFO>W7_@+cWJD^|(4_Y!{_gENgxFhqQery?Vu-~Z8M1*}V>7PM; zYP)+()!uWShdrG~ttYF5XeJdc=^@YN$ao_;nxU;b3wu9yjEtF}s*@)*2@9bt-%|O= zQV5K1m*>i9ajaFqEfL^D@i@x4lZ{R{Pz;#X`L{=skdhf$IqjYJwALa(3r4yy{CJT( z%d_&7w3!KLMPTEA@NY9-x>W&fNe+copow(Aox(0{;e;TCKnaIBbdE(XQlbU=&q}aK zv^N1HBhil#xzRvf2p69;S6fAttBUuE;hKK`>~QuNb!#y|2a#n#?=@EAZsmMxX^Q5% zZ_SSWcl#+x%adVFwCqgnC#?+Q9kb+HJIXlI)F;bOSI1|s(J(L)v%Zbm{-rw+rI9Nn zNaEqJWO5a%o)6OnH!TT38r;pp~>r(mTGh0`?y8~!r(LtIq3>(OvWUcFK%{lZY zN(O8f*qxNLxV8BZkjtV_fFH*hOEV;=3GTGz z&`EEGlQU%bMSZb?6wka?$F(t*N>sqRPPv5X9F1;F?(96s;07#U7}xk)hX-GLcc{A5 zjc}z$fdk&lFad}@qY*`T6@!OPH1})qHTJZ#W_JOlX@zUpzSoGgx~4zJN{uzYNL!|M zpI5mGR?Ci-6elM;Pv6rF!izlMJN<6{;58$L9Pbd|iC+v7U$6ZA+vgk4_sgpf&V$l< z%;gVF>asj0RNXT_A;@4fzhCL&;_?!s8vMS+gxWT@L6G|$;Ejoh^a+58FJrwE?&*)) zE4I913rsu9eVZSJ;*|46&_%v%W9tj2m8n1p{M%u@A&62XR%lK&p+b?(HDa2xRoAvs@&gD9KIBI zPZ=e^R{bTCsl=Cuz1|%>3(cYXPFqUOkHmC|H4-D2sTN`Pqkfow`v;PpO1+y$)V#IN zo@~GZTJ|+~<$GhkR=|G!!M0ZBVkwg6%fRXp2%o;r57n?LuxA!?kLLiq81f8;O{OC% zavKpL%3MAQFGNe<-{XNp3b)55?7~W%Cp9|UGNAD#)bQF3!)Cz-b*=%}b!A6O$@{$_ z#KG>x2)VzwZNVQ$2BRC5T*W##C2AmGye!itljgBB5FHYfXc=GcrDXm(3p!Y~UPn<|zsg!R8+in^%osb`(;wB{8# zC`5QlY9ONW>swI?AXbxqKr>E~`}}X%4QZzWD$4#|(r3!Yd=F8wcyA@1HxKw~LJUzwMhFaE@9sC&Yu5MdXG|uQkBWQ~&V8;%Fvcb~6ECk*!@Y z7+Ny#OlMtA$UFp68xcxabVz!lmY4#wO{V^yKamtMt0-(#A9;=oXk-`4jwG7`BnUf- zXo7Upzbt$37dfu7LP$(fF0P=1zbJ4AGpexF+W1G(Vj?kAc(I;Wape|xG(9%$n-?cm zoQ(5>^3J$>V)!&F+BUf(zueu4S{-aBk+f%eD!>zcLYAC8U&8u=l&U!EZruIC#;{Q3 z-$(siucXQL5UJ(IY^WXb8sHtW zjxJny8WV~qE*w+p7^tdGCZ>9zDa%#1Ae&O+b#57@N9m4O&%(TXeI}~JO~B>3FiHmC zG?&^i%%<7@cn)XQw9*IjG+DQVPFfGX%YNQl-LUC90XZSz0HKm8;17hV64cf93)6%5 zlw+7(;!OG5wCuq5*NjJ!#vxUObBR$fTx=_zWKP#Nh&CbNF_tsWEgFVQp-ZN{qxfAX ze$^X&;ep8xgv!jfg*RNASjj>ylaTfX@;%$O8ki)!eGNabHp%V1NL21}Se@|G=*|ux zhS_JH#h)%f8IKf2GxsLu)0ZdzvVmCKcUTDajZjwpMQH8tVM{S$IHd=O*Qkg1meTpM zyT>NDEoo1Zdt_2mneMthd0S_J22Ub=CV7zcxgnF*7^uIhEQD3s&Nm>-ul%g|R4p$|Xs5qYM;t_%-uUxqM{GSW zu`DM{MimOBH>4N!7H%Hf??C%XvpbthHrVV|?panNhvU@#ydEFssuLHgdhEOCeN+tF zk9{kX&!qz{L^0dR;y$pYHkdfn9#U2*8VSWPx{+oq=x8?v1MtgQq{|aP?=qM016`gS zrGD@H_{PZNWtnNbo1~813mwtWyj`%TZSa5|DSp14@6lK$CzN?`xVOw&p{Ei3#+USj z6?3Y5DpD^3FLPHXTZPK9@K=^Z0wmq3v6NIhMq~fDj}A;Ta@pPcT32@;ij)t>iwa8+P%%W zSiPbSIKiy>1Ze@(3*D_>UOr^T(Ch7S3>Uh};O z_3x|P=0@$ZrKG(5`#jpq{rNmE`**?j`5&|Bk>SO zd8eygqAkmp>sY-+=KkM3af47p##Z4L#oWzh?3Kw1g!BCZG2&rmCd=A4H%}IoR2p~t zTVi276+PLSEr_}TU1v4eP1kaB;mBY~>=yABu@J;&1`1LQDY?wY08w_1KewAZa~Rr} zmjEqSx4c2pT47sGMCeh?EUW{fbxu8S`l6EcGCuV%J9s@x)GarNn*;zgh3vfY=T(k* zQjW`U!x9W`7bUm>%(~D9?E65o3#f@dU1dW3oCZVRj8E^bh+2#%L>oR=^$sVcxFMY6 zzgofiJw9=>MuGlo?^hxni1sU;buW!}7wU(N{860xr9>b9`XLp#>UA2j>6C+=hz(zu zk8czj7$=32mHNlEpz2I$(xdC-5=M^Z%90jN#gF2W%t@x%7_4jw!nyV2t(~t%ImS~n z;*2xcAqF`DAT@WKRmuFOS;Q^dYmk-FH~TYm^NmKtpH0T-DvOTf3sMl3D_}+jE*pwx zq6AdO8s}Ch;dtpK5)Z^yxzFcnsmjDJ^M1Qs-uq2|l-iJ+3-#L7QkMC9tvgIqTmG6= z{Hm$YrqO9FJI;n63BO6FU7ziF8ox9gyrk!zu^w6d@YWkyeuHyC=*=rM4QmvhJJYr% znb@Dyj~C!on<`ZEI^^#Hfd?bKvvu~C@N%uA`2cjcXb+CSXe(@!~7&vcz|nEvn? z7x*A=m7x6KAN8)@Z>m7GtJb5Rgd)GLK9$WZ#OhJo8FhPo#kO@FFL+=@r6PY#)88c| z-5j%*%D=NqyPZYMr4$Pr=1cIEJ>z&3G1N|xTZDu|!ebz?4}_P)X(wI!08Bp7F4MzX z*jrY$B& zTT`O!Qp4IByfFwWF-p8vO*6~{(`qg^Xbdz7w8;!=qE1vC zK{D}6m+SC5H6cZXZG8i9FJF`PFE(#@W81cUW7~FaY}>YNJ2$p(Y}Ae9zSuM~w&``6 zsr3d1K_1epyMsNgi!@9S{==nAZ4}dk^l=$ih;W{#a>jz)e~D}|bL)dAAlt>5S~=yI z$}|I-{-RwmHir>rAr!*aa__X|+(cDG8Q1rj{Sn-82ew)YLI!QJ3@nL62R@w>J$lws z&OeRJJYNuZ(LP$UC~=*&3dT_M$7E{@Fs4!{2~9I#B0R6wc$-#5`_wbSo;`T5zwYgB zym$EI#>Ex;jaRrbc{+G}T_%UFlOh+2wG4iE1m=CVnd*(n zS%JV#qnLFnJ=S^Ec)E&h=&?1VGiPKrC}#tL|B~x`V>;Z->o3je*ylh3iKr%!QTLbD zw5&K3{z3&lHR7cV;p&-P+9UEYwNoJK>fT?3%u%UdqF!d*nJqT8t)#+_M7ft|CxJo?9FNX8ZC|%57=b5fP~ZT-_E?bZIKer8b)Wj)ksg=&%@m% z-Ud`n2=*$TTD!GSi;Pw)-FHJw9IZ^AmzT?VjElSY>MY)buai~dZ%_H&^KXdZTza`k ziWJsALG}}kB@D0BK7()Nt4H7MJz)-drRpm+1$+EMl~**j5H~;jte3EPn!EV`Nq93N zBbPm5Lq+wFkK`Gw>U1udu*fjpgdc@<2!pB!)+|GZt&CapuoQ`I?B|cLO^y)QE}1`! z4TRQ3=wKDVC^F6&F*j__@!X0)#>isfciyUht*R8YwHi7IqtaBm=^Co`O4?@`OQJ1K z(F$Z}t0zA1x9uN|gTP(+X^g}ld{^$fZ2kdmUb-M_k#bq`u>Bq2p&VIWXTEHW*uME* ztyBgz_2D9OI=iVXar0ZY#^M18CWWrBep&HY?V78EJ$`1%*DiBF`}-?xK9}@52^NaB zUQ_)k+{9u2JISt*)j+}>B&Ic;va#VS7#Ub|v@QHPY^&%(IGOLj+`LM(}sOHssF@S-B2 z_6`A{6XY3>&M%)OI?wQ}jmmxv>_u)Sk4G-1E0aau#8#l>Ior6Vx8ax$y4dAiM&3z% zL6F81&!W5*Mct`^Uh0d+2~R>5ElNet9QkQ*j_T+a2Hr86~GKj!zV`7Kd%QqrlKqhc^)CbmXJQVdvMnFhJQ{?Pal zVB@i9)p`kbeBx=2V3$}k%6Ha1WsbsTRPAE9<@;K^Gqx#l{L+GpL)5`WUfy}%%Au6d z`|E}Afoz8997b>G6nAqUS91HI1Oy-X>#)jfHfeyNR%s=X)h<590y$iI$Kbs=ft%}? znXqh99xPd8tQ|!s@{3?-??G(NUQ4!-_dye|V5Sk`o1=Z$%lIqcwZit`GxFE+#Cw=7 z^6z7~w_{>kk$rptGi_H{VqEF7tdZtDw5pQw-3-8J?Y-u$(rdakzC*(n!F=6l?kEuY zbSTqQM+_2FJe?9_fd1Zxe1sm-TC9^~XkXL^)UcdeNN1na{0@5A1Xk;#g>xFTzf)VH z@}5-h7!}B40i=w-$S=73)=2k%le=-{s04j>s?TM0 zj;f>Ia8~)Q8mlj_J4wcgI1PTA<@T&&P(*CG-<_?Zw}#M#bY@1{da$TrWG`9@TTg%cny(iMq!U79)+?M?H;h^pmWU9Xm-bLsqgi0dzHQ zCaOthL3J2+V?S~{g@0VaBMp16OVcnxiL;7CFH-4Gp1XGr$HwieZBhVO$gD?fl{~5C z-G#>wBG#tJH&FbA;Tu{DIR#%=TRPWYl;A0m*_su)mm0Vu_qve%K01Ci3gntPBEN-F z2xO2_|(0Qo9H4~B?39+zH<&n5%mhUr*Y2;@Box9PA5IM=cgD|h%Pm)6Gt z-cxC}^%w8kWslRX0(&BN7MyD@+A~8=&A=%hl?cZv8m()f2vnatjWeuIsGD=s_0GCd z7rjVl>xuNOm-96ldn-(|j?a~ijty=eL5x;95AjRnmzah;W{_k+w>f#e7Ea+7B^iQ; z(xlU6dYof!W7OT|EF^BkYzmMdabGK2$-Yenl{Yxnv!jDHR#0BZtB@b@zuM*vL|S)z z+fzO#6f%|=F!~r?m^hzpiua3ofn6mSrK~p}Nd@XlPcaNQ2g)%%-xyMKSniJmo)wLH z77lc0fa2RvSzkGZRn%okfht1 zPWiyj{^}VAz9~;oXW^*SBklaC z3pB5xTwz!Bp^I#sE>eX*kW@WH^-y{MuAis;iL0Wlm(}yco>{$WrW~o%*)O~L5xp{3 zU4!d&hBMOttaf!fxZDSPDrg6g3!KcHE1|a830{HVAknr+ZsRzs;guE<#Pd%%cnDX+ zx8oAuLLAal`>B#yXsD@cbYN(S231!)<&NxM0CgJWJ2b-T8H%4trZ?;A#U3k)c8WYy zINWZBusoKk6cBnMbryOx%t0JTQE!YniYdWoEk>HnDVfRp&G>*M)W<*6xO)b$EqfC; z8^)%$P5eFa3cdJ_pPxX2$H?ro@@0auV2xd69k1g1vpDgz@ae8~PF!$KAl~FFd&N=e zB7&sLmX9{UQv)=#KHqx+S1S;|D&D#8lD?$`e%5QQ#2n7aJ--#)h!?2oF_D#C1u9qZ zk0;ej=OSGWF0=cLvOqwz1x@h5h*cGX)2ftmk9AeihBTWMyqb_bnFCn>bv_AzcV`+i zO8Mxm$7#dr#q-Z_A2zVO@YX)fBFrc61NfieA|oa`nPfhd^T1+YhUBUy!bK%}nxFF^ z{EH)Pdr0&iWQ4~v2a~~aqgSGwo;+)6nhhMpPkhDXaDrh4WeLGxgP_+fjr0u9W}oGQD6sE{EdKt$yG#mv zpldxGSQ(@1e$vKU_OT6NFOrCF2LelY?V_B+l^+`4=)67H;lFaAbH-sw=`j+LyefS< zJBhv0VYI_GCPGP?*^6B}YMf$DGP5K-g2v0KBi{A>K;z%S5FprY5bP?JkdzJ>6k24r z9pZ?G?2MzNRgdJX9KMdTkJ!1fvJZwUBC6zUP zI=ev)@Vkw~Z2$o<0aQ2sA3O=&ZP=WAL{ploDNCU(#xM4Hqy58>uv|#Lvxw%~fu&p^ z_jEsQS=S2&t(K}Q`Xtb#2{Kq_s>glyvLc`*=o^t8`xD`yX)p_7E`bW`N)VaM8?@rd zn(OfdC%C23_M4fwYbZGN3uKzVPBijU5-#eGoce8t;>2^mc?VK^S!$_bRhaoz3r3by zLBXREA|}`n+RZ1N?#jV$3Hl@n-Qx~5o0djafAj$ItRW`Hj!&|Jj5SMK;F5^5&ky`I z2X}RUG^`E*vXBBLf9*3ZyViBU0#G5&M) zzNDb^*eWhgH0}%9iXor*acqw9edPk}aF1gd`g3XMrUXY>Zn+OxgM z0XsV8)i-H3Q3YxEi zrXVvUjot9=8_(KrJkiLzLq4Y7+w;6>H z>e42mAQB77(-_Y2P7Q36jrvMw#0RdSF5Eqh8y3T866`m?lRKpAWjmbO@NMy81?b=c zvE#Mnwju6l`Ht~7Xxlwt*jcA*jkqX|y3>&w%j zqEE;ykf*S1uwLT298`eYm3RmAtfXDLA8y1Vp*<|81Rjj{V;-Dij7A=z61?yCv0sZg z+w9JHc&3RcHxlmrIHXGn5IL$ZON(sDS(Gfm6Y5R5D@kXB zwo*)AJ?!Ec*$uV>>`q4~vE;0wFPw@Llq$8os)bbGoM5-H|CtDjs-5_ygnebgE75j+ zTl1QZd%z_h6*Ts>oFUX^^va#yQ6rAEA?6wvW9{f|>LAE=%d(?M#u9UF;e0|7PCU-C zHuO<$6SQPQe$~p7u!B8EiE2eC$7f#PVPD2YOO2aaI9(H9JN<$iBbn}aO_Qr;oUdAU zBPsa6;_ccy)R8a(s!@8~AZ9wzaplm0AAR$XgzKPSzIDtc@@m zPpY!2;`-QxTq-M-o&w$JMQ&QRGQ2ZsR86$_n84%hKGC8_`G>?@SYavDf?H1LG_# zF15xPr8mYkZFFo^LT)ZB8w)8&^W1C-k$c)C|MLf4{p0fPy<8wxBuyX$iht<+ zXT!a9cKhdf*jscF?LEMJtIU)7*@k zh-5!}Q-8k}4;%XPj9+hapE@b^6g=e@gcn z2r+DI{yO<%Vt=@*S?H7BIu2lV1?>9tsh?BgMg8!jV|4qgnII8=~d6q`**W zY7^eSd;7>U%t>rlOBKR~sb=8Gs=bdQmcTG0h7p+vPOrj7nqwKK57W-r6uTNxW-f9z zIS}4n`w(3yj26cdacPU)^T;Ul-&d)R(zKMgRgQ*tEQU9XV8-^Rd z@W&;1(3u`{`E!)T9nm%^m31VXMhbFX30Q~>&C)46(#IBB_@Y8<{tYQFvexH_{br0` z&a`QK)9xf@55!GVQD?air2(B4pFkADpDIka_*`MD;EMzS73)%(*Azh z(cZ**?%m6p4?hME0c+nIY&3t=vbRO**P?5o^*olEj3(AKb~@q9JRHk(P@ubwX-YBM zw=0D(iC}nETr&p!WCgr|5C-sB&WkIxqag(ED>gJ3O68sP@IB9owPS)6wf)v z?|UfvhZ1%K%1`0!EZvZAjyreYQ4oG;A@UfzK~UAx1x|V^YRlKDDTea&7qPlgSA|r= z_EZ9SBGcvr{yop4H2+mdTJpAWlWPfFtMPIhGfB8J?8 z^zb+VL6OMGU*;~#grn=?ZBc_7ZhF>X^k`x#m#j*#R84xS=w=Ol8g0CqFmM5#q8p?e z&E*ZQ->^+mN!d1@u3p3TG7%Ot!Lry+Ph+yWF~(J~3P(@lIMiNmd1T*aoRT z5)VP#%U{g~Sx1ZDekXZdPM$#Gm05yG$0Ce}o@~otC@3&~y!7mr7)cW6DS`V`X2hWL zo`^cxD%+xSFgQvXTqjF8ro`B_uGjLYQW#9(lp-L%ucDE##yN+8lj&aFcBBXM8+u`F zoA5u?V6VMZVyB-N6m{ITE(WH-gM9K3w*@Z)O9q*ZfOTS34qwjXJ4#cV6!nQ5w|qyz zVLHyHCGD$AxNZ(*>;lwMCJ3VVaz}iMNzhI<}s&l)~wSJ z&9Xb5;&AREPX)Tz!uiB(^s;OdWNqr`o)Fm3*wwPCzeLtnPtsBiic{G|(5@)0k$LJi zY=m;Z@+P|t{w&-p=}b4a+@?#twlc@9SJ%EZ&!hUs>NRJ>y-c1FK4!F)+k(AH|Jtd< z_1f$WSGmaKUIvw}D2=SFqy8AiAuPFH4s~<*BW;8cF?6xPug#fhP-P|6utCKoO07eP zc?a0Z#+NGw3!XFV>mv2+{p-6Z6P30SBn4JHjBMrJ5J&BJIi{H;f9in8yPLcRau1Os zy_lS3&rUIDvK*Y+kp=lyO}^kUA6}%ZbJ~KF zTiqAVLsPotIVdZ9TBZsyZ`HFj#IVz6rfbGIo-BCKGRx1`Mhe~Qc@C@?y?)vs;mIHLd%RMk(L*a^4wb}AfaPWG7KC?4=wIERSl%pG*vdOws|bIkN6 ztMq$xVk;=N63RyKXjw8CF+zE6c&yXct>kk`J(rxydmX~S_P*xgtX1^eW-4Qf{TjAgaM?S{AP zp{Saz+!K<0RXIS)Wm87jf@!Zmo}b?v`~6AOpUj^ag3fapS*(1*KQ=G4iuOs9bzv1; zL&ztE^|n3C;;{!M;GL$ri#pnx)M?p2h0#B4Ql~#e6iE4Oqi=q{Tapg8h|%p<;0v#B z1i0Iy>YBE{q~sVrIkKg6n+29!#~w(MqOv=tKCZ`LW7TqaGh1)(nlPA)I0m1fyjdX= zWlHFSzr2r=n1j*X)*G4fm@&DeU`-|vlkRw>Ejmnz*7@*)bsj@Xhgy{uP9Ux#-+kqml@)NCqkL2RN(Utp<{1wwrn;lkNBQg|FfCT@Cz@)xK4Q zXRvnGrk!4%E8eU7uHOth2+5b*8Cbrq*YMH0ARbf}0%+UHI6s~vn1X3f0BCd#m(TVf zUsSqVo-JTCB=>K-8QZ-Kx`;-FG?b7FfC#DiiJcV-v%d5m$VpbsT=DPoUHj#>T7Iq= ziA~Q2P8DmNdudkM?A(Uobm!1N?R!+0-+9u3p`nw=UeZ!P#YuN=J0h5pEsth-`6O zyemc$vLC~7s#k}2{feTv{&KfI&odl79q&zO0!^XGqCs#~P5jlN@h|D*!~pLGk+RDa z+%fy6Wrn6b_q_%=!&aCav+Ya#?%=kEczN)NISHQZ@DlW43f>>2TlUE{WNCE%>J2|_ zaDK>(>(tHg@~oAh&|xl5oBqtgH+8))W}Y#^dr&0M6|q|;)(@AeU5uQZEk1X2a~n#33KnL(QdYR?;-urn0t74tybO0Nl-bL?C&vel;%XDMB zCQaZ!!s)HfRo_)lV3sPWOhXH!DJ6%=1Ql`*zuIS{af~%8#QjK?l~vJl%;MF#a=zK1 zH?MT_e|_uSQr+9w0w;+9}i@y?r4-px+I<~kqUid{x<(g9` z9)w^9Dv2tUF*Jm35~(bqkBZ>UAn!3tJVzZYG16G3#~Os~Uohb!=XEfW!qG=2y@2YD z61hp-60+AdJXtL1lR@t!-Zs>+DyqZ3f|QMv*+9|Ozcvh);|wTIUr=BTa!M;9w#Ett zV`S8ncV_cn7LG=(tqYJxH})t0^AH#@2a3_r{v;ofS=W|Ll6}X@b9)>^_q>c{?j5w* z0+6U^^qC0DlPIeqL9pJ*wJ#dz(d+pYnBS=x9YeoGaOp{A*nGm}sSYSvDu5?fb1wVj!5R|5Xn3V5c+gQKIDmWc$eicK?AhFls$m~Xx3 zLhYT=Q8^@+#xqHBlLSTBcvpI~>9=#2Z-_p`at;CC^`&0YLlvPk=hwpSk0r(4Da?cJ9O(U`=2>4LX^QI?Wn;4)}TrSB2ns0*G8 z4#FS*V6b zXoq`UJ&;4A8zBP0v02N2a#9Gp2_2FBPALsiv{QK6tV@gk*RnS-KL*R zCYE9@C5p_g^x+DU9FjTE^i` zZ%ATi>{bC{#qzwmP+?y$gc7W7U9#D6fT*Ox9I-F3DnnW-S>KwwypHV zIeX`c-YKNGLbr5khx0IT1%j$mQ2#pkkjz2thq7vtaIyR$u3fnx1B>DBb*+>`ckMor z^jzgh7_M;a)g-IWXvMA9OSjQLX!5RP#L z>0%kdHXFCPGBdS3J%(j=iZA*iUL*4&P#|Qf*S4Xj06eQxfD)r^^DRV|G2b!3>WcOe`fd$F z_-+M(uk-AaD2b#Nq7tj`i=Y&ekSHmo9guWCeJKhI*=BhmAOKpoKa{+A_7T11i3j!z zlaz>w)0By?V2(bVGF`qI@kM zgU`LmZX1exeHuTO42p*q`8~)KO>(PNYJl&$!sD(W`}KNfM&S1=ZNVGCYvvJ>0=pEE z!;ZhIo)D4*x)enNkG-R>FG_XtY!dTTq1z4M~T+gUIz{h84YP(E@AKa`Kc$KJsqh0 zg>M9?0002$f+*YkR)P=J=*;S5#M;d2=+J(Z2;EEA36bIsdy{j1?juI=c7?+LBXk}5 zNs~-2F~J2xYXLnpa;c|`?bCB^HR*fUz4S}@njoV0gA3|X>y~Sk`p8RqY<_Vb$*l4= z2hZoKja~6+-&e}kS69iUvySYEhl9&d$P(35EVrs{j;>+Ji_xdm%Jzq6y^Tfo3 zHb>UxXT@vcb7s7L|2FmOh--LrGS3{(>%SOBu~L)15$e8q!!EgKaeVv;B2$M+c5H zwuk-$2SxHw|9)pk;UKzq$zNL2PFHc$Uf%d?Te9_M#wr)c#V0*gRob3F7g&VO_FTyy zB7^ZSfyCw}2#x@;q_VupD`{mq(O)!nj%D~;R|?dFe5v91N8P#6c=yXuJyFabV$05@ zpFkg1{2%@6w9$uI;Ji2CK7lmid-_*ffiwZT;=5PN zVp{)x|6O<~(|57O(akBe%)Jk^c`fbfEeIEKj@^&DZiW|_XFZ`fxIHMXUPn={7R~DzeoG-D%en3e@G$Ei zMSr%bAHWa1`ON@_X^pU5hJOSTNAd$w@3pir50D?hnU zAg?8u){&0hzesu6G5L+m*TnrB$}F$l8n*l*0zOIJ^#G}B$A4b~yx{Hh7&dQE`#&%F zQ0gaGQr?fYW3%|%`DW>bKQv!@ixuTxa?pGs(gyjGvAn_4Af!$$*LsR_d{W(DI*O7Nd!Jq2rYAB#fy-p?3g#+D-H&-Ux@WJqD=JYk-UOqtP z(yyAR`TUwcuGxL`C~bcDY^cIC*M8OcW){Coee4`k>Bv32pA#^Kz8OL>T-c&=ry@MQ z1;s`9%ZrV?CGc3kZf!$w5`WPX-kM5+A=vvsHkrOhd9{+guC#-C_XI%j4t-1*kl)4B zr!&p0o*)p3LMf(WuS@EVyj4KnWNf*A-FjQdk4x8MS+)C_@)dV5XuqqfZru~SLckcg zk)}>PLu|;sy1e$jv1B0hxDj8k`+@u9RC_*sU&?6a#IN5)Y+XQ~c@n~Cd2MO*&nnFd zTig0AJvX~j3U$r6{B-Q?@X&Y(^t_X{YC3OJfeHsO^Kj>bqPP9L+fvpU887p_Vz7oy zlg^aBOt3%|5aze*&PLoM+u;33V`gw(ZliSK&(qDYh0Mtc#qJ*XLa>Rrwe`N&Tr^Z0e;mi?BCT)&!3%)XY2 z(#3Z&kHii6=|Xn>CnOK7ffG)qMi+7eL7iij&*SS2R^)LDtiR?9Wk}JwNkh zullP73xMHLdutKubID9T+V{T2CpzxmO@7nEpber^3;2SNlY)TE^>``jt^fjPPXGbr zq(DHS0sq?E)xf#_v-95vgzvMeh#-xGj3}Lpu>q~CwUwL{5HJb=1pxWoFbw`n9QeP* zp#Y%&M1S|CMU({o6a6^`__p)!P#tlI1+j0Tf9)v$2IToCR9ZkrLR3UiiB?+lUmBnR z|F^G@|E6K+d-VT2|0gQ_|GPuje?y)B17&4yK=)6N|AqYLtP%bj5)J5o?fnb++t|U` z%Gi-c-_D$dk(PxeAUa|+)g0Kk6$ DBY org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-webapp @@ -101,6 +101,11 @@ jetty-xml ${project.version} + + org.eclipse.jetty + jetty-webapp-verifier + ${project.version} + junit junit diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java index f39bc648fd6..8e897d257ce 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java @@ -4,11 +4,11 @@ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. -// The Eclipse Public License is available at +// The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php -// You may elect to redistribute this code under either of these licenses. +// You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.webapp; @@ -19,6 +19,7 @@ import java.net.MalformedURLException; import java.security.PermissionCollection; import java.util.EventListener; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.servlet.http.HttpSessionActivationListener; @@ -49,28 +50,29 @@ import org.eclipse.jetty.util.resource.Resource; * {@link org.eclipse.jetty.security.ConstraintSecurityHandler}, {@link org.eclipse.jetty.server.session.SessionHandler} * and {@link org.eclipse.jetty.servlet.ServletHandler}. * The handlers are configured by pluggable configuration classes, with - * the default being {@link org.eclipse.jetty.server.server.webapp.WebXmlConfiguration} and + * the default being {@link org.eclipse.jetty.server.server.webapp.WebXmlConfiguration} and * {@link org.eclipse.jetty.server.server.webapp.JettyWebXmlConfiguration}. - * + * * @org.apache.xbean.XBean description="Creates a servlet web application at a given context from a resource base" * * * */ public class WebAppContext extends ServletContextHandler -{ +{ public static final String TEMPDIR = "javax.servlet.context.tempdir"; public final static String WEB_DEFAULTS_XML="org/eclipse/jetty/webapp/webdefault.xml"; public final static String ERROR_PAGE="org.eclipse.jetty.server.error_page"; + public final static String SERVER_CONFIG = "org.eclipse.jetty.webapp.configuration"; - private static String[] __dftConfigurationClasses = - { - "org.eclipse.jetty.webapp.WebInfConfiguration", - "org.eclipse.jetty.webapp.WebXmlConfiguration", + private static String[] __dftConfigurationClasses = + { + "org.eclipse.jetty.webapp.WebInfConfiguration", + "org.eclipse.jetty.webapp.WebXmlConfiguration", "org.eclipse.jetty.webapp.MetaInfConfiguration", "org.eclipse.jetty.webapp.FragmentConfiguration", "org.eclipse.jetty.webapp.JettyWebXmlConfiguration", - "org.eclipse.jetty.webapp.TagLibConfiguration" + "org.eclipse.jetty.webapp.TagLibConfiguration" } ; private String[] _configurationClasses=__dftConfigurationClasses; private Configuration[] _configurations; @@ -84,8 +86,8 @@ public class WebAppContext extends ServletContextHandler private boolean _parentLoaderPriority= Boolean.getBoolean("org.eclipse.jetty.server.webapp.parentLoaderPriority"); private PermissionCollection _permissions; private String[] _systemClasses = { - "java.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2) - "javax.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2) + "java.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2) + "javax.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2) "org.xml.", // needed by javax.xml "org.w3c.", // needed by javax.xml "org.apache.commons.logging.", // special case. @@ -100,7 +102,7 @@ public class WebAppContext extends ServletContextHandler "-org.eclipse.jetty.plus.jaas.", // don't hide jaas modules "-org.eclipse.jetty.servlet.DefaultServlet", // webapp cannot change default servlets "org.eclipse.jetty." // hide rest of jetty classes - }; + }; private File _tmpDir; private String _war; private String _extraClasspath; @@ -117,9 +119,9 @@ public class WebAppContext extends ServletContextHandler { ContextHandler handler = context.getContextHandler(); if (handler instanceof WebAppContext) - return (ContextHandler)handler; + return handler; } - return null; + return null; } /* ------------------------------------------------------------ */ @@ -162,12 +164,13 @@ public class WebAppContext extends ServletContextHandler super(null,sessionHandler,securityHandler,servletHandler,errorHandler); setErrorHandler(errorHandler!=null?errorHandler:new ErrorPageErrorHandler()); - } + } /* ------------------------------------------------------------ */ /** * @param servletContextName The servletContextName to set. */ + @Override public void setDisplayName(String servletContextName) { super.setDisplayName(servletContextName); @@ -190,9 +193,9 @@ public class WebAppContext extends ServletContextHandler /** Set Resource Alias. * Resource aliases map resource uri's within a context. * They may optionally be used by a handler when looking for - * a resource. - * @param alias - * @param uri + * a resource. + * @param alias + * @param uri */ public void setResourceAlias(String alias, String uri) { @@ -235,6 +238,7 @@ public class WebAppContext extends ServletContextHandler /* (non-Javadoc) * @see org.eclipse.jetty.server.server.handler.ContextHandler#setClassLoader(java.lang.ClassLoader) */ + @Override public void setClassLoader(ClassLoader classLoader) { super.setClassLoader(classLoader); @@ -243,6 +247,7 @@ public class WebAppContext extends ServletContextHandler } /* ------------------------------------------------------------ */ + @Override public Resource getResource(String uriInContext) throws MalformedURLException { IOException ioe= null; @@ -299,14 +304,15 @@ public class WebAppContext extends ServletContextHandler } /* ------------------------------------------------------------ */ - /* + /* * @see org.eclipse.thread.AbstractLifeCycle#doStart() */ + @Override protected void doStart() throws Exception { try { - // Setup configurations + // Setup configurations loadConfigurations(); @@ -319,14 +325,14 @@ public class WebAppContext extends ServletContextHandler _ownClassLoader=true; } - if (Log.isDebugEnabled()) + if (Log.isDebugEnabled()) { ClassLoader loader = getClassLoader(); Log.debug("Thread Context class loader is: " + loader); loader=loader.getParent(); while(loader!=null) { - Log.debug("Parent class loader is: " + loader); + Log.debug("Parent class loader is: " + loader); loader=loader.getParent(); } } @@ -344,7 +350,7 @@ public class WebAppContext extends ServletContextHandler _configurations[i].postConfigure(this); - if (isLogUrlOnStart()) + if (isLogUrlOnStart()) dumpUrl(); } catch (Exception e) @@ -360,10 +366,10 @@ public class WebAppContext extends ServletContextHandler /* * Dumps the current web app name and URL to the log */ - public void dumpUrl() + public void dumpUrl() { Connector[] connectors = getServer().getConnectors(); - for (int i=0;i serverConfigs = (List)getServer().getAttribute(SERVER_CONFIG); + if (serverConfigs != null) + { + configsLen += serverConfigs.size(); + } + + _configurations = new Configuration[configsLen]; + for (int i = 0; i < _configurationClasses.length; i++) { _configurations[i]=(Configuration)Loader.loadClass(this.getClass(), _configurationClasses[i]).newInstance(); } + + if (serverConfigs != null) + { + int offset = _configurationClasses.length; + for (int i = 0, n = serverConfigs.size(); i < n; i++) + { + _configurations[i + offset] = serverConfigs.get(i); + } + } } /* ------------------------------------------------------------ */ + @Override protected boolean isProtectedTarget(String target) { while (target.startsWith("//")) @@ -628,6 +687,7 @@ public class WebAppContext extends ServletContextHandler /* ------------------------------------------------------------ */ + @Override public String toString() { return super.toString()+(_war==null?"":(","+_war)); @@ -656,7 +716,7 @@ public class WebAppContext extends ServletContextHandler } /* ------------------------------------------------------------ */ - /** + /** * The default descriptor is a web.xml format file that is applied to the context before the standard WEB-INF/web.xml * @param defaultsDescriptor The defaultsDescriptor to set. */ @@ -703,6 +763,7 @@ public class WebAppContext extends ServletContextHandler } /* ------------------------------------------------------------ */ + @Override public void setEventListeners(EventListener[] eventListeners) { if (_sessionHandler!=null) @@ -731,9 +792,10 @@ public class WebAppContext extends ServletContextHandler * Conveniance method that calls {@link #setEventListeners(EventListener[])} * @param listener */ + @Override public void addEventListener(EventListener listener) { - setEventListeners((EventListener[])LazyList.addToArray(getEventListeners(), listener, EventListener.class)); + setEventListeners((EventListener[])LazyList.addToArray(getEventListeners(), listener, EventListener.class)); } @@ -775,12 +837,12 @@ public class WebAppContext extends ServletContextHandler } /* ------------------------------------------------------------ */ - /** + /** * Set the server classes patterns. *

* Server classes/packages are classes used to implement the server and are hidden * from the context. If the context needs to load these classes, it must have its - * own copy of them in WEB-INF/lib or WEB-INF/classes. + * own copy of them in WEB-INF/lib or WEB-INF/classes. * A class pattern is a string of one of the forms:

*
org.package.Classname
Match a specific class
*
org.package.
Match a specific package hierarchy
@@ -789,7 +851,7 @@ public class WebAppContext extends ServletContextHandler *
* @param serverClasses The serverClasses to set. */ - public void setServerClasses(String[] serverClasses) + public void setServerClasses(String[] serverClasses) { _serverClasses = serverClasses==null?null:(String[])serverClasses.clone(); } @@ -882,7 +944,7 @@ public class WebAppContext extends ServletContextHandler } /* ------------------------------------------------------------ */ - public boolean isLogUrlOnStart() + public boolean isLogUrlOnStart() { return _logUrlOnStart; } @@ -893,12 +955,13 @@ public class WebAppContext extends ServletContextHandler * * @param logOnStart whether or not the log message is created */ - public void setLogUrlOnStart(boolean logOnStart) + public void setLogUrlOnStart(boolean logOnStart) { this._logUrlOnStart = logOnStart; } /* ------------------------------------------------------------ */ + @Override protected void startContext() throws Exception { @@ -911,5 +974,4 @@ public class WebAppContext extends ServletContextHandler super.startContext(); } - } diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebappVerifierConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebappVerifierConfiguration.java new file mode 100644 index 00000000000..a47e2a750b8 --- /dev/null +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebappVerifierConfiguration.java @@ -0,0 +1,97 @@ +// ======================================================================== +// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.webapp; + +import java.io.File; +import java.net.URI; +import java.util.Collection; + +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.webapp.verifier.RuleSet; +import org.eclipse.jetty.webapp.verifier.Severity; +import org.eclipse.jetty.webapp.verifier.Violation; +import org.eclipse.jetty.webapp.verifier.WebappVerifier; + +/** + * WebappVerifierConfiguration + */ +public class WebappVerifierConfiguration implements Configuration +{ + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.webapp.Configuration#configure(org.eclipse.jetty.webapp.WebAppContext) + */ + public void configure(WebAppContext context) throws Exception + { + + } + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.webapp.Configuration#deconfigure(org.eclipse.jetty.webapp.WebAppContext) + */ + public void deconfigure(WebAppContext context) throws Exception + { + + } + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.webapp.Configuration#postConfigure(org.eclipse.jetty.webapp.WebAppContext) + */ + public void postConfigure(WebAppContext context) throws Exception + { + + } + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.webapp.Configuration#preConfigure(org.eclipse.jetty.webapp.WebAppContext) + */ + public void preConfigure(WebAppContext context) throws Exception + { + if(Log.isDebugEnabled()) + { + Log.debug("Configuring webapp verifier"); + } + + URI configurationUri = new File( System.getProperty( "jetty.home" )).toURI().resolve( "etc/default-webapp-verifier.xml" ); + + RuleSet suite = RuleSet.load( configurationUri.toURL() ); + + WebappVerifier verifier = suite.createWebappVerifier( new URI( context.getWar() ) ); + + verifier.visitAll(); + + Collection violations = verifier.getViolations(); + + boolean haltWebapp = false; + + Log.info( " Webapp Verifier Report: " + violations.size() + " violations" ); + + for (Violation violation : violations) + { + if ( violation.getSeverity() == Severity.ERROR ) + { + haltWebapp = true; + } + + Log.info( violation.toString() ); + } + + if ( haltWebapp ) + { + throw new InstantiationException( "Configuration exception: webapp failed webapp verification" ); + } + } +} diff --git a/jetty-xml/pom.xml b/jetty-xml/pom.xml index 5b085aa2db7..d1e38a0c1be 100644 --- a/jetty-xml/pom.xml +++ b/jetty-xml/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 jetty-xml diff --git a/pom.xml b/pom.xml index e2e4603a59b..4a7793bc6d0 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT Jetty :: Project ${jetty.url} pom @@ -132,6 +132,7 @@ jetty-jaspi jetty-servlet jetty-webapp + jetty-webapp-verifier jetty-servlets jetty-deploy jetty-ajp diff --git a/test-continuation-jetty6/pom.xml b/test-continuation-jetty6/pom.xml index c75b5a97db5..536d58dabdb 100644 --- a/test-continuation-jetty6/pom.xml +++ b/test-continuation-jetty6/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 test-continuation-jetty6 diff --git a/test-continuation/pom.xml b/test-continuation/pom.xml index 48aa192ef09..7a6c1199e62 100644 --- a/test-continuation/pom.xml +++ b/test-continuation/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 test-continuation diff --git a/test-jetty-servlet/pom.xml b/test-jetty-servlet/pom.xml index 09516965400..27ef6e12ded 100644 --- a/test-jetty-servlet/pom.xml +++ b/test-jetty-servlet/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 test-jetty-servlet diff --git a/test-jetty-webapp/pom.xml b/test-jetty-webapp/pom.xml index 3aaa1e590fc..43388db7b48 100644 --- a/test-jetty-webapp/pom.xml +++ b/test-jetty-webapp/pom.xml @@ -2,7 +2,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 org.eclipse.jetty diff --git a/tests/pom.xml b/tests/pom.xml index 8754868f45d..ca02bef2378 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -21,7 +21,7 @@ org.eclipse.jetty jetty-project - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT org.eclipse.jetty.tests tests-parent diff --git a/tests/test-integration/pom.xml b/tests/test-integration/pom.xml index 8e98e1775a7..203a37497da 100644 --- a/tests/test-integration/pom.xml +++ b/tests/test-integration/pom.xml @@ -20,7 +20,7 @@ org.eclipse.jetty.tests tests-parent - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT 4.0.0 test-integration diff --git a/tests/test-webapps/pom.xml b/tests/test-webapps/pom.xml index 5565e4224f2..e8ee33cc0e4 100644 --- a/tests/test-webapps/pom.xml +++ b/tests/test-webapps/pom.xml @@ -21,7 +21,7 @@ org.eclipse.jetty.tests tests-parent - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT test-webapps-parent Jetty Tests :: WebApps :: Parent diff --git a/tests/test-webapps/test-webapp-logging-commons/pom.xml b/tests/test-webapps/test-webapp-logging-commons/pom.xml index 2427b6a3793..37178c84f51 100644 --- a/tests/test-webapps/test-webapp-logging-commons/pom.xml +++ b/tests/test-webapps/test-webapp-logging-commons/pom.xml @@ -21,7 +21,7 @@ org.eclipse.jetty.tests test-webapps-parent - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT test-webapp-logging-commons Jetty Tests :: WebApp :: Commons Logging diff --git a/tests/test-webapps/test-webapp-logging-java/pom.xml b/tests/test-webapps/test-webapp-logging-java/pom.xml index 05474728677..f7b5163ec46 100644 --- a/tests/test-webapps/test-webapp-logging-java/pom.xml +++ b/tests/test-webapps/test-webapp-logging-java/pom.xml @@ -21,7 +21,7 @@ org.eclipse.jetty.tests test-webapps-parent - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT test-webapp-logging-java Jetty Tests :: WebApp :: JavaSE Logging diff --git a/tests/test-webapps/test-webapp-logging-log4j/pom.xml b/tests/test-webapps/test-webapp-logging-log4j/pom.xml index cedbcc4debe..71bfcd0713a 100644 --- a/tests/test-webapps/test-webapp-logging-log4j/pom.xml +++ b/tests/test-webapps/test-webapp-logging-log4j/pom.xml @@ -21,7 +21,7 @@ org.eclipse.jetty.tests test-webapps-parent - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT test-webapp-logging-log4j Jetty Tests :: WebApp :: Log4J Logging diff --git a/tests/test-webapps/test-webapp-logging-slf4j/pom.xml b/tests/test-webapps/test-webapp-logging-slf4j/pom.xml index f8b1f1eaca3..8a6ce463804 100644 --- a/tests/test-webapps/test-webapp-logging-slf4j/pom.xml +++ b/tests/test-webapps/test-webapp-logging-slf4j/pom.xml @@ -21,7 +21,7 @@ org.eclipse.jetty.tests test-webapps-parent - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT test-webapp-logging-slf4j Jetty Tests :: WebApp :: Slf4J Logging diff --git a/tests/test-webapps/test-webapp-rfc2616/pom.xml b/tests/test-webapps/test-webapp-rfc2616/pom.xml index 39e0a79507f..a94fe7667d9 100644 --- a/tests/test-webapps/test-webapp-rfc2616/pom.xml +++ b/tests/test-webapps/test-webapp-rfc2616/pom.xml @@ -21,7 +21,7 @@ org.eclipse.jetty.tests test-webapps-parent - 7.0.0.RC6-SNAPSHOT + 7.0.1-SNAPSHOT test-webapp-rfc2616 Jetty Tests :: WebApp :: RFC2616