You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mm...@apache.org on 2007/07/24 07:05:34 UTC
svn commit: r558932 - in /myfaces/core/branches/1_2_1/api/src/main:
java/javax/faces/webapp/FacesServlet.java
java/javax/faces/webapp/_ErrorPageWriter.java resources/rsc/
resources/rsc/facelet-dev-debug.xml resources/rsc/facelet-dev-error.xml
Author: mmarinschek
Date: Mon Jul 23 22:05:33 2007
New Revision: 558932
URL: http://svn.apache.org/viewvc?view=rev&rev=558932
Log:
commit for https://issues.apache.org/jira/browse/MYFACES-1685: Enabled exception handling like in Facelets for the rest of the MyFaces LifeCycle
Added:
myfaces/core/branches/1_2_1/api/src/main/java/javax/faces/webapp/_ErrorPageWriter.java
myfaces/core/branches/1_2_1/api/src/main/resources/rsc/
myfaces/core/branches/1_2_1/api/src/main/resources/rsc/facelet-dev-debug.xml
myfaces/core/branches/1_2_1/api/src/main/resources/rsc/facelet-dev-error.xml
Modified:
myfaces/core/branches/1_2_1/api/src/main/java/javax/faces/webapp/FacesServlet.java
Modified: myfaces/core/branches/1_2_1/api/src/main/java/javax/faces/webapp/FacesServlet.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/1_2_1/api/src/main/java/javax/faces/webapp/FacesServlet.java?view=diff&rev=558932&r1=558931&r2=558932
==============================================================================
--- myfaces/core/branches/1_2_1/api/src/main/java/javax/faces/webapp/FacesServlet.java (original)
+++ myfaces/core/branches/1_2_1/api/src/main/java/javax/faces/webapp/FacesServlet.java Mon Jul 23 22:05:33 2007
@@ -16,6 +16,8 @@
package javax.faces.webapp;
import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
import javax.faces.FactoryFinder;
import javax.faces.context.FacesContext;
@@ -47,6 +49,9 @@
public static final String LIFECYCLE_ID_ATTR = "javax.faces.LIFECYCLE_ID";
private static final String SERVLET_INFO = "FacesServlet of the MyFaces API implementation";
+ private static final String ERROR_HANDLING_PARAMETER = "org.apache.myfaces.ERROR_HANDLING";
+ private static final String ERROR_HANDLER_PARAMETER = "org.apache.myfaces.ERROR_HANDLER";
+
private ServletConfig _servletConfig;
private FacesContextFactory _facesContextFactory;
private Lifecycle _lifecycle;
@@ -111,17 +116,16 @@
{
StringBuffer buffer = new StringBuffer();
- buffer.append(" Someone is trying to access a secure resource : "
- + pathInfo);
- buffer.append("\n remote address is " + httpRequest.getRemoteAddr());
- buffer.append("\n remote host is " + httpRequest.getRemoteHost());
- buffer.append("\n remote user is " + httpRequest.getRemoteUser());
- buffer.append("\n request URI is " + httpRequest.getRequestURI());
+ buffer.append(" Someone is trying to access a secure resource : ").append(pathInfo);
+ buffer.append("\n remote address is ").append(httpRequest.getRemoteAddr());
+ buffer.append("\n remote host is ").append(httpRequest.getRemoteHost());
+ buffer.append("\n remote user is ").append(httpRequest.getRemoteUser());
+ buffer.append("\n request URI is ").append(httpRequest.getRequestURI());
log.warn(buffer.toString());
// Why does RI return a 404 and not a 403, SC_FORBIDDEN ?
-
+
((HttpServletResponse) response)
.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
@@ -137,29 +141,54 @@
_lifecycle.execute(facesContext);
_lifecycle.render(facesContext);
}
- catch (Throwable e)
+ catch (Exception e)
{
- if (e instanceof IOException)
- {
- throw (IOException)e;
- }
- else if (e instanceof ServletException)
- {
- throw (ServletException)e;
- }
- else if (e.getMessage() != null)
- {
- throw new ServletException(e.getMessage(), e);
- }
- else
- {
- throw new ServletException(e);
- }
+ handleLifecycleException(facesContext, e);
}
finally
{
facesContext.release();
}
if(log.isTraceEnabled()) log.trace("service end");
+ }
+
+ private void handleLifecycleException(FacesContext facesContext, Exception e) throws IOException, ServletException {
+
+ boolean errorHandling = getBooleanValue(facesContext.getExternalContext().getInitParameter(ERROR_HANDLING_PARAMETER), true);
+
+ if(errorHandling) {
+ String errorHandlerClass = facesContext.getExternalContext().getInitParameter(ERROR_HANDLER_PARAMETER);
+ if(errorHandlerClass != null) {
+ try {
+ Class clazz = Class.forName(errorHandlerClass);
+
+ Object errorHandler = clazz.newInstance();
+
+ Method m = clazz.getMethod("handleException", new Class[]{FacesContext.class,Exception.class});
+ m.invoke(errorHandler, new Object[]{facesContext, e});
+ }
+ catch(ClassNotFoundException ex) {
+ throw new ServletException("Error-Handler : " +errorHandlerClass+ " was not found. Fix your web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
+ } catch (IllegalAccessException ex) {
+ throw new ServletException("Constructor of error-Handler : " +errorHandlerClass+ " is not accessible. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
+ } catch (InstantiationException ex) {
+ throw new ServletException("Error-Handler : " +errorHandlerClass+ " could not be instantiated. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
+ } catch (NoSuchMethodException ex) {
+ throw new ServletException("Error-Handler : " +errorHandlerClass+ " did not have a method with name : handleException and parameters : javax.faces.context.FacesContext, java.lang.Exception. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
+ } catch (InvocationTargetException ex) {
+ throw new ServletException("Excecution of method handleException in Error-Handler : " +errorHandlerClass+ " caused an exception. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
+ }
+ }
+ else {
+ _ErrorPageWriter.handleException(facesContext, e);
+ }
+ }
+ else {
+ _ErrorPageWriter.throwException(e);
+ }
+ }
+
+ private boolean getBooleanValue(String initParameter, boolean defaultVal) {
+ return initParameter != null && (initParameter.equalsIgnoreCase("on") || initParameter.equals("1") || initParameter.equalsIgnoreCase("true")) || defaultVal;
}
}
Added: myfaces/core/branches/1_2_1/api/src/main/java/javax/faces/webapp/_ErrorPageWriter.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/1_2_1/api/src/main/java/javax/faces/webapp/_ErrorPageWriter.java?view=auto&rev=558932
==============================================================================
--- myfaces/core/branches/1_2_1/api/src/main/java/javax/faces/webapp/_ErrorPageWriter.java (added)
+++ myfaces/core/branches/1_2_1/api/src/main/java/javax/faces/webapp/_ErrorPageWriter.java Mon Jul 23 22:05:33 2007
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package javax.faces.webapp;
+
+import javax.faces.context.FacesContext;
+import java.io.Writer;
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.text.DateFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.el.Expression;
+import javax.el.ValueExpression;
+import javax.el.MethodExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.context.ExternalContext;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletException;
+
+/**
+ * @author Jacob Hookom (ICLA with ASF filed).
+ */
+public final class _ErrorPageWriter {
+
+ private final static String TS = "<";
+
+ private static final String ERROR_TEMPLATE = "META-INF/rsc/facelet-dev-error.xml";
+
+ private static String[] ERROR_PARTS;
+
+ private static final String DEBUG_TEMPLATE = "META-INF/rsc/facelet-dev-debug.xml";
+
+ private static String[] DEBUG_PARTS;
+
+ public _ErrorPageWriter() {
+ super();
+ }
+
+ public static void main(String[] argv) throws Exception {
+ init();
+ }
+
+ private static void init() throws IOException {
+ if (ERROR_PARTS == null) {
+ ERROR_PARTS = splitTemplate(ERROR_TEMPLATE);
+ }
+
+ if (DEBUG_PARTS == null) {
+ DEBUG_PARTS = splitTemplate(DEBUG_TEMPLATE);
+ }
+ }
+
+ private static String[] splitTemplate(String rsc) throws IOException {
+ InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(rsc);
+ if (is == null) {
+ throw new FileNotFoundException(rsc);
+ }
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buff = new byte[512];
+ int read;
+ while ((read = is.read(buff)) != -1) {
+ baos.write(buff, 0, read);
+ }
+ String str = baos.toString();
+ return str.split("@@");
+ }
+
+ public static void debugHtml(Writer writer, FacesContext faces, Exception e) throws IOException {
+ init();
+ Date now = new Date();
+ for (int i = 0; i < ERROR_PARTS.length; i++) {
+ if ("message".equals(ERROR_PARTS[i])) {
+ String msg = e.getMessage();
+ if (msg != null) {
+ writer.write(msg.replaceAll("<", TS));
+ } else {
+ writer.write(e.getClass().getName());
+ }
+ } else if ("trace".equals(ERROR_PARTS[i])) {
+ writeException(writer, e);
+ } else if ("now".equals(ERROR_PARTS[i])) {
+ writer.write(DateFormat.getDateTimeInstance().format(now));
+ } else if ("tree".equals(ERROR_PARTS[i])) {
+ writeComponent(writer, faces.getViewRoot());
+ } else if ("vars".equals(ERROR_PARTS[i])) {
+ writeVariables(writer, faces);
+ } else {
+ writer.write(ERROR_PARTS[i]);
+ }
+ }
+ }
+
+ private static void writeException(Writer writer, Exception e) throws IOException {
+ StringWriter str = new StringWriter(256);
+ PrintWriter pstr = new PrintWriter(str);
+ e.printStackTrace(pstr);
+ pstr.close();
+ writer.write(str.toString().replaceAll("<", TS));
+ }
+
+ public static void debugHtml(Writer writer, FacesContext faces) throws IOException {
+ init();
+ Date now = new Date();
+ for (int i = 0; i < DEBUG_PARTS.length; i++) {
+ if ("message".equals(DEBUG_PARTS[i])) {
+ writer.write(faces.getViewRoot().getViewId());
+ } else if ("now".equals(DEBUG_PARTS[i])) {
+ writer.write(DateFormat.getDateTimeInstance().format(now));
+ } else if ("tree".equals(DEBUG_PARTS[i])) {
+ writeComponent(writer, faces.getViewRoot());
+ } else if ("vars".equals(DEBUG_PARTS[i])) {
+ writeVariables(writer, faces);
+ } else {
+ writer.write(DEBUG_PARTS[i]);
+ }
+ }
+ }
+
+ private static void writeVariables(Writer writer, FacesContext faces) throws IOException {
+ ExternalContext ctx = faces.getExternalContext();
+ writeVariables(writer, ctx.getRequestParameterMap(), "Request Parameters");
+ writeVariables(writer, ctx.getRequestMap(), "Request Attributes");
+ if (ctx.getSession(false) != null) {
+ writeVariables(writer, ctx.getSessionMap(), "Session Attributes");
+ }
+ writeVariables(writer, ctx.getApplicationMap(), "Application Attributes");
+ }
+
+ private static void writeVariables(Writer writer, Map vars, String caption) throws IOException {
+ writer.write("<table><caption>");
+ writer.write(caption);
+ writer.write("</caption><thead><tr><th style=\"width: 10%; \">Name</th><th style=\"width: 90%; \">Value</th></tr></thead><tbody>");
+ boolean written = false;
+ if (!vars.isEmpty()) {
+ SortedMap map = new TreeMap(vars);
+ Map.Entry entry = null;
+ String key = null;
+ for (Iterator itr = map.entrySet().iterator(); itr.hasNext(); ) {
+ entry = (Map.Entry) itr.next();
+ key = entry.getKey().toString();
+ if (key.indexOf('.') == -1) {
+ writer.write("<tr><td>");
+ writer.write(key.replaceAll("<", TS));
+ writer.write("</td><td>");
+ writer.write(entry.getValue().toString().replaceAll("<", TS));
+ writer.write("</td></tr>");
+ written = true;
+ }
+ }
+ }
+ if (!written) {
+ writer.write("<tr><td colspan=\"2\"><em>None</em></td></tr>");
+ }
+ writer.write("</tbody></table>");
+ }
+
+ private static void writeComponent(Writer writer, UIComponent c) throws IOException {
+ writer.write("<dl><dt");
+ if (isText(c)) {
+ writer.write(" class=\"uicText\"");
+ }
+ writer.write(">");
+
+ boolean hasChildren = c.getChildCount() > 0 || c.getFacets().size() > 0;
+
+ writeStart(writer, c, hasChildren);
+ writer.write("</dt>");
+ if (hasChildren) {
+ if (c.getFacets().size() > 0) {
+ Map.Entry entry;
+ for (Iterator itr = c.getFacets().entrySet().iterator(); itr.hasNext(); ) {
+ entry = (Map.Entry) itr.next();
+ writer.write("<dd class=\"uicFacet\">");
+ writer.write("<span>");
+ writer.write((String) entry.getKey());
+ writer.write("</span>");
+ writeComponent(writer, (UIComponent) entry.getValue());
+ writer.write("</dd>");
+ }
+ }
+ if (c.getChildCount() > 0) {
+ for (Iterator itr = c.getChildren().iterator(); itr.hasNext(); ) {
+ writer.write("<dd>");
+ writeComponent(writer, (UIComponent) itr.next());
+ writer.write("</dd>");
+ }
+ }
+ writer.write("<dt>");
+ writeEnd(writer, c);
+ writer.write("</dt>");
+ }
+ writer.write("</dl>");
+ }
+
+ private static void writeEnd(Writer writer, UIComponent c) throws IOException {
+ if (!isText(c)) {
+ writer.write(TS);
+ writer.write('/');
+ writer.write(getName(c));
+ writer.write('>');
+ }
+ }
+
+ private final static String[] IGNORE = new String[] { "parent", "rendererType" };
+
+ private static void writeAttributes(Writer writer, UIComponent c) {
+ try {
+ BeanInfo info = Introspector.getBeanInfo(c.getClass());
+ PropertyDescriptor[] pd = info.getPropertyDescriptors();
+ Method m = null;
+ Object v = null;
+ String str = null;
+ for (int i = 0; i < pd.length; i++) {
+ if (pd[i].getWriteMethod() != null && Arrays.binarySearch(IGNORE, pd[i].getName()) < 0) {
+ m = pd[i].getReadMethod();
+ try {
+ v = m.invoke(c, null);
+ if (v != null) {
+ if (v instanceof Collection || v instanceof Map || v instanceof Iterator) {
+ continue;
+ }
+ writer.write(" ");
+ writer.write(pd[i].getName());
+ writer.write("=\"");
+ if (v instanceof Expression) {
+ str = ((Expression) v).getExpressionString();
+ }
+ else if(v instanceof MethodExpression) {
+ str = ((Expression) v).getExpressionString();
+ }
+ else {
+ ValueExpression ve = c.getValueExpression(pd[i].getName());
+ str = ve!=null?(ve.getExpressionString()+"="+v.toString()):v.toString();
+ }
+ writer.write(str.replaceAll("<", TS));
+ writer.write("\"");
+ }
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }
+
+ ValueExpression binding = c.getValueExpression("binding");
+ if (binding != null) {
+ writer.write(" binding=\"");
+ writer.write(binding.getExpressionString().replaceAll("<", TS));
+ writer.write("\"");
+ }
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+
+ private static void writeStart(Writer writer, UIComponent c, boolean children) throws IOException {
+ if (isText(c)) {
+ String str = c.toString().trim();
+ writer.write(str.replaceAll("<", TS));
+ } else {
+ writer.write(TS);
+ writer.write(getName(c));
+ writeAttributes(writer, c);
+ if (children) {
+ writer.write('>');
+ } else {
+ writer.write("/>");
+ }
+ }
+ }
+
+ private static String getName(UIComponent c) {
+ String nm = c.getClass().getName();
+ return nm.substring(nm.lastIndexOf('.') + 1);
+ }
+
+ private static boolean isText(UIComponent c) {
+ return (c.getClass().getName().startsWith("com.sun.facelets.compiler"));
+ }
+
+ public static void handleException(FacesContext facesContext, Exception ex) throws ServletException, IOException {
+
+ prepareExceptionStack(ex);
+
+ Object response = facesContext.getExternalContext().getResponse();
+ if(response instanceof HttpServletResponse) {
+ HttpServletResponse httpResp = (HttpServletResponse) response;
+ if (!httpResp.isCommitted()) {
+ httpResp.reset();
+ httpResp.setContentType("text/html; charset=UTF-8");
+ Writer writer = httpResp.getWriter();
+
+ debugHtml(writer, facesContext, ex);
+ }
+ }
+ else {
+ throwException(ex);
+ }
+ }
+
+ private static void prepareExceptionStack(Throwable ex) {
+
+ if(ex==null)
+ return;
+
+ if(ex instanceof ServletException) {
+ try
+ {
+ Throwable rootCause = ((ServletException) ex).getRootCause();
+
+ if(rootCause != null) {
+ Method m = ServletException.class.getMethod("initCause",new Class[]{Throwable.class});
+ m.invoke(ex,new Object[]{rootCause});
+ }
+ } catch (Exception e1) {
+ //ignore if the method is not found - or cause has already been set.
+ }
+ }
+
+ prepareExceptionStack(ex.getCause());
+ }
+
+ static void throwException(Exception e) throws IOException, ServletException {
+ if (e instanceof IOException)
+ {
+ throw (IOException)e;
+ }
+ else if (e instanceof ServletException)
+ {
+ throw (ServletException)e;
+ }
+ else
+ {
+ ServletException ex;
+
+ if (e.getMessage() != null) {
+ ex=new ServletException(e.getMessage(), e);
+ }
+ else {
+ ex=new ServletException(e);
+ }
+
+ try {
+ Method m = ServletException.class.getMethod("initCause",new Class[]{Throwable.class});
+ m.invoke(ex,new Object[]{e});
+ } catch (Exception e1) {
+ //ignore if the method is not found - or cause has already been set.
+ }
+
+ throw ex;
+ }
+ }
+}
Added: myfaces/core/branches/1_2_1/api/src/main/resources/rsc/facelet-dev-debug.xml
URL: http://svn.apache.org/viewvc/myfaces/core/branches/1_2_1/api/src/main/resources/rsc/facelet-dev-debug.xml?view=auto&rev=558932
==============================================================================
--- myfaces/core/branches/1_2_1/api/src/main/resources/rsc/facelet-dev-debug.xml (added)
+++ myfaces/core/branches/1_2_1/api/src/main/resources/rsc/facelet-dev-debug.xml Mon Jul 23 22:05:33 2007
@@ -0,0 +1,53 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Debug - @@message@@</title>
+<style type="text/css">
+body, div, span, td, th, caption { font-family: 'Trebuchet MS', Verdana, Arial, Sans-Serif; font-size: small; }
+ul, li, pre { padding: 0; margin: 0; }
+h1 { color: #090; }
+h2, h2 span { font-size: large; color: #339; }
+h2 a { text-decoration: none; color: #339; }
+.grayBox { padding: 8px; margin: 10px 0; border: 1px solid #CCC; background-color: #f9f9f9; }
+#view { color: #090; font-weight: bold; font-size: medium; }
+#tree, #vars { display: none; }
+code { font-size: medium; }
+#tree dl { color: #006; }
+#tree dd { margin-top: 2px; margin-bottom: 2px; }
+#tree dt { border: 1px solid #DDD; padding: 4px; border-left: 2px solid #666; font-family: "Courier New", Courier, mono; font-size: small; }
+.uicText { color: #999; }
+table { border: 1px solid #CCC; border-collapse: collapse; border-spacing: 0px; width: 100%; text-align: left; }
+td { border: 1px solid #CCC; }
+thead tr th { padding: 2px; color: #030; background-color: #F9F9F9; }
+tbody tr td { padding: 10px 6px; }
+table caption { text-align: left; padding: 10px 0; font-size: large; }
+</style>
+<style type="text/css" media="print">
+#trace, #tree, #vars { display: block; }
+</style>
+<script language="javascript" type="text/javascript">
+function toggle(id) {
+ var style = document.getElementById(id).style;
+ if ("block" == style.display) {
+ style.display = "none";
+ document.getElementById(id+"Off").style.display = "inline";
+ document.getElementById(id+"On").style.display = "none";
+ } else {
+ style.display = "block";
+ document.getElementById(id+"Off").style.display = "none";
+ document.getElementById(id+"On").style.display = "inline";
+ }
+}
+</script>
+</head>
+<body>
+<h1>Debug Output</h1>
+<div id="error" class="grayBox" style="border: 1px solid #090;">@@message@@</div>
+<h2><a href="#" onclick="toggle('tree'); return false;"><span id="treeOff">+</span><span id="treeOn" style="display: none;">-</span> Component Tree</a></h2>
+<div id="tree" class="grayBox"><code>@@tree@@</code></div>
+<h2><a href="#" onclick="toggle('vars'); return false;"><span id="varsOff">+</span><span id="varsOn" style="display: none;">-</span> Scoped Variables</a></h2>
+<div id="vars">@@vars@@</div>
+<div class="grayBox" style="text-align: right; color: #666;">@@now@@ - Generated by Facelets</div>
+</body>
+</html>
Added: myfaces/core/branches/1_2_1/api/src/main/resources/rsc/facelet-dev-error.xml
URL: http://svn.apache.org/viewvc/myfaces/core/branches/1_2_1/api/src/main/resources/rsc/facelet-dev-error.xml?view=auto&rev=558932
==============================================================================
--- myfaces/core/branches/1_2_1/api/src/main/resources/rsc/facelet-dev-error.xml (added)
+++ myfaces/core/branches/1_2_1/api/src/main/resources/rsc/facelet-dev-error.xml Mon Jul 23 22:05:33 2007
@@ -0,0 +1,55 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Error - @@message@@</title>
+<style type="text/css">
+body, div, span, td, th, caption { font-family: 'Trebuchet MS', Verdana, Arial, Sans-Serif; font-size: small; }
+ul, li, pre { padding: 0; margin: 0; }
+h1 { color: #900; }
+h2, h2 span { font-size: large; color: #339; }
+h2 a { text-decoration: none; color: #339; }
+.grayBox { padding: 8px; margin: 10px 0; border: 1px solid #CCC; background-color: #f9f9f9; }
+#error { color: #900; font-weight: bold; font-size: medium; }
+#trace, #tree, #vars { display: none; }
+code { font-size: medium; }
+#tree dl { color: #006; }
+#tree dd { margin-top: 2px; margin-bottom: 2px; }
+#tree dt { border: 1px solid #DDD; padding: 4px; border-left: 2px solid #666; font-family: "Courier New", Courier, mono; font-size: small; }
+.uicText { color: #999; }
+table { border: 1px solid #CCC; border-collapse: collapse; border-spacing: 0px; width: 100%; text-align: left; }
+td { border: 1px solid #CCC; }
+thead tr th { padding: 2px; color: #030; background-color: #F9F9F9; }
+tbody tr td { padding: 10px 6px; }
+table caption { text-align: left; padding: 10px 0; font-size: large; }
+</style>
+<style type="text/css" media="print">
+#trace, #tree, #vars { display: block; }
+</style>
+<script language="javascript" type="text/javascript">
+function toggle(id) {
+ var style = document.getElementById(id).style;
+ if ("block" == style.display) {
+ style.display = "none";
+ document.getElementById(id+"Off").style.display = "inline";
+ document.getElementById(id+"On").style.display = "none";
+ } else {
+ style.display = "block";
+ document.getElementById(id+"Off").style.display = "none";
+ document.getElementById(id+"On").style.display = "inline";
+ }
+}
+</script>
+</head>
+<body>
+<h1>An Error Occurred:</h1>
+<div id="error" class="grayBox" style="border: 1px solid #900;">@@message@@</div>
+<h2><a href="#" onclick="toggle('trace'); return false;"><span id="traceOff">+</span><span id="traceOn" style="display: none;">-</span> Stack Trace</a></h2>
+<div id="trace" class="grayBox"><pre><code>@@trace@@</code></pre></div>
+<h2><a href="#" onclick="toggle('tree'); return false;"><span id="treeOff">+</span><span id="treeOn" style="display: none;">-</span> Component Tree</a></h2>
+<div id="tree" class="grayBox"><code>@@tree@@</code></div>
+<h2><a href="#" onclick="toggle('vars'); return false;"><span id="varsOff">+</span><span id="varsOn" style="display: none;">-</span> Scoped Variables</a></h2>
+<div id="vars">@@vars@@</div>
+<div class="grayBox" style="text-align: right; color: #666;">@@now@@ - Generated by Facelets</div>
+</body>
+</html>