diff --git a/README.md b/README.md index 431048b..7e6d876 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,10 @@ For example: <%@ page isErrorPage="true" %> <%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %> -${pageContext.errorData.statusCode} <hs:reason default="Server Error"/> +<hs:code/> <hs:reason default="Server Error"/>

+Cause:
... ``` @@ -29,12 +30,37 @@ would display on a [501 status code](http://www.w3.org/Protocols/rfc2616/rfc2616 ---- -The **** tag attributes are: +## hs:cause -Attribute | Description | Required ------------- | ----------------------------------------------------------------------------- | -------- -`statusCode` | The HTTP status error code. If not specified the current status code is used. | No -`default` | The fallback value to output. | No +The `` tag displays the cause of current HTTP status code, if any. A shorthand for: + +```jsp +<%= pageContext.getErrorData().getThrowable().getCause().getLocalizedMessage() %> +``` + +Optional attributes are: + +Attribute | Description +----------- | ------------------------------------------------------------------------------------------- +`default` | The fallback value to output, if no cause is available. +`escapeXml` | Converts <,>,&,'," to their corresponding [entity codes](http://dev.w3.org/html5/html-author/charref). Value is true by default. + +## hs:code +The `` tag displays the current HTTP status code, if any. A shorthand for: + +```jsp +<%= pageContext.getErrorData().getStatusCode() %> +``` + +## hs:reason + +The `` tag displays the reason for a HTTP status code, if any. Optional attributes are: + +Attribute | Description +----------- | ------------------------------------------------------------------------------------------- +`code` | The HTTP status error code. If not specified the current status code is used. +`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. The reasons are defined in a [ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html) properties as follows: diff --git a/src/main/java/net/thauvin/erik/httpstatus/Utils.java b/src/main/java/net/thauvin/erik/httpstatus/Utils.java new file mode 100644 index 0000000..910e2c9 --- /dev/null +++ b/src/main/java/net/thauvin/erik/httpstatus/Utils.java @@ -0,0 +1,134 @@ +/* + * Utils.java + * + * Copyright (c) 2015, 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 the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.httpstatus; + +import java.io.IOException; +import java.io.Writer; + +/** + * The Utils class. + * + * @author Erik C. Thauvin + * @created 2015-12-03 + * @since 1.0 + */ +public class Utils +{ + + /** + * Disables the default constructor. + * + * @throws UnsupportedOperationException if an error occurred. if the constructor is called. + */ + private Utils() + throws UnsupportedOperationException + { + throw new UnsupportedOperationException("Illegal constructor call."); + } + + /** + * Writes a string value. + * + * @param out The writer to output the value to. + * @param value The string value. + * @param defaultValue The default value. + * @param xml The xml flag. + */ + public static void outWrite(Writer out, String value, String defaultValue, boolean xml) + throws IOException + { + if (xml) + { + if (value != null) + { + out.write(escapeXml(value)); + } + else if (defaultValue != null) + { + out.write(escapeXml(defaultValue)); + } + } + else + { + if (value != null) + { + out.write(value); + } + else if (defaultValue != null) + { + out.write(defaultValue); + } + } + } + + /** + * Escapes a string value. + * + * @param value The string value to escape. + * + * @return The escaped string value. + */ + public static String escapeXml(String value) + { + final StringBuilder escaped = new StringBuilder(); + + 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; + } + } + + return escaped.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java new file mode 100644 index 0000000..d9f9be6 --- /dev/null +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CauseTag.java @@ -0,0 +1,72 @@ +/* + * CauseTag.java + * + * Copyright (c) 2015, 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 the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.httpstatus.taglibs; + +import net.thauvin.erik.httpstatus.Utils; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspWriter; +import javax.servlet.jsp.PageContext; +import java.io.IOException; + +/** + * The CauseTag class. + * + * @author Erik C. Thauvin + * @created 2015-12-03 + * @since 1.0 + */ +public class CauseTag extends XmlSupport +{ + @Override + public void doTag() + throws JspException, IOException + { + final PageContext pageContext = (PageContext) getJspContext(); + final JspWriter out = pageContext.getOut(); + + String cause; + + try + { + cause = pageContext.getErrorData().getThrowable().getCause().getLocalizedMessage(); + } + catch (NullPointerException ignore) + { + cause = defaultValue; + } + + Utils.outWrite(out, cause, defaultValue, escapeXml); + } +} \ No newline at end of file diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java new file mode 100644 index 0000000..c2f1517 --- /dev/null +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/CodeTag.java @@ -0,0 +1,60 @@ +/* + * CodeTag.java + * + * Copyright (c) 2015, 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 the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.httpstatus.taglibs; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspWriter; +import javax.servlet.jsp.PageContext; +import javax.servlet.jsp.tagext.SimpleTagSupport; +import java.io.IOException; + +/** + * The CodeTag class. + * + * @author Erik C. Thauvin + * @created 2015-12-03 + * @since 1.0 + */ +public class CodeTag extends SimpleTagSupport +{ + @Override + public void doTag() + throws JspException, IOException + { + final PageContext pageContext = (PageContext) getJspContext(); + final JspWriter out = pageContext.getOut(); + + out.write(String.valueOf(pageContext.getErrorData().getStatusCode())); + } +} \ No newline at end of file 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 ac81538..b77f2a2 100644 --- a/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/ReasonTag.java @@ -34,11 +34,11 @@ package net.thauvin.erik.httpstatus.taglibs; import net.thauvin.erik.httpstatus.Reasons; +import net.thauvin.erik.httpstatus.Utils; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; -import javax.servlet.jsp.tagext.SimpleTagSupport; import java.io.IOException; /** @@ -48,41 +48,29 @@ import java.io.IOException; * @created 2015-12-02 * @since 1.0 */ -public class ReasonTag extends SimpleTagSupport +public class ReasonTag extends XmlSupport { private int statusCode; - private String defaultValue; @Override public void doTag() - throws JspException + throws JspException, IOException { final PageContext pageContext = (PageContext) getJspContext(); final JspWriter out = pageContext.getOut(); try { - try + if (statusCode > 0) { - if (statusCode > 0) - { - out.write(Reasons.getReasonPhrase(statusCode)); - } - else - { - out.write(Reasons.getReasonPhrase(pageContext.getErrorData().getStatusCode())); - } + Utils.outWrite(out, Reasons.getReasonPhrase(statusCode), defaultValue, escapeXml); } - catch(NullPointerException npe) + else { - if (defaultValue != null) - { - out.write(defaultValue); - } - else - { - out.write(""); - } + Utils.outWrite(out, + Reasons.getReasonPhrase(pageContext.getErrorData().getStatusCode()), + defaultValue, + escapeXml); } } catch (IOException ignore) @@ -96,19 +84,11 @@ public class ReasonTag extends SimpleTagSupport * * @param statusCode The status code. */ - public void setStatusCode(int statusCode) + @SuppressWarnings("unused") + public void setCode(int statusCode) { this.statusCode = statusCode; } - /** - * Set the default value. - * - * @param defaultValue The default value. - */ - public void setDefault(String defaultValue) - { - this.defaultValue = defaultValue; - } -} \ No newline at end of file +} diff --git a/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java b/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java new file mode 100644 index 0000000..d466137 --- /dev/null +++ b/src/main/java/net/thauvin/erik/httpstatus/taglibs/XmlSupport.java @@ -0,0 +1,72 @@ +/* + * XmlSupport.java + * + * Copyright (c) 2015, 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 the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.httpstatus.taglibs; + +import javax.servlet.jsp.tagext.SimpleTagSupport; + +/** + * The XmlSupport class. + * + * @author Erik C. Thauvin + * @created 2015-12-03 + * @since 1.0 + */ +public abstract class XmlSupport extends SimpleTagSupport +{ + protected String defaultValue; + + protected boolean escapeXml = true; + + /** + * Sets the default value. + * + * @param defaultValue The default value. + */ + @SuppressWarnings("unused") + public void setDefault(String defaultValue) + { + this.defaultValue = defaultValue; + } + + /** + * Sets the escapeXMl flag. + * + * @param escapeXml true or false + */ + @SuppressWarnings("unused") + public void setEscapeXml(boolean escapeXml) + { + this.escapeXml = escapeXml; + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/httpstatus.tld b/src/main/resources/META-INF/httpstatus.tld index 15801fb..2c42b1f 100644 --- a/src/main/resources/META-INF/httpstatus.tld +++ b/src/main/resources/META-INF/httpstatus.tld @@ -43,6 +43,40 @@ hs http://erik.thauvin.net/taglibs/httpstatus + + + Returns the cause (if any) for the current HTTP Status Error Code. + + cause + net.thauvin.erik.httpstatus.taglibs.CauseTag + empty + + + Default value if the resulting cause is null. + + default + false + true + + + + Converts <,>,&,'," to their corresponding entity codes. Value is true by default. + + escapeXml + false + true + + + + + + Outputs the HTTP Status Error Code. + + code + net.thauvin.erik.httpstatus.taglibs.CodeTag + empty + + Returns the Reason Phrase for the current (or specified) HTTP Status Error Code. @@ -62,7 +96,15 @@ HTTP Status Error Code to be looked up. - statusCode + code + false + true + + + + Converts <,>,&,'," to their corresponding entity codes. Value is true by default. + + escapeXml false true diff --git a/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java b/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java index ab43c50..fa05d71 100644 --- a/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java +++ b/src/test/java/net/thauvin/erik/httpstatus/ReasonsTest.java @@ -46,6 +46,7 @@ import java.util.ResourceBundle; * @created 2015-12-03 * @since 1.0 */ +@SuppressWarnings("unused") public class ReasonsTest { @DataProvider(name = "reasons") diff --git a/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java new file mode 100644 index 0000000..735e693 --- /dev/null +++ b/src/test/java/net/thauvin/erik/httpstatus/UtilsTest.java @@ -0,0 +1,58 @@ +/* + * UtilsTest.java + * + * Copyright (c) 2015, 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 the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.httpstatus; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * The UtilsTest class. + * + * @author Erik C. Thauvin + * @created 2015-12-03 + * @since 1.0 + */ +@SuppressWarnings("unused") +public class UtilsTest +{ + @Test + public void testEscapeXml() + throws Exception + { + Assert.assertEquals( + "This is a test. We wan't to make sure that everything is <encoded> according the "encoding" parameter & value.", + Utils.escapeXml( + "This is a test. We wan't to make sure that everything is according the \"encoding\" parameter & value.")); + } +} \ No newline at end of file