Added <hs:cause/> and <hs:code/> tags and associated parameters.

This commit is contained in:
Erik C. Thauvin 2015-12-03 18:55:47 -08:00
parent 92a6bb21de
commit da35797ffb
9 changed files with 485 additions and 40 deletions

View file

@ -10,9 +10,10 @@ For example:
<%@ page isErrorPage="true" %>
<%@ taglib prefix="hs" uri="http://erik.thauvin.net/taglibs/httpstatus" %>
<html><head>
<title>${pageContext.errorData.statusCode} <hs:reason default="Server Error"/></title>
<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>
...
```
@ -29,12 +30,37 @@ would display on a [501 status code](http://www.w3.org/Protocols/rfc2616/rfc2616
----
The **<hs:reason>** 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 `<hs:cause/>` 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 &lt;,&gt;,&amp;,'," to their corresponding [entity codes](http://dev.w3.org/html5/html-author/charref). Value is true by default.
## hs:code
The `<hs:code/>` tag displays the current HTTP status code, if any. A shorthand for:
```jsp
<%= pageContext.getErrorData().getStatusCode() %>
```
## hs:reason
The `<hs:reason/>` 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 &lt;,&gt;,&amp;,'," 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:

View file

@ -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 <code>Utils</code> class.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @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("&lt;");
break;
case '>':
escaped.append("&gt;");
break;
case '&':
escaped.append("&amp;");
break;
case '\'':
escaped.append("&#039;");
break;
case '"':
escaped.append("&#034;");
break;
default:
escaped.append(c);
break;
}
}
return escaped.toString();
}
}

View file

@ -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 <code>CauseTag</code> class.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @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);
}
}

View file

@ -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 <code>CodeTag</code> class.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @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()));
}
}

View file

@ -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;
}
}

View file

@ -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 <code>XmlSupport</code> class.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @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 <code>true</code> or <code>false</code>
*/
@SuppressWarnings("unused")
public void setEscapeXml(boolean escapeXml)
{
this.escapeXml = escapeXml;
}
}

View file

@ -43,6 +43,40 @@
<short-name>hs</short-name>
<uri>http://erik.thauvin.net/taglibs/httpstatus</uri>
<tag>
<description>
Returns the cause (if any) for the current HTTP Status Error Code.
</description>
<name>cause</name>
<tag-class>net.thauvin.erik.httpstatus.taglibs.CauseTag</tag-class>
<body-content>empty</body-content>
<attribute>
<description>
Default value if the resulting cause is null.
</description>
<name>default</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<description>
Converts &lt;,&gt;,&amp;,'," to their corresponding entity codes. Value is true by default.
</description>
<name>escapeXml</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<description>
Outputs the HTTP Status Error Code.
</description>
<name>code</name>
<tag-class>net.thauvin.erik.httpstatus.taglibs.CodeTag</tag-class>
<body-content>empty</body-content>
</tag>
<tag>
<description>
Returns the Reason Phrase for the current (or specified) HTTP Status Error Code.
@ -62,7 +96,15 @@
<description>
HTTP Status Error Code to be looked up.
</description>
<name>statusCode</name>
<name>code</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<description>
Converts &lt;,&gt;,&amp;,'," to their corresponding entity codes. Value is true by default.
</description>
<name>escapeXml</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>

View file

@ -46,6 +46,7 @@ import java.util.ResourceBundle;
* @created 2015-12-03
* @since 1.0
*/
@SuppressWarnings("unused")
public class ReasonsTest
{
@DataProvider(name = "reasons")

View file

@ -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 <code>UtilsTest</code> class.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @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&#039;t to make sure that everything is &lt;encoded&gt; according the &#034;encoding&#034; parameter &amp; value.",
Utils.escapeXml(
"This is a test. We wan't to make sure that everything is <encoded> according the \"encoding\" parameter & value."));
}
}