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()");
+ }
+}