private void writeException(final PrintWriter writer, ExceptionAnalysis analysis)
{
final Formatter f = new Formatter(writer);
writer.print("EXCEPTION STACK:\n\n");
Request request = requestGlobals.getRequest();
// Figure out what all the property names are so that we can set the width of the column that lists
// property names.
Flow<String> propertyNames = F.flow(analysis.getExceptionInfos())
.mapcat(EXCEPTION_INFO_TO_PROPERTY_NAMES).append("Exception type", "Message");
if (request != null)
{
propertyNames = propertyNames.concat(request.getParameterNames()).concat(request.getHeaderNames());
}
final int maxPropertyNameLength = propertyNames.map(STRING_TO_LENGTH).reduce(MAX, 0);
final String propertyNameFormat = " %" + maxPropertyNameLength + "s: %s\n";
PropertyWriter pw = new PropertyWriter()
{
@SuppressWarnings("rawtypes")
@Override
public void write(String name, Object value)
{
if (value.getClass().isArray())
{
write(name, toList(value));
return;
}
if (value instanceof Iterable)
{
boolean first = true;
Iterable iterable = (Iterable) value;
Iterator i = iterable.iterator();
while (i.hasNext())
{
if (first)
{
f.format(propertyNameFormat, name, i.next());
first = false;
} else
{
for (int j = 0; j < maxPropertyNameLength + 4; j++)
writer.write(' ');
writer.println(i.next());
}
}
return;
}
// TODO: Handling of arrays & collections
f.format(propertyNameFormat, name, value);
}
@SuppressWarnings({"rawtypes", "unchecked"})
private List toList(Object array)
{
int count = Array.getLength(array);
List result = new ArrayList(count);
for (int i = 0; i < count; i++)
{
result.add(Array.get(array, i));
}
return result;
}
};
boolean first = true;
for (ExceptionInfo info : analysis.getExceptionInfos())
{
if (first)
{
writer.println();
first = false;
}
pw.write("Exception type", info.getClassName());
pw.write("Message", info.getMessage());
for (String name : info.getPropertyNames())
{
pw.write(name, info.getProperty(name));
}
if (!info.getStackTrace().isEmpty())
{
writer.write("\n Stack trace:\n");
for (StackTraceElement e : info.getStackTrace())
{
f.format(" - %s\n", e.toString());
}
}
writer.println();
}
if (request != null)
{
writer.print("REQUEST:\n\nBasic Information:\n");
List<String> flags = CollectionFactory.newList();
if (request.isXHR())
{
flags.add("XHR");
}
if (request.isRequestedSessionIdValid())
{
flags.add("requestedSessionIdValid");
}
if (request.isSecure())
{
flags.add("secure");
}
pw.write("contextPath", contextPath);
if (!flags.isEmpty())
{
pw.write("flags", InternalUtils.joinSorted(flags));
}
pw.write("method", request.getMethod());
pw.write("path", request.getPath());
pw.write("locale", request.getLocale());
pw.write("serverName", request.getServerName());
pw.write("remoteHost", request.getRemoteHost());
writer.print("\nHeaders:\n");
for (String name : request.getHeaderNames())
{
pw.write(name, request.getHeader(name));
}
if (!request.getParameterNames().isEmpty())
{
writer.print("\nParameters:\n");
for (String name : request.getParameterNames())
{
// TODO: Support multi-value parameters
pw.write(name, request.getParameters(name));
}
}
// TODO: Session if it exists
}