From 85064609614901fd6ee3f0fa6ea9b598d9c3ad37 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 1 May 2021 23:17:48 -0700 Subject: [PATCH 01/29] Updated dependencies. --- README.md | 8 ++++---- build.gradle | 8 ++++---- config/pmd.xml | 2 -- gradle/wrapper/gradle-wrapper.properties | 2 +- src/main/java/net/thauvin/erik/httpstatus/Reasons.java | 3 +-- version.properties | 2 +- 6 files changed, 11 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 101a07f..808a8a2 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ Include the following in your `build.gradle` file: ```gradle dependencies { - implementation 'net.thauvin.erik.httpstatus:httpstatus:1.0.5' + implementation 'net.thauvin.erik.httpstatus:httpstatus:1.0.6' } ``` @@ -190,7 +190,7 @@ or as a Maven artifact: net.thauvin.erik.httpstatus httpstatus - 1.0.5 + 1.0.6 ``` @@ -198,7 +198,7 @@ or as a Maven artifact: You can query the reason phrase for status codes as follows: ```sh -$ java -jar httpstatus-1.0.5.jar 404 500 +$ java -jar httpstatus-1.0.6.jar 404 500 404: Not Found 500: Internal Server Error ``` @@ -206,7 +206,7 @@ $ java -jar httpstatus-1.0.5.jar 404 500 If no status code is specified, all will be printed: ```sh -$ java -jar httpstatus-1.0.5.jar +$ java -jar httpstatus-1.0.6.jar 100: Continue 101: Switching Protocols 102: Processing diff --git a/build.gradle b/build.gradle index f7ab512..55810fd 100644 --- a/build.gradle +++ b/build.gradle @@ -9,8 +9,8 @@ plugins { id 'pmd' id 'com.github.ben-manes.versions' version '0.38.0' id 'net.thauvin.erik.gradle.semver' version '1.0.4' - id 'com.github.spotbugs' version '4.7.0' - id 'org.sonarqube' version '3.1.1' + id 'com.github.spotbugs' version '4.7.1' + id 'org.sonarqube' version '3.2.0' } import com.github.spotbugs.snom.SpotBugsTask @@ -34,7 +34,7 @@ mainClassName = 'net.thauvin.erik.httpstatus.Reasons' ext { versions = [ - spotbugs: '4.2.2' + spotbugs: '4.2.3' ] } @@ -161,7 +161,7 @@ signing { } task copyToDeploy(type: Copy) { - from(configurations.runtime) { + from(configurations.runtimeClasspath) { exclude 'javax.servlet-api-*.jar' exclude 'jsp-api-*.jar' } diff --git a/config/pmd.xml b/config/pmd.xml index 32ca5ab..2ce525b 100644 --- a/config/pmd.xml +++ b/config/pmd.xml @@ -237,7 +237,6 @@ - @@ -250,7 +249,6 @@ - diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 442d913..f371643 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/net/thauvin/erik/httpstatus/Reasons.java b/src/main/java/net/thauvin/erik/httpstatus/Reasons.java index 14bc9a1..e551ce0 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/Reasons.java +++ b/src/main/java/net/thauvin/erik/httpstatus/Reasons.java @@ -87,7 +87,6 @@ public final class Reasons { * @param statusCode The status code. * @return The reason phrase, or null. */ - @SuppressWarnings({"WeakerAccess"}) public static String getReasonPhrase(final String statusCode) { return REASON_PHRASES.get(statusCode); } @@ -118,4 +117,4 @@ public final class Reasons { System.out.println("Total: " + REASON_PHRASES.size()); } } -} \ No newline at end of file +} diff --git a/version.properties b/version.properties index 2759f0f..9ba483e 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ #Generated by the Semver Plugin for Gradle -#Sun May 05 23:59:32 PDT 2019 +#Sat May 01 23:16:37 PDT 2021 version.buildmeta= version.major=1 version.minor=0 From 74aaaf26cdd3e3636393c1cbaff51562d1aa1ad8 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sun, 2 May 2021 21:03:55 -0700 Subject: [PATCH 02/29] Added support for snapshot. --- build.gradle | 6 +++++- version.properties | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 55810fd..6006695 100644 --- a/build.gradle +++ b/build.gradle @@ -149,7 +149,11 @@ publishing { repositories { maven { name = "ossrh" - url = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" + project.afterEvaluate { + url = project.version.contains("SNAPSHOT") + ? "https://oss.sonatype.org/content/repositories/snapshots/" + : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" + } credentials(PasswordCredentials) } } diff --git a/version.properties b/version.properties index 9ba483e..4799ec4 100644 --- a/version.properties +++ b/version.properties @@ -1,8 +1,8 @@ #Generated by the Semver Plugin for Gradle -#Sat May 01 23:16:37 PDT 2021 +#Sun May 02 22:01:06 PDT 2021 version.buildmeta= version.major=1 version.minor=0 version.patch=6 -version.prerelease= -version.semver=1.0.6 +version.prerelease=SNAPSHOT +version.semver=1.0.6-SNAPSHOT From 6f154330347e38583796effd1a4a9fda2b133cd9 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Tue, 11 May 2021 20:43:59 -0700 Subject: [PATCH 03/29] Upgraded to Gradle 7.0.1 --- build.gradle | 4 ++++ gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6006695..be3edf1 100644 --- a/build.gradle +++ b/build.gradle @@ -91,6 +91,10 @@ clean { } test { + testLogging { + exceptionFormat "full" + } + useTestNG() } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f371643..e5338d3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 37789dc6332e49ce72476cda7d2984681e7f5869 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 19 May 2021 22:52:19 -0700 Subject: [PATCH 04/29] Moved Sonarqube to GitHub action. --- .github/workflows/gradle.yml | 42 ++++++++++++++++++++++++ .travis.yml | 10 ------ build.gradle | 7 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- 4 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/gradle.yml diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..28fd6fb --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,42 @@ +name: Java CI with Gradle + +on: [push, pull_request, workflow_dispatch] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Test with Gradle + env: + CI_NAME: "GitHub CI" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: ./gradlew check sonarqube + - name: Cleanup Gradle Cache + run: | + rm -f ~/.gradle/caches/modules-2/modules-2.lock + rm -f ~/.gradle/caches/modules-2/gc.properties diff --git a/.travis.yml b/.travis.yml index 7ee8f56..dbd6b8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,15 +5,5 @@ jdk: - oraclejdk8 - openjdk14 -addons: - sonarcloud: - organization: "ethauvin-github" - before_install: - chmod +x gradlew - -after_success: - - | - if [ "${TRAVIS_TEST_RESULT}" == 0 ] && [ "$TRAVIS_JDK_VERSION" == "openjdk14" ]; then - ./gradlew sonarqube - fi diff --git a/build.gradle b/build.gradle index be3edf1..c21ebf1 100644 --- a/build.gradle +++ b/build.gradle @@ -93,6 +93,7 @@ clean { test { testLogging { exceptionFormat "full" + events "passed", "skipped", "failed" } useTestNG() @@ -178,7 +179,7 @@ task copyToDeploy(type: Copy) { } task deploy(dependsOn: ['clean', 'build', 'copyToDeploy']) { - description = 'Copies all needed files to the ${deployDir} directory.' + description = "Copies all needed files to the ${deployDir} directory." group = 'Publishing' outputs.dir deployDir inputs.files copyToDeploy @@ -219,7 +220,9 @@ jacocoTestReport { sonarqube { properties { - property("sonar.projectKey", "ethauvin_HttpStatus") + property "sonar.organization", "ethauvin-github" + property "sonar.projectKey", "ethauvin_semver" + property "sonar.host.url", "https://sonarcloud.io" property("sonar.sourceEncoding", "UTF-8") } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e5338d3..0f80bbf 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 31b8c48bad242cfcb9ab34becaeff10baf2445b1 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 19 May 2021 22:55:52 -0700 Subject: [PATCH 05/29] Fixed sonarcloud project name. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c21ebf1..bf8f4a8 100644 --- a/build.gradle +++ b/build.gradle @@ -221,7 +221,7 @@ jacocoTestReport { sonarqube { properties { property "sonar.organization", "ethauvin-github" - property "sonar.projectKey", "ethauvin_semver" + property "sonar.projectKey", "ethauvin_httpsatus" property "sonar.host.url", "https://sonarcloud.io" property("sonar.sourceEncoding", "UTF-8") } From 08621866338ebb7ab7cb7b50657578d2c508c370 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 19 May 2021 23:00:32 -0700 Subject: [PATCH 06/29] Fixed typo. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bf8f4a8..3c00aac 100644 --- a/build.gradle +++ b/build.gradle @@ -221,7 +221,7 @@ jacocoTestReport { sonarqube { properties { property "sonar.organization", "ethauvin-github" - property "sonar.projectKey", "ethauvin_httpsatus" + property "sonar.projectKey", "ethauvin_httpstatus" property "sonar.host.url", "https://sonarcloud.io" property("sonar.sourceEncoding", "UTF-8") } From c30a705a858f1b297a1e5f5e930acf907b181ee5 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 19 May 2021 23:03:24 -0700 Subject: [PATCH 07/29] Fixed typo, again. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3c00aac..3c0b588 100644 --- a/build.gradle +++ b/build.gradle @@ -221,7 +221,7 @@ jacocoTestReport { sonarqube { properties { property "sonar.organization", "ethauvin-github" - property "sonar.projectKey", "ethauvin_httpstatus" + property "sonar.projectKey", "ethauvin_HttpStatus" property "sonar.host.url", "https://sonarcloud.io" property("sonar.sourceEncoding", "UTF-8") } From f9fcd3a4259b03030cc0d202a0325d1ba9c76fe3 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 20 May 2021 21:51:25 -0700 Subject: [PATCH 08/29] Removed TravisCI. --- .github/workflows/gradle.yml | 2 +- .travis.yml | 9 --------- README.md | 2 +- 3 files changed, 2 insertions(+), 11 deletions(-) delete mode 100644 .travis.yml diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 28fd6fb..280a6a1 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,4 +1,4 @@ -name: Java CI with Gradle +name: gradle-ci on: [push, pull_request, workflow_dispatch] diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index dbd6b8a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: java -dist: trusty - -jdk: - - oraclejdk8 - - openjdk14 - -before_install: - - chmod +x gradlew diff --git a/README.md b/README.md index 808a8a2..c19b75d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Release](https://img.shields.io/github/release/ethauvin/httpstatus.svg)](https://github.com/ethauvin/httpstatus/releases/latest) [![Maven Central](https://img.shields.io/maven-central/v/net.thauvin.erik.httpstatus/httpstatus.svg?label=maven%20central)](https://search.maven.org/search?q=g:%22net.thauvin.erik.httpstatus%22%20AND%20a:%22httpstatus%22) [![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](http://opensource.org/licenses/BSD-3-Clause) [![Known Vulnerabilities](https://snyk.io/test/github/ethauvin/httpstatus/badge.svg?targetFile=build.gradle)](https://snyk.io/test/github/ethauvin/httpstatus?targetFile=build.gradle) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=ethauvin_HttpStatus&metric=alert_status)](https://sonarcloud.io/dashboard?id=ethauvin_HttpStatus) -[![Build Status](https://travis-ci.com/ethauvin/HttpStatus.svg?branch=master)](https://travis-ci.com/ethauvin/HttpStatus) [![Build status](https://ci.appveyor.com/api/projects/status/w5j4kul3w2rkigxb?svg=true)](https://ci.appveyor.com/project/ethauvin/httpstatus) [![CircleCI](https://circleci.com/gh/ethauvin/HttpStatus/tree/master.svg?style=shield)](https://circleci.com/gh/ethauvin/HttpStatus/tree/master) +[![GitHub CI](https://github.com/ethauvin/httpstatus/actions/workflows/gradle.yml/badge.svg)](https://github.com/ethauvin/httpstatus/actions/workflows/gradle.yml) [![Build status](https://ci.appveyor.com/api/projects/status/w5j4kul3w2rkigxb?svg=true)](https://ci.appveyor.com/project/ethauvin/httpstatus) [![CircleCI](https://circleci.com/gh/ethauvin/HttpStatus/tree/master.svg?style=shield)](https://circleci.com/gh/ethauvin/HttpStatus/tree/master) A simple [JSP](http://www.oracle.com/technetwork/java/javaee/jsp/index.html) Tag Library to display the [code](#hscode), [reason](#hsreason), [cause](#hscode) and/or [message](#hsmessage) for [HTTP status codes](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) in JSP error pages. From 8b87ddae42d3a93c680a20bc95d4867efa5f2b39 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 21 May 2021 00:03:32 -0700 Subject: [PATCH 09/29] Moved to JDK 11 and 15. --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 0ee7361..301727a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,8 +19,8 @@ cache: environment: matrix: - - JAVA_HOME: C:\Program Files\Java\jdk1.8.0 - - JAVA_HOME: C:\Program Files (x86)\Java\jdk1.8.0 + - JAVA_HOME: C:\Program Files\Java\jdk15 + - JAVA_HOME: C:\Program Files\Java\jdk11 matrix: fast_finish: true From 8dd40acdfbbe290df59b902d4652f1151d975c2c Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 21 May 2021 14:46:08 -0700 Subject: [PATCH 10/29] Added branch to appveyor. --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 301727a..c41c1ab 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,6 +13,7 @@ test_script: branches: only: - master + - 1.0.6-dev cache: - C:\Users\appveyor\.gradle From c3adfb1f07f25ef9e966629744a3edae469f6699 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 21 May 2021 14:52:56 -0700 Subject: [PATCH 11/29] Added Visual Studio 2019 image. --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index c41c1ab..f858073 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,3 +1,6 @@ +image: + - Visual Studio 2019 + version: "{branch} {build}" skip_tags: true From b967f1323014b4b26c415a2a65f1aeba7a3a79e3 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 29 May 2021 21:54:19 -0700 Subject: [PATCH 12/29] Updated PMD rules. --- build.gradle | 35 +-- config/pmd.xml | 286 ++++-------------- docs/README.html | 10 +- .../thauvin/erik/httpstatus/UtilsTest.java | 4 +- 4 files changed, 90 insertions(+), 245 deletions(-) diff --git a/build.gradle b/build.gradle index 3c0b588..9ebf6da 100644 --- a/build.gradle +++ b/build.gradle @@ -34,6 +34,7 @@ mainClassName = 'net.thauvin.erik.httpstatus.Reasons' ext { versions = [ + pmd: '6.35.0', spotbugs: '4.2.3' ] } @@ -92,8 +93,8 @@ clean { test { testLogging { - exceptionFormat "full" - events "passed", "skipped", "failed" + exceptionFormat = "full" + events("passed", "skipped", "failed") } useTestNG() @@ -105,6 +106,7 @@ spotbugs { } pmd { + toolVersion = versions.pmd ignoreFailures = true ruleSets = [] ruleSetFiles = files("${projectDir}/config/pmd.xml") @@ -121,9 +123,9 @@ tasks.withType(Checkstyle) { publishing { publications { mavenJava(MavenPublication) { - from components.java - groupId project.group - artifactId rootProject.name + from(components.java) + groupId = project.group + artifactId = rootProject.name pom { name = mavenName @@ -171,19 +173,18 @@ signing { task copyToDeploy(type: Copy) { from(configurations.runtimeClasspath) { - exclude 'javax.servlet-api-*.jar' - exclude 'jsp-api-*.jar' + exclude('javax.servlet-api-*.jar', 'jsp-api-*.jar') } - from jar - into deployDir + from(jar) + into(deployDir) } task deploy(dependsOn: ['clean', 'build', 'copyToDeploy']) { description = "Copies all needed files to the ${deployDir} directory." group = 'Publishing' - outputs.dir deployDir - inputs.files copyToDeploy - mustRunAfter clean + outputs.dir(deployDir) + inputs.files(copyToDeploy) + mustRunAfter(clean) } task release(dependsOn: ['wrapper', 'deploy', 'pandoc', 'publishToMavenLocal']) { @@ -203,8 +204,8 @@ task pandoc(type: Exec) { if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine(['cmd', '/c', 'pandoc'] + pandoc_args) } else { - executable 'pandoc' - args pandoc_args + executable = 'pandoc' + args(pandoc_args) } standardOutput = new ByteArrayOutputStream() ext.output = { @@ -220,9 +221,9 @@ jacocoTestReport { sonarqube { properties { - property "sonar.organization", "ethauvin-github" - property "sonar.projectKey", "ethauvin_HttpStatus" - property "sonar.host.url", "https://sonarcloud.io" + property("sonar.organization", "ethauvin-github") + property("sonar.projectKey", "ethauvin_HttpStatus") + property("sonar.host.url", "https://sonarcloud.io") property("sonar.sourceEncoding", "UTF-8") } } diff --git a/config/pmd.xml b/config/pmd.xml index 2ce525b..890a490 100644 --- a/config/pmd.xml +++ b/config/pmd.xml @@ -1,120 +1,82 @@ - - Erik's Ruleset - - - - - - - - - + + + + + + + value="//MethodDeclaration[@Name='hashCode' or @Name='equals' or @Name='toString']"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + @@ -122,86 +84,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -209,59 +96,16 @@ - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + diff --git a/docs/README.html b/docs/README.html index b04e36c..c024860 100644 --- a/docs/README.html +++ b/docs/README.html @@ -80,7 +80,7 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni

HttpStatus JSP Tag Library

Release Maven Central
License (3-Clause BSD) Known Vulnerabilities Quality Gate Status
-Build Status Build status CircleCI

+GitHub CI Build status CircleCI

A simple JSP Tag Library to display the code, reason, cause and/or message for HTTP status codes in JSP error pages.

For example:

<%@ page isErrorPage="true" %>
@@ -547,22 +547,22 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
 

Usage with Gradle or Maven

Include the following in your build.gradle file:

dependencies {
-    implementation 'net.thauvin.erik.httpstatus:httpstatus:1.0.5'
+    implementation 'net.thauvin.erik.httpstatus:httpstatus:1.0.6'
 }
 

or as a Maven artifact:

Command Line Usage

You can query the reason phrase for status codes as follows:

-
$ java -jar httpstatus-1.0.5.jar 404 500
+
 

If no status code is specified, all will be printed:

-
$ java -jar httpstatus-1.0.5.jar
+
$ java -jar httpstatus-1.0.6.jar
 100: Continue
 101: Switching Protocols
 102: Processing
diff --git a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java
index 9b9b660..e03ec34 100644
--- a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java
+++ b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java
@@ -61,7 +61,7 @@ public class UtilsTest {
     @SuppressFBWarnings("CE_CLASS_ENVY")
     @Test
     public void testOutWrite() throws IOException {
-        try (final StringWriter sw = new StringWriter()) {
+        try (StringWriter sw = new StringWriter()) {
             Utils.outWrite(sw, null, "default", false);
             assertEquals(sw.toString(), "default", "outWrite(default)");
 
@@ -98,4 +98,4 @@ public class UtilsTest {
             assertEquals(sw.toString(), "", "outWrite(null, xml)");
         }
     }
-}
\ No newline at end of file
+}

From 12936688ae3a7ca4603272ea3c7e7c66821d94dc Mon Sep 17 00:00:00 2001
From: "Erik C. Thauvin" 
Date: Mon, 31 May 2021 11:53:29 -0700
Subject: [PATCH 13/29] Added Github workflow martix for JDK 1.8, 11 & 15.

---
 .github/workflows/gradle.yml | 21 +++++++++++++------
 build.gradle                 | 40 +++++++++++++++++++-----------------
 2 files changed, 36 insertions(+), 25 deletions(-)

diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
index 280a6a1..eef517b 100644
--- a/.github/workflows/gradle.yml
+++ b/.github/workflows/gradle.yml
@@ -5,17 +5,24 @@ on: [push, pull_request, workflow_dispatch]
 jobs:
   build:
     runs-on: ubuntu-latest
+    env:
+      GRADLE_OPTS: "-Dorg.gradle.jvmargs=-XX:MaxMetaspaceSize=512m"
+      SONAR_JDK: "11"
+    strategy:
+      matrix:
+        java-version: [ 1.8, 11, 15 ]
     steps:
       - uses: actions/checkout@v2
         with:
           fetch-depth: 0
-      - name: Set up JDK 11
+      - name: Set up JDK ${{ matrix.java-version }}
         uses: actions/setup-java@v1
         with:
-          java-version: 11
+          java-version: ${{ matrix.java-version }}
       - name: Grant execute permission for gradlew
         run: chmod +x gradlew
       - name: Cache SonarCloud packages
+        if: matrix.java-version == env.SONAR_JDK
         uses: actions/cache@v1
         with:
           path: ~/.sonar/cache
@@ -27,15 +34,17 @@ jobs:
           path: |
             ~/.gradle/caches
             ~/.gradle/wrapper
-          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+          key: ${{ runner.os }}-gradle-${{ matrix.java-version }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
           restore-keys: |
-            ${{ runner.os }}-gradle-
+            ${{ runner.os }}-gradle-${{ matrix.java-version }}-
       - name: Test with Gradle
+        run: ./gradlew build check --stacktrace
+      - name: SonarCloud
+        if: success() && matrix.java-version == env.SONAR_JDK
         env:
-          CI_NAME: "GitHub CI"
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
-        run: ./gradlew check sonarqube
+        run: ./gradlew sonarqube
       - name: Cleanup Gradle Cache
         run: |
           rm -f ~/.gradle/caches/modules-2/modules-2.lock
diff --git a/build.gradle b/build.gradle
index 9ebf6da..0700f6c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -93,8 +93,8 @@ clean {
 
 test {
     testLogging {
-        exceptionFormat  = "full"
-        events("passed", "skipped", "failed")
+        exceptionFormat = 'full'
+        events('passed', 'skipped', 'failed')
     }
 
     useTestNG()
@@ -123,7 +123,7 @@ tasks.withType(Checkstyle) {
 publishing {
     publications {
         mavenJava(MavenPublication) {
-            from(components.java)
+            from components.java
             groupId = project.group
             artifactId = rootProject.name
 
@@ -155,11 +155,11 @@ publishing {
     }
     repositories {
         maven {
-            name = "ossrh"
+            name = 'ossrh'
             project.afterEvaluate {
-                url = project.version.contains("SNAPSHOT")
-                        ? "https://oss.sonatype.org/content/repositories/snapshots/"
-                        : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
+                url = project.version.contains('SNAPSHOT')
+                        ? 'https://oss.sonatype.org/content/repositories/snapshots/'
+                        : 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
                 }
             credentials(PasswordCredentials)
         }
@@ -175,21 +175,23 @@ task copyToDeploy(type: Copy) {
     from(configurations.runtimeClasspath) {
         exclude('javax.servlet-api-*.jar', 'jsp-api-*.jar')
     }
-    from(jar)
-    into(deployDir)
+    from jar
+    into deployDir
 }
 
-task deploy(dependsOn: ['clean', 'build', 'copyToDeploy']) {
+task deploy {
     description = "Copies all needed files to the ${deployDir} directory."
     group = 'Publishing'
-    outputs.dir(deployDir)
-    inputs.files(copyToDeploy)
-    mustRunAfter(clean)
+    dependsOn(clean, build, 'copyToDeploy')
+    outputs.dir deployDir
+    inputs.files copyToDeploy
+    mustRunAfter clean
 }
 
-task release(dependsOn: ['wrapper', 'deploy', 'pandoc', 'publishToMavenLocal']) {
+task release {
     group = 'Publishing'
     description = 'Releases new version.'
+    dependsOn(wrapper, 'deploy', 'pandoc', publishToMavenLocal)
 }
 
 task pandoc(type: Exec) {
@@ -221,13 +223,13 @@ jacocoTestReport {
 
 sonarqube {
     properties {
-        property("sonar.organization", "ethauvin-github")
-        property("sonar.projectKey", "ethauvin_HttpStatus")
-        property("sonar.host.url", "https://sonarcloud.io")
-        property("sonar.sourceEncoding", "UTF-8")
+        property('sonar.organization', 'ethauvin-github')
+        property('sonar.projectKey', 'ethauvin_HttpStatus')
+        property('sonar.host.url', 'https://sonarcloud.io')
+        property('sonar.sourceEncoding', 'UTF-8')
     }
 }
 
 tasks.sonarqube {
-    dependsOn("jacocoTestReport")
+    dependsOn 'jacocoTestReport'
 }

From 95f4c9714e743b7e11ba5299fffe2057c608bd26 Mon Sep 17 00:00:00 2001
From: "Erik C. Thauvin" 
Date: Tue, 1 Jun 2021 02:37:32 -0700
Subject: [PATCH 14/29] Implemented StatusCode bean. Closes #5

---
 .github/workflows/gradle.yml                  |  10 ++
 README.md                                     |  76 +++++++--
 build.gradle                                  |   8 +
 .../thauvin/erik/httpstatus/StatusCode.java   | 149 ++++++++++++++++++
 .../erik/httpstatus/taglibs/ReasonTag.java    |   2 -
 .../erik/httpstatus/StatusCodeTest.java       |  76 +++++++++
 6 files changed, 306 insertions(+), 15 deletions(-)
 create mode 100644 src/main/java/net/thauvin/erik/httpstatus/StatusCode.java
 create mode 100644 src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java

diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
index eef517b..251e704 100644
--- a/.github/workflows/gradle.yml
+++ b/.github/workflows/gradle.yml
@@ -5,22 +5,28 @@ on: [push, pull_request, workflow_dispatch]
 jobs:
   build:
     runs-on: ubuntu-latest
+
     env:
       GRADLE_OPTS: "-Dorg.gradle.jvmargs=-XX:MaxMetaspaceSize=512m"
       SONAR_JDK: "11"
+
     strategy:
       matrix:
         java-version: [ 1.8, 11, 15 ]
+
     steps:
       - uses: actions/checkout@v2
         with:
           fetch-depth: 0
+
       - name: Set up JDK ${{ matrix.java-version }}
         uses: actions/setup-java@v1
         with:
           java-version: ${{ matrix.java-version }}
+
       - name: Grant execute permission for gradlew
         run: chmod +x gradlew
+
       - name: Cache SonarCloud packages
         if: matrix.java-version == env.SONAR_JDK
         uses: actions/cache@v1
@@ -28,6 +34,7 @@ jobs:
           path: ~/.sonar/cache
           key: ${{ runner.os }}-sonar
           restore-keys: ${{ runner.os }}-sonar
+
       - name: Cache Gradle packages
         uses: actions/cache@v2
         with:
@@ -37,14 +44,17 @@ jobs:
           key: ${{ runner.os }}-gradle-${{ matrix.java-version }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
           restore-keys: |
             ${{ runner.os }}-gradle-${{ matrix.java-version }}-
+
       - name: Test with Gradle
         run: ./gradlew build check --stacktrace
+
       - name: SonarCloud
         if: success() && matrix.java-version == env.SONAR_JDK
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
         run: ./gradlew sonarqube
+
       - name: Cleanup Gradle Cache
         run: |
           rm -f ~/.gradle/caches/modules-2/modules-2.lock
diff --git a/README.md b/README.md
index c19b75d..ee683a2 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,25 @@ would display on a [501 status code](http://www.w3.org/Protocols/rfc2616/rfc2616
 
     Not Implemented
 
+## Usage with [Gradle](https://gradle.org/) or [Maven](http://maven.apache.org/)
+Include the following in your `build.gradle` file:
+
+```gradle
+dependencies {
+    implementation 'net.thauvin.erik.httpstatus:httpstatus:1.0.6'
+}
+```
+
+or as a Maven artifact:
+
+```xml
+
+    net.thauvin.erik.httpstatus
+    httpstatus
+    1.0.6
+
+```
+
 ## hs:cause
 
 The `` tag displays the cause of current HTTP status code, if any. A shorthand for:
@@ -175,24 +194,55 @@ Status Code | Reason
 `598`       | Network Read Timeout Error
 `599`       | Network Connect Timeout Error
 
-## Usage with [Gradle](https://gradle.org/) or [Maven](http://maven.apache.org/)
-Include the following in your `build.gradle` file:
+## StatusCode Bean
 
-```gradle
-dependencies {
-    implementation 'net.thauvin.erik.httpstatus:httpstatus:1.0.6'
+The `StatusCode` bean can be used to check the class of the status code error. For example, using the JSTL:
+
+```jsp
+<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+
+
+
+
+    
+        An error occurred on your side. ()
+    
+    
+        An error occurred on our side. ()
+    
+
+```
+
+or in a Servlet:
+
+```java
+import net.thauvin.erik.httpstatus.StatusCode;
+
+// ---
+
+final StatusCode statusCode = new StatusCode((Integer) request.getAttribute("javax.servlet.error.status_code"));
+if (statusCode.isError()) {
+    if (statusCode.isServerError()) {
+        final String reason = statusCode.getReason();
+    } else {
+        // ...
+    }
 }
 ```
 
-or as a Maven artifact:
+The `StatusCode` bean methods are:
 
-```xml
-
-    net.thauvin.erik.httpstatus
-    httpstatus
-    1.0.6
-
-```
+Method            | Description
+----------------- | ------------------------------------------------------------------
+`getReason`       | Returns the reason for the status code (eg: Internal Server Error)
+'isClientError'   | Checks if the status code is a client error.
+`isError`         | Checks if the status code is a server or client error.
+`isInfo`          | Checks if the status code is informational.
+`isRedirect`      | Checks if the status code is a redirect.
+`isServerError'   | Checks if the status code is a server error.
+`isSuccess`       | Checks if the status code is a success. (`OK`)
+`isValid`         | Checks if the status code is valid.
 
 ## Command Line Usage
 You can query the reason phrase for status codes as follows:
diff --git a/build.gradle b/build.gradle
index 0700f6c..4746236 100644
--- a/build.gradle
+++ b/build.gradle
@@ -103,6 +103,7 @@ test {
 spotbugs {
     toolVersion = versions.spotbugs
     excludeFilter = file("$projectDir/config/spotbugs/excludeFilter.xml")
+
 }
 
 pmd {
@@ -120,6 +121,13 @@ tasks.withType(Checkstyle) {
     }
 }
 
+tasks.withType(SpotBugsTask) {
+    reports {
+        xml.enabled = false
+        html.enabled = true
+    }
+}
+
 publishing {
     publications {
         mavenJava(MavenPublication) {
diff --git a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java
new file mode 100644
index 0000000..e6a4df7
--- /dev/null
+++ b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java
@@ -0,0 +1,149 @@
+/*
+ * StatusCode.java
+ *
+ * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ *
+ *   Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ *
+ *   Neither the name of this project nor the names of its contributors may be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package net.thauvin.erik.httpstatus;
+
+import java.io.Serializable;
+
+/**
+ * The StatusCode class implements methods to check the class of a HTTP status code.
+ *
+ * @author Erik C. Thauvin
+ */
+public class StatusCode implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private int code;
+
+    /**
+     * Creates a new statusCode object.
+     */
+    public StatusCode() {
+        // Default construtor.
+    }
+    
+    /**
+     * Creates a new StatusCode object.
+     *
+     * @param code The status code.
+     */
+    public StatusCode(final int code) {
+        this.code = code;
+    }
+
+    /**
+     * Returns the status code.
+     */
+    public int getCode() {
+        return code;
+    }
+
+    /**
+     * Returns the reason for the status code.
+     *
+     * @return The reason, or null.
+     */
+    public String getReason() {
+        return Reasons.getReasonPhrase(code);
+    }
+
+    /**
+     * Checks if the status code is a client error.
+     *
+     * @return true if the status code is a client error, false otherwise.
+     */
+    public boolean isClientError() {
+        return code >= 400 && code < 500;
+    }
+
+    /**
+     * Checks if the status code is a client or server error.
+     *
+     * @return true if the status code is an error, false otherwise.
+     */
+    public boolean isError() {
+        return code >= 400 && code < 600;
+    }
+
+    /**
+     * Checks if the status code is informational.
+     *
+     * @return true if the status code is informational, false otherwise.
+     */
+    public boolean isInfo() {
+        return code >= 100 && code < 200;
+    }
+
+    /**
+     * Checks if the status code is a redirect.
+     *
+     * @return true if the status code is a redirect, false otherwise.
+     */
+    public boolean isRedirect() {
+        return code >= 300 && code < 400;
+    }
+
+    /**
+     * Checks if the status code is a server error.
+     *
+     * @return true if the status code is a server error, false otherwise.
+     */
+    public boolean isServerError() {
+        return code >= 500 && code < 600;
+    }
+
+    /**
+     * Checks if the status code is a (OK) success.
+     *
+     * @return true if the status code is a success, false otherwise.
+     */
+    public boolean isSuccess() {
+        return code >= 200 && code < 300;
+    }
+
+    /**
+     * Checks if the status code is valid.
+     *
+     * @return true if the status code is valid, false otherwise.
+     */
+    public boolean isValid() {
+        return code >= 100 && code < 600;
+    }
+
+    /**
+     * Sets the status code.
+     *
+     * @param code The HTTP status code.
+     */
+    public void setCode(final int code) {
+        this.code = code;
+    }
+}
diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java
index 684449f..b862eac 100644
--- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java
+++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java
@@ -79,6 +79,4 @@ public class ReasonTag extends XmlSupport {
     public void setCode(final int statusCode) {
         this.statusCode = statusCode;
     }
-
-
 }
diff --git a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java
new file mode 100644
index 0000000..0ce8357
--- /dev/null
+++ b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java
@@ -0,0 +1,76 @@
+/*
+ * StatusCodeTest.java
+ *
+ * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ *
+ *   Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ *
+ *   Neither the name of this project nor the names of its contributors may be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package net.thauvin.erik.httpstatus;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * StatusCode Tests.
+ *
+ * @author Erik C. Thauvin
+ */
+@SuppressFBWarnings("CE_CLASS_ENVY")
+public class StatusCodeTest {
+    @Test
+    void testStatusCode() {
+        final StatusCode statusCode = new StatusCode(100);
+
+        assertEquals(statusCode.getCode(), 100, "100 is 100");
+        assertTrue(statusCode.isInfo(), "100 is informational");
+
+        statusCode.setCode(200);
+        assertEquals(statusCode.getCode(), 200, "200 is 200");
+        assertTrue(statusCode.isSuccess(), "200 is OK");
+
+        statusCode.setCode(300);
+        assertTrue(statusCode.isRedirect(), "300 is redirect");
+
+        statusCode.setCode(400);
+        assertTrue(statusCode.isClientError(), "400 is client error");
+        assertTrue(statusCode.isError(), "400 is error");
+
+        statusCode.setCode(500);
+        assertTrue(statusCode.isServerError(), "500 is server error");
+        assertTrue(statusCode.isError(), "500 is error");
+        assertEquals(statusCode.getReason(), Reasons.getReasonPhrase(500), "500 reason phrase");
+        assertTrue(statusCode.isValid(), "500 is valid");
+
+        statusCode.setCode(600);
+        assertFalse(statusCode.isValid(), "600 is invalid()");
+    }
+}

From e77c8595cba91cb3b9b5066b01106e147c3983d7 Mon Sep 17 00:00:00 2001
From: "Erik C. Thauvin" 
Date: Tue, 1 Jun 2021 03:03:55 -0700
Subject: [PATCH 15/29] Cleanup.

---
 README.md                                     | 102 +++++++++---------
 .../thauvin/erik/httpstatus/StatusCode.java   |   2 +-
 .../erik/httpstatus/ReasonsMainTest.java      |   2 +-
 .../thauvin/erik/httpstatus/ReasonsTest.java  |   4 +-
 .../erik/httpstatus/StatusCodeTest.java       |   6 +-
 .../thauvin/erik/httpstatus/UtilsTest.java    |   2 +-
 6 files changed, 60 insertions(+), 58 deletions(-)

diff --git a/README.md b/README.md
index ee683a2..a8f2c4c 100644
--- a/README.md
+++ b/README.md
@@ -98,6 +98,58 @@ Attribute   | Description
 `default`   | The fallback value to output, if no reason is available.
 `escapeXml` | Converts <, >, &, ', " to their corresponding [entity codes](http://dev.w3.org/html5/html-author/charref). Value is `true` by default.
 
+## StatusCode Bean
+
+The `StatusCode` bean can be used to check the class of the status code error. For example, using the JSTL:
+
+```jsp
+<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+
+
+
+
+    
+        An error occurred on your side. ()
+    
+    
+        An error occurred on our side. ()
+    
+
+```
+
+or in a Servlet:
+
+```java
+import net.thauvin.erik.httpstatus.StatusCode;
+
+// ---
+
+StatusCode statusCode = new StatusCode((Integer) request.getAttribute("javax.servlet.error.status_code"));
+if (statusCode.isError()) {
+    if (statusCode.isServerError()) {
+        String reason = statusCode.getReason();
+    } else {
+        // ...
+    }
+}
+```
+
+The `StatusCode` bean methods are:
+
+Method            | Description
+----------------- | --------------------------------------------------------------------
+`getReason`       | Returns the reason for the status code (eg: `Internal Server Error`)
+`isClientError`   | Checks if the status code is a client error.
+`isError`         | Checks if the status code is a server or client error.
+`isInfo`          | Checks if the status code is informational.
+`isRedirect`      | Checks if the status code is a redirect.
+`isServerError`   | Checks if the status code is a server error.
+`isSuccess`       | Checks if the status code is a success. (`OK`)
+`isValid`         | Checks if the status code is valid.
+
+## Reasons
+
 The reasons are defined in a [ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html) properties as follows:
 
 Status Code | Reason
@@ -194,56 +246,6 @@ Status Code | Reason
 `598`       | Network Read Timeout Error
 `599`       | Network Connect Timeout Error
 
-## StatusCode Bean
-
-The `StatusCode` bean can be used to check the class of the status code error. For example, using the JSTL:
-
-```jsp
-<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
-
-
-
-    
-        An error occurred on your side. ()
-    
-    
-        An error occurred on our side. ()
-    
-
-```
-
-or in a Servlet:
-
-```java
-import net.thauvin.erik.httpstatus.StatusCode;
-
-// ---
-
-final StatusCode statusCode = new StatusCode((Integer) request.getAttribute("javax.servlet.error.status_code"));
-if (statusCode.isError()) {
-    if (statusCode.isServerError()) {
-        final String reason = statusCode.getReason();
-    } else {
-        // ...
-    }
-}
-```
-
-The `StatusCode` bean methods are:
-
-Method            | Description
------------------ | ------------------------------------------------------------------
-`getReason`       | Returns the reason for the status code (eg: Internal Server Error)
-'isClientError'   | Checks if the status code is a client error.
-`isError`         | Checks if the status code is a server or client error.
-`isInfo`          | Checks if the status code is informational.
-`isRedirect`      | Checks if the status code is a redirect.
-`isServerError'   | Checks if the status code is a server error.
-`isSuccess`       | Checks if the status code is a success. (`OK`)
-`isValid`         | Checks if the status code is valid.
-
 ## Command Line Usage
 You can query the reason phrase for status codes as follows:
 
diff --git a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java
index e6a4df7..a09f7e2 100644
--- a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java
+++ b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java
@@ -76,7 +76,7 @@ public class StatusCode implements Serializable {
     }
 
     /**
-     * Checks if the status code is a client error.
+     * Checks if the status code is a client error. (eg: Interal Server Error)
      *
      * @return true if the status code is a client error, false otherwise.
      */
diff --git a/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java b/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java
index a4175b4..642dfb6 100644
--- a/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java
+++ b/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java
@@ -45,7 +45,7 @@ import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
 
 /**
- * The TestMain class.
+ * Main Class Tests.
  *
  * @author Erik C. Thauvin
  * @created 2019-05-06
diff --git a/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java b/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java
index 7dee1d8..76806c2 100644
--- a/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java
+++ b/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java
@@ -39,7 +39,7 @@ import java.util.ResourceBundle;
 import static org.testng.Assert.assertEquals;
 
 /**
- * The ReasonsTest class.
+ * Reasons Tests.
  *
  * @author Erik C. Thauvin
  * @created 2015-12-03
@@ -56,4 +56,4 @@ public class ReasonsTest {
         }
 
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java
index 0ce8357..1bee73a 100644
--- a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java
+++ b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java
@@ -48,12 +48,12 @@ import static org.testng.Assert.assertTrue;
 public class StatusCodeTest {
     @Test
     void testStatusCode() {
-        final StatusCode statusCode = new StatusCode(100);
-
+        StatusCode statusCode = new StatusCode();
+        statusCode.setCode(100);
         assertEquals(statusCode.getCode(), 100, "100 is 100");
         assertTrue(statusCode.isInfo(), "100 is informational");
 
-        statusCode.setCode(200);
+        statusCode = new StatusCode(200);
         assertEquals(statusCode.getCode(), 200, "200 is 200");
         assertTrue(statusCode.isSuccess(), "200 is OK");
 
diff --git a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java
index e03ec34..93bb6ff 100644
--- a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java
+++ b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java
@@ -41,7 +41,7 @@ import java.io.StringWriter;
 import static org.testng.Assert.assertEquals;
 
 /**
- * The UtilsTest class.
+ * Utils Tests.
  *
  * @author Erik C. Thauvin
  * @created 2015-12-03

From 7dc9a51a7fd9486e64cfcf0ba0a3d8bb8456f69e Mon Sep 17 00:00:00 2001
From: "Erik C. Thauvin" 
Date: Fri, 25 Mar 2022 11:50:32 -0700
Subject: [PATCH 16/29] Updated dependencies.

---
 .circleci/config.yml                         |  74 +++--
 .github/workflows/gradle.yml                 |   2 +-
 .idea/.name                                  |   1 +
 .idea/HttpStatus.iml                         |   9 -
 .idea/compiler.xml                           |   6 +
 .idea/inspectionProfiles/Project_Default.xml |   7 +-
 .idea/jarRepositories.xml                    |  30 ++
 .idea/misc.xml                               |   2 +
 .idea/modules.xml                            |   8 -
 .idea/vcs.xml                                |   1 +
 appveyor.yml                                 |   2 +-
 build.gradle                                 |  32 +-
 docs/README.html                             | 299 ++++++++++++-------
 gradle/wrapper/gradle-wrapper.jar            | Bin 59203 -> 59821 bytes
 gradle/wrapper/gradle-wrapper.properties     |   2 +-
 gradlew                                      | 269 ++++++++++-------
 16 files changed, 449 insertions(+), 295 deletions(-)
 create mode 100644 .idea/.name
 delete mode 100644 .idea/HttpStatus.iml
 create mode 100644 .idea/compiler.xml
 create mode 100644 .idea/jarRepositories.xml
 delete mode 100644 .idea/modules.xml

diff --git a/.circleci/config.yml b/.circleci/config.yml
index be10f4a..d873524 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,37 +1,55 @@
 version: 2
-jobs:
-  build:
-    docker:
-      - image: circleci/openjdk:8-jdk
+defaults: &defaults
+  working_directory: ~/repo
+  environment:
+    JVM_OPTS: -Xmx3200m
+    TERM: dumb
+    CI_NAME: "CircleCI"
 
-    working_directory: ~/repo
-
-    environment:
-      JVM_OPTS: -Xmx3200m
-      TERM: dumb
-
-    steps:
-      - checkout
-      - restore_cache:
-          keys:
+defaults_gradle: &defaults_gradle
+  steps:
+    - checkout
+    - restore_cache:
+        keys:
           - gradle-dependencies-{{ checksum "build.gradle" }}
           # fallback to using the latest cache if no exact match is found
           - gradle-dependencies-
+    - run:
+        name: Gradle Dependencies
+        command: ./gradlew dependencies
+    - save_cache:
+        paths:
+          - ~/.m2
+        key: gradle-dependencies-{{ checksum "build.gradle" }}
+    - run:
+        name: Run All Checks
+        command: ./gradlew check
+    - store_artifacts:
+        path: build/reports/
+        destination: reports
+    - store_test_results:
+        path: build/reports/
 
-      - run:
-          name: Gradle Dependencies
-          command: ./gradlew dependencies
+jobs:
+  build_gradle_jdk17:
+    <<: *defaults
 
-      - save_cache:
-          paths: ~/.m2
-          key: gradle-dependencies-{{ checksum "build.gradle" }}
+    docker:
+      - image: cimg/openjdk:17.0
 
-      - run:
-          name: Run All Checks
-          command: ./gradlew check
+    <<: *defaults_gradle
 
-      - store_artifacts:
-          path: build/reports/
-          destination: reports
-      - store_test_results:
-          path: build/reports/
+  build_gradle_jdk8:
+    <<: *defaults
+
+    docker:
+      - image: circleci/openjdk:8-jdk
+
+    <<: *defaults_gradle
+
+workflows:
+  version: 2
+  gradle:
+    jobs:
+      - build_gradle_jdk8
+      - build_gradle_jdk17
diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
index 251e704..86d7e7f 100644
--- a/.github/workflows/gradle.yml
+++ b/.github/workflows/gradle.yml
@@ -12,7 +12,7 @@ jobs:
 
     strategy:
       matrix:
-        java-version: [ 1.8, 11, 15 ]
+        java-version: [ 1.8, 11, 17, 18 ]
 
     steps:
       - uses: actions/checkout@v2
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..6bf8b6f
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+httpstatus
\ No newline at end of file
diff --git a/.idea/HttpStatus.iml b/.idea/HttpStatus.iml
deleted file mode 100644
index d6ebd48..0000000
--- a/.idea/HttpStatus.iml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-  
-    
-    
-    
-    
-  
-
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+  
+    
+  
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 78c3966..63787bb 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -2,7 +2,6 @@
   
     
 
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..4e9cedf
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+  
+    
+      
+    
+      
+    
+      
+    
+      
+    
+      
+  
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 28a804d..9d92aa6 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,8 @@
 
 
+  
   
     
+  
 
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 4c575ac..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-  
-    
-      
-    
-  
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7..49e611e 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,6 +1,7 @@
 
 
   
+    
     
   
 
\ No newline at end of file
diff --git a/appveyor.yml b/appveyor.yml
index f858073..877b3ed 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -23,7 +23,7 @@ cache:
 
 environment:
   matrix:
-  - JAVA_HOME: C:\Program Files\Java\jdk15
+  - JAVA_HOME: C:\Program Files\Java\jdk17
   - JAVA_HOME: C:\Program Files\Java\jdk11
 
 matrix:
diff --git a/build.gradle b/build.gradle
index 4746236..eea5bf9 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,4 @@
 plugins {
-    id 'checkstyle'
     id 'java'
     id 'jacoco'
     id 'idea'
@@ -7,10 +6,10 @@ plugins {
     id 'maven-publish'
     id 'signing'
     id 'pmd'
-    id 'com.github.ben-manes.versions' version '0.38.0'
+    id 'com.github.ben-manes.versions' version '0.42.0'
     id 'net.thauvin.erik.gradle.semver' version '1.0.4'
-    id 'com.github.spotbugs' version '4.7.1'
-    id 'org.sonarqube' version '3.2.0'
+    id 'com.github.spotbugs' version '5.0.6'
+    id 'org.sonarqube' version '3.3'
 }
 
 import com.github.spotbugs.snom.SpotBugsTask
@@ -35,20 +34,20 @@ mainClassName = 'net.thauvin.erik.httpstatus.Reasons'
 ext {
     versions = [
             pmd: '6.35.0',
-            spotbugs: '4.2.3'
+            spotbugs: '4.6.0'
     ]
 }
 
 repositories {
     mavenLocal()
     mavenCentral()
+    maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
 }
 
 dependencies {
-    implementation 'javax.servlet:javax.servlet-api:4.0.1'
-    implementation 'javax.servlet.jsp:jsp-api:2.2.1-b03'
-    implementation 'javax.el:javax.el-api:3.0.1-b06'
-
+    compileOnly 'javax.servlet:javax.servlet-api:4.0.1'
+    compileOnly 'javax.servlet.jsp:jsp-api:2.2.1-b03'
+    compileOnly 'javax.el:javax.el-api:3.0.1-b06'
 
     spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.11.0'
     spotbugsPlugins 'com.mebigfatguy.sb-contrib:sb-contrib:7.4.7'
@@ -56,7 +55,7 @@ dependencies {
     compileOnly "com.github.spotbugs:spotbugs-annotations:$versions.spotbugs"
     testCompileOnly "com.github.spotbugs:spotbugs-annotations:$versions.spotbugs"
 
-    testImplementation 'org.testng:testng:7.4.0'
+    testImplementation 'org.testng:testng:7.5'
 }
 
 tasks.withType(JavaCompile) {
@@ -114,13 +113,6 @@ pmd {
     consoleOutput = true
 }
 
-tasks.withType(Checkstyle) {
-    reports {
-        xml.enabled = false
-        html.enabled = true
-    }
-}
-
 tasks.withType(SpotBugsTask) {
     reports {
         xml.enabled = false
@@ -223,9 +215,13 @@ task pandoc(type: Exec) {
     }
 }
 
+jacoco {
+        toolVersion = '0.8.8-SNAPSHOT'
+}
+
 jacocoTestReport {
     reports {
-        xml.enabled true
+        xml.required = true
     }
 }
 
diff --git a/docs/README.html b/docs/README.html
index c024860..4afcd01 100644
--- a/docs/README.html
+++ b/docs/README.html
@@ -5,74 +5,75 @@
   
   
   HttpStatus JSP Tag Library
-  
-  
   
 
@@ -83,24 +84,36 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
 GitHub CI Build status CircleCI

A simple JSP Tag Library to display the code, reason, cause and/or message for HTTP status codes in JSP error pages.

For example:

- +
<%@ page isErrorPage="true" %>
+<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
+<html><head>
+<title><hs:code/> <hs:reason default="Server Error"/></title>
+</head>
+<h1><hs:reason default="Server Error"/></h1>
+Cause: <pre><hs:cause default="Unable to complete your request."/></pre>
+Message: <pre><hs:message default="A server error has occured."/></pre>
+...

or

- +
<%@ page isErrorPage="true" import="net.thauvin.erik.httpstatus.Reasons" %>
+<%= Reasons.getReasonPhrase(pageContext.getErrorData().getStatusCode()) %>

would display on a 501 status code:

Not Implemented
 
+

Usage with Gradle or Maven

+

Include the following in your build.gradle file:

+
dependencies {
+    implementation 'net.thauvin.erik.httpstatus:httpstatus:1.0.6'
+}
+
+

or as a Maven artifact:

+
<dependency>
+    <groupId>net.thauvin.erik.httpstatus</groupId>
+    <artifactId>httpstatus</artifactId>
+    <version>1.0.6</version>
+</dependency>

hs:cause

The <hs:cause/> tag displays the cause of current HTTP status code, if any. A shorthand for:

- +
<%= pageContext.getErrorData().getThrowable().getCause().getLocalizedMessage() %>

Optional attributes are:

@@ -122,10 +135,10 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni

hs:code

The <hs:code/> tag displays the current HTTP status code, if any. A shorthand for:

- +
<%= pageContext.getErrorData().getStatusCode() %>

hs:message

The <hs:message/> tag displays the current error message, if any. A shorthand for:

- +
<%= request.getAttribute("javax.servlet.error.message") %>

Optional attributes are:

@@ -169,6 +182,78 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
+

StatusCode Bean

+

The StatusCode bean can be used to check the class of the status code error. For example, using the JSTL:

+
<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+
+<jsp:useBean id="statusCode" class="net.thauvin.erik.httpstatus.StatusCode"/>
+<c:set target="${statusCode}" property="code"><hs:code/></c:set>
+<c:choose>
+    <c:when test="${statusCode.isClientError()}">
+        An error occurred on your side. (<hs:reason/>)
+    </c:when>
+    <c:otherwise>
+        An error occurred on our side. (<hs:message/>)
+    </c:otherwise>
+</c:choose>
+

or in a Servlet:

+
import net.thauvin.erik.httpstatus.StatusCode;
+
+// ---
+
+StatusCode statusCode = new StatusCode((Integer) request.getAttribute("javax.servlet.error.status_code"));
+if (statusCode.isError()) {
+    if (statusCode.isServerError()) {
+        String reason = statusCode.getReason();
+    } else {
+        // ...
+    }
+}
+

The StatusCode bean methods are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodDescription
getReasonReturns the reason for the status code (eg: Internal Server Error)
isClientErrorChecks if the status code is a client error.
isErrorChecks if the status code is a server or client error.
isInfoChecks if the status code is informational.
isRedirectChecks if the status code is a redirect.
isServerErrorChecks if the status code is a server error.
isSuccessChecks if the status code is a success. (OK)
isValidChecks if the status code is valid.
+

Reasons

The reasons are defined in a ResourceBundle properties as follows:

@@ -544,39 +629,27 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
-

Usage with Gradle or Maven

-

Include the following in your build.gradle file:

-
dependencies {
-    implementation 'net.thauvin.erik.httpstatus:httpstatus:1.0.6'
-}
-
-

or as a Maven artifact:

-

Command Line Usage

You can query the reason phrase for status codes as follows:

- +
$ java -jar httpstatus-1.0.6.jar 404 500
+404: Not Found
+500: Internal Server Error

If no status code is specified, all will be printed:

- +
$ java -jar httpstatus-1.0.6.jar
+100: Continue
+101: Switching Protocols
+102: Processing
+103: Early Hints
+200: OK
+201: Created
+202: Accepted
+203: Non-Authoritative Information
+204: No Content
+205: Reset Content
+206: Partial Content
+207: Multi-Status
+208: Already Reported
+226: IM Used
+...
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..41d9927a4d4fb3f96a785543079b8df6723c946b 100644 GIT binary patch delta 20926 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 i_W%EDg1>@4`_NK(#)z|gdCiK zZ19IgEQKVM;e!GLTY~`u6G=uzBTBA>r3SXu@HH_0ZQF6ePkvLCrcP-MXyt&CtBl8 zI2ywicWO8wRUWX&l9}W4lH)UT<0<%j(l1233wevM!-_fz|76_{OY^OCEQ4HeWgke1 zT=Z%Lhs{aMYNDJmsQ@3uVM*Y)O^T#8jLXRke9ss&QIC4~HiDqf%shkQ-0hBOsPn=0 zZM61To*2R1#}373ZXnptZ#LlLo(7x*JKzIHgRU}7zaxVv4mMKS44eyjh3GzH1TPcH zcy2H|*oOV|1Xok`jc4kZ-H@W`x-X#kBrF?T7;D9l>eZomayDXD3;#t(mdd2qwu<%z z+ge!1by=vGTFac&-%I3qNF?;KCr-x1P2?aL(vE{6#3E#O7Kj+O9|Oj5w0slB zbuj6u#UaYwoFmw_xK!j?o;{e|^l*l0YC+yEh}A9HPkz7nH`va*zd8DxZ@rE^6={FB zo29_AS6??>E~EhsDGZl-a6uXN<+^7zDnwncQHW zb1)(1r6-UOYP{gOjS7Xupa%#>P@{LUtq|pP+e2s|7Z>hnQ{C}55dNmD6fTrgRXG^X zMk5xB=dj#ng|0fU58$`k?J0y!{X65O=!xVK^wGemq-*T6}j8e{fyp6ivF=H0-3An--i1iZCR(wQrLTZX3(3!uc(ls|1|1^41alD1Y_n zk1%twmda_ZU7|eob(Fz1w~fsXV_^&z%|2Z{MmTnH32O#rZ>%)RP0vZRnGg(N<7FKW z%{{Hshli~sFZB&Dh5{yM8d$b9RBtiS=vI@8vDe%WkKLj4xs|pre4MG$_!>p<->kt9c za2G9Dpo9uDtTUpD#M4qLmdt(yIA?l6zMl95RAPZB*OJ6817Je9vhmh_OYKEQ3pg$e#kd= zS+58w2qL+ResowRR8(d<6Ql=(*kcX(V_?Zmm4#gVE=Cn5%0fEA#86m&00Ilw7SaL{ z+!N*e+0~n7uOq~w#>tk6yt!Dck5+8&UoVZA*j)~*)Me(Usnb0DPzo0hh1_lEHG-q= z`i>qi+USBOv6$*Z7gLZ~Ma;-ax)zQ%V^&)TgdrZL#ewL47*EPmumbs89H-{!ZhWi=h3Z7o-u%0pHduII({b zG0gWv?1NYPyGQhN=A8C0#V8juG=mbBf%kcZtXMV%b?5D>h)xDn+?jH};DCYzcL8CYeu^_}io=b91O0!EWBA4zKPe`HBNz&>|3V}A= z9~Q;P<&L`^i@c`xu%mL$DRapF@3<3lzNbiR%Eph?ZgZZazDRFAO2;=VD6RG+HT*-s z`XMaZyjcGpvYyH1xa0E>2Uu!(A4+K%krgojA2s2ci#MP%9KULUo;LA^zeR75pCz>w)M+ru?^=p$*4e31>5gM(vVyDpX z*7-K|mD?lPdG$(thCB{Y)!G5WjOl3cCT(^(aW$%}(jpy7y!?SlOvA!^S>)?eUAqvi z%I*y@Dp2f%f2yM@sJ37Sq5Pf~84|}2h?5?eb(%tEglv#kZeYcNNr}&@=bXytQky&0p;2y_R+cmkfUgKtJ?w<^QsY z7+*G#G&XnFVt05f8BxMt3GnB&{QfW7M1ZqIPld%Jg3*UQ>PNlqm^qMP&1k(I-?aVG z8JlXtCWuC;pfj>{mE^!wi!Gl@qKBM+zJfmEuoO{@6{(V+h|hJE*8f#dOkvx46+ePd zDKbxnYJ#U)oq$P$!;<8|{^zWURzDi*j31j5%@i&A=P%x1=go!#Zv=Q%nZXS{TW+1$ z@A-G!7x5Dh&yRk7euU3Alo0YmoEKgYxSZJa9**XlNjcWTH%thSpOWK3N&IPcTLk8N2nF8xf1Y0#tQ6`oojv4&F#dD zhO46h>Aw*r#qa_5INPk%b2?dVqNKj*Il^O|8Mffa`|9#-vHdwzD_HTG`>my?2Wa@q zP$7yLSRRKAC{&YyHqL%3utXyGtOuyhZtCXWkos0;6pyVP*fIkTT-Y*|wtj}Hu;(RY z{u&6Q))W@Uii8l2lZ>B(p64%|hdCFCB`QjhL{^Kcv@e5T_q zTP*jOG~#*Be9NZSe2wNEBkgYk$#+k}0LYFBQDzPU?p~uQ4MmCNHPBC+gzRzjP`??8PzSe%iSN z*{C3SdApv+Ht|>Y3l&m*g5V(su0jT0Z0(#?&9YH7RbOjH&~xTqb0Vg)Ji#TF#?F!YZA zYeDMn`+_q8@~m(+Izgyi#($|nT1F)Eo#IHO%cz( zs`w)iVPzu;o72xRg6kfRz78weFPK$8IGTn~mgv=UsF}4-aLUut~Qf|fN`QB>0 z!p7zw#Sa3(kbkp1Z9g!C4EoXyIxD`DvH@?A8W zKhaT)t>k}>E)Qmz^CspyN_=EJDv4h=LLXo$ydRcbE0v+aqT7=C&ryQMeTj)}-*$1S zb%K|>v3aR$Nng3%>XW~*;Q^vxflz0CIxuw{R!4nK?v~twaw=2iKU{ge=IDN0q5%zB zHA<~DO7EAeRGUY;3Lt}6q49i(988g{z1}T*$7RtUowzTBdcP>ngozZ3Og)M0e!set z5XT&VuHM|YHBi0+StfJF^yShq1l%%_{{7yr8n&Pm!lx3!ZipHHV@lgdzNa^uQ&63_ z`a12N10{uB69h+S@3a&IC{0vg*aGhGLowAqe}#WtVQvWcQ=+vb-ID?c78cnH0ME>o z0a~bv(7%g6)lB|on64UY4*Wt+lc!_!?bJSv)&7S&7=QjY#cgOG^=f@ElwwU1f@Va5 zHbH*M8zdB$i3B}xhBRZjr632IZrx}f@*&bzk7orie>l-rie3DPi}1XzU@YDRwFKmy5##?##FD26Ru#MD}NfK z5tuAq$9=H!Tkb~_T!>jyy^be_j;rrZmM_hN;a1wVHPTGP$ZVDs3h>)NBFEWxpM9d| z0yexwY2)CpoE|{b>G1-`xh8rVb+_S`3&P{`U+n0->HU{!*s{b zh0ps#6^qc4Vdotq#sXVQ{1U!0Q6P2Jv;upQRENURxu0Xq3x|&?Z@F#yw5IFmRkG$v z)O4w|jNG(&A#isVUSfk7sqE~AWeZ^^lSj6<9gJ!^gX|sQ_}OLB9rCm|6IM_4loGz! z;VXJ1o^%@XoVxOx``v`ic^Hcc&s z?)j5`Vbp5nK=nQ-x2mktC8NCJ0!{-yTeeg|Lsb!fdCoysq)iULdCGe3C-=+#b?4VSwxn}fKF}Z$udG5?r zVczA{U!wZJ6{Pi^!d`pdVaqiz$1$^b<63%Nw(@Jk+grk3W7zuIL+LFp>YgyQmo-1D zEIYg{J)K`^1XDM?>?yyDf@%KS%?SIl(qfqjQwf)0HBhas>TkHKqM}8UpX#0(U1`(( zkvW?bMl<_nl~;V6WO-F#_extCTd=IrEf3Dc@pox~;@HL(WO8C7pX%)>vuJ6w?yl-* zVY9K|o9msu=ynP3)}Vn3S8lU;i(&urM|x4Qan@i*^KoJ6M6K+s^=Iw!a45BCME&~) zg;#IX4p7u)vC%Uu`1)pVNRpo^{wlK(@%)3||2vHrj{dgvnjpEQ5QoZl8@>Q`Tyger zW*>|tJ{uekfQzu4d0T?a4ZR~y);H||zVnAiS9Li2H66W?%`@nCkXL0?_8ImWc4BUkbgv91o3du*oNcHF-6M1; z&|5JV4d*9Q$VBI+sy)RhJcF>zG&Y=cdD4lCQ;%^B`8sVJ51o7@-zcg_24|21-nxWg z=JXW+J&nK#A|nJXS47Q9A@yw`3&G>q=9O&^BHC;WT04y1AbmU^ti~CQVqABvaVY!^ z?}5Q9KilKbIq^3(umZp5hng5{##*BUAoOASe>Psul2||iY<`&F>(#R~ACY$iiC3b2Pl(ez*Bx=D~eCf`HRyn$-~KYm5K zer-XOrJvi5E^HrNE2)j~DZkSqmf2L4kNc>{+_;(W>t7He1+HD# zT22wmE#9rL=1*#cjhhXY#_n`2xIrL{{+6U-GCkflEj4UkI6W}ks%6BjTZ9lmtw)3E ziI4m7`pF$a+{boU{LL#&S&?=EFu{Gs7jE__Oo=N{epkUUqmG49#zHP)4*C5j2qrDi zEXy!31Pty*<59nWzIgQvkCgixv6VIQ!POhyCz|&sShkU*($QFGPCb+K?*k;Lh&Rl4 zjWufiEolliWh2@}9Oy@P707bS1c5pNSSXqQfPL&t9-lQK59(OQA3LjO#18Rktw6u#SzF46}%g2(@1pM584UD!=%P}TC+>vgp19n z{qghOzYsjhUm%?Zb4aL!(&k1+zE{MN*TWxQR@^l2Hf~^m@g}30leXq*C%AR_Sb&Vk zVkg6^z2}gl3W5247Zc9|*jK^AlgtVU+ZKGp$me6P;S3A=xusy8ax#Y*Wt8Kp1j6+& z3=Lgux9$m&+pew%T6L1vPxj%RG_#)lbj92>L#KIAyj19F!CNZZOr9{tC4BrqIL z`%dX?k3$SEw1Py4A&eIdq3Jycxy+@G6E2r4RA03gR}VXNv9`H@Wh3;fzTEF7apq6%wN$6)i--FS z+IMlqv+}31_B;aXi^f`Q7vtc*B~7->Ur!}HM)BnUVxaQ)bL;a?TAj3y9#T2uee^J5ohGslCH8ejViE@UFsnirgXB&W$+j%+hjvE26+6*S zTMl$sfpw)N6M1<|b0W0SQ6c;?!G$ z@rn0bBsGYhxMECJx=($!IwxK(I>>d$@c#Q%nKhi!^%fWIm!j)>S~+aHZ-P$2{^o03 z(2eaYQLj>-8pLt=0?Qzl_9sBVhbRQ}A#;3u7t*{%M~puxpDMZ&TdFMohAWOJG&qa- zAv(x(M~BG5FENOsXu};?PW##tw!7B`;mSXCk#x*Wbh__>J)?Y_x={F=?r{(2pTjnh zolI#ARMSY3@9*?MVyFv&jJ98zrFM!XzcZZbM1Y}usOAs;BAGukn1{!T17A8ozY+Tf zCa`$xiMs{tWrYC;c$0&E9Ll_b%HUm@>m@0*^ z60ey`T-+j$OJ0gs3RKtH17i$mM(Vbrsk*OmY9Ix5SOsI(>OA=@kBZ%bMA$H9jMP(y zh%Y!ou3F_4Dw37AIp<0FkRrfNX7n)ywaO@`%19+4e0x+8M@0`^O`-)ut2n|Ys{-@C za%*GCyHLZ zab?Ca^+`6^c)}m_j>6f5tnz0)mYAqhFaF5l+KeQ4Z+V1iB4KZ=hGE z4W@qHd)fW4XW_w4Uusu1GiRdq%ZRQ;Gi3%96y4cAk_s^8)|`73GqgFR8K_;)`)NqAn&=vRs!_HE z9ZQrjY+sd(i;=F?#9MYU=X1-`V)c*iAuazFs=Xmu878=4`No zU4!wq8cv02z%=zfZeOZpJ5s4w>#k5f&pF9{DUp5N3x*X(lMk3m*Jk+DRc2TXYM=Kq zhF=oB89Luc_+F$G#MPrYK0mE!zeQk-8&J4nE3|n@abjRSe234l=auM*P&4GSI_0bO zoMW9G^C>g~;uPc1p0SV7Bsn@aj&FEK0JyJin7YzGQ@6)3tH70Vpl2)_v(Qqwp)wOCi#~RbxRWQ-9ywE z+e%G&805L5f9UJE(;fC80D7>weaPl=kLxL6ztg&H>js>0)EIf_|8i?`51~A}F6nGO-+pEgkto<8m%#+ zVVlW=-<_M<$od-d43QS+zNwqhSeoFTnDML_L-RH!?R2NcX-}U{>*BN{S~U_WiLw0| zk<77*VKj!XD_C~kPPil@7|2z;l6>RmmG{&n4F8I6UR4uK+tkiqG5GM?mul-)lscnSGV$uT1_C&R11T% zC!>?g9H#C!mT=S8qUk7|d`vZgsB7{1!U~fs>bRM4{`L#{9AjF!y7GU>$p}2J&^&e+ z2b#&Syo`W0$QQ#C^WWF6QTk-?1!Yle>ug;+SEha1kU>#V7JIZGBq2~GxmQTpBu#9W zSM-72%J#KVJ(sE8`PvetYj&dZBY%Z|_BhUK)=CLn5+*F`WIi z^W!kq3%$O(gW% z;5#w!eLtAQS6UKXa0;K;#D}^ zvZ3Ix!CO4`Of%#ZA9^B_vaCFZa~n%LC42qdcw?TSX_d1qLw-8)(W4E0(Lx@pWlGGO z-@aO&N_o>{{Z4vI(<}@Nw{h8AwTaBna5oE3lKt2>Px|2pm z&2TpT&MW3^J1iS`T-w~6O(VsDP_|i;-Pt6uSC_T^9X?mtHjVF+g4nifxy1+iqgFGf zySG7%tEJA(RJrM;BA6h20tso-aCrrkXYlwy1D)crNPZWVC2PapW1E&-V_hcpR|XA` zs4OaLF7JUhPDAi!ihwOrJgg?W>FFSZx16+& zGYPv)v|<rG(Di#UwtddEW7$_&tNxB8o;j{3T9k2vX+s zz_QqW@P2HsPxZcgzxQw8 z@&-!!7Hn?Z%N3-Qtkp!I>n}Q_w-sR-y_2+=5(&z~f6JF){ zOhao=c3S zKvsfi<5XcnF$s#qsOI4<;#GJ6|YsusW7{nIZiTM6d$T`L`+pHi$& zMSr#KbV-%6I1yESl*Znoty2UP0h*C-8p6!+PD8Bg!+YM_eJ~h7rpGH zZ$zDsM^ki$l^~JmyZU~0)%fl#rg%|e*phm>M~ZFsu3J|QI9CIBtSgIgf!iCS24RnP z(m$dJpM~j=Rd1lx;)P-@DgITC2E+r6uiZcL?=S9kR1u_m5(f4*Da1Bdc?u!$ck zfPuj$j<~@f&cp@Y=w3Da-_gB#c$g8C3V4`Nlp6f-M=(GoZQs&1cnG;>h+#={9#2LX zrW4F_DCZQbB zGrh?Rf=+j9`xLGjY9NrUUC|gL8|2ngaB5LOpk5IO28#A8WBuNlJv-O4K6&>j>@Hcz{b9%rAM7?2>~1;ic05`yG1-)WOocz*wJEFv z)+OK^y%vVlNN8~I!y_8%IjPLSq*!VzUf_VhdzfsEYNptTKM?#5<2f2Q2xt$`Gms|^ zl7CM(;d(|1Qc_iXO7ajIuNyVQgO*wFe@wIomvqPa%W>fRxLDU0(Vp(|Q|OKe`(+PI z=W1}V2#u*vB*}#cvF-@W1`?y_<=KHusRC$TKzM_AmiaDo=Kl@;WLMgQM|5Bhnm!FB z6~*UUZ8!z{Cp^qo>~|FrGEN~_UiHS*1;#(6grp95K`z|EPvx?f^#`ctO3V~t8zkw5 zqb6;{Vf%k5jEj;bQ=41CcZ|4dpM}4O|94cfhLA+=3jqd(``=D0xl~jL5M}WHQRFM9 zN2>>yg))pI6GJJ%#H?`ZpdI$B;d9KP`iso5eNMb+en^h#LuG`mNls4|kzHYSYCZRb z=Vm=~TL=I?Ae0BlAf1mav=x=9$8Lqo=y;=C^f?lQWk&IWRi0jZ=?pn-gG`!zhjv{j zZM2yPwD`;5VYZw%^VYC{-r4GAQuG=pP>=0(Gk>{ZsfKrZRKKsri{6%d8&arW%|hpG ztNx$A16FHOhU%vii1oJ6lr_jij+~)Zp(&w;c+2yxcz@N+Yp#}tFFov)yd2;1s`WYS z{%E$Jj`4R_tj@?^`fs+QE-8f}j+)*iR+Xz@>+yo<7SBY8zdf`YK1Z6?{ubBHh zFmY>E5tgnuII4UM4#bWRmTM{f8dUJr!=z#)J{Ilf5`tJ=0ZCAH2;gTzcvb}*up0z; zZeLIovm2^@?yMFIYc|aSdSkz~AzMjFC>;*cB31O+Oh_#TgcpV|{#R)utyK^l{ zb465cBpZkBjiWzlp>~S_gv2AZG@^cX4MZ=^vFOC>H5sGXLxCI|ON#Iz*NopkDA_)d z?Hatmqalapt0QkbJ-X?>;>IivQqY*(IlHu`7|~(==4h~lH*fg8o1=zsUi|MvB7q%w zKsXg+fPpbGfPwu;M&%_;j+Q_IsG7P>yyzoCnC+0Hf6$poL6|0^kmEp5&?7Eg$lWK! zOrh;|v%nfO*J8HR*6P~+7l94Vf@&+st!XzlboJ70?SIyGZDV)&ZTS0_D*QX`%^W8O zeSiJ?8v1vq>t)Mz_Fm{T&*wD!U&jp&D#QM77#pTjIkg|txC`=$WljWHK;;6)_-XTx zR2S*PbE1QMew>mYvk8rv3sZ3Sc7keIP6?;CTR#Z*no2Uuot+cPZhZ@l3Y=vE z({1#LO3w9BOS(E#y|E_rQo9)zyqpsT2;lC~4Dm{M4Jq>{OLa)5C+^&0W|3}bW2-H^ z+!J;tf0jJtfYqm-c8K`H0IN{#nvxgd@9v`7#3iJL#Cs1%9U_NeKWdL+@$!jFG_;X& zV;Ag_%4A;c(kk^JJ`~T_tDKugHX*tN`uIxBtP*VB3>KQ9&Otk+cMh?;4E5Mh=f3_* z37q$#ct#i{(*u5F_}~ty@tiiAwp&Cc*LJpBs7H!_k|@ziau-~kfdmg%>OP+%+*C`8 z1Tz9;C(^NP-*N6%ZW`KkaK-TlRn!Wp!<`@Qks4j?j{H3{KBb`gksEl`nCueJZxnyw z!%6mDe(AJ1!vW$HSYk8_A%YUFAw+|P?tU%n57gLt^9B3^nav2v%g(7*feSVVU3V3- zO!j2?LieZ3pRHUDK$nw&*h6bAV#{V5hn+*GliYMGqC9jgHhwyuh6>q^&a$0eqSvWy z8LT_(K6aZY&U^~)o}c`eby3q|bA}~5Wz9^L;-qzamWDvu{I?Pg8O(c%^w$EF-NN=~~S5pa%#NLgwE$~`97?YYaH9Kq@7C{4rgo!gL7Hf&(zV4NW zkJ3f5cBFNH^(3Jct$>B*Tm|8zUgAoMuVY)0JUZdC^J3jbZwokiXb1VU!AR0EU6vY4 z*+)f1FQb+6VfEZLcW1WEx=by<;}m^O&G^J6sitOyNv?a#Yn^nP?_gSA9!Nv=}wk$LF&n{hSA@;phy)TRM2d34U|Gfy1o$hQ;(Vu2c`4;NXm zlhZ-%s<%a-gSD=UcFU5%@8&0j2p+hqLcIHv5}PVdMmfK-0ds@j+Ru)3MF^Ww7Mob5 zDMK3P&>Gt+kR9U?$`)Hc|5}Xar*jz3qR_L{OiJk2fwh$-4W@G%zu;Z7Q0FCc=w|5P z5cD08=rGo{qTH;JZaXw{^cf0jO(y)piPz+iOu-F8x8x3EU53fg~qnR-}(=Gvc7I3+)QbLEZb3;~feu7cUEY{sXKijeF zVJ${UB*{dA4eePwD6=aya5HS)1WefN+TvX+vMOv`N2cTsSL=HF4MgF#)_(6+As4zm zcaR{RWjVp3BeCh=#Ej(4X^33FHG?%DB0xpTZc^#uy#zRlN#ZDK)wyEw2tXm@(_K0&iKy}VnnKX{*bjEciAk_C5}b1fiyNZ8|B7$9=s*(YmmRmlH&eRBB(h-dLgdf?2|8 zSW~BfI$u6O%l!)vFgO+S4WHTFbCh*0p9z1H%)KeX z&Sd0O8poeuz#M>&N`@b}hGoNzqq<_I)!d928kFotHpgmR4Jl~~-3Q(u4e?vi_mRx+ z8`h)kc{Z>Ob4oAuB52LD+ox->i}g;s-iUJJoqo?i`ob(iQ(=(yc%aFV4>Yz>1MYT}o;=?_^ z&&jc6(${hA8g)2)hXn*|rczoyhIYlsO*>WFj10D-UZ#=$*g|jY!onI|KJSYPy=EMg zGz-ISU-^O`*w%zVzwTvzJWFmNh|nw}>0}l_3JxoUfRjp6-bB0XKfY$Au+v6i$b|`H zY|;1jZXc8#GA7=Xr5Hw6WNB5#fIr1*H(9b;-ajyR=1*20R0Rws5*BlxEc7}RYcvhP zvz=mTpGOeRJ_vhJpQf36TgwhS$So}|QD8g6l`#>lcJU@z-^rmbKMcH8PH*l8c>$vx zqCm)V=*URppX7OQW+u0g>flsW1(F4PuC%u;?!#!*Abz@Zrq#Fb2o5KZ`span{@)NV z|0*AgQ4E*$ZXlN>7Z_54D=sg2yZc`HD>Z*cDO#f2R4MXTzWJD>rW5Z!^)bue?x^K= zvu^%jK;1)A5?}PlNk%j5#06TVbypNYN=HP$d@lYUB1X4CLfC3v`nOYTJfZT3hXWjj zM135o;qp6p-rr+PHXpxc>Tj!g|0MyT`$Xk}OK+2YQ2m($i=OYs< z$CNPS7Y`eKe@v3|_&M*uHLzYmP2t{zf7gu@hIe6ur062@qs?)TA*siTWv}kfcDS| zK!xGzszMroZI{%4A`Z3*hf*Nc;oKkcFWY$1*iB}c^6|jU zQdi>3<@az`aW{H69D(yCCW=LqUz%-mD%O4>wUAXLFXC8sjq0vxeArF*YTG`$>JRfi z0S~!cxa;tj-h1OLSd;JT3|BwVVev_f-5fF{+j}40xql&2;IPuOhul?!R z2q<*?(n@AiipP`;uz!PKFHpywDHvN*q7hEN2F4XRYRARdEwa&Wip!2hqSr6YKb&1` zT6Q|3CSagOD^O+XCYM?p%IA^9bKUQK05N(N+<_(BJ8^;*o25ic+sMh#$f&RqZQY@1 z_odtGgcUP!yCuRk1a-R;^ZTM4D2{t9_pHCiAvK;Ox61Ena^8?=EwLB0Kc{U-KvSU^ zC1VPin}a!7h+SE-2br!8C32kHSJP^(qOSS?R6z~(Fq_dbuGUPcXo>NnkKmm#8H}S^M1BcyM>F6z z&@SMGd0GpCPu)>t;77|6Dn21l% z)N~H{ut=4%J}_w+7@b$7658md^p#QN#Wr?M}L$7NS`QK8@8_BQJOBaq@TewO z?03~w`8teD{qv;U*gs(jp_d?E%x z42@*cqPz)^fd>PUndY!fa!|bdBYP3lJPtp9Ak@w?>M9!bSF}3-D;$5%tC`sc-~^0{ z>*?0(OT^q@%pHmz&hYmRhA)1eXS-3o!fK}{azeHG$3EMtm&_aBZBOHEi#<|K8`jS! z_5swyyLh2*+|#QSe-yHq2U0)T6T(hVyxzsXSiR;})jlq+2rtrRloPiZI!DgrJmUUm6Jq}duH5rMu}ZTv@XhSK4jKa{r-Z0rlk zUfnm8`od)#0c5Og1Rwnnlupg_YVxU#8nOPASm3E5n-p+`f~`ADgY z(9F20)1a>gm&VoRHQ!j&F|4(|1+f%0u-q%6yN-5`IJb^WFmo_F4-!i2N*p0OE9;vh z>69t7q{*{_WNYagYoRs&d_`JlE6hh;qC4mFN(LU)(p$s`1xi#)x@Fo=D%)|D3FNr@=0)wt1~Jb~*5k7iL?_cW{Kfb2riV?uj3ZQ`H~(5Sx8 z@(6oNNOz^LoFt>_EV2FpLSd1X@N)v|;K!yi zapFuxUD-7`0szua~YNc!z-yv zFzwt;DKM=6l%M2|#hV`3E5O*44SK*BHmVVndOoQ|yIr9nhc;?i2RGvr>>4YBJ^4)^t`YeDcRN1!0f(9h3hKAQa)1tlaSJ-Y z-1%L59nw)>QmF5Ps{dRC>dfqRJbCY#JKzKAIhNSO$P2FTlg08&9Mp{Ov>my91{))D ziy8byQ?nw`BsypnS$XEtwD2pDic;AFavxs6zUm zp}koQ#NGDgOl`dbol|sgidy|`9qE~v|5lRSL?1m6-4jfVcm$%o;6{A8X1wV1eezhu zR3e2p30kcy*<+_XZlN$FuV~Wgh|%m?!!L3TACuazm_sYox5G?{mOyCjA52|QU`*1O zrNVGH0~=ySZ8HVN^(6RyRW>kHN2sP`ms%(S0)6bkF{@(U5wwzRoJ92-yHqZuyrEru z;VF2DVpwEI%>PAY(Jr&pyh4*fS=aPke>4e5fusj zQII@ma!pLDA^mwD#E`ezsD$f7cf}gN1HJeU6{`!ZYdQan!^@Y|Hb%&dLB@C0D%MZn zlcQ(R02vqRadm&P5T5kMKcvd;3CwRc|H{Vkdg8eG6gBXM!xA)G2y!OBcXD_KE7KEz zl1Gja`!9RxBjHqV|F4VdfQD=9!s7}e7@ZgsW%NOmga{*QB)S;A_eAeC-i(q6qTldz z(IO!sAxe}GEj*%)-bFAvd4dS>Pv(E`{m*~yy6f(}&$sv8_pE!?I%}PMK3D{HCA84V zE~fWJ7x&+*m=;_#>~nSL4|EZsJP6?v7KYVS!)Z9IypZl~r`9_J2^yhMNXNOzJA1{Za_ z6>v8PZWDpafs`YR3~qGyZ@u(?)M6Xo9lYV4v7u1iZKc?gVUeR_f-&rU*B`);qEMDP zH+UiRc&CYqb2}gRg>l~7`HE+_Kd&gcjZ?Ng>XGI3>m{X%X=q4xb|pVVMNZC9J1i23 zTQLho*(@&ip$;5pCv)<8yaisjG6of7NsQ+lP{t_*D@x(R*AIky?|b=-Yi_G-=y0#h zk>p1H;W>@1(lKuU$TT!61mZ!cl`eLdWjm0J(}kI|hlaLGJ+b_EN6*y}cP3SA3lgHcytA6-jzbi^OxnBiY=YEPESFY`k16Q!W1B zZ}WQh!84d^ab7XXuEZFr-jOt$nyj^dG0pcx`{dq9_6MO(sSo1%X~{A!a|REvvWuxn zl9=n|Uw5*FUwDhH@)}omh&#FPnUy#c=XA-~?LZ4}Key{L7gZ9SS~3}ltp8lCcP=pY zT9z`I0P5Xj$q@|=+EpQHfCgj9YmHvc9-KZpFs~ZERq>QQ99Q?Mw1DdPJ)e2z3U}m9 zT2e3hqJ?@BJHcaX4oV56GRH_Hc2PscfRS9T#M*nQ!r7!)S8K4}Y^Rz$HdHjakw)#P z(t(1~Qty#AhWC^@Z4Te^hi8C|0<84zJ*cUAjnZ3JYMypFN2B_yt@dFtdqGZ!rh$U- zk3pW=idJL#-vvx)^V)FyFM1U#rUux%#CL@!e(JnGeduO8G%ggEGFBp+&dFn$L3?&H zAQNMbj=+V1R=i{;YWY9zhxlf$xT23&;p zkMTv|^-9_sZFD7f~qVUUOLk>bckM-SEc7)Z1#ViqwaGd9(-Aj~n9S7;{uf*STcG4d1 zh|-Hu$%xy3N!2&2azpoAuW`cSfiH38Wy=QYZ$w5IybfDizwh<#O@95n*E-qpZewrq z^N_OBenePTui;XC3Q{OUqWU%@WcOuQxsXb&+s#_zCn<#&@VVCM_x(a#USLWa?jawh z)VsY{zFF7{HZuM7j6pyDQK1zBtgm`^szFWv z7h@*$Vs$gy>oF-ic}e^9jwg4K{%r=*(gs(gD#q7Wy2~V;Gac}XZWYcoqiBQ8rd^ZA z)vY1ZS>02@W`h#Uqw;b`!9VqtOT!-|%<9X=eg zFLhk3mu+$`t6z$ef7&p}ASkOGWrsJ8U~QwHW3;SB_fTd0rrfe%iIvv;Rxmrrze9s0 zrB`6$qTk}>`=s5~^^?TKA{w%i4!sOZ$S@8DW3jrX@qbdXF$Uf4WXopWMfJ@FO`7fJ zS|K)CIiHm}fkpH`^D8ZVbKrM!qQB_m#4dLO?z;9#G|Z^6L3Oit5if><9=t_0H{j-G z5E{<0KHYlJ_1Jqt#>0+iMz5l8pFCByW}En@PjT-W%Tv6YlY$FEeNG{pQ%9}S3XNN= z(eXZ~RM*+bI{52sHoo#UupkddmEXkG;y8QWYS}c7+a7RtTAg)0{d&>E6D=CHn;is$Y~$wiQpzLV-d%8ck;ZSq>MaRF+9Ld3~Jt|3hk*Jsbp;r#yyRj zF#kbknt!cNP<}QnfOxj(+n+n-{wbK@E9y`jN3|ZTe{cKBWCNOfVmQlS0j+NF}!> zv7G^D$KZ_B`jPGl@+B{4?W!_wN}a3Rb)fk$acEKyHIUIF-ER0(*h1x_bkPV*)|teIdxCk3OTRWw?p;qE8j7z^w3cf0D)ghm{A)QdJrY30o zajOp7bxUaVPOIyKZB#sn=dHajw7~P^tGz?ccX>tb^Mik$7MgJV$YCnDDKa==&nsr% z@y)5R4+BqZ*icaOIj^k4E9ZVpzGG@#3|fT#7IXei!$E%j@AO&*44W#3)5hN0RKBrw zx$=e#vvR4Seglugurm_{K7C!+zgAhc*4W`IEwO54A`U?RgL^+npZCRKhsH zTe3Xs+vb2WRfkgKmLo=AW1>;y!EC$=j)XO4V;r3ik9nj&d8A1j&VeTyBj_Q~?bnp9 z+0au=+KQ#8Pqvrc8{b`RR27HU`5_o85Z+V^hwJyscoFJ>BR#b|k^$_CQbovY`R11> z1m{y9AJ_FSebqAlB{7GL4twf|U8Z6envXF?iI{2AI(it$7#b01X&}tS5MA`rM zowK)qw0lJHWL6bOcKu7F0Ila_fDJz|V@?;)@(0)E41rXCP-$KcX!i%hgRg)C3v}Rz zc^IG@L{Qnl{dpY#@*6mq3I`{`SbyaL#w@^qGz`(?89_^MKmz+%qS_xxO+>86&{6-L zWKlROiqOde`hJ!G1RfE^?$4?~Pb^U^OJMjl8lb@<40s<;H036FODHZ~?mK1@#e1dqL7-fvm zbFLWt@LU!YT}A>VB}7ofvNUk=f+#L7D*_uYiP3sr(-VTzfzB&1K(T^o;;P~xnuKcp zolHn2p%Vcz;l+XBb}+e15cI$!frVazhyYs#{yQM!co;x70Pf+PfQdoSVpSd#nScuZ w|E&DqkiEp6nWHb}B;da$<=?F+{O4J~(cC2_GD0yC1R_ni)(HQ!%J47kKb!F!p8x;= diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f80bbf..00e33ed 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0..1b6c787 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" From 1ab96e5b3adaf6d18b5e91c2485528da440598cd Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 25 Mar 2022 12:04:05 -0700 Subject: [PATCH 17/29] Cleanup. --- .../net/thauvin/erik/httpstatus/StatusCode.java | 9 +++++---- .../thauvin/erik/httpstatus/taglibs/CauseTag.java | 13 +++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java index a09f7e2..fec1713 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java +++ b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java @@ -35,7 +35,7 @@ package net.thauvin.erik.httpstatus; import java.io.Serializable; /** - * The StatusCode class implements methods to check the class of a HTTP status code. + * The StatusCode bean implements methods to check the class of an HTTP status code. * * @author Erik C. Thauvin */ @@ -44,10 +44,10 @@ public class StatusCode implements Serializable { private int code; /** - * Creates a new statusCode object. + * Creates a new StatusCode object. */ public StatusCode() { - // Default construtor. + // Default constructor. } /** @@ -70,13 +70,14 @@ public class StatusCode implements Serializable { * Returns the reason for the status code. * * @return The reason, or null. + * @see Reasons#getReasonPhrase(int) */ public String getReason() { return Reasons.getReasonPhrase(code); } /** - * Checks if the status code is a client error. (eg: Interal Server Error) + * Checks if the status code is a client error. (eg: Internal Server Error) * * @return true if the status code is a client error, false otherwise. */ diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java index e7bb05d..8a44fd6 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java @@ -54,16 +54,13 @@ public class CauseTag extends XmlSupport { final PageContext pageContext = (PageContext) getJspContext(); @SuppressWarnings("PMD.CloseResource") final JspWriter out = pageContext.getOut(); - String cause; + final Throwable cause = pageContext.getErrorData().getThrowable().getCause(); - try { - cause = pageContext.getErrorData().getThrowable().getCause().getLocalizedMessage(); - } catch (NullPointerException ignore) { - cause = defaultValue; + String message = defaultValue; + if (cause != null && cause.getLocalizedMessage() != null) { + message = cause.getLocalizedMessage(); } - Utils.outWrite(out, cause, defaultValue, escapeXml); - - + Utils.outWrite(out, message, defaultValue, escapeXml); } } \ No newline at end of file From 6344d7a68bc766577235191e8eb3ac4fee518b2f Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 25 Mar 2022 12:05:07 -0700 Subject: [PATCH 18/29] Only use XML character entities in Utils.escapeXml(). Closes #6 --- src/main/java/net/thauvin/erik/httpstatus/Utils.java | 4 ++-- src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/thauvin/erik/httpstatus/Utils.java b/src/main/java/net/thauvin/erik/httpstatus/Utils.java index 2752b60..ed962d0 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/Utils.java +++ b/src/main/java/net/thauvin/erik/httpstatus/Utils.java @@ -76,10 +76,10 @@ public final class Utils { escaped.append("&"); break; case '\'': - escaped.append("'"); + escaped.append("'"); break; case '"': - escaped.append("""); + escaped.append("""); break; default: escaped.append(c); diff --git a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java index 93bb6ff..6e0f485 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java @@ -53,8 +53,8 @@ public class UtilsTest { assertEquals(Utils.escapeXml( "This is a test. We wan't to make sure that everything is according the \"encoding\" " + "parameter & value."), - "This is a test. We wan't to make sure that everything is <encoded> according the " - + ""encoding" parameter & value."); + "This is a test. We wan't to make sure that everything is <encoded> according the " + + ""encoding" parameter & value."); } @SuppressWarnings("PMD.AvoidDuplicateLiterals") @@ -79,7 +79,7 @@ public class UtilsTest { sw.getBuffer().setLength(0); Utils.outWrite(sw, "wan't", "default", true); - assertEquals(sw.toString(), "wan't", "outWrite(wan't)"); + assertEquals(sw.toString(), "wan't", "outWrite(wan't)"); sw.getBuffer().setLength(0); Utils.outWrite(sw, null, "1 & 1", true); From 5486074d1ef4f515ef2004785e956fa9f2f65d36 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 25 Mar 2022 12:56:41 -0700 Subject: [PATCH 19/29] Updated copyright. --- src/main/java/net/thauvin/erik/httpstatus/Reasons.java | 2 +- src/main/java/net/thauvin/erik/httpstatus/StatusCode.java | 2 +- src/main/java/net/thauvin/erik/httpstatus/Utils.java | 2 +- .../java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java | 2 +- .../java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java | 2 +- .../java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java | 4 ++-- .../java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java | 2 +- .../java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java | 2 +- .../java/net/thauvin/erik/httpstatus/ReasonsMainTest.java | 2 +- src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java | 2 +- src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java | 2 +- src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/thauvin/erik/httpstatus/Reasons.java b/src/main/java/net/thauvin/erik/httpstatus/Reasons.java index e551ce0..db59093 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/Reasons.java +++ b/src/main/java/net/thauvin/erik/httpstatus/Reasons.java @@ -1,7 +1,7 @@ /* * Reasons.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java index fec1713..e8221ce 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java +++ b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java @@ -1,7 +1,7 @@ /* * StatusCode.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/java/net/thauvin/erik/httpstatus/Utils.java b/src/main/java/net/thauvin/erik/httpstatus/Utils.java index ed962d0..e7b97fd 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/Utils.java +++ b/src/main/java/net/thauvin/erik/httpstatus/Utils.java @@ -1,7 +1,7 @@ /* * Utils.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java index 8a44fd6..a5078b0 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java @@ -1,7 +1,7 @@ /* * CauseTag.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java index 2753d6b..079e551 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java @@ -1,7 +1,7 @@ /* * CodeTag.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java index f6211df..ae81a96 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java @@ -1,7 +1,7 @@ /* * CauseTag.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,7 @@ import java.io.IOException; * The <hs:message> tag returns the message (if any) for the current error. * * @author Erik C. Thauvin - * @created 2021-03-16 + * @created 2022-03-16 * @since 1.0.5 */ public class MessageTag extends XmlSupport { diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java index b862eac..1720752 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java @@ -1,7 +1,7 @@ /* * ReasonTag.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java index 8ef8ddc..83083b7 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java @@ -1,7 +1,7 @@ /* * XmlSupport.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java b/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java index 642dfb6..94eb207 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java @@ -1,7 +1,7 @@ /* * ReasonsMainTest.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java b/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java index 76806c2..8ca1c39 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java @@ -1,7 +1,7 @@ /* * ReasonsTest.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java index 1bee73a..2981fc7 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java @@ -1,7 +1,7 @@ /* * StatusCodeTest.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java index 6e0f485..d0af31d 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java @@ -1,7 +1,7 @@ /* * UtilsTest.java * - * Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) + * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without From 3616136f4e07b612b75a54e09e2bd2f1e0719044 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 25 Mar 2022 12:57:00 -0700 Subject: [PATCH 20/29] Improved status code testing. --- .../erik/httpstatus/StatusCodeTest.java | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java index 2981fc7..b5d7553 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java @@ -35,9 +35,9 @@ package net.thauvin.erik.httpstatus; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; +import java.util.ResourceBundle; + +import static org.testng.Assert.*; /** * StatusCode Tests. @@ -48,29 +48,24 @@ import static org.testng.Assert.assertTrue; public class StatusCodeTest { @Test void testStatusCode() { + final ResourceBundle bundle = ResourceBundle.getBundle(Reasons.BUNDLE_BASENAME); StatusCode statusCode = new StatusCode(); - statusCode.setCode(100); - assertEquals(statusCode.getCode(), 100, "100 is 100"); - assertTrue(statusCode.isInfo(), "100 is informational"); + for (final String key : bundle.keySet()) { + final int code = Integer.parseInt(key); + statusCode.setCode(code); + assertEquals(statusCode.getCode(), code, "is not " + code); + assertEquals(statusCode.isInfo(), code >= 100 && code < 200, code + " is info"); + assertEquals(statusCode.isSuccess(), code >= 200 && code < 300, code + " is ok"); + assertEquals(statusCode.isRedirect(), code >= 300 && code < 400, code + " is redirect"); + assertEquals(statusCode.isClientError(), code >= 400 && code < 500, code + " is client error"); + assertEquals(statusCode.isServerError(), code >= 500 && code < 600, code + " is server error"); + assertEquals(statusCode.isError(), code >= 400 && code < 600, code + " is error"); + assertTrue(statusCode.isValid(), code + "is valid"); - statusCode = new StatusCode(200); - assertEquals(statusCode.getCode(), 200, "200 is 200"); - assertTrue(statusCode.isSuccess(), "200 is OK"); + assertEquals(statusCode.getReason(), Reasons.getReasonPhrase(code), code + "reason phrase is not valid"); + } - statusCode.setCode(300); - assertTrue(statusCode.isRedirect(), "300 is redirect"); - - statusCode.setCode(400); - assertTrue(statusCode.isClientError(), "400 is client error"); - assertTrue(statusCode.isError(), "400 is error"); - - statusCode.setCode(500); - assertTrue(statusCode.isServerError(), "500 is server error"); - assertTrue(statusCode.isError(), "500 is error"); - assertEquals(statusCode.getReason(), Reasons.getReasonPhrase(500), "500 reason phrase"); - assertTrue(statusCode.isValid(), "500 is valid"); - - statusCode.setCode(600); - assertFalse(statusCode.isValid(), "600 is invalid()"); + statusCode = new StatusCode(600); + assertFalse(statusCode.isValid(), "600 is invalid"); } } From 8ed5bc951ff88a681c5a0944763c09ff444947f8 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 25 Mar 2022 13:06:48 -0700 Subject: [PATCH 21/29] More status code tests improvements. --- .../net/thauvin/erik/httpstatus/StatusCodeTest.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java index b5d7553..d814eca 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java @@ -50,8 +50,9 @@ public class StatusCodeTest { void testStatusCode() { final ResourceBundle bundle = ResourceBundle.getBundle(Reasons.BUNDLE_BASENAME); StatusCode statusCode = new StatusCode(); + int code; for (final String key : bundle.keySet()) { - final int code = Integer.parseInt(key); + code = Integer.parseInt(key); statusCode.setCode(code); assertEquals(statusCode.getCode(), code, "is not " + code); assertEquals(statusCode.isInfo(), code >= 100 && code < 200, code + " is info"); @@ -65,7 +66,15 @@ public class StatusCodeTest { assertEquals(statusCode.getReason(), Reasons.getReasonPhrase(code), code + "reason phrase is not valid"); } - statusCode = new StatusCode(600); + code = 600; + statusCode = new StatusCode(code); + assertEquals(statusCode.getCode(), 600, "is not " + code); + assertFalse(statusCode.isInfo(), code + " is info"); + assertFalse(statusCode.isSuccess(), code + " is ok"); + assertFalse(statusCode.isRedirect(), code + " is redirect"); + assertFalse(statusCode.isClientError(), code + " is client error"); + assertFalse(statusCode.isServerError(), code + " is server error"); + assertFalse(statusCode.isError(), code + " is error"); assertFalse(statusCode.isValid(), "600 is invalid"); } } From c4edb4fd1fecd0b146cc0123c7a303cdf1b7a4da Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sun, 24 Apr 2022 00:49:11 -0700 Subject: [PATCH 22/29] Cleaned up and updated dependencies --- .idea/checkstyle-idea.xml | 16 - .idea/inspectionProfiles/Project_Default.xml | 52 +- .idea/misc.xml | 5 +- .idea/modules/httpstatus.iml | 40 - .idea/vcs.xml | 3 +- HttpStatus.ipr | 686 ------------------ build.gradle | 26 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../net/thauvin/erik/httpstatus/Reasons.java | 2 +- .../thauvin/erik/httpstatus/StatusCode.java | 2 +- .../net/thauvin/erik/httpstatus/Utils.java | 2 +- .../erik/httpstatus/taglibs/CauseTag.java | 2 +- .../erik/httpstatus/taglibs/CodeTag.java | 2 +- .../erik/httpstatus/taglibs/MessageTag.java | 2 +- .../erik/httpstatus/taglibs/ReasonTag.java | 2 +- .../erik/httpstatus/taglibs/XmlSupport.java | 2 +- .../erik/httpstatus/ReasonsMainTest.java | 2 +- .../thauvin/erik/httpstatus/ReasonsTest.java | 2 +- .../erik/httpstatus/StatusCodeTest.java | 31 +- .../thauvin/erik/httpstatus/UtilsTest.java | 2 +- 20 files changed, 80 insertions(+), 803 deletions(-) delete mode 100644 .idea/checkstyle-idea.xml delete mode 100644 .idea/modules/httpstatus.iml delete mode 100644 HttpStatus.ipr diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml deleted file mode 100644 index 95c433c..0000000 --- a/.idea/checkstyle-idea.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 63787bb..60682bf 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,15 +1,6 @@ \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 9d92aa6..2ce963b 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,8 +1,5 @@ - - - + \ No newline at end of file diff --git a/.idea/modules/httpstatus.iml b/.idea/modules/httpstatus.iml deleted file mode 100644 index 24d0b52..0000000 --- a/.idea/modules/httpstatus.iml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 49e611e..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,7 +1,6 @@ - - + \ No newline at end of file diff --git a/HttpStatus.ipr b/HttpStatus.ipr deleted file mode 100644 index 7e19236..0000000 --- a/HttpStatus.ipr +++ /dev/null @@ -1,686 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Android Lint - - - Java - - - Portability issuesJava - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.8.x - - - - - - - - \ No newline at end of file diff --git a/build.gradle b/build.gradle index eea5bf9..9b02669 100644 --- a/build.gradle +++ b/build.gradle @@ -17,15 +17,15 @@ import org.apache.tools.ant.taskdefs.condition.Os defaultTasks 'deploy' -def deployDir = 'deploy' +final def deployDir = 'deploy' -def mavenName = 'HttpStatus' -def mavenDescription = 'HttpStatus JSP Tag Library' -def mavenUrl = 'https://github.com/ethauvin/HttpStatus' -def mavenLicense = 'The BSD 3-Clause License' -def mavenLicenseUrl = 'http://opensource.org/licenses/BSD-3-Clause' -def mavenScmCon = 'https://github.com/ethauvin/HttpStatus.git' -def mavenScmDevCon = 'git@github.com:ethauvin/HttpStatus.git' +final def mavenName = 'HttpStatus' +final def mavenDescription = 'HttpStatus JSP Tag Library' +final def mavenUrl = 'https://github.com/ethauvin/HttpStatus' +final def mavenLicense = 'The BSD 3-Clause License' +final def mavenLicenseUrl = 'http://opensource.org/licenses/BSD-3-Clause' +final def mavenScmCon = 'https://github.com/ethauvin/HttpStatus.git' +final def mavenScmDevCon = 'git@github.com:ethauvin/HttpStatus.git' group = 'net.thauvin.erik.httpstatus' @@ -49,7 +49,7 @@ dependencies { compileOnly 'javax.servlet.jsp:jsp-api:2.2.1-b03' compileOnly 'javax.el:javax.el-api:3.0.1-b06' - spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.11.0' + spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.12.0' spotbugsPlugins 'com.mebigfatguy.sb-contrib:sb-contrib:7.4.7' compileOnly "com.github.spotbugs:spotbugs-annotations:$versions.spotbugs" @@ -115,8 +115,8 @@ pmd { tasks.withType(SpotBugsTask) { reports { - xml.enabled = false - html.enabled = true + xml.required = false + html.required = true } } @@ -196,7 +196,7 @@ task release { task pandoc(type: Exec) { group = 'Documentation' - def pandoc_args = ['--from', 'gfm', + final def pandoc_args = ['--from', 'gfm', '--to', 'html5', '--metadata', "pagetitle=$mavenDescription", '-s', @@ -216,7 +216,7 @@ task pandoc(type: Exec) { } jacoco { - toolVersion = '0.8.8-SNAPSHOT' + toolVersion = '0.8.9-SNAPSHOT' } jacocoTestReport { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 00e33ed..aa991fc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/net/thauvin/erik/httpstatus/Reasons.java b/src/main/java/net/thauvin/erik/httpstatus/Reasons.java index db59093..44b5283 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/Reasons.java +++ b/src/main/java/net/thauvin/erik/httpstatus/Reasons.java @@ -42,7 +42,7 @@ import java.util.concurrent.ConcurrentHashMap; * Populates the {@link #REASON_PHRASES reason phrases} map from {@link #BUNDLE_BASENAME bundle properties}, and * implements accessor methods. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin * @created 2015-12-02 * @since 1.0 */ diff --git a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java index e8221ce..526331f 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java +++ b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java @@ -37,7 +37,7 @@ import java.io.Serializable; /** * The StatusCode bean implements methods to check the class of an HTTP status code. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin */ public class StatusCode implements Serializable { private static final long serialVersionUID = 1L; diff --git a/src/main/java/net/thauvin/erik/httpstatus/Utils.java b/src/main/java/net/thauvin/erik/httpstatus/Utils.java index e7b97fd..b40967a 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/Utils.java +++ b/src/main/java/net/thauvin/erik/httpstatus/Utils.java @@ -38,7 +38,7 @@ import java.io.Writer; /** * The Utils class implements a collection of utility methods used throughout this project. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin * @created 2015-12-03 * @since 1.0 */ diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java index a5078b0..df4f7e8 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java @@ -41,7 +41,7 @@ import java.io.IOException; /** * The <hs:cause> tag returns the cause (if any) for the current HTTP Status Error Code. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin * @created 2015-12-03 * @since 1.0 */ diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java index 079e551..0e17111 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java @@ -40,7 +40,7 @@ import java.io.IOException; /** * The <hs:code> tag returns the HTTP Status Error Code. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin * @created 2015-12-03 * @since 1.0 */ diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java index ae81a96..12d4e7b 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java @@ -41,7 +41,7 @@ import java.io.IOException; /** * The <hs:message> tag returns the message (if any) for the current error. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin * @created 2022-03-16 * @since 1.0.5 */ diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java index 1720752..04fd948 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java @@ -43,7 +43,7 @@ import java.io.IOException; * The <hs:reason> tag returns the Reason Phrase for the current (or specified) HTTP Status Error * Code. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin * @created 2015-12-02 * @since 1.0 */ diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java index 83083b7..ecf0ed6 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java @@ -37,7 +37,7 @@ import javax.servlet.jsp.tagext.SimpleTagSupport; /** * Adds support for the default and escapeXml tag attributes. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin * @created 2015-12-03 * @since 1.0 */ diff --git a/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java b/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java index 94eb207..5eedc85 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/ReasonsMainTest.java @@ -47,7 +47,7 @@ import static org.testng.Assert.assertTrue; /** * Main Class Tests. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin * @created 2019-05-06 * @since 1.0 */ diff --git a/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java b/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java index 8ca1c39..6409642 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java @@ -41,7 +41,7 @@ import static org.testng.Assert.assertEquals; /** * Reasons Tests. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin * @created 2015-12-03 * @since 1.0 */ diff --git a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java index d814eca..cf11aeb 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/StatusCodeTest.java @@ -42,7 +42,7 @@ import static org.testng.Assert.*; /** * StatusCode Tests. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin */ @SuppressFBWarnings("CE_CLASS_ENVY") public class StatusCodeTest { @@ -50,9 +50,8 @@ public class StatusCodeTest { void testStatusCode() { final ResourceBundle bundle = ResourceBundle.getBundle(Reasons.BUNDLE_BASENAME); StatusCode statusCode = new StatusCode(); - int code; for (final String key : bundle.keySet()) { - code = Integer.parseInt(key); + final int code = Integer.parseInt(key); statusCode.setCode(code); assertEquals(statusCode.getCode(), code, "is not " + code); assertEquals(statusCode.isInfo(), code >= 100 && code < 200, code + " is info"); @@ -66,15 +65,21 @@ public class StatusCodeTest { assertEquals(statusCode.getReason(), Reasons.getReasonPhrase(code), code + "reason phrase is not valid"); } - code = 600; - statusCode = new StatusCode(code); - assertEquals(statusCode.getCode(), 600, "is not " + code); - assertFalse(statusCode.isInfo(), code + " is info"); - assertFalse(statusCode.isSuccess(), code + " is ok"); - assertFalse(statusCode.isRedirect(), code + " is redirect"); - assertFalse(statusCode.isClientError(), code + " is client error"); - assertFalse(statusCode.isServerError(), code + " is server error"); - assertFalse(statusCode.isError(), code + " is error"); - assertFalse(statusCode.isValid(), "600 is invalid"); + final int[] unknowns = {0, 99, 600}; + for (final int code : unknowns) { + statusCode.setCode(code); + assertEquals(statusCode.getCode(), code, "is not " + code); + assertFalse(statusCode.isInfo(), code + " is info"); + assertFalse(statusCode.isSuccess(), code + " is ok"); + assertFalse(statusCode.isRedirect(), code + " is redirect"); + assertFalse(statusCode.isClientError(), code + " is client error"); + assertFalse(statusCode.isServerError(), code + " is server error"); + assertFalse(statusCode.isError(), code + " is error"); + assertFalse(statusCode.isValid(), "600 is invalid"); + assertNull(statusCode.getReason(), code + "reason phrase is not null."); + } + + statusCode = new StatusCode(900); + assertEquals(statusCode.getCode(), 900, "is not 900"); } } diff --git a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java index d0af31d..8636fee 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java @@ -43,7 +43,7 @@ import static org.testng.Assert.assertEquals; /** * Utils Tests. * - * @author Erik C. Thauvin + * @author Erik C. Thauvin * @created 2015-12-03 * @since 1.0 */ From 45af218f3937b262c06b53d012244a2bf058216d Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 27 Aug 2022 18:08:57 -0700 Subject: [PATCH 23/29] Moved to Jakarta EE. Closes #7 --- .github_changelog_generator | 2 +- .idea/compiler.xml | 2 +- .idea/misc.xml | 5 +- CHANGELOG.md | 2 +- LICENSE.txt | 2 +- README.md | 8 +- appveyor.yml | 2 +- build.gradle | 48 ++-- deploy.sh | 4 + docs/README.html | 237 +++++++++++------- gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 60756 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 6 + gradlew.bat | 14 +- .../erik/httpstatus/taglibs/CauseTag.java | 4 +- .../erik/httpstatus/taglibs/CodeTag.java | 7 +- .../erik/httpstatus/taglibs/MessageTag.java | 6 +- .../erik/httpstatus/taglibs/ReasonTag.java | 4 +- .../erik/httpstatus/taglibs/XmlSupport.java | 2 +- version.properties | 6 +- 20 files changed, 224 insertions(+), 139 deletions(-) create mode 100644 deploy.sh diff --git a/.github_changelog_generator b/.github_changelog_generator index 073fac8..19e45d2 100644 --- a/.github_changelog_generator +++ b/.github_changelog_generator @@ -1 +1 @@ -future-release=1.0.6 +future-release=1.1.0 diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 61a9130..fb7f4a8 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 2ce963b..c55072b 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,8 @@ - + + + + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 15337f6..5a59454 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [1.0.5](https://github.com/ethauvin/HttpStatus/tree/1.0.5) (2021-03-19) +## [1.0.5](https://github.com/ethauvin/HttpStatus/tree/1.0.5) (2021-03-20) [Full Changelog](https://github.com/ethauvin/HttpStatus/compare/1.0.4...1.0.5) diff --git a/LICENSE.txt b/LICENSE.txt index 2fba8ed..bc71010 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2015-2021, Erik C. Thauvin (erik@thauvin.net) +Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index a8f2c4c..cabb8b2 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Include the following in your `build.gradle` file: ```gradle dependencies { - implementation 'net.thauvin.erik.httpstatus:httpstatus:1.0.6' + implementation 'net.thauvin.erik.httpstatus:httpstatus:1.1.0' } ``` @@ -47,7 +47,7 @@ or as a Maven artifact: net.thauvin.erik.httpstatus httpstatus - 1.0.6 + 1.1.0 ``` @@ -250,7 +250,7 @@ Status Code | Reason You can query the reason phrase for status codes as follows: ```sh -$ java -jar httpstatus-1.0.6.jar 404 500 +$ java -jar httpstatus-1.1.0.jar 404 500 404: Not Found 500: Internal Server Error ``` @@ -258,7 +258,7 @@ $ java -jar httpstatus-1.0.6.jar 404 500 If no status code is specified, all will be printed: ```sh -$ java -jar httpstatus-1.0.6.jar +$ java -jar httpstatus-1.1.0.jar 100: Continue 101: Switching Protocols 102: Processing diff --git a/appveyor.yml b/appveyor.yml index 877b3ed..9747d51 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ test_script: branches: only: - master - - 1.0.6-dev + - 1.1.0-dev cache: - C:\Users\appveyor\.gradle diff --git a/build.gradle b/build.gradle index 9b02669..12a7d51 100644 --- a/build.gradle +++ b/build.gradle @@ -8,8 +8,8 @@ plugins { id 'pmd' id 'com.github.ben-manes.versions' version '0.42.0' id 'net.thauvin.erik.gradle.semver' version '1.0.4' - id 'com.github.spotbugs' version '5.0.6' - id 'org.sonarqube' version '3.3' + id 'com.github.spotbugs' version '5.0.10' + id 'org.sonarqube' version '3.4.0.2513' } import com.github.spotbugs.snom.SpotBugsTask @@ -33,8 +33,8 @@ mainClassName = 'net.thauvin.erik.httpstatus.Reasons' ext { versions = [ - pmd: '6.35.0', - spotbugs: '4.6.0' + pmd : '6.47.0', + spotbugs: '4.7.1' ] } @@ -45,9 +45,13 @@ repositories { } dependencies { - compileOnly 'javax.servlet:javax.servlet-api:4.0.1' - compileOnly 'javax.servlet.jsp:jsp-api:2.2.1-b03' - compileOnly 'javax.el:javax.el-api:3.0.1-b06' +// compileOnly 'javax.servlet:javax.servlet-api:4.0.1' +// compileOnly 'javax.servlet.jsp:jsp-api:2.2.1-b03' +// compileOnly 'javax.el:javax.el-api:3.0.1-b06' + + compileOnly 'jakarta.servlet:jakarta.servlet-api:6.0.0' + compileOnly 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.1.0' + compileOnly 'jakarta.el:jakarta.el-api:5.0.1' spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.12.0' spotbugsPlugins 'com.mebigfatguy.sb-contrib:sb-contrib:7.4.7' @@ -55,7 +59,7 @@ dependencies { compileOnly "com.github.spotbugs:spotbugs-annotations:$versions.spotbugs" testCompileOnly "com.github.spotbugs:spotbugs-annotations:$versions.spotbugs" - testImplementation 'org.testng:testng:7.5' + testImplementation 'org.testng:testng:7.6.1' } tasks.withType(JavaCompile) { @@ -63,8 +67,8 @@ tasks.withType(JavaCompile) { } java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 withJavadocJar() withSourcesJar() } @@ -106,7 +110,7 @@ spotbugs { } pmd { - toolVersion = versions.pmd + toolVersion = versions.pmd ignoreFailures = true ruleSets = [] ruleSetFiles = files("${projectDir}/config/pmd.xml") @@ -160,7 +164,7 @@ publishing { url = project.version.contains('SNAPSHOT') ? 'https://oss.sonatype.org/content/repositories/snapshots/' : 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' - } + } credentials(PasswordCredentials) } } @@ -173,7 +177,11 @@ signing { task copyToDeploy(type: Copy) { from(configurations.runtimeClasspath) { - exclude('javax.servlet-api-*.jar', 'jsp-api-*.jar') + exclude('javax.servlet-api-*.jar', + 'jsp-api-*.jar', + 'jakarta.servlet-*.jar', + 'jakarta-servlet.*.jar', + 'jakarta.el-api*.jar') } from jar into deployDir @@ -197,12 +205,12 @@ task release { task pandoc(type: Exec) { group = 'Documentation' final def pandoc_args = ['--from', 'gfm', - '--to', 'html5', - '--metadata', "pagetitle=$mavenDescription", - '-s', - '-c', 'github-pandoc.css', - '-o', 'docs/README.html', - 'README.md'] + '--to', 'html5', + '--metadata', "pagetitle=$mavenDescription", + '-s', + '-c', 'github-pandoc.css', + '-o', 'docs/README.html', + 'README.md'] if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine(['cmd', '/c', 'pandoc'] + pandoc_args) } else { @@ -216,7 +224,7 @@ task pandoc(type: Exec) { } jacoco { - toolVersion = '0.8.9-SNAPSHOT' + toolVersion = '0.8.9-SNAPSHOT' } jacocoTestReport { diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..0497b23 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +./gradlew deploy +[ $? -eq 0 ] && scp deploy/*.jar nix3.thauvin.us:/opt/lib/jtalk-ee/httpstatus diff --git a/docs/README.html b/docs/README.html index 4afcd01..f4eafc6 100644 --- a/docs/README.html +++ b/docs/README.html @@ -15,6 +15,7 @@ pre > code.sourceCode { white-space: pre; position: relative; } pre > code.sourceCode > span { display: inline-block; line-height: 1.25; } pre > code.sourceCode > span:empty { height: 1.2em; } + .sourceCode { overflow: visible; } code.sourceCode > span { color: inherit; text-decoration: inherit; } div.sourceCode { margin: 1em 0; } pre.sourceCode { margin: 0; } @@ -49,7 +50,7 @@ code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */ code span.at { color: #7d9029; } /* Attribute */ code span.bn { color: #40a070; } /* BaseN */ - code span.bu { } /* BuiltIn */ + code span.bu { color: #008000; } /* BuiltIn */ code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */ code span.ch { color: #4070a0; } /* Char */ code span.cn { color: #880000; } /* Constant */ @@ -62,7 +63,7 @@ code span.ex { } /* Extension */ code span.fl { color: #40a070; } /* Float */ code span.fu { color: #06287e; } /* Function */ - code span.im { } /* Import */ + code span.im { color: #008000; font-weight: bold; } /* Import */ code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */ code span.kw { color: #007020; font-weight: bold; } /* Keyword */ code span.op { color: #666666; } /* Operator */ @@ -74,46 +75,86 @@ code span.va { color: #19177c; } /* Variable */ code span.vs { color: #4070a0; } /* VerbatimString */ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */ + .display.math{display: block; text-align: center; margin: 0.5rem auto;} +

HttpStatus JSP Tag Library

-

Release Maven Central
-License (3-Clause BSD) Known Vulnerabilities Quality Gate Status
-GitHub CI Build status CircleCI

-

A simple JSP Tag Library to display the code, reason, cause and/or message for HTTP status codes in JSP error pages.

+


+
+

+

A simple JSP +Tag Library to display the code, reason, cause and/or message for HTTP +status codes in JSP error pages.

For example:

-
<%@ page isErrorPage="true" %>
-<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
-<html><head>
-<title><hs:code/> <hs:reason default="Server Error"/></title>
-</head>
-<h1><hs:reason default="Server Error"/></h1>
-Cause: <pre><hs:cause default="Unable to complete your request."/></pre>
-Message: <pre><hs:message default="A server error has occured."/></pre>
-...
+
<%@ page isErrorPage="true" %>
+<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
+<html><head>
+<title><hs:code/> <hs:reason default="Server Error"/></title>
+</head>
+<h1><hs:reason default="Server Error"/></h1>
+Cause: <pre><hs:cause default="Unable to complete your request."/></pre>
+Message: <pre><hs:message default="A server error has occured."/></pre>
+...

or

-
<%@ page isErrorPage="true" import="net.thauvin.erik.httpstatus.Reasons" %>
-<%= Reasons.getReasonPhrase(pageContext.getErrorData().getStatusCode()) %>
-

would display on a 501 status code:

-
Not Implemented
-
-

Usage with Gradle or Maven

+
<%@ page isErrorPage="true" import="net.thauvin.erik.httpstatus.Reasons" %>
+<%= Reasons.getReasonPhrase(pageContext.getErrorData().getStatusCode()) %>
+

would display on a 501 +status code:

+
Not Implemented
+

Usage with Gradle or Maven

Include the following in your build.gradle file:

-
dependencies {
-    implementation 'net.thauvin.erik.httpstatus:httpstatus:1.0.6'
-}
-
+
dependencies {
+    implementation 'net.thauvin.erik.httpstatus:httpstatus:1.1.0'
+}

or as a Maven artifact:

-
<dependency>
-    <groupId>net.thauvin.erik.httpstatus</groupId>
-    <artifactId>httpstatus</artifactId>
-    <version>1.0.6</version>
-</dependency>
+
<dependency>
+    <groupId>net.thauvin.erik.httpstatus</groupId>
+    <artifactId>httpstatus</artifactId>
+    <version>1.1.0</version>
+</dependency>

hs:cause

-

The <hs:cause/> tag displays the cause of current HTTP status code, if any. A shorthand for:

-
<%= pageContext.getErrorData().getThrowable().getCause().getLocalizedMessage() %>
+

The <hs:cause/> tag displays the cause of current +HTTP status code, if any. A shorthand for:

+
<%= pageContext.getErrorData().getThrowable().getCause().getLocalizedMessage() %>

Optional attributes are:

@@ -129,16 +170,22 @@ - +
escapeXmlConverts <, >, &, ', " to their corresponding entity codes. Value is true by default.Converts <, >, &, ', " to their corresponding entity codes. +Value is true by default.

hs:code

-

The <hs:code/> tag displays the current HTTP status code, if any. A shorthand for:

-
<%= pageContext.getErrorData().getStatusCode() %>
+

The <hs:code/> tag displays the current HTTP +status code, if any. A shorthand for:

+
<%= pageContext.getErrorData().getStatusCode() %>

hs:message

-

The <hs:message/> tag displays the current error message, if any. A shorthand for:

-
<%= request.getAttribute("javax.servlet.error.message") %>
+

The <hs:message/> tag displays the current error +message, if any. A shorthand for:

+
<%= request.getAttribute("javax.servlet.error.message") %>

Optional attributes are:

@@ -154,12 +201,15 @@ - +
escapeXmlConverts <, >, &, ', " to their corresponding entity codes. Value is true by default.Converts <, >, &, ', " to their corresponding entity codes. +Value is true by default.

hs:reason

-

The <hs:reason/> tag displays the reason for a HTTP status code, if any. Optional attributes are:

+

The <hs:reason/> tag displays the reason for a +HTTP status code, if any. Optional attributes are:

@@ -170,7 +220,8 @@ - + @@ -178,38 +229,43 @@ - +
codeThe HTTP status error code. If not specified the current status code is used.The HTTP status error code. If not specified the current status code +is used.
default
escapeXmlConverts <, >, &, ', " to their corresponding entity codes. Value is true by default.Converts <, >, &, ', " to their corresponding entity codes. +Value is true by default.

StatusCode Bean

-

The StatusCode bean can be used to check the class of the status code error. For example, using the JSTL:

-
<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
-<jsp:useBean id="statusCode" class="net.thauvin.erik.httpstatus.StatusCode"/>
-<c:set target="${statusCode}" property="code"><hs:code/></c:set>
-<c:choose>
-    <c:when test="${statusCode.isClientError()}">
-        An error occurred on your side. (<hs:reason/>)
-    </c:when>
-    <c:otherwise>
-        An error occurred on our side. (<hs:message/>)
-    </c:otherwise>
-</c:choose>
+

The StatusCode bean can be used to check the class of +the status code error. For example, using the JSTL:

+
<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+
+<jsp:useBean id="statusCode" class="net.thauvin.erik.httpstatus.StatusCode"/>
+<c:set target="${statusCode}" property="code"><hs:code/></c:set>
+<c:choose>
+    <c:when test="${statusCode.isClientError()}">
+        An error occurred on your side. (<hs:reason/>)
+    </c:when>
+    <c:otherwise>
+        An error occurred on our side. (<hs:message/>)
+    </c:otherwise>
+</c:choose>

or in a Servlet:

-
import net.thauvin.erik.httpstatus.StatusCode;
-
-// ---
-
-StatusCode statusCode = new StatusCode((Integer) request.getAttribute("javax.servlet.error.status_code"));
-if (statusCode.isError()) {
-    if (statusCode.isServerError()) {
-        String reason = statusCode.getReason();
-    } else {
-        // ...
-    }
-}
+
import net.thauvin.erik.httpstatus.StatusCode;
+
+// ---
+
+StatusCode statusCode = new StatusCode((Integer) request.getAttribute("javax.servlet.error.status_code"));
+if (statusCode.isError()) {
+    if (statusCode.isServerError()) {
+        String reason = statusCode.getReason();
+    } else {
+        // ...
+    }
+}

The StatusCode bean methods are:

@@ -221,7 +277,8 @@ - + @@ -254,7 +311,9 @@
getReasonReturns the reason for the status code (eg: Internal Server Error)Returns the reason for the status code (eg: +Internal Server Error)
isClientError

Reasons

-

The reasons are defined in a ResourceBundle properties as follows:

+

The reasons are defined in a ResourceBundle +properties as follows:

@@ -631,25 +690,27 @@

Command Line Usage

You can query the reason phrase for status codes as follows:

-
$ java -jar httpstatus-1.0.6.jar 404 500
-404: Not Found
-500: Internal Server Error
+
$ java -jar httpstatus-1.1.0.jar 404 500
+404: Not Found
+500: Internal Server Error

If no status code is specified, all will be printed:

-
$ java -jar httpstatus-1.0.6.jar
-100: Continue
-101: Switching Protocols
-102: Processing
-103: Early Hints
-200: OK
-201: Created
-202: Accepted
-203: Non-Authoritative Information
-204: No Content
-205: Reset Content
-206: Partial Content
-207: Multi-Status
-208: Already Reported
-226: IM Used
-...
+
$ java -jar httpstatus-1.1.0.jar
+100: Continue
+101: Switching Protocols
+102: Processing
+103: Early Hints
+200: OK
+201: Created
+202: Accepted
+203: Non-Authoritative Information
+204: No Content
+205: Reset Content
+206: Partial Content
+207: Multi-Status
+208: Already Reported
+226: IM Used
+...
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d4fb3f96a785543079b8df6723c946b..249e5832f090a2944b7473328c07c9755baa3196 100644 GIT binary patch delta 10197 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fc..ae04661 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787..a69d9cb 100755 --- a/gradlew +++ b/gradlew @@ -205,6 +205,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index 107acd3..f127cfd 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java index df4f7e8..63fc6b7 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java @@ -32,10 +32,10 @@ package net.thauvin.erik.httpstatus.taglibs; +import jakarta.servlet.jsp.JspWriter; +import jakarta.servlet.jsp.PageContext; import net.thauvin.erik.httpstatus.Utils; -import javax.servlet.jsp.JspWriter; -import javax.servlet.jsp.PageContext; import java.io.IOException; /** diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java index 0e17111..5d5b47a 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java @@ -32,9 +32,10 @@ package net.thauvin.erik.httpstatus.taglibs; -import javax.servlet.jsp.JspWriter; -import javax.servlet.jsp.PageContext; -import javax.servlet.jsp.tagext.SimpleTagSupport; +import jakarta.servlet.jsp.JspWriter; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.SimpleTagSupport; + import java.io.IOException; /** diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java index 12d4e7b..7ec8862 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java @@ -32,10 +32,10 @@ package net.thauvin.erik.httpstatus.taglibs; +import jakarta.servlet.jsp.JspWriter; +import jakarta.servlet.jsp.PageContext; import net.thauvin.erik.httpstatus.Utils; -import javax.servlet.jsp.JspWriter; -import javax.servlet.jsp.PageContext; import java.io.IOException; /** @@ -55,7 +55,7 @@ public class MessageTag extends XmlSupport { @SuppressWarnings("PMD.CloseResource") final JspWriter out = pageContext.getOut(); final String message = (String) pageContext.getRequest().getAttribute( - javax.servlet.RequestDispatcher.ERROR_MESSAGE); + jakarta.servlet.RequestDispatcher.ERROR_MESSAGE); Utils.outWrite(out, message, defaultValue, escapeXml); } diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java index 04fd948..10bbc2c 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java @@ -32,11 +32,11 @@ package net.thauvin.erik.httpstatus.taglibs; +import jakarta.servlet.jsp.JspWriter; +import jakarta.servlet.jsp.PageContext; import net.thauvin.erik.httpstatus.Reasons; import net.thauvin.erik.httpstatus.Utils; -import javax.servlet.jsp.JspWriter; -import javax.servlet.jsp.PageContext; import java.io.IOException; /** diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java index ecf0ed6..672d4c4 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java @@ -32,7 +32,7 @@ package net.thauvin.erik.httpstatus.taglibs; -import javax.servlet.jsp.tagext.SimpleTagSupport; +import jakarta.servlet.jsp.tagext.SimpleTagSupport; /** * Adds support for the default and escapeXml tag attributes. diff --git a/version.properties b/version.properties index 4799ec4..98bcbf2 100644 --- a/version.properties +++ b/version.properties @@ -2,7 +2,7 @@ #Sun May 02 22:01:06 PDT 2021 version.buildmeta= version.major=1 -version.minor=0 -version.patch=6 +version.minor=1 +version.patch=0 version.prerelease=SNAPSHOT -version.semver=1.0.6-SNAPSHOT +version.semver=1.1.0-SNAPSHOT From c75ba0b38b6b857e9d130fe309518ab88a4e1ca3 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 27 Aug 2022 18:25:28 -0700 Subject: [PATCH 24/29] Removed Java 8 from CIs --- .circleci/config.yml | 10 +++++----- .github/workflows/gradle.yml | 2 +- appveyor.yml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d873524..2958369 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,19 +31,19 @@ defaults_gradle: &defaults_gradle path: build/reports/ jobs: - build_gradle_jdk17: + build_gradle_jdk18: <<: *defaults docker: - - image: cimg/openjdk:17.0 + - image: cimg/openjdk:18-jdk <<: *defaults_gradle - build_gradle_jdk8: + build_gradle_jdk11: <<: *defaults docker: - - image: circleci/openjdk:8-jdk + - image: cimg/openjdk:11-jdk <<: *defaults_gradle @@ -51,5 +51,5 @@ workflows: version: 2 gradle: jobs: - - build_gradle_jdk8 + - build_gradle_jdk11 - build_gradle_jdk17 diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 86d7e7f..5881074 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: - java-version: [ 1.8, 11, 17, 18 ] + java-version: [ 11, 17, 18 ] steps: - uses: actions/checkout@v2 diff --git a/appveyor.yml b/appveyor.yml index 9747d51..7c2afa9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ image: - - Visual Studio 2019 + - Visual Studio 2022 version: "{branch} {build}" skip_tags: true From 1f0a920ca32d882e8e4d44a5424ace8dfad27b33 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 27 Aug 2022 18:34:22 -0700 Subject: [PATCH 25/29] Fixed CIs, maybe... --- .circleci/config.yml | 2 +- .github/workflows/gradle.yml | 2 +- appveyor.yml | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2958369..76aad89 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -52,4 +52,4 @@ workflows: gradle: jobs: - build_gradle_jdk11 - - build_gradle_jdk17 + - build_gradle_jdk18 diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 5881074..a0b7843 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: - java-version: [ 11, 17, 18 ] + java-version: [ 11, 18 ] steps: - uses: actions/checkout@v2 diff --git a/appveyor.yml b/appveyor.yml index 7c2afa9..b66b878 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,7 +24,6 @@ cache: environment: matrix: - JAVA_HOME: C:\Program Files\Java\jdk17 - - JAVA_HOME: C:\Program Files\Java\jdk11 - + matrix: fast_finish: true From 84cfe6098d294f301d4b4a86c1b65b6b06821fb7 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 27 Aug 2022 18:47:13 -0700 Subject: [PATCH 26/29] Fixed OpenJDK image aliases --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 76aad89..b76d7e8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -35,7 +35,7 @@ jobs: <<: *defaults docker: - - image: cimg/openjdk:18-jdk + - image: cimg/openjdk:18.0 <<: *defaults_gradle @@ -43,7 +43,7 @@ jobs: <<: *defaults docker: - - image: cimg/openjdk:11-jdk + - image: cimg/openjdk:11.0 <<: *defaults_gradle From 68975a497bca258e089cac5f755ee5f899b22dc0 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 10 May 2023 00:21:31 -0700 Subject: [PATCH 27/29] Moved from Gradle to bld --- .circleci/config.yml | 42 +- .github/workflows/bld.yml | 32 + .github/workflows/gradle.yml | 61 -- .gitignore | 80 +- .idea/.name | 1 - .idea/app.iml | 29 + .idea/bld.iml | 14 + .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/compiler.xml | 6 - .idea/copyright/Erik_s_Copyright.xml | 13 + .idea/copyright/profiles_settings.xml | 3 + .idea/inspectionProfiles/Project_Default.xml | 64 -- .idea/jarRepositories.xml | 30 - .idea/libraries/bld.xml | 17 + .idea/libraries/compile.xml | 13 + .idea/libraries/runtime.xml | 14 + .idea/libraries/test.xml | 14 + .idea/misc.xml | 18 +- .idea/modules.xml | 9 + .idea/runConfigurations/Run Tests.xml | 9 + .vscode/launch.json | 11 + .vscode/settings.json | 15 + LICENSE.txt | 2 +- README.md | 18 +- appveyor.yml | 6 +- bld | 2 + bld.bat | 4 + build.gradle | 247 ------ config/checkstyle/checkstyle.xml | 277 ------- config/pmd.xml | 21 +- config/spotbugs/excludeFilter.xml | 16 - deploy.sh | 0 docs/README.html | 716 ------------------ docs/github-pandoc.css | 425 ----------- gradle/wrapper/gradle-wrapper.jar | Bin 60756 -> 0 bytes gradle/wrapper/gradle-wrapper.properties | 5 - gradlew | 240 ------ gradlew.bat | 91 --- lib/bld/bld-wrapper.jar | Bin 0 -> 25099 bytes lib/bld/bld-wrapper.properties | 6 + pom.xml | 50 ++ settings.gradle | 19 - .../erik/httpstatus/HttpStatusBuild.java | 128 ++++ .../net/thauvin/erik/httpstatus/Reasons.java | 2 +- .../thauvin/erik/httpstatus/StatusCode.java | 6 +- .../net/thauvin/erik/httpstatus/Utils.java | 26 +- .../erik/httpstatus/taglibs/CauseTag.java | 2 +- .../erik/httpstatus/taglibs/CodeTag.java | 2 +- .../erik/httpstatus/taglibs/MessageTag.java | 4 +- .../erik/httpstatus/taglibs/ReasonTag.java | 4 +- .../erik/httpstatus/taglibs/XmlSupport.java | 2 +- src/main/resources/META-INF/httpstatus.tld | 2 +- .../erik/httpstatus/reasons.properties | 32 + .../erik/httpstatus/ReasonsMainTest.java | 55 +- .../thauvin/erik/httpstatus/ReasonsTest.java | 17 +- .../erik/httpstatus/StatusCodeTest.java | 49 +- .../thauvin/erik/httpstatus/UtilsTest.java | 41 +- version.properties | 8 - 58 files changed, 632 insertions(+), 2393 deletions(-) create mode 100644 .github/workflows/bld.yml delete mode 100644 .github/workflows/gradle.yml delete mode 100644 .idea/.name create mode 100644 .idea/app.iml create mode 100644 .idea/bld.iml create mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 .idea/compiler.xml create mode 100644 .idea/copyright/Erik_s_Copyright.xml create mode 100644 .idea/copyright/profiles_settings.xml delete mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/libraries/bld.xml create mode 100644 .idea/libraries/compile.xml create mode 100644 .idea/libraries/runtime.xml create mode 100644 .idea/libraries/test.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/runConfigurations/Run Tests.xml create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100755 bld create mode 100644 bld.bat delete mode 100644 build.gradle delete mode 100644 config/checkstyle/checkstyle.xml delete mode 100644 config/spotbugs/excludeFilter.xml mode change 100644 => 100755 deploy.sh delete mode 100644 docs/README.html delete mode 100644 docs/github-pandoc.css delete mode 100644 gradle/wrapper/gradle-wrapper.jar delete mode 100644 gradle/wrapper/gradle-wrapper.properties delete mode 100755 gradlew delete mode 100644 gradlew.bat create mode 100644 lib/bld/bld-wrapper.jar create mode 100644 lib/bld/bld-wrapper.properties create mode 100644 pom.xml delete mode 100644 settings.gradle create mode 100644 src/bld/java/net/thauvin/erik/httpstatus/HttpStatusBuild.java delete mode 100644 version.properties diff --git a/.circleci/config.yml b/.circleci/config.yml index b76d7e8..e66c437 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,50 +6,38 @@ defaults: &defaults TERM: dumb CI_NAME: "CircleCI" -defaults_gradle: &defaults_gradle +defaults_gradle: &defaults_bld steps: - checkout - - restore_cache: - keys: - - gradle-dependencies-{{ checksum "build.gradle" }} - # fallback to using the latest cache if no exact match is found - - gradle-dependencies- - run: - name: Gradle Dependencies - command: ./gradlew dependencies - - save_cache: - paths: - - ~/.m2 - key: gradle-dependencies-{{ checksum "build.gradle" }} + - name: Grant execute permission for bld + command: chmod +x bld - run: - name: Run All Checks - command: ./gradlew check - - store_artifacts: - path: build/reports/ - destination: reports - - store_test_results: - path: build/reports/ - + - name: Download the dependencies + command: ./bld download + - run: + - name: Run tests with bld + command: ./bld c jobs: - build_gradle_jdk18: + bld_jdk17: <<: *defaults docker: - - image: cimg/openjdk:18.0 + - image: cimg/openjdk:17.0 - <<: *defaults_gradle + <<: *defaults_bld - build_gradle_jdk11: + bld_jdk11: <<: *defaults docker: - image: cimg/openjdk:11.0 - <<: *defaults_gradle + <<: *defaults_bld workflows: version: 2 gradle: jobs: - - build_gradle_jdk11 - - build_gradle_jdk18 + - bld_jdk11 + - bld_gradle_jdk17 diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml new file mode 100644 index 0000000..ddcc35c --- /dev/null +++ b/.github/workflows/bld.yml @@ -0,0 +1,32 @@ +name: bld-ci + +on: [ push, pull_request, workflow_dispatch ] + +jobs: + build-bld-project: + runs-on: ubuntu-latest + + strategy: + matrix: + java-version: [ 17, 19, 20 ] + + steps: + - name: Checkout source repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up JDK ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: ${{ matrix.java-version }} + + - name: Grant execute permission for bld + run: chmod +x bld + + - name: Download the dependencies + run: ./bld download + + - name: Run tests with bld + run: ./bld compile test \ No newline at end of file diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml deleted file mode 100644 index a0b7843..0000000 --- a/.github/workflows/gradle.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: gradle-ci - -on: [push, pull_request, workflow_dispatch] - -jobs: - build: - runs-on: ubuntu-latest - - env: - GRADLE_OPTS: "-Dorg.gradle.jvmargs=-XX:MaxMetaspaceSize=512m" - SONAR_JDK: "11" - - strategy: - matrix: - java-version: [ 11, 18 ] - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v1 - with: - java-version: ${{ matrix.java-version }} - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Cache SonarCloud packages - if: matrix.java-version == env.SONAR_JDK - uses: actions/cache@v1 - with: - path: ~/.sonar/cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - - name: Cache Gradle packages - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ matrix.java-version }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle-${{ matrix.java-version }}- - - - name: Test with Gradle - run: ./gradlew build check --stacktrace - - - name: SonarCloud - if: success() && matrix.java-version == env.SONAR_JDK - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: ./gradlew sonarqube - - - name: Cleanup Gradle Cache - run: | - rm -f ~/.gradle/caches/modules-2/modules-2.lock - rm -f ~/.gradle/caches/modules-2/gc.properties diff --git a/.gitignore b/.gitignore index cb14895..091e664 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,57 @@ -**/.idea/dictionaries -**/.idea/gradle.xml -**/.idea/libraries -**/.idea/tasks.xml -**/.idea/workspace.xml -*.iws -.DS_Store -.classpath .gradle -.nb-gradle -.project -.settings -/bin -/build -/deploy -/dist -/gen -/gradle.properties -/local.properties -/out -/proguard-project.txt -/project.properties -/test-output -Thumbs.db -ehthumbs.db \ No newline at end of file +.DS_Store +build +lib/bld/** +!lib/bld/bld-wrapper.properties +!lib/bld/bld-wrapper.jar +lib/compile/ +lib/runtime/ +lib/standalone/ +lib/test/ + +# IDEA ignores + +# User-specific +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Editor-based Rest Client +.idea/httpRequests + +local.properties \ No newline at end of file diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 6bf8b6f..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -httpstatus \ No newline at end of file diff --git a/.idea/app.iml b/.idea/app.iml new file mode 100644 index 0000000..787b59b --- /dev/null +++ b/.idea/app.iml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/bld.iml b/.idea/bld.iml new file mode 100644 index 0000000..e63e11e --- /dev/null +++ b/.idea/bld.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..d91f848 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index fb7f4a8..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/copyright/Erik_s_Copyright.xml b/.idea/copyright/Erik_s_Copyright.xml new file mode 100644 index 0000000..2bffb46 --- /dev/null +++ b/.idea/copyright/Erik_s_Copyright.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..1419e40 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 60682bf..1e01b48 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -1,72 +1,8 @@ \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index 4e9cedf..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/bld.xml b/.idea/libraries/bld.xml new file mode 100644 index 0000000..71decad --- /dev/null +++ b/.idea/libraries/bld.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/compile.xml b/.idea/libraries/compile.xml new file mode 100644 index 0000000..9bd86aa --- /dev/null +++ b/.idea/libraries/compile.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/runtime.xml b/.idea/libraries/runtime.xml new file mode 100644 index 0000000..2ae5c4b --- /dev/null +++ b/.idea/libraries/runtime.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/test.xml b/.idea/libraries/test.xml new file mode 100644 index 0000000..b80486a --- /dev/null +++ b/.idea/libraries/test.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index c55072b..fa84ea4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,8 +1,18 @@ - - - + + + + + + + + + - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..55adcb9 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Run Tests.xml b/.idea/runConfigurations/Run Tests.xml new file mode 100644 index 0000000..99dc892 --- /dev/null +++ b/.idea/runConfigurations/Run Tests.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2dd24a5 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Run Tests", + "request": "launch", + "mainClass": "net.thauvin.erik.httpstatus.HttpStatusTest" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..84f1103 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "java.project.sourcePaths": [ + "src/main/java", + "src/main/resources", + "src/test/java", + "src/bld/java" + ], + "java.configuration.updateBuildConfiguration": "automatic", + "java.project.referencedLibraries": [ + "${HOME}/.rife2/dist/rife2-1.6.3.jar", + "lib/compile/*.jar", + "lib/runtime/*.jar", + "lib/test/*.jar" + ] +} diff --git a/LICENSE.txt b/LICENSE.txt index bc71010..3f79a9e 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) +Copyright (c) 2015-2023, Erik C. Thauvin (erik@thauvin.net) All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index cabb8b2..ab2b264 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,14 @@ # HttpStatus JSP Tag Library -[![Release](https://img.shields.io/github/release/ethauvin/httpstatus.svg)](https://github.com/ethauvin/httpstatus/releases/latest) [![Maven Central](https://img.shields.io/maven-central/v/net.thauvin.erik.httpstatus/httpstatus.svg?label=maven%20central)](https://search.maven.org/search?q=g:%22net.thauvin.erik.httpstatus%22%20AND%20a:%22httpstatus%22) -[![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](http://opensource.org/licenses/BSD-3-Clause) [![Known Vulnerabilities](https://snyk.io/test/github/ethauvin/httpstatus/badge.svg?targetFile=build.gradle)](https://snyk.io/test/github/ethauvin/httpstatus?targetFile=build.gradle) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=ethauvin_HttpStatus&metric=alert_status)](https://sonarcloud.io/dashboard?id=ethauvin_HttpStatus) -[![GitHub CI](https://github.com/ethauvin/httpstatus/actions/workflows/gradle.yml/badge.svg)](https://github.com/ethauvin/httpstatus/actions/workflows/gradle.yml) [![Build status](https://ci.appveyor.com/api/projects/status/w5j4kul3w2rkigxb?svg=true)](https://ci.appveyor.com/project/ethauvin/httpstatus) [![CircleCI](https://circleci.com/gh/ethauvin/HttpStatus/tree/master.svg?style=shield)](https://circleci.com/gh/ethauvin/HttpStatus/tree/master) +[![Java](https://img.shields.io/badge/java-17%2B-blue)](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) +[![Release](https://img.shields.io/github/release/ethauvin/httpstatus.svg)](https://github.com/ethauvin/httpstatus/releases/latest) +[![Maven Central](https://img.shields.io/maven-central/v/net.thauvin.erik.httpstatus/httpstatus.svg?label=maven%20central)](https://search.maven.org/search?q=g:%22net.thauvin.erik.httpstatus%22%20AND%20a:%22httpstatus%22) +![Sonatype Nexus (Snapshots)](https://img.shields.io/nexus/s/net.thauvin.erik.httpstatus/httpstatus?server=https%3A%2F%2Foss.sonatype.org) +[![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](http://opensource.org/licenses/BSD-3-Clause) +[![Known Vulnerabilities](https://snyk.io/test/github/ethauvin/httpstatus/badge.svg?targetFile=pom.xml)](https://snyk.io/test/github/ethauvin/httpstatus?targetFile=pom.xml) +[![GitHub CI](https://github.com/ethauvin/httpstatus/actions/workflows/bld.yml/badge.svg)](https://github.com/ethauvin/httpstatus/actions/workflows/bld.yml) +[![Build status](https://ci.appveyor.com/api/projects/status/w5j4kul3w2rkigxb?svg=true)](https://ci.appveyor.com/project/ethauvin/httpstatus) +[![CircleCI](https://circleci.com/gh/ethauvin/HttpStatus/tree/master.svg?style=shield)](https://circleci.com/gh/ethauvin/HttpStatus/tree/master) A simple [JSP](http://www.oracle.com/technetwork/java/javaee/jsp/index.html) Tag Library to display the [code](#hscode), [reason](#hsreason), [cause](#hscode) and/or [message](#hsmessage) for [HTTP status codes](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) in JSP error pages. @@ -36,6 +42,10 @@ would display on a [501 status code](http://www.w3.org/Protocols/rfc2616/rfc2616 Include the following in your `build.gradle` file: ```gradle +repositories { + mavenCentral() +} + dependencies { implementation 'net.thauvin.erik.httpstatus:httpstatus:1.1.0' } @@ -150,7 +160,7 @@ Method | Description ## Reasons -The reasons are defined in a [ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html) properties as follows: +The reasons are defined in a [ResourceBundle](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ResourceBundle.html) properties as follows: Status Code | Reason ----------- | ----------------------------------- diff --git a/appveyor.yml b/appveyor.yml index b66b878..b335d11 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,11 +7,11 @@ skip_tags: true build: verbosity: detailed -build_script: - - gradlew.bat assemble --info --no-daemon +download_script: + - bld.bat download test_script: - - gradlew.bat check --info --no-daemon + - bld.bat compile test branches: only: diff --git a/bld b/bld new file mode 100755 index 0000000..0880033 --- /dev/null +++ b/bld @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +java -jar "$(dirname "$0")/lib/bld/bld-wrapper.jar" "$0" --build net.thauvin.erik.httpstatus.HttpStatusBuild "$@" \ No newline at end of file diff --git a/bld.bat b/bld.bat new file mode 100644 index 0000000..2810ee8 --- /dev/null +++ b/bld.bat @@ -0,0 +1,4 @@ +@echo off +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +java -jar "%DIRNAME%/lib/bld/bld-wrapper.jar" "%0" --build net.thauvin.erik.httpstatus.HttpStatusBuild %* \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 12a7d51..0000000 --- a/build.gradle +++ /dev/null @@ -1,247 +0,0 @@ -plugins { - id 'java' - id 'jacoco' - id 'idea' - id 'application' - id 'maven-publish' - id 'signing' - id 'pmd' - id 'com.github.ben-manes.versions' version '0.42.0' - id 'net.thauvin.erik.gradle.semver' version '1.0.4' - id 'com.github.spotbugs' version '5.0.10' - id 'org.sonarqube' version '3.4.0.2513' -} - -import com.github.spotbugs.snom.SpotBugsTask -import org.apache.tools.ant.taskdefs.condition.Os - -defaultTasks 'deploy' - -final def deployDir = 'deploy' - -final def mavenName = 'HttpStatus' -final def mavenDescription = 'HttpStatus JSP Tag Library' -final def mavenUrl = 'https://github.com/ethauvin/HttpStatus' -final def mavenLicense = 'The BSD 3-Clause License' -final def mavenLicenseUrl = 'http://opensource.org/licenses/BSD-3-Clause' -final def mavenScmCon = 'https://github.com/ethauvin/HttpStatus.git' -final def mavenScmDevCon = 'git@github.com:ethauvin/HttpStatus.git' - -group = 'net.thauvin.erik.httpstatus' - -mainClassName = 'net.thauvin.erik.httpstatus.Reasons' - -ext { - versions = [ - pmd : '6.47.0', - spotbugs: '4.7.1' - ] -} - -repositories { - mavenLocal() - mavenCentral() - maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } -} - -dependencies { -// compileOnly 'javax.servlet:javax.servlet-api:4.0.1' -// compileOnly 'javax.servlet.jsp:jsp-api:2.2.1-b03' -// compileOnly 'javax.el:javax.el-api:3.0.1-b06' - - compileOnly 'jakarta.servlet:jakarta.servlet-api:6.0.0' - compileOnly 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.1.0' - compileOnly 'jakarta.el:jakarta.el-api:5.0.1' - - spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.12.0' - spotbugsPlugins 'com.mebigfatguy.sb-contrib:sb-contrib:7.4.7' - - compileOnly "com.github.spotbugs:spotbugs-annotations:$versions.spotbugs" - testCompileOnly "com.github.spotbugs:spotbugs-annotations:$versions.spotbugs" - - testImplementation 'org.testng:testng:7.6.1' -} - -tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' -} - -java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - withJavadocJar() - withSourcesJar() -} - -javadoc { - doFirst { - title = mavenDescription + ' ' + project.version - } - options.source = 8 - options.tags = ['created'] - options.author = true - options.links('https://docs.oracle.com/javase/8/docs/api/') - options.addStringOption('Xdoclint:none', '-quiet') -} - -jar { - manifest.attributes('Main-Class': mainClassName) -} - -clean { - doLast { - project.delete(fileTree(deployDir)) - } -} - -test { - testLogging { - exceptionFormat = 'full' - events('passed', 'skipped', 'failed') - } - - useTestNG() -} - -spotbugs { - toolVersion = versions.spotbugs - excludeFilter = file("$projectDir/config/spotbugs/excludeFilter.xml") - -} - -pmd { - toolVersion = versions.pmd - ignoreFailures = true - ruleSets = [] - ruleSetFiles = files("${projectDir}/config/pmd.xml") - consoleOutput = true -} - -tasks.withType(SpotBugsTask) { - reports { - xml.required = false - html.required = true - } -} - -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - groupId = project.group - artifactId = rootProject.name - - pom { - name = mavenName - description = mavenDescription - url = mavenUrl - licenses { - license { - name = mavenLicense - url = mavenLicenseUrl - } - } - developers { - developer { - id = 'ethauvin' - name = 'Erik C. Thauvin' - email = 'erik@thauvin.net' - url = 'https://erik.thauvin.net/' - } - } - scm { - connection = 'scm:git:' + mavenScmCon - developerConnection = 'scm:git:' + mavenScmDevCon - url = mavenUrl - } - } - } - } - repositories { - maven { - name = 'ossrh' - project.afterEvaluate { - url = project.version.contains('SNAPSHOT') - ? 'https://oss.sonatype.org/content/repositories/snapshots/' - : 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' - } - credentials(PasswordCredentials) - } - } -} - -signing { - useGpgCmd() - sign publishing.publications.mavenJava -} - -task copyToDeploy(type: Copy) { - from(configurations.runtimeClasspath) { - exclude('javax.servlet-api-*.jar', - 'jsp-api-*.jar', - 'jakarta.servlet-*.jar', - 'jakarta-servlet.*.jar', - 'jakarta.el-api*.jar') - } - from jar - into deployDir -} - -task deploy { - description = "Copies all needed files to the ${deployDir} directory." - group = 'Publishing' - dependsOn(clean, build, 'copyToDeploy') - outputs.dir deployDir - inputs.files copyToDeploy - mustRunAfter clean -} - -task release { - group = 'Publishing' - description = 'Releases new version.' - dependsOn(wrapper, 'deploy', 'pandoc', publishToMavenLocal) -} - -task pandoc(type: Exec) { - group = 'Documentation' - final def pandoc_args = ['--from', 'gfm', - '--to', 'html5', - '--metadata', "pagetitle=$mavenDescription", - '-s', - '-c', 'github-pandoc.css', - '-o', 'docs/README.html', - 'README.md'] - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - commandLine(['cmd', '/c', 'pandoc'] + pandoc_args) - } else { - executable = 'pandoc' - args(pandoc_args) - } - standardOutput = new ByteArrayOutputStream() - ext.output = { - return standardOutput.toString() - } -} - -jacoco { - toolVersion = '0.8.9-SNAPSHOT' -} - -jacocoTestReport { - reports { - xml.required = true - } -} - -sonarqube { - properties { - property('sonar.organization', 'ethauvin-github') - property('sonar.projectKey', 'ethauvin_HttpStatus') - property('sonar.host.url', 'https://sonarcloud.io') - property('sonar.sourceEncoding', 'UTF-8') - } -} - -tasks.sonarqube { - dependsOn 'jacocoTestReport' -} diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml deleted file mode 100644 index c5f6465..0000000 --- a/config/checkstyle/checkstyle.xml +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/config/pmd.xml b/config/pmd.xml index 890a490..1039e40 100644 --- a/config/pmd.xml +++ b/config/pmd.xml @@ -9,6 +9,7 @@ + @@ -25,9 +26,10 @@ - + + @@ -37,6 +39,12 @@ + + + + + + @@ -72,8 +80,6 @@ - - @@ -89,13 +95,6 @@ - - - - ^ignore$ - - - @@ -108,4 +107,4 @@ - + \ No newline at end of file diff --git a/config/spotbugs/excludeFilter.xml b/config/spotbugs/excludeFilter.xml deleted file mode 100644 index ddb2db1..0000000 --- a/config/spotbugs/excludeFilter.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - diff --git a/deploy.sh b/deploy.sh old mode 100644 new mode 100755 diff --git a/docs/README.html b/docs/README.html deleted file mode 100644 index f4eafc6..0000000 --- a/docs/README.html +++ /dev/null @@ -1,716 +0,0 @@ - - - - - - - HttpStatus JSP Tag Library - - - - - -

HttpStatus JSP Tag Library

-


-
-

-

A simple JSP -Tag Library to display the code, reason, cause and/or message for HTTP -status codes in JSP error pages.

-

For example:

-
<%@ page isErrorPage="true" %>
-<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
-<html><head>
-<title><hs:code/> <hs:reason default="Server Error"/></title>
-</head>
-<h1><hs:reason default="Server Error"/></h1>
-Cause: <pre><hs:cause default="Unable to complete your request."/></pre>
-Message: <pre><hs:message default="A server error has occured."/></pre>
-...
-

or

-
<%@ page isErrorPage="true" import="net.thauvin.erik.httpstatus.Reasons" %>
-<%= Reasons.getReasonPhrase(pageContext.getErrorData().getStatusCode()) %>
-

would display on a 501 -status code:

-
Not Implemented
-

Usage with Gradle or Maven

-

Include the following in your build.gradle file:

-
dependencies {
-    implementation 'net.thauvin.erik.httpstatus:httpstatus:1.1.0'
-}
-

or as a Maven artifact:

-
<dependency>
-    <groupId>net.thauvin.erik.httpstatus</groupId>
-    <artifactId>httpstatus</artifactId>
-    <version>1.1.0</version>
-</dependency>
-

hs:cause

-

The <hs:cause/> tag displays the cause of current -HTTP status code, if any. A shorthand for:

-
<%= pageContext.getErrorData().getThrowable().getCause().getLocalizedMessage() %>
-

Optional attributes are:

- - - - - - - - - - - - - - - - - -
AttributeDescription
defaultThe fallback value to output, if no cause is available.
escapeXmlConverts <, >, &, ', " to their corresponding entity codes. -Value is true by default.
-

hs:code

-

The <hs:code/> tag displays the current HTTP -status code, if any. A shorthand for:

-
<%= pageContext.getErrorData().getStatusCode() %>
-

hs:message

-

The <hs:message/> tag displays the current error -message, if any. A shorthand for:

-
<%= request.getAttribute("javax.servlet.error.message") %>
-

Optional attributes are:

- - - - - - - - - - - - - - - - - -
AttributeDescription
defaultThe fallback value to output, if no error message is available.
escapeXmlConverts <, >, &, ', " to their corresponding entity codes. -Value is true by default.
-

hs:reason

-

The <hs:reason/> tag displays the reason for a -HTTP status code, if any. Optional attributes are:

- - - - - - - - - - - - - - - - - - - - - -
AttributeDescription
codeThe HTTP status error code. If not specified the current status code -is used.
defaultThe fallback value to output, if no reason is available.
escapeXmlConverts <, >, &, ', " to their corresponding entity codes. -Value is true by default.
-

StatusCode Bean

-

The StatusCode bean can be used to check the class of -the status code error. For example, using the JSTL:

-
<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
-<jsp:useBean id="statusCode" class="net.thauvin.erik.httpstatus.StatusCode"/>
-<c:set target="${statusCode}" property="code"><hs:code/></c:set>
-<c:choose>
-    <c:when test="${statusCode.isClientError()}">
-        An error occurred on your side. (<hs:reason/>)
-    </c:when>
-    <c:otherwise>
-        An error occurred on our side. (<hs:message/>)
-    </c:otherwise>
-</c:choose>
-

or in a Servlet:

-
import net.thauvin.erik.httpstatus.StatusCode;
-
-// ---
-
-StatusCode statusCode = new StatusCode((Integer) request.getAttribute("javax.servlet.error.status_code"));
-if (statusCode.isError()) {
-    if (statusCode.isServerError()) {
-        String reason = statusCode.getReason();
-    } else {
-        // ...
-    }
-}
-

The StatusCode bean methods are:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodDescription
getReasonReturns the reason for the status code (eg: -Internal Server Error)
isClientErrorChecks if the status code is a client error.
isErrorChecks if the status code is a server or client error.
isInfoChecks if the status code is informational.
isRedirectChecks if the status code is a redirect.
isServerErrorChecks if the status code is a server error.
isSuccessChecks if the status code is a success. (OK)
isValidChecks if the status code is valid.
-

Reasons

-

The reasons are defined in a ResourceBundle -properties as follows:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Status CodeReason
100Continue
101Switching Protocols
102Processing
103Early Hints
200OK
201Created
202Accepted
203Non-Authoritative Information
204No Content
205Reset Content
206Partial Content
207Multi-Status
208Already Reported
218This is fine
226IM Used
300Multiple Choices
301Moved Permanently
302Found/Moved Temporarily
303See Other
304Not Modified
305Use Proxy
306Switch Proxy
307Temporary Redirect
308Permanent Redirect
400Bad Request
401Unauthorized
402Payment Required
403Forbidden
404Not Found
405Method Not Allowed
406Not Acceptable
407Proxy Authentication Required
408Request Timeout
409Conflict
410Gone
411Length Required
412Precondition Failed
413Request Entity/Payload Too Large
414Request-URI Too Long
415Unsupported Media Type
416Requested Range Not Satisfiable
417Expectation Failed
418I'm A Teapot
419Insufficient Space on Resource
420Method Failure
421Misdirected Request
422Unprocessable Entity
423Locked
424Failed Dependency
426Upgrade Required
428Precondition Required
429Too Many Requests
430Request Header Fields Too Large
431Request Header Fields Too Large
440Login Timeout
444No Response
449Retry With
450Blocked by Windows Parental Controls
451Unavailable For Legal Reasons
460Client Closed Connection Before Load Balancer Idle Timeout
463X-Forwarded-For Header with More than 30 IP Addresses
494Request Header Too Large
495SSL Certificate Error
496No SSL Certificate
497HTTP Request Sent to HTTPS Port
498Token Expired/Invalid
499Client Closed Request
500Internal Server Error
501Not Implemented
502Bad Gateway
503Service Unavailable
504Gateway Timeout
505HTTP Version Not Supported
506Variant Also Negotiates
507Insufficient Storage
508Loop Detected
509Bandwidth Limit Exceeded
510Not Extended
511Network Authentication Required
520Unknown Error
521Web Server Is Down
522Origin Connection Time-out
523Origin Is Unreachable
524A Timeout Occurred
525SSL Handshake Failed
526Invalid SSL Certificate
527Railgun Error
529Site is overloaded
530Site is frozen
598Network Read Timeout Error
599Network Connect Timeout Error
-

Command Line Usage

-

You can query the reason phrase for status codes as follows:

-
$ java -jar httpstatus-1.1.0.jar 404 500
-404: Not Found
-500: Internal Server Error
-

If no status code is specified, all will be printed:

-
$ java -jar httpstatus-1.1.0.jar
-100: Continue
-101: Switching Protocols
-102: Processing
-103: Early Hints
-200: OK
-201: Created
-202: Accepted
-203: Non-Authoritative Information
-204: No Content
-205: Reset Content
-206: Partial Content
-207: Multi-Status
-208: Already Reported
-226: IM Used
-...
- - diff --git a/docs/github-pandoc.css b/docs/github-pandoc.css deleted file mode 100644 index d7edd25..0000000 --- a/docs/github-pandoc.css +++ /dev/null @@ -1,425 +0,0 @@ -/* github-pandoc.css found at https://gist.github.com/dashed/6714393 */ -/*! normalize.css v2.1.3 | MIT License | git.io/normalize */ - -/* ========================================================================== - HTML5 display definitions - ========================================================================== */ - -/** - * Correct `block` display not defined in IE 8/9. - */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -nav, -section, -summary { - display: block; -} - -/** - * Correct `inline-block` display not defined in IE 8/9. - */ - -audio, -canvas, -video { - display: inline-block; -} - -/** - * Prevent modern browsers from displaying `audio` without controls. - * Remove excess height in iOS 5 devices. - */ - -audio:not([controls]) { - display: none; - height: 0; -} - -/** - * Address `[hidden]` styling not present in IE 8/9. - * Hide the `template` element in IE, Safari, and Firefox < 22. - */ - -[hidden], -template { - display: none; -} - -/* ========================================================================== - Base - ========================================================================== */ - -/** - * 1. Set default font family to sans-serif. - * 2. Prevent iOS text size adjust after orientation change, without disabling - * user zoom. - */ - -html { - font-family: sans-serif; /* 1 */ - -ms-text-size-adjust: 100%; /* 2 */ - -webkit-text-size-adjust: 100%; /* 2 */ -} - -/** - * Remove default margin. - */ - -body { - margin: 0; -} - -/* ========================================================================== - Links - ========================================================================== */ - -/** - * Remove the gray background color from active links in IE 10. - */ - -a { - background: transparent; -} - -/** - * Address `outline` inconsistency between Chrome and other browsers. - */ - -a:focus { - outline: thin dotted; -} - -/** - * Improve readability when focused and also mouse hovered in all browsers. - */ - -a:active, -a:hover { - outline: 0; -} - -/* ========================================================================== - Typography - ========================================================================== */ - -/** - * Address variable `h1` font-size and margin within `section` and `article` - * contexts in Firefox 4+, Safari 5, and Chrome. - */ - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -/** - * Address styling not present in IE 8/9, Safari 5, and Chrome. - */ - -abbr[title] { - border-bottom: 1px dotted; -} - -/** - * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. - */ - -b, -strong { - font-weight: bold; -} - -/** - * Address styling not present in Safari 5 and Chrome. - */ - -dfn { - font-style: italic; -} - -/** - * Address differences between Firefox and other browsers. - */ - -hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} - -/** - * Address styling not present in IE 8/9. - */ - -mark { - background: #ff0; - color: #000; -} - -/** - * Correct font family set oddly in Safari 5 and Chrome. - */ - -code, -kbd, -pre, -samp { - font-family: monospace, serif; - font-size: 1em; -} - -/** - * Improve readability of pre-formatted text in all browsers. - */ - -pre { - white-space: pre-wrap; -} - -/** - * Set consistent quote types. - */ - -q { - quotes: "\201C" "\201D" "\2018" "\2019"; -} - -/** - * Address inconsistent and variable font size in all browsers. - */ - -small { - font-size: 80%; -} - -/** - * Prevent `sub` and `sup` affecting `line-height` in all browsers. - */ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -/* ========================================================================== - Embedded content - ========================================================================== */ - -/** - * Remove border when inside `a` element in IE 8/9. - */ - -img { - border: 0; -} - -/** - * Correct overflow displayed oddly in IE 9. - */ - -svg:not(:root) { - overflow: hidden; -} - -/* ========================================================================== - Figures - ========================================================================== */ - -/** - * Address margin not present in IE 8/9 and Safari 5. - */ - -figure { - margin: 0; -} - -/* ========================================================================== - Forms - ========================================================================== */ - -/** - * Define consistent border, margin, and padding. - */ - -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} - -/** - * 1. Correct `color` not being inherited in IE 8/9. - * 2. Remove padding so people aren't caught out if they zero out fieldsets. - */ - -legend { - border: 0; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * 1. Correct font family not being inherited in all browsers. - * 2. Correct font size not being inherited in all browsers. - * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. - */ - -button, -input, -select, -textarea { - font-family: inherit; /* 1 */ - font-size: 100%; /* 2 */ - margin: 0; /* 3 */ -} - -/** - * Address Firefox 4+ setting `line-height` on `input` using `!important` in - * the UA stylesheet. - */ - -button, -input { - line-height: normal; -} - -/** - * Address inconsistent `text-transform` inheritance for `button` and `select`. - * All other form control elements do not inherit `text-transform` values. - * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. - * Correct `select` style inheritance in Firefox 4+ and Opera. - */ - -button, -select { - text-transform: none; -} - -/** - * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` - * and `video` controls. - * 2. Correct inability to style clickable `input` types in iOS. - * 3. Improve usability and consistency of cursor style between image-type - * `input` and others. - */ - -button, -html input[type="button"], /* 1 */ -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; /* 2 */ - cursor: pointer; /* 3 */ -} - -/** - * Re-set default cursor for disabled elements. - */ - -button[disabled], -html input[disabled] { - cursor: default; -} - -/** - * 1. Address box sizing set to `content-box` in IE 8/9/10. - * 2. Remove excess padding in IE 8/9/10. - */ - -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. - * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome - * (include `-moz` to future-proof). - */ - -input[type="search"] { - -webkit-appearance: textfield; /* 1 */ - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; /* 2 */ - box-sizing: content-box; -} - -/** - * Remove inner padding and search cancel button in Safari 5 and Chrome - * on OS X. - */ - -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -/** - * Remove inner padding and border in Firefox 4+. - */ - -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} - -/** - * 1. Remove default vertical scrollbar in IE 8/9. - * 2. Improve readability and alignment in all browsers. - */ - -textarea { - overflow: auto; /* 1 */ - vertical-align: top; /* 2 */ -} - -/* ========================================================================== - Tables - ========================================================================== */ - -/** - * Remove most spacing between table cells. - */ - -table { - border-collapse: collapse; - border-spacing: 0; -} - -.go-top { -position: fixed; -bottom: 2em; -right: 2em; -text-decoration: none; -background-color: #E0E0E0; -font-size: 12px; -padding: 1em; -display: inline; -} - -/* Github css */ - -html,body{ margin: auto; - padding-right: 1em; - padding-left: 1em; - max-width: 44em; color:black;}*:not('#mkdbuttons'){margin:0;padding:0}body{font:13.34px helvetica,arial,freesans,clean,sans-serif;-webkit-font-smoothing:subpixel-antialiased;line-height:1.4;padding:3px;background:#fff;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px}p{margin:1em 0}a{color:#4183c4;text-decoration:none}body{background-color:#fff;padding:30px;margin:15px;font-size:14px;line-height:1.6}body>*:first-child{margin-top:0!important}body>*:last-child{margin-bottom:0!important}@media screen{body{box-shadow:0 0 0 1px #cacaca,0 0 0 4px #eee}}h1,h2,h3,h4,h5,h6{margin:20px 0 10px;padding:0;font-weight:bold;-webkit-font-smoothing:subpixel-antialiased;cursor:text}h1{font-size:28px;color:#000}h2{font-size:24px;border-bottom:1px solid #ccc;color:#000}h3{font-size:18px;color:#333}h4{font-size:16px;color:#333}h5{font-size:14px;color:#333}h6{color:#777;font-size:14px}p,blockquote,table,pre{margin:15px 0}ul{padding-left:30px}ol{padding-left:30px}ol li ul:first-of-type{margin-top:0}hr{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;border:0 none;color:#ccc;height:4px;padding:0}body>h2:first-child{margin-top:0;padding-top:0}body>h1:first-child{margin-top:0;padding-top:0}body>h1:first-child+h2{margin-top:0;padding-top:0}body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child{margin-top:0;padding-top:0}a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6{margin-top:0;padding-top:0}h1+p,h2+p,h3+p,h4+p,h5+p,h6+p,ul li>:first-child,ol li>:first-child{margin-top:0}dl{padding:0}dl dt{font-size:14px;font-weight:bold;font-style:italic;padding:0;margin:15px 0 5px}dl dt:first-child{padding:0}dl dt>:first-child{margin-top:0}dl dt>:last-child{margin-bottom:0}dl dd{margin:0 0 15px;padding:0 15px}dl dd>:first-child{margin-top:0}dl dd>:last-child{margin-bottom:0}blockquote{border-left:4px solid #DDD;padding:0 15px;color:#777}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}table{border-collapse:collapse;border-spacing:0;font-size:100%;font:inherit}table th{font-weight:bold;border:1px solid #ccc;padding:6px 13px}table td{border:1px solid #ccc;padding:6px 13px}table tr{border-top:1px solid #ccc;background-color:#fff}table tr:nth-child(2n){background-color:#f8f8f8}img{max-width:100%}code,tt{margin:0 2px;padding:0 5px;white-space:nowrap;border:1px solid #eaeaea;background-color:#f8f8f8;border-radius:3px;font-family:Consolas,'Liberation Mono',Courier,monospace;font-size:12px;color:#333}pre>code{margin:0;padding:0;white-space:pre;border:0;background:transparent}.highlight pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre code,pre tt{background-color:transparent;border:0}.poetry pre{font-family:Georgia,Garamond,serif!important;font-style:italic;font-size:110%!important;line-height:1.6em;display:block;margin-left:1em}.poetry pre code{font-family:Georgia,Garamond,serif!important;word-break:break-all;word-break:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;hyphens:auto;white-space:pre-wrap}sup,sub,a.footnote{font-size:1.4ex;height:0;line-height:1;vertical-align:super;position:relative}sub{vertical-align:sub;top:-1px}@media print{body{background:#fff}img,pre,blockquote,table,figure{page-break-inside:avoid}body{background:#fff;border:0}code{background-color:#fff;color:#333!important;padding:0 .2em;border:1px solid #dedede}pre{background:#fff}pre code{background-color:white!important;overflow:visible}}@media screen{body.inverted{color:#eee!important;border-color:#555;box-shadow:none}.inverted body,.inverted hr .inverted p,.inverted td,.inverted li,.inverted h1,.inverted h2,.inverted h3,.inverted h4,.inverted h5,.inverted h6,.inverted th,.inverted .math,.inverted caption,.inverted dd,.inverted dt,.inverted blockquote{color:#eee!important;border-color:#555;box-shadow:none}.inverted td,.inverted th{background:#333}.inverted h2{border-color:#555}.inverted hr{border-color:#777;border-width:1px!important}::selection{background:rgba(157,193,200,0.5)}h1::selection{background-color:rgba(45,156,208,0.3)}h2::selection{background-color:rgba(90,182,224,0.3)}h3::selection,h4::selection,h5::selection,h6::selection,li::selection,ol::selection{background-color:rgba(133,201,232,0.3)}code::selection{background-color:rgba(0,0,0,0.7);color:#eee}code span::selection{background-color:rgba(0,0,0,0.7)!important;color:#eee!important}a::selection{background-color:rgba(255,230,102,0.2)}.inverted a::selection{background-color:rgba(255,230,102,0.6)}td::selection,th::selection,caption::selection{background-color:rgba(180,237,95,0.5)}.inverted{background:#0b2531;background:#252a2a}.inverted body{background:#252a2a}.inverted a{color:#acd1d5}}.highlight .c{color:#998;font-style:italic}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .k,.highlight .o{font-weight:bold}.highlight .cm{color:#998;font-style:italic}.highlight .cp{color:#999;font-weight:bold}.highlight .c1{color:#998;font-style:italic}.highlight .cs{color:#999;font-weight:bold;font-style:italic}.highlight .gd{color:#000;background-color:#fdd}.highlight .gd .x{color:#000;background-color:#faa}.highlight .ge{font-style:italic}.highlight .gr{color:#a00}.highlight .gh{color:#999}.highlight .gi{color:#000;background-color:#dfd}.highlight .gi .x{color:#000;background-color:#afa}.highlight .go{color:#888}.highlight .gp{color:#555}.highlight .gs{font-weight:bold}.highlight .gu{color:#800080;font-weight:bold}.highlight .gt{color:#a00}.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr{font-weight:bold}.highlight .kt{color:#458;font-weight:bold}.highlight .m{color:#099}.highlight .s{color:#d14}.highlight .na{color:#008080}.highlight .nb{color:#0086b3}.highlight .nc{color:#458;font-weight:bold}.highlight .no{color:#008080}.highlight .ni{color:#800080}.highlight .ne,.highlight .nf{color:#900;font-weight:bold}.highlight .nn{color:#555}.highlight .nt{color:#000080}.highlight .nv{color:#008080}.highlight .ow{font-weight:bold}.highlight .w{color:#bbb}.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:#099}.highlight .sb,.highlight .sc,.highlight .sd,.highlight .s2,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .bp{color:#999}.highlight .vc,.highlight .vg,.highlight .vi{color:#008080}.highlight .il{color:#099}.highlight .gc{color:#999;background-color:#eaf2f5}.type-csharp .highlight .k,.type-csharp .highlight .kt{color:#00F}.type-csharp .highlight .nf{color:#000;font-weight:normal}.type-csharp .highlight .nc{color:#2b91af}.type-csharp .highlight .nn{color:#000}.type-csharp .highlight .s,.type-csharp .highlight .sc{color:#a31515} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 249e5832f090a2944b7473328c07c9755baa3196..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60756 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 '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index f127cfd..0000000 --- a/gradlew.bat +++ /dev/null @@ -1,91 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/lib/bld/bld-wrapper.jar b/lib/bld/bld-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..808a03cde5b1bda2621d81220803f2967a26ced4 GIT binary patch literal 25099 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 bGyV6bQBy)e{j-Ypv{65esQIUL1cd(u*QxW` literal 0 HcmV?d00001 diff --git a/lib/bld/bld-wrapper.properties b/lib/bld/bld-wrapper.properties new file mode 100644 index 0000000..bf89ff6 --- /dev/null +++ b/lib/bld/bld-wrapper.properties @@ -0,0 +1,6 @@ +bld.downloadExtensionJavadoc=false +bld.downloadExtensionSources=true +bld.extension-pmd=com.uwyn.rife2:bld-pmd:0.9.1 +bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES +rife2.downloadLocation= +rife2.version=1.6.3 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..9a3ab33 --- /dev/null +++ b/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + net.thauvin.erik.httpstatus + httpstatus + 1.1.0-SNAPSHOT + HttpStatus + HttpStatus JSP Tag Library + https://github.com/ethauvin/HttpStatus + + + The BSD 3-Clause License + http://opensource.org/licenses/BSD-3-Clause + + + + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + compile + + + jakarta.servlet.jsp + jakarta.servlet.jsp-api + 3.1.1 + compile + + + jakarta.el + jakarta.el-api + 5.0.1 + compile + + + + + ethauvin + Erik C. Thauvin + erik@thauvin.net + https://erik.thauvin.net/ + + + + scm:git:https://github.com/ethauvin/HttpStatus.git + scm:git:git@github.com:ethauvin/HttpStatus.git + https://github.com/ethauvin/HttpStatus + + diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index b28649f..0000000 --- a/settings.gradle +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This settings file was auto generated by the Gradle buildInit task - * by 'erik' at '12/2/15 1:19 PM' with Gradle 2.9 - * - * The settings file is used to specify which projects to include in your build. - * In a single project build this file can be empty or even removed. - * - * Detailed information about configuring a multi-project build in Gradle can be found - * in the user guide at https://docs.gradle.org/2.9/userguide/multi_project_builds.html - */ - -/* -// To declare projects as part of a multi-project build use the 'include' method -include 'shared' -include 'api' -include 'services:webservice' -*/ - -rootProject.name = 'httpstatus' \ No newline at end of file diff --git a/src/bld/java/net/thauvin/erik/httpstatus/HttpStatusBuild.java b/src/bld/java/net/thauvin/erik/httpstatus/HttpStatusBuild.java new file mode 100644 index 0000000..79cbac7 --- /dev/null +++ b/src/bld/java/net/thauvin/erik/httpstatus/HttpStatusBuild.java @@ -0,0 +1,128 @@ +/* + * HttpStatusBuild.java + * + * Copyright 2023 sErik C. Thauvin (erik@thauvin.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of this project nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.thauvin.erik.httpstatus; + +import rife.bld.BuildCommand; +import rife.bld.Project; +import rife.bld.dependencies.Dependency; +import rife.bld.extension.PmdOperation; +import rife.bld.publish.PublishDeveloper; +import rife.bld.publish.PublishInfo; +import rife.bld.publish.PublishLicense; +import rife.bld.publish.PublishScm; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.List; + +import static rife.bld.dependencies.Repository.*; +import static rife.bld.dependencies.Scope.compile; +import static rife.bld.dependencies.Scope.test; +import static rife.bld.operations.JavadocOptions.DocLinkOption.NO_MISSING; + +public class HttpStatusBuild extends Project { + public HttpStatusBuild() { + pkg = "net.thauvin.erik.httpstatus"; + name = "HttpStatus"; + version = version(1, 1, 0, "SNAPSHOT"); + + var description = "HttpStatus JSP Tag Library"; + var url = "https://github.com/ethauvin/HttpStatus"; + + mainClass = "net.thauvin.erik.httpstatus.Reasons"; + + javaRelease = 17; + + downloadSources = true; + repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, SONATYPE_SNAPSHOTS); + + scope(compile) + .include(dependency("jakarta.servlet", "jakarta.servlet-api", version(6, 0, 0))) + .include(dependency("jakarta.servlet.jsp", "jakarta.servlet.jsp-api", version(3, 1, 1))) + .include(dependency("jakarta.el", "jakarta.el-api", version(5, 0, 1))); + scope(test) + .include(dependency("org.assertj", "assertj-joda-time", version(2, 2, 0))) + .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 9, 3))) + .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 9, 3))); + + javadocOperation().javadocOptions() + .docTitle(description + ' ' + version.toString()) + .docLint(NO_MISSING) + .link("https://jakarta.ee/specifications/platform/9/apidocs/"); + + publishOperation() + .repository(version.isSnapshot() ? repository(SONATYPE_SNAPSHOTS_LEGACY.location()) + .withCredentials(property("sonatype.user"), property("sonatype.password")) + : repository(SONATYPE_RELEASES.location()) + .withCredentials(property("sonatype.user"), property("sonatype.password"))) + .repository(MAVEN_LOCAL) + .info(new PublishInfo() + .groupId(pkg) + .artifactId(name.toLowerCase()) + .name(name) + .description(description) + .url(url) + .developer(new PublishDeveloper().id("ethauvin").name("Erik C. Thauvin").email("erik@thauvin.net") + .url("https://erik.thauvin.net/")) + .license(new PublishLicense().name("The BSD 3-Clause License") + .url("http://opensource.org/licenses/BSD-3-Clause")) + .scm(new PublishScm().connection("scm:git:" + url + ".git") + .developerConnection("scm:git:git@github.com:ethauvin/" + name + ".git") + .url(url)) + .signKey(property("sign.key")) + .signPassphrase(property("sign.passphrase"))); + } + + public static void main(String[] args) { + new HttpStatusBuild().start(args); + } + + @Override + public void publish() throws Exception { + super.publish(); + var pomPath = Path.of(MAVEN_LOCAL.getArtifactLocation(new Dependency(pkg, name.toLowerCase(), version)), + version.toString(), + name.toLowerCase() + '-' + version + ".pom"); + Files.copy(pomPath, Path.of(workDirectory.getAbsolutePath(), "pom.xml"), StandardCopyOption.REPLACE_EXISTING); + } + + @BuildCommand(summary = "Runs PMD analysis") + public void pmd() throws Exception { + new PmdOperation() + .fromProject(this) + .failOnViolation(true) + .ruleSets("config/pmd.xml") + .execute(); + } +} \ No newline at end of file diff --git a/src/main/java/net/thauvin/erik/httpstatus/Reasons.java b/src/main/java/net/thauvin/erik/httpstatus/Reasons.java index 44b5283..6147a78 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/Reasons.java +++ b/src/main/java/net/thauvin/erik/httpstatus/Reasons.java @@ -1,7 +1,7 @@ /* * Reasons.java * - * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) + * Copyright 2023 sErik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java index 526331f..fdcc6e2 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java +++ b/src/main/java/net/thauvin/erik/httpstatus/StatusCode.java @@ -1,7 +1,7 @@ /* * StatusCode.java * - * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) + * Copyright 2023 sErik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ package net.thauvin.erik.httpstatus; +import java.io.Serial; import java.io.Serializable; /** @@ -40,6 +41,7 @@ import java.io.Serializable; * @author Erik C. Thauvin */ public class StatusCode implements Serializable { + @Serial private static final long serialVersionUID = 1L; private int code; @@ -49,7 +51,7 @@ public class StatusCode implements Serializable { public StatusCode() { // Default constructor. } - + /** * Creates a new StatusCode object. * diff --git a/src/main/java/net/thauvin/erik/httpstatus/Utils.java b/src/main/java/net/thauvin/erik/httpstatus/Utils.java index b40967a..8cf691b 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/Utils.java +++ b/src/main/java/net/thauvin/erik/httpstatus/Utils.java @@ -1,7 +1,7 @@ /* * Utils.java * - * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) + * Copyright 2023 sErik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,24 +66,12 @@ public final class Utils { for (int i = 0; i < value.length(); i++) { final char c = value.charAt(i); switch (c) { - case '<': - escaped.append("<"); - break; - case '>': - escaped.append(">"); - break; - case '&': - escaped.append("&"); - break; - case '\'': - escaped.append("'"); - break; - case '"': - escaped.append("""); - break; - default: - escaped.append(c); - break; + case '<' -> escaped.append("<"); + case '>' -> escaped.append(">"); + case '&' -> escaped.append("&"); + case '\'' -> escaped.append("'"); + case '"' -> escaped.append("""); + default -> escaped.append(c); } } diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java index 63fc6b7..54b01a7 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java @@ -1,7 +1,7 @@ /* * CauseTag.java * - * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) + * Copyright 2023 sErik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java index 5d5b47a..763157a 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java @@ -1,7 +1,7 @@ /* * CodeTag.java * - * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) + * Copyright 2023 sErik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java index 7ec8862..7a72750 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/MessageTag.java @@ -1,7 +1,7 @@ /* - * CauseTag.java + * MessageTag.java * - * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) + * Copyright 2023 sErik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java index 10bbc2c..dccf365 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java @@ -1,7 +1,7 @@ /* * ReasonTag.java * - * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) + * Copyright 2023 sErik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -65,7 +65,7 @@ public class ReasonTag extends XmlSupport { Utils.outWrite(out, Reasons.getReasonPhrase(pageContext.getErrorData().getStatusCode()), defaultValue, escapeXml); } - } catch (IOException ignore) { + } catch (IOException ignored) { // Ignore. } } diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java index 672d4c4..31b9abb 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java @@ -1,7 +1,7 @@ /* * XmlSupport.java * - * Copyright (c) 2015-2022, Erik C. Thauvin (erik@thauvin.net) + * Copyright 2023 sErik C. Thauvin (erik@thauvin.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/main/resources/META-INF/httpstatus.tld b/src/main/resources/META-INF/httpstatus.tld index 2f3d7c1..d7ea066 100644 --- a/src/main/resources/META-INF/httpstatus.tld +++ b/src/main/resources/META-INF/httpstatus.tld @@ -2,7 +2,7 @@