You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2011/11/30 19:17:57 UTC
svn commit: r1208626 - in /myfaces/core/branches/2.0.x/impl/src:
main/java/org/apache/myfaces/renderkit/
test/java/org/apache/myfaces/renderkit/
Author: lu4242
Date: Wed Nov 30 18:17:57 2011
New Revision: 1208626
URL: http://svn.apache.org/viewvc?rev=1208626&view=rev
Log:
MYFACES-3413 Default MyFaces Error handling throws NullPointerException during component tree when javax.el.Expression.getExpressionString() is null
Added:
myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/ErrorPageWriterTest.java (with props)
myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/NullReturningGetExpressionStringValueExpression.java (with props)
Modified:
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/ErrorPageWriter.java
Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/ErrorPageWriter.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/ErrorPageWriter.java?rev=1208626&r1=1208625&r2=1208626&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/ErrorPageWriter.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/renderkit/ErrorPageWriter.java Wed Nov 30 18:17:57 2011
@@ -81,13 +81,13 @@ import org.apache.myfaces.view.facelets.
/**
* This class provides utility methods to generate the
* MyFaces error and debug pages.
- *
+ *
* @author Jacob Hookom (ICLA with ASF filed)
* @author Jakob Korherr (refactored and moved here from javax.faces.webapp._ErrorPageWriter)
*/
public final class ErrorPageWriter
{
-
+
/**
* This bean aims to generate the error page html for inclusion on a facelet error page via
* <ui:include src="javax.faces.error.xhtml" />. When performing this include the facelet
@@ -99,26 +99,26 @@ public final class ErrorPageWriter
*/
public static class ErrorPageBean implements Serializable
{
-
+
private static final long serialVersionUID = -79513324193326616L;
public String getErrorPageHtml() throws IOException
{
FacesContext facesContext = FacesContext.getCurrentInstance();
Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
-
+
Throwable t = (Throwable) requestMap.get(EXCEPTION_KEY);
if (t == null)
{
throw new IllegalStateException("No Exception to handle");
}
-
+
UIViewRoot view = (UIViewRoot) requestMap.get(VIEW_KEY);
-
+
StringWriter writer = new StringWriter();
ErrorPageWriter.debugHtml(writer, facesContext, view, null, t);
String html = writer.toString();
-
+
// change the HTML in the buffer to be included in an existing html page
String body;
try
@@ -130,7 +130,7 @@ public final class ErrorPageWriter
// no body found - return the entire html
return html;
}
-
+
String head;
try
{
@@ -141,7 +141,7 @@ public final class ErrorPageWriter
// no head found - return entire body
return body;
}
-
+
// extract style and script information from head and add it to body
StringBuilder builder = new StringBuilder(body);
// extract <style>
@@ -176,17 +176,17 @@ public final class ErrorPageWriter
break;
}
}
-
+
return builder.toString();
}
-
+
}
-
+
/**
* The key which is used to store the ErrorPageBean in the view map of a facelet error page.
*/
public static final String ERROR_PAGE_BEAN_KEY = "__myFacesErrorPageBean";
-
+
private static final String EXCEPTION_KEY = "javax.servlet.error.exception";
public static final String VIEW_KEY = "org.apache.myfaces.error.UIViewRoot";
@@ -199,14 +199,14 @@ public final class ErrorPageWriter
/**
* Indicate the template name used to render the default error page used by MyFaces specific
* error handler implementation.
- *
+ *
* <p>See org.apache.myfaces.ERROR_HANDLING for details about
* how to enable/disable it.</p>
*/
@JSFWebConfigParam(defaultValue="META-INF/rsc/myfaces-dev-error.xml", since="1.2.4")
private static final String ERROR_TEMPLATE_RESOURCE = "org.apache.myfaces.ERROR_TEMPLATE_RESOURCE";
- private static String[] ERROR_PARTS;
+ private static String[] errorParts;
private static final String DEBUG_TEMPLATE = "META-INF/rsc/myfaces-dev-debug.xml";
@@ -216,42 +216,42 @@ public final class ErrorPageWriter
@JSFWebConfigParam(defaultValue="META-INF/rsc/myfaces-dev-debug.xml", since="1.2.4")
private static final String DEBUG_TEMPLATE_RESOURCE = "org.apache.myfaces.DEBUG_TEMPLATE_RESOURCE";
- private static String[] DEBUG_PARTS;
-
+ private static String[] debugParts;
+
private static final String REGEX_PATTERN = ".*?\\Q,Id:\\E\\s*(\\S+)\\s*\\].*?";
-
+
private final static String[] IGNORE = new String[] { "parent", "rendererType" };
-
+
private final static String[] ALWAYS_WRITE = new String[] { "class", "clientId" };
-
+
/**
* Extended debug info is stored under this key in the request
* map for every UIInput component when in Development mode.
* ATTENTION: this constant is duplicate in javax.faces.component.UIInput
*/
public static final String DEBUG_INFO_KEY = "org.apache.myfaces.debug.DEBUG_INFO";
-
+
/**
* The number of facets of this component which have already been visited while
* creating the extended component tree is saved under this key in the component's
* attribute map.
*/
//private static final String VISITED_FACET_COUNT_KEY = "org.apache.myfaces.debug.VISITED_FACET_COUNT";
-
- private static final Map<UIComponent, Integer> visitedFacetCount = new HashMap<UIComponent, Integer>();
+ private static Map<UIComponent, Integer> visitedFacetCount = new HashMap<UIComponent, Integer>();
/**
* Indicate if myfaces is responsible to handle errors.
* See http://wiki.apache.org/myfaces/Handling_Server_Errors for details.
*/
- @JSFWebConfigParam(defaultValue="false, on Development Project stage: true",expectedValues="true,false", since="1.2.4")
+ @JSFWebConfigParam(defaultValue="false, on Development Project stage: true",
+ expectedValues="true,false", since="1.2.4")
public static final String ERROR_HANDLING_PARAMETER = "org.apache.myfaces.ERROR_HANDLING";
public ErrorPageWriter()
{
super();
}
-
+
/**
* Generates the HTML error page for the given Throwable
* and writes it to the given writer.
@@ -264,64 +264,17 @@ public final class ErrorPageWriter
{
debugHtml(writer, faces, faces.getViewRoot(), null, e);
}
-
- /*
- private static void debugHtml(Writer writer, FacesContext faces, Throwable e, UIViewRoot view) throws IOException
- {
- _init(faces);
- 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]))
- {
- if (view != null)
- {
- _writeComponent(faces, writer, view, _getErrorId(e));
- }
- }
- else if ("vars".equals(ERROR_PARTS[i]))
- {
- _writeVariables(writer, faces, view);
- }
- else if ("cause".equals(ERROR_PARTS[i]))
- {
- _writeCause(writer, e);
- }
- else
- {
- writer.write(ERROR_PARTS[i]);
- }
- }
- }*/
-
- private static void debugHtml(Writer writer, FacesContext faces, UIViewRoot view, Collection<UIComponent> components, Throwable... exs) throws IOException
+
+ private static void debugHtml(Writer writer, FacesContext faces, UIViewRoot view,
+ Collection<UIComponent> components, Throwable... exs) throws IOException
{
_init(faces);
Date now = new Date();
- for (int i = 0; i < ERROR_PARTS.length; i++)
+ for (int i = 0; i < errorParts.length; i++)
{
- if ("view".equals((ERROR_PARTS[i]))) {
+ if ("view".equals((errorParts[i])))
+ {
if (faces.getViewRoot() != null)
{
String viewId = faces.getViewRoot().getViewId();
@@ -345,9 +298,9 @@ public final class ErrorPageWriter
writer.write("phaseId=" + faces.getCurrentPhaseId());
writer.write("<br/>");
writer.write("<br/>");
- }
+ }
}
- else if ("message".equals(ERROR_PARTS[i]))
+ else if ("message".equals(errorParts[i]))
{
boolean printed = false;
//Iterator<UIComponent> iterator = null;
@@ -362,13 +315,6 @@ public final class ErrorPageWriter
{
writer.write("<br/>");
}
- //if (iterator != null)
- //{
- // UIComponent uiComponent = iterator.next();
- // if (uiComponent != null) {
- // _writeComponent(faces, writer, uiComponent, null, /* writeChildren */false);
- // }
- //}
if (msg != null)
{
writer.write(msg.replaceAll("<", TS));
@@ -380,7 +326,7 @@ public final class ErrorPageWriter
printed = true;
}
}
- else if ("trace".equals(ERROR_PARTS[i]))
+ else if ("trace".equals(errorParts[i]))
{
boolean printed = false;
for (Throwable e : exs)
@@ -393,11 +339,11 @@ public final class ErrorPageWriter
printed = true;
}
}
- else if ("now".equals(ERROR_PARTS[i]))
+ else if ("now".equals(errorParts[i]))
{
writer.write(DateFormat.getDateTimeInstance().format(now));
}
- else if ("tree".equals(ERROR_PARTS[i]))
+ else if ("tree".equals(errorParts[i]))
{
if (view != null)
{
@@ -405,16 +351,16 @@ public final class ErrorPageWriter
_writeComponent(faces, writer, view, errorIds, true);
}
}
- else if ("vars".equals(ERROR_PARTS[i]))
+ else if ("vars".equals(errorParts[i]))
{
_writeVariables(writer, faces, view);
}
- else if ("cause".equals(ERROR_PARTS[i]))
+ else if ("cause".equals(errorParts[i]))
{
boolean printed = false;
Iterator<UIComponent> iterator = null;
if (components != null)
- {
+ {
iterator = components.iterator();
}
for (Throwable e : exs)
@@ -427,11 +373,9 @@ public final class ErrorPageWriter
if (iterator != null)
{
UIComponent uiComponent = iterator.next();
- if (uiComponent != null) {
+ if (uiComponent != null)
+ {
_writeComponent(faces, writer, uiComponent, null, /* writeChildren */false);
- //writer.write("<br/>");
- //writer.write(RendererUtils.getPathToComponent(uiComponent));
- //writer.write("<br/>");
}
}
printed = true;
@@ -439,7 +383,7 @@ public final class ErrorPageWriter
}
else
{
- writer.write(ERROR_PARTS[i]);
+ writer.write(errorParts[i]);
}
}
}
@@ -455,42 +399,43 @@ public final class ErrorPageWriter
{
_init(faces);
Date now = new Date();
- for (int i = 0; i < DEBUG_PARTS.length; i++)
+ for (int i = 0; i < debugParts.length; i++)
{
- if ("message".equals(DEBUG_PARTS[i]))
+ if ("message".equals(debugParts[i]))
{
writer.write(faces.getViewRoot().getViewId());
}
- else if ("now".equals(DEBUG_PARTS[i]))
+ else if ("now".equals(debugParts[i]))
{
writer.write(DateFormat.getDateTimeInstance().format(now));
}
- else if ("tree".equals(DEBUG_PARTS[i]))
+ else if ("tree".equals(debugParts[i]))
{
_writeComponent(faces, writer, faces.getViewRoot(), null, true);
}
- else if ("extendedtree".equals(DEBUG_PARTS[i]))
+ else if ("extendedtree".equals(debugParts[i]))
{
_writeExtendedComponentTree(writer, faces);
}
- else if ("vars".equals(DEBUG_PARTS[i]))
+ else if ("vars".equals(debugParts[i]))
{
_writeVariables(writer, faces, faces.getViewRoot());
}
else
{
- writer.write(DEBUG_PARTS[i]);
+ writer.write(debugParts[i]);
}
}
}
-
- public static void handle(FacesContext facesContext, Collection<UIComponent> components, Throwable... exs) throws FacesException
+
+ public static void handle(FacesContext facesContext, Collection<UIComponent> components,
+ Throwable... exs) throws FacesException
{
for (Throwable ex : exs)
{
_prepareExceptionStack(ex);
}
-
+
if (!facesContext.getExternalContext().isResponseCommitted())
{
facesContext.getExternalContext().responseReset();
@@ -513,7 +458,7 @@ public final class ErrorPageWriter
{
facesContext.getExternalContext().setResponseStatus(responseStatus);
}
-
+
// normal request --> html error page
facesContext.getExternalContext().setResponseContentType("text/html");
facesContext.getExternalContext().setResponseCharacterEncoding("UTF-8");
@@ -549,16 +494,16 @@ public final class ErrorPageWriter
public static void handleThrowable(FacesContext facesContext, Throwable ex) throws FacesException
{
_prepareExceptionStack(ex);
-
+
boolean errorPageWritten = false;
-
+
// check if an error page is present in web.xml
// if so, do not generate an error page
//WebXml webXml = WebXml.getWebXml(facesContext.getExternalContext());
//if (webXml.isErrorPagePresent())
WebConfigProvider webConfigProvider = WebConfigProviderFactory.getWebConfigProviderFactory(
facesContext.getExternalContext()).getWebConfigProvider(facesContext.getExternalContext());
-
+
if(webConfigProvider.isErrorPagePresent(facesContext.getExternalContext()))
{
// save current view in the request map to access it on the error page
@@ -581,7 +526,7 @@ public final class ErrorPageWriter
{
httpResp.reset();
if (facesContext.getPartialViewContext().isAjaxRequest())
- {
+ {
// ajax request --> xml error page
httpResp.setContentType("text/xml; charset=UTF-8");
try
@@ -609,7 +554,7 @@ public final class ErrorPageWriter
}
}
else
- {
+ {
// normal request --> html error page
httpResp.setContentType("text/html; charset=UTF-8");
try
@@ -623,16 +568,16 @@ public final class ErrorPageWriter
}
}
log.log(Level.SEVERE, "An exception occurred", ex);
-
+
// mark the response as complete
facesContext.responseComplete();
-
+
errorPageWritten = true;
}
}
}
}
-
+
// rethrow the throwable, if we did not write the error page
if (!errorPageWritten)
{
@@ -671,20 +616,20 @@ public final class ErrorPageWriter
private static void _init(FacesContext context) throws IOException
{
- if (ERROR_PARTS == null)
+ if (errorParts == null)
{
- ERROR_PARTS = _splitTemplate(_getErrorTemplate(context));
+ errorParts = _splitTemplate(_getErrorTemplate(context));
}
- if (DEBUG_PARTS == null)
+ if (debugParts == null)
{
- DEBUG_PARTS = _splitTemplate(_getDebugTemplate(context));
+ debugParts = _splitTemplate(_getDebugTemplate(context));
}
}
private static String[] _splitTemplate(String rsc) throws IOException
{
- InputStream is = ClassUtils.getContextClassLoader().getResourceAsStream(rsc);
+ InputStream is = ClassUtils.getContextClassLoader().getResourceAsStream(rsc);
if (is == null)
{
// try to get the resource from ExternalContext
@@ -694,7 +639,7 @@ public final class ErrorPageWriter
// fallback
is = ErrorPageWriter.class.getClassLoader().getResourceAsStream(rsc);
}
- }
+ }
if (is == null)
{
@@ -714,25 +659,27 @@ public final class ErrorPageWriter
String str = baos.toString();
return str.split("@@");
}
-
+
private static List<String> _getErrorId(Collection<UIComponent> components, Throwable... exs)
{
List<String> list = null;
for (Throwable e : exs)
{
String message = e.getMessage();
-
+
if (message == null)
+ {
continue;
-
+ }
+
Pattern pattern = Pattern.compile(REGEX_PATTERN);
Matcher matcher = pattern.matcher(message);
-
+
while (matcher.find())
{
if (list == null)
{
- list = new ArrayList<String>();
+ list = new ArrayList<String>();
}
list.add(matcher.group(1));
}
@@ -744,7 +691,8 @@ public final class ErrorPageWriter
else if (components != null)
{
list = new ArrayList<String>();
- for (UIComponent uiComponent : components) {
+ for (UIComponent uiComponent : components)
+ {
if (uiComponent != null)
{
list.add(uiComponent.getId());
@@ -763,7 +711,7 @@ public final class ErrorPageWriter
pstr.close();
writer.write(str.toString().replaceAll("<", TS));
}
-
+
private static void _writeCause(Writer writer, Throwable ex) throws IOException
{
String msg = ex.getMessage();
@@ -771,8 +719,8 @@ public final class ErrorPageWriter
if (ex instanceof ContextAware)
{
ContextAware caex = (ContextAware) ex;
- contextAwareLocation = caex.getLocation().toString() + " " +
- caex.getQName() + "=\"" +
+ contextAwareLocation = caex.getLocation().toString() + " " +
+ caex.getQName() + "=\"" +
caex.getExpressionString() + "\"";
}
while (ex.getCause() != null)
@@ -781,12 +729,14 @@ public final class ErrorPageWriter
if (ex instanceof ContextAware)
{
ContextAware caex = (ContextAware) ex;
- contextAwareLocation = caex.getLocation().toString() + " " +
- caex.getQName() + "=\"" +
+ contextAwareLocation = caex.getLocation().toString() + " " +
+ caex.getQName() + "=\"" +
caex.getExpressionString() + "\"";
}
if (ex.getMessage() != null)
+ {
msg = ex.getMessage();
+ }
}
if (msg != null)
@@ -800,7 +750,7 @@ public final class ErrorPageWriter
}
StackTraceElement stackTraceElement = ex.getStackTrace()[0];
writer.write("<br/> at " + stackTraceElement.toString());
-
+
if (contextAwareLocation != null)
{
writer.write("<br/> <br/>");
@@ -826,12 +776,13 @@ public final class ErrorPageWriter
_writeVariables(writer, ctx.getApplicationMap(), "Application Attributes");
}
- private static void _writeVariables(Writer writer, Map<String, ? extends Object> vars, String caption) throws IOException
+ private static void _writeVariables(Writer writer, Map<String, ? extends Object> 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>");
+ 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())
{
@@ -845,10 +796,14 @@ public final class ErrorPageWriter
writer.write(key.replaceAll("<", TS));
writer.write("</td><td>");
Object value = entry.getValue();
- // in some (very rare) situations value can be null or not null but with null toString() representation
- if (value != null && value.toString() != null) {
+ // in some (very rare) situations value can be null or not null
+ // but with null toString() representation
+ if (value != null && value.toString() != null)
+ {
writer.write(value.toString().replaceAll("<", TS));
- } else {
+ }
+ else
+ {
writer.write("null");
}
writer.write("</td></tr>");
@@ -863,7 +818,8 @@ public final class ErrorPageWriter
writer.write("</tbody></table>");
}
- private static void _writeComponent(FacesContext faces, Writer writer, UIComponent c, List<String> highlightId, boolean writeChildren) throws IOException
+ private static void _writeComponent(FacesContext faces, Writer writer, UIComponent c, List<String> highlightId,
+ boolean writeChildren) throws IOException
{
writer.write("<dl><dt");
if (_isText(c))
@@ -937,55 +893,55 @@ public final class ErrorPageWriter
}
writer.write("</dl>");
}
-
+
/**
* Creates the Extended Component Tree via UIViewRoot.visitTree()
* and ExtendedComponentTreeVisitCallback as VisitCallback.
- *
+ *
* @param writer
* @param facesContext
* @throws IOException
*/
- private static void _writeExtendedComponentTree(Writer writer,
+ private static void _writeExtendedComponentTree(Writer writer,
FacesContext facesContext) throws IOException
{
VisitContext visitContext = VisitContext.createVisitContext(
facesContext, null, EnumSet.of(VisitHint.SKIP_UNRENDERED));
facesContext.getViewRoot().visitTree(visitContext, new ExtendedComponentTreeVisitCallback(writer));
}
-
+
/**
* The VisitCallback that is used to create the Extended Component Tree.
- *
+ *
* @author Jakob Korherr
*/
private static class ExtendedComponentTreeVisitCallback implements VisitCallback
{
private Writer _writer;
-
+
public ExtendedComponentTreeVisitCallback(Writer writer)
{
_writer = writer;
}
-
+
@SuppressWarnings("unchecked")
public VisitResult visit(VisitContext context, UIComponent target)
{
final Map<String, Object> requestMap = context.getFacesContext()
.getExternalContext().getRequestMap();
-
+
try
{
if (!(target instanceof UIViewRoot))
{
_writer.write("<dd>");
}
-
+
UIComponent parent = target.getParent();
boolean hasChildren = (target.getChildCount() > 0 || target.getFacets().size() > 0);
String facetName = _getFacetName(target);
-
+
if (!(target instanceof UIColumn))
{
if (parent instanceof UIColumn
@@ -1009,10 +965,10 @@ public final class ErrorPageWriter
_writeStart(_writer, parent, true, false);
_writer.write("</dt><dd>");
}
-
+
if (facetName != null)
{
- _writer.write("<span>" + facetName + "</span>");
+ _writer.write("<span>" + facetName + "</span>");
_incrementVisitedFacetCount(parent);
}
_writer.write("<dl><dt");
@@ -1021,7 +977,7 @@ public final class ErrorPageWriter
_writer.write(" class=\"uicText\"");
}
_writer.write(">");
-
+
Map<String, List<Object[]>> debugInfos = null;
// is the target a EditableValueHolder component?
// If so, debug infos from DebugPhaseListener should be available
@@ -1031,7 +987,7 @@ public final class ErrorPageWriter
debugInfos = (Map<String, List<Object[]>>) requestMap
.get(DEBUG_INFO_KEY + target.getClientId());
}
-
+
// Get the component's renderer.
// Note that getRenderer(FacesContext context) is definded in UIComponent,
// but it is protected, so we have to use reflection!
@@ -1048,18 +1004,18 @@ public final class ErrorPageWriter
{
// nothing - do not output renderer information
}
-
+
// write the component start
_writeStart(_writer, target, (hasChildren || debugInfos != null || renderer != null), false);
_writer.write("</dt>");
-
+
if (renderer != null)
{
// write renderer info
_writer.write("<div class=\"renderer\">Rendered by ");
_writer.write(renderer.getClass().getCanonicalName());
_writer.write("</div>");
-
+
if (!hasChildren && debugInfos == null)
{
// close the component
@@ -1068,7 +1024,7 @@ public final class ErrorPageWriter
_writer.write("</dt>");
}
}
-
+
if (debugInfos != null)
{
final String fieldid = target.getClientId() + "_lifecycle";
@@ -1083,7 +1039,7 @@ public final class ErrorPageWriter
_writer.write("<div id=\"");
_writer.write(fieldid);
_writer.write("\" class=\"lifecycle_values\">");
-
+
// process any available debug info
for (Map.Entry<String, List<Object[]>> entry : debugInfos.entrySet())
{
@@ -1098,7 +1054,7 @@ public final class ErrorPageWriter
// - 1: old value
// - 2: new value
// - 3: StackTraceElement List
-
+
// oldValue and newValue could be null
String oldValue = debugInfo[1] == null ? "null" : debugInfo[1].toString();
String newValue = debugInfo[2] == null ? "null" : debugInfo[2].toString();
@@ -1110,7 +1066,7 @@ public final class ErrorPageWriter
_writer.write(newValue);
_writer.write("</b> in Phase ");
_writer.write(debugInfo[0].toString());
-
+
// check if a call stack is available
if (debugInfo[3] != null)
{
@@ -1127,7 +1083,7 @@ public final class ErrorPageWriter
_writer.write(stackTraceId);
_writer.write("\" class=\"stacktrace_values\">");
_writer.write("<ul>");
- for (StackTraceElement stackTraceElement
+ for (StackTraceElement stackTraceElement
: (List<StackTraceElement>) debugInfo[3])
{
_writer.write("<li>");
@@ -1136,20 +1092,20 @@ public final class ErrorPageWriter
}
_writer.write("</ul></div></div>");
}
-
+
_writer.write("</li>");
-
+
i++;
}
_writer.write("</ol>");
}
-
+
_writer.write("</div></div>");
-
+
// now remove the debug info from the request map,
// so that it does not appear in the scope values of the debug page
requestMap.remove(DEBUG_INFO_KEY + target.getClientId());
-
+
if (!hasChildren)
{
// close the component
@@ -1159,21 +1115,21 @@ public final class ErrorPageWriter
}
}
}
-
+
if (!hasChildren)
{
_writer.write("</dl>");
-
- while (parent != null
- && ((parent.getChildCount()>0 && parent.getChildren().get(parent.getChildCount() - 1) == target)
- || (parent.getFacetCount() != 0
+
+ while (parent != null &&
+ ((parent.getChildCount()>0 && parent.getChildren().get(parent.getChildCount()-1) == target)
+ || (parent.getFacetCount() != 0
&& _getVisitedFacetCount(parent) == parent.getFacetCount())))
{
// target is last child of parent or the "last" facet
-
+
// remove the visited facet count from the attribute map
_removeVisitedFacetCount(parent);
-
+
// check for componentes that visit their children multiple times
if (parent instanceof UIData)
{
@@ -1193,18 +1149,18 @@ public final class ErrorPageWriter
break;
}
}
-
+
_writer.write("</dd><dt>");
_writeEnd(_writer, parent);
_writer.write("</dt></dl>");
-
+
if (!(parent instanceof UIViewRoot))
{
_writer.write("</dd>");
}
-
+
target = parent;
- parent = target.getParent();
+ parent = target.getParent();
}
}
}
@@ -1212,12 +1168,12 @@ public final class ErrorPageWriter
{
throw new FacesException(ioe);
}
-
+
return VisitResult.ACCEPT;
}
-
+
}
-
+
private static boolean _isFirstUIColumn(UIComponent uidata, UIColumn uicolumn)
{
for (int i = 0, childCount = uidata.getChildCount(); i < childCount; i++)
@@ -1230,7 +1186,7 @@ public final class ErrorPageWriter
}
return false;
}
-
+
private static String _getFacetName(UIComponent component)
{
UIComponent parent = component.getParent();
@@ -1249,7 +1205,7 @@ public final class ErrorPageWriter
}
return null;
}
-
+
private static int _getVisitedFacetCount(UIComponent component)
{
Integer count = visitedFacetCount.get(component);
@@ -1259,12 +1215,12 @@ public final class ErrorPageWriter
}
return 0;
}
-
+
private static void _incrementVisitedFacetCount(UIComponent component)
{
visitedFacetCount.put(component, _getVisitedFacetCount(component) + 1);
}
-
+
private static void _removeVisitedFacetCount(UIComponent component)
{
visitedFacetCount.remove(component);
@@ -1293,7 +1249,8 @@ public final class ErrorPageWriter
String str = null;
for (int i = 0; i < pd.length; i++)
{
- if ((pd[i].getWriteMethod() != null || Arrays.binarySearch(ALWAYS_WRITE, pd[i].getName()) > -1) && Arrays.binarySearch(IGNORE, pd[i].getName()) < 0)
+ if ((pd[i].getWriteMethod() != null || Arrays.binarySearch(ALWAYS_WRITE, pd[i].getName()) > -1)
+ && Arrays.binarySearch(IGNORE, pd[i].getName()) < 0)
{
m = pd[i].getReadMethod();
try
@@ -1302,7 +1259,12 @@ public final class ErrorPageWriter
valueExpression = c.getValueExpression(pd[i].getName());
if (valueExpressionValues && valueExpression != null)
{
- _writeAttribute(writer, pd[i].getName(), valueExpression.getExpressionString());
+ String expressionString = valueExpression.getExpressionString();
+ if (null == expressionString)
+ {
+ expressionString = "";
+ }
+ _writeAttribute(writer, pd[i].getName(), expressionString);
}
else
{
@@ -1329,7 +1291,7 @@ public final class ErrorPageWriter
{
str = v.toString();
}
-
+
_writeAttribute(writer, pd[i].getName(), str);
}
}
@@ -1346,7 +1308,7 @@ public final class ErrorPageWriter
{
_writeAttribute(writer, "binding", binding.getExpressionString());
}
-
+
// write the location
String location = _getComponentLocation(c);
if (location != null)
@@ -1359,7 +1321,7 @@ public final class ErrorPageWriter
// do nothing
}
}
-
+
private static void _writeAttribute(Writer writer, String name, String value) throws IOException
{
writer.write(" ");
@@ -1369,7 +1331,7 @@ public final class ErrorPageWriter
writer.write("\"");
}
- private static void _writeStart(Writer writer, UIComponent c,
+ private static void _writeStart(Writer writer, UIComponent c,
boolean children, boolean valueExpressionValues) throws IOException
{
if (_isText(c))
@@ -1408,7 +1370,9 @@ public final class ErrorPageWriter
{
if (ex == null)
+ {
return;
+ }
// check for getRootCause and getCause-methods
if (!_initCausePerReflection(ex, "getRootCause"))
@@ -1436,7 +1400,9 @@ public final class ErrorPageWriter
private static boolean _initCauseIfAvailable(Throwable th, Throwable cause)
{
if (cause == null)
+ {
return false;
+ }
try
{
@@ -1449,7 +1415,7 @@ public final class ErrorPageWriter
return false;
}
}
-
+
/**
* Gets the Location of the given UIComponent from its attribute map.
* @param component
Added: myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/ErrorPageWriterTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/ErrorPageWriterTest.java?rev=1208626&view=auto
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/ErrorPageWriterTest.java (added)
+++ myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/ErrorPageWriterTest.java Wed Nov 30 18:17:57 2011
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.myfaces.renderkit;
+
+import java.io.StringWriter;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UIViewRoot;
+import javax.faces.component.html.HtmlOutputText;
+import javax.validation.constraints.AssertTrue;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.myfaces.renderkit.html.HtmlTextRenderer;
+import org.apache.myfaces.shared.util.StateUtils;
+import org.apache.myfaces.shared_impl.util.serial.DefaultSerialFactory;
+import org.apache.myfaces.test.base.AbstractJsfTestCase;
+import org.apache.myfaces.test.mock.MockRenderKitFactory;
+import org.apache.myfaces.test.mock.MockResponseWriter;
+
+/**
+ * @author Bruno Aranda (latest modification by $Author: struberg $)
+ * @version $Revision: 1188235 $ $Date: 2011-10-24 13:09:33 -0400 (Mon, 24 Oct 2011) $
+ */
+public class ErrorPageWriterTest extends AbstractJsfTestCase
+{
+ public static Test suite()
+ {
+ return new TestSuite(ErrorPageWriterTest.class); // needed in maven
+ }
+
+ private MockResponseWriter writer ;
+ private HtmlOutputText outputText;
+
+ public ErrorPageWriterTest(String name)
+ {
+ super(name);
+ }
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ outputText = new HtmlOutputText();
+
+ writer = new MockResponseWriter(new StringWriter(), null, null);
+ facesContext.setResponseWriter(writer);
+ // TODO remove these two lines once myfaces-test goes alpha, see MYFACES-1155
+ facesContext.getViewRoot().setRenderKitId(MockRenderKitFactory.HTML_BASIC_RENDER_KIT);
+ facesContext.getRenderKit().addRenderer(
+ outputText.getFamily(),
+ outputText.getRendererType(),
+ new HtmlTextRenderer());
+ servletContext.setAttribute(StateUtils.SERIAL_FACTORY, new DefaultSerialFactory());
+
+ facesContext.getAttributes().put("org.apache.myfaces.RENDERED_JSF_JS", Boolean.TRUE);
+ }
+
+ public void tearDown() throws Exception
+ {
+ super.tearDown();
+ outputText = null;
+ writer = null;
+ }
+
+ public void testValueExpressionGetExpressionStringReturnsNull()
+ {
+ //See MYFACES-3413 for details
+ UIViewRoot root = facesContext.getViewRoot();
+// UIForm form = new UIForm();
+// form.setId("formId");
+//
+// form.getChildren().add(inputText);
+ root.getChildren().add(outputText);
+
+ ValueExpression ve = new NullReturningGetExpressionStringValueExpression();
+
+ outputText.setValueExpression("rendered", ve);
+ String id = "testValueExpressionGetExpressionStringReturnsNullOutputComponent";
+ outputText.setId(id);
+ try
+ {
+ StringWriter w = new StringWriter();
+ Throwable t = new Throwable("Placeholder throwable");
+ ErrorPageWriter.debugHtml(w, facesContext, t);
+ String output = w.toString();
+ int indexOfOutputComponentId = output.indexOf(id);
+ String surroundingText = "output component not found.";
+ if (-1 != indexOfOutputComponentId) {
+ surroundingText = output.substring(Math.max(0, indexOfOutputComponentId - 20), Math.min(output.length(), indexOfOutputComponentId + 280));
+ }
+ int indexOfHasRenderedAttribute = output.indexOf("rendered=\"\"");
+ boolean hasRenderedAttribute = (-1 != indexOfHasRenderedAttribute);
+ assertTrue("rendered attribute wasn't written correctly: " + surroundingText, hasRenderedAttribute);
+ }
+ catch (Exception e)
+ {
+ fail(e.getMessage());
+ }
+ }
+
+}
Propchange: myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/ErrorPageWriterTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/NullReturningGetExpressionStringValueExpression.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/NullReturningGetExpressionStringValueExpression.java?rev=1208626&view=auto
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/NullReturningGetExpressionStringValueExpression.java (added)
+++ myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/NullReturningGetExpressionStringValueExpression.java Wed Nov 30 18:17:57 2011
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.myfaces.renderkit;
+import java.io.Serializable;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.PropertyNotFoundException;
+import javax.el.PropertyNotWritableException;
+import javax.el.ValueExpression;
+
+public class NullReturningGetExpressionStringValueExpression extends ValueExpression implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public String getExpressionString() {
+ return null;
+ }
+
+ @Override
+ public boolean isReadOnly(ELContext arg0) {
+ return true;
+ }
+
+ @Override
+ public Class<?> getExpectedType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Class<?> getType(ELContext arg0)
+ throws NullPointerException, PropertyNotFoundException,
+ ELException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Object getValue(ELContext arg0) throws NullPointerException,
+ PropertyNotFoundException, ELException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setValue(ELContext arg0, Object arg1)
+ throws NullPointerException, PropertyNotFoundException,
+ PropertyNotWritableException, ELException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean equals(Object arg0) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public boolean isLiteralText() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ }
+
Propchange: myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/renderkit/NullReturningGetExpressionStringValueExpression.java
------------------------------------------------------------------------------
svn:eol-style = native