[OLINGO-659] better debug output in error case

Change-Id: I3f0a270807c4a929027894ed42c51523e56bbc14

Signed-off-by: Michael Bolz <michael.bolz@sap.com>
This commit is contained in:
Klaus Straubinger 2015-09-02 15:04:44 +02:00 committed by Michael Bolz
parent ccf361b8fe
commit 83a098f22b
15 changed files with 150 additions and 225 deletions

View File

@ -32,26 +32,25 @@ public interface DebugSupport {
public static final String ODATA_DEBUG_DOWNLOAD = "download"; public static final String ODATA_DEBUG_DOWNLOAD = "download";
/** /**
* Initializes the debug support implementation. Is called before {@link #isUserAuthorized()} and * Initializes the debug support implementation.
* {@link #createDebugResponse(String, DebugInformation)} * Is called before {@link #isUserAuthorized()} and
* {@link #createDebugResponse(String, DebugInformation)}.
* @param odata * @param odata
*/ */
void init(OData odata); void init(OData odata);
/** /**
* This method is called to make sure that the user that requested the debug output is authorized to see this output. * Ensures that the user that requested the debug output is authorized to see this output.
* @return true if the current user is authorized * @return true if the current user is authorized
*/ */
boolean isUserAuthorized(); boolean isUserAuthorized();
/** /**
* This method should create a debug response and deliver it back to the Olingo library. This method MUST NEVER throw * Creates a debug response and delivers it back to the Olingo library.
* an exception. * This method MUST NEVER throw an exception.
* @param debugFormat which is requested via the odata-debug query parameter * @param debugFormat the value of the odata-debug query parameter
* @param request object which was send to the server * @param debugInfo all necessary information to construct debug output
* @param response object which was filled by the application * @return a new debug response which will be sent to the client
* @param exception which has been thrown. Might be null in case there was no exception
* @return a new debug response which will be send to the client
*/ */
ODataResponse createDebugResponse(String debugFormat, DebugInformation debugInfo); ODataResponse createDebugResponse(String debugFormat, DebugInformation debugInfo);

View File

@ -74,7 +74,7 @@ public class ODataHandler {
public ODataResponse process(final ODataRequest request) { public ODataResponse process(final ODataRequest request) {
ODataResponse response = new ODataResponse(); ODataResponse response = new ODataResponse();
int measurementHandel = debugger.startRuntimeMeasurement("ODataHandler", "processInternal"); final int responseHandle = debugger.startRuntimeMeasurement("ODataHandler", "process");
try { try {
processInternal(request, response); processInternal(request, response);
} catch (final UriValidationException e) { } catch (final UriValidationException e) {
@ -111,29 +111,51 @@ public class ODataHandler {
ODataServerError serverError = ODataExceptionHelper.createServerErrorObject(e); ODataServerError serverError = ODataExceptionHelper.createServerErrorObject(e);
handleException(request, response, serverError, e); handleException(request, response, serverError, e);
} }
debugger.stopRuntimeMeasurement(measurementHandel); debugger.stopRuntimeMeasurement(responseHandle);
return response; return response;
} }
private void processInternal(final ODataRequest request, final ODataResponse response) private void processInternal(final ODataRequest request, final ODataResponse response)
throws ODataApplicationException, ODataLibraryException { throws ODataApplicationException, ODataLibraryException {
final int measurementHandle = debugger.startRuntimeMeasurement("ODataHandler", "processInternal");
response.setHeader(HttpHeader.ODATA_VERSION, ODataServiceVersion.V40.toString()); response.setHeader(HttpHeader.ODATA_VERSION, ODataServiceVersion.V40.toString());
try {
validateODataVersion(request); validateODataVersion(request);
} catch (final ODataHandlerException e) {
debugger.stopRuntimeMeasurement(measurementHandle);
throw e;
}
int measurementUriParser = debugger.startRuntimeMeasurement("UriParser", "parseUri"); final int measurementUriParser = debugger.startRuntimeMeasurement("UriParser", "parseUri");
try {
uriInfo = new Parser().parseUri(request.getRawODataPath(), request.getRawQueryPath(), null, uriInfo = new Parser().parseUri(request.getRawODataPath(), request.getRawQueryPath(), null,
serviceMetadata.getEdm()); serviceMetadata.getEdm());
} catch (final ODataLibraryException e) {
debugger.stopRuntimeMeasurement(measurementUriParser);
debugger.stopRuntimeMeasurement(measurementHandle);
throw e;
}
debugger.stopRuntimeMeasurement(measurementUriParser); debugger.stopRuntimeMeasurement(measurementUriParser);
int measurementUriValidator = debugger.startRuntimeMeasurement("UriValidator", "validate"); final int measurementUriValidator = debugger.startRuntimeMeasurement("UriValidator", "validate");
final HttpMethod method = request.getMethod(); final HttpMethod method = request.getMethod();
try {
new UriValidator().validate(uriInfo, method); new UriValidator().validate(uriInfo, method);
} catch (final UriValidationException e) {
debugger.stopRuntimeMeasurement(measurementUriValidator);
debugger.stopRuntimeMeasurement(measurementHandle);
throw e;
}
debugger.stopRuntimeMeasurement(measurementUriValidator); debugger.stopRuntimeMeasurement(measurementUriValidator);
int measurementDispatcher = debugger.startRuntimeMeasurement("Dispatcher", "dispatch"); final int measurementDispatcher = debugger.startRuntimeMeasurement("ODataDispatcher", "dispatch");
try {
new ODataDispatcher(uriInfo, this).dispatch(request, response); new ODataDispatcher(uriInfo, this).dispatch(request, response);
} finally {
debugger.stopRuntimeMeasurement(measurementDispatcher); debugger.stopRuntimeMeasurement(measurementDispatcher);
debugger.stopRuntimeMeasurement(measurementHandle);
}
} }
public void handleException(final ODataRequest request, final ODataResponse response, public void handleException(final ODataRequest request, final ODataResponse response,
@ -154,13 +176,12 @@ public class ODataHandler {
} catch (final ContentNegotiatorException e) { } catch (final ContentNegotiatorException e) {
requestedContentType = ContentType.JSON; requestedContentType = ContentType.JSON;
} }
int measurementHandle = debugger.startRuntimeMeasurement("ErrorProcessor", "processError"); final int measurementHandle = debugger.startRuntimeMeasurement("ErrorProcessor", "processError");
exceptionProcessor.processError(request, response, serverError, requestedContentType); exceptionProcessor.processError(request, response, serverError, requestedContentType);
debugger.stopRuntimeMeasurement(measurementHandle); debugger.stopRuntimeMeasurement(measurementHandle);
} }
private void validateODataVersion(final ODataRequest request) private void validateODataVersion(final ODataRequest request) throws ODataHandlerException {
throws ODataHandlerException {
final String maxVersion = request.getHeader(HttpHeader.ODATA_MAX_VERSION); final String maxVersion = request.getHeader(HttpHeader.ODATA_MAX_VERSION);
if (maxVersion != null && ODataServiceVersion.isBiggerThan(ODataServiceVersion.V40.toString(), maxVersion)) { if (maxVersion != null && ODataServiceVersion.isBiggerThan(ODataServiceVersion.V40.toString(), maxVersion)) {
throw new ODataHandlerException("ODataVersion not supported: " + maxVersion, throw new ODataHandlerException("ODataVersion not supported: " + maxVersion,

View File

@ -45,10 +45,10 @@ import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ODataServerError; import org.apache.olingo.server.api.ODataServerError;
import org.apache.olingo.server.api.ServiceMetadata; import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.debug.DebugSupport; import org.apache.olingo.server.api.debug.DebugSupport;
import org.apache.olingo.server.api.deserializer.DeserializerException;
import org.apache.olingo.server.api.etag.CustomETagSupport; import org.apache.olingo.server.api.etag.CustomETagSupport;
import org.apache.olingo.server.api.processor.Processor; import org.apache.olingo.server.api.processor.Processor;
import org.apache.olingo.server.api.serializer.CustomContentTypeSupport; import org.apache.olingo.server.api.serializer.CustomContentTypeSupport;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.core.debug.ServerCoreDebugger; import org.apache.olingo.server.core.debug.ServerCoreDebugger;
public class ODataHttpHandlerImpl implements ODataHttpHandler { public class ODataHttpHandlerImpl implements ODataHttpHandler {
@ -72,21 +72,17 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler {
ODataResponse odResponse; ODataResponse odResponse;
debugger.resolveDebugMode(request); debugger.resolveDebugMode(request);
int processMethodHandel = debugger.startRuntimeMeasurement("ODataHttpHandlerImpl", "process"); final int processMethodHandle = debugger.startRuntimeMeasurement("ODataHttpHandlerImpl", "process");
try { try {
int requestHandel = debugger.startRuntimeMeasurement("ODataHttpHandlerImpl", "fillODataRequest");
fillODataRequest(odRequest, request, split); fillODataRequest(odRequest, request, split);
debugger.stopRuntimeMeasurement(requestHandel);
int responseHandel = debugger.startRuntimeMeasurement("ODataHandler", "process");
odResponse = handler.process(odRequest); odResponse = handler.process(odRequest);
debugger.stopRuntimeMeasurement(responseHandel);
// ALL future methods after process must not throw exceptions! // ALL future methods after process must not throw exceptions!
} catch (Exception e) { } catch (Exception e) {
exception = e; exception = e;
odResponse = handleException(odRequest, e); odResponse = handleException(odRequest, e);
} }
debugger.stopRuntimeMeasurement(processMethodHandel); debugger.stopRuntimeMeasurement(processMethodHandle);
if (debugger.isDebugMode()) { if (debugger.isDebugMode()) {
Map<String, String> serverEnvironmentVariables = createEnvironmentVariablesMap(request); Map<String, String> serverEnvironmentVariables = createEnvironmentVariablesMap(request);
@ -95,7 +91,7 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler {
exception = handler.getLastThrownException(); exception = handler.getLastThrownException();
} }
odResponse = odResponse =
debugger.createDebugResponse(request, exception, odRequest, odResponse, handler.getUriInfo(), debugger.createDebugResponse(odRequest, odResponse, exception, handler.getUriInfo(),
serverEnvironmentVariables); serverEnvironmentVariables);
} }
@ -103,7 +99,7 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler {
} }
private Map<String, String> createEnvironmentVariablesMap(HttpServletRequest request) { private Map<String, String> createEnvironmentVariablesMap(HttpServletRequest request) {
LinkedHashMap<String, String> environment = new LinkedHashMap<String, String>(); Map<String, String> environment = new LinkedHashMap<String, String>();
environment.put("authType", request.getAuthType()); environment.put("authType", request.getAuthType());
environment.put("localAddr", request.getLocalAddr()); environment.put("localAddr", request.getLocalAddr());
environment.put("localName", request.getLocalName()); environment.put("localName", request.getLocalName());
@ -186,9 +182,9 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler {
} }
} }
private ODataRequest fillODataRequest(final ODataRequest odRequest, final HttpServletRequest httpRequest, private ODataRequest fillODataRequest(ODataRequest odRequest, final HttpServletRequest httpRequest,
final int split) final int split) throws ODataLibraryException {
throws ODataLibraryException { final int requestHandle = debugger.startRuntimeMeasurement("ODataHttpHandlerImpl", "fillODataRequest");
try { try {
odRequest.setBody(httpRequest.getInputStream()); odRequest.setBody(httpRequest.getInputStream());
odRequest.setProtocol(httpRequest.getProtocol()); odRequest.setProtocol(httpRequest.getProtocol());
@ -198,13 +194,14 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler {
return odRequest; return odRequest;
} catch (final IOException e) { } catch (final IOException e) {
throw new SerializerException("An I/O exception occurred.", e, throw new DeserializerException("An I/O exception occurred.", e,
SerializerException.MessageKeys.IO_EXCEPTION); DeserializerException.MessageKeys.IO_EXCEPTION);
} finally {
debugger.stopRuntimeMeasurement(requestHandle);
} }
} }
static HttpMethod extractMethod(final HttpServletRequest httpRequest) static HttpMethod extractMethod(final HttpServletRequest httpRequest) throws ODataLibraryException {
throws ODataLibraryException {
try { try {
HttpMethod httpRequestMethod = HttpMethod.valueOf(httpRequest.getMethod()); HttpMethod httpRequestMethod = HttpMethod.valueOf(httpRequest.getMethod());

View File

@ -65,7 +65,7 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
} }
@Override @Override
public ODataResponse createDebugResponse(DebugInformation debugInfo) { public ODataResponse createDebugResponse(final DebugInformation debugInfo) {
try { try {
final List<DebugTab> parts = createParts(debugInfo); final List<DebugTab> parts = createParts(debugInfo);
@ -100,7 +100,7 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
} }
} }
private List<DebugTab> createParts(DebugInformation debugInfo) { private List<DebugTab> createParts(final DebugInformation debugInfo) {
List<DebugTab> parts = new ArrayList<DebugTab>(); List<DebugTab> parts = new ArrayList<DebugTab>();
// request // request
@ -182,20 +182,18 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
} }
/** /**
* Get version field information for response. * Gets version field information for response. Result is never null.
* Result is never null.
*
* @return version field information * @return version field information
*/ */
private String getVersion() { protected static String getVersion() {
final String version = DebugResponseHelperImpl.class.getPackage().getImplementationVersion(); final Package pack = DebugResponseHelperImpl.class.getPackage();
if (version == null) { final String name = pack.getImplementationTitle();
return "Olingo"; final String version = pack.getImplementationVersion();
} return (name == null ? "Olingo" : name)
return "Olingo " + version; + (version == null ? "" : " Version " + version);
} }
private InputStream wrapInHtml(final List<DebugTab> parts, String title) throws IOException { private InputStream wrapInHtml(final List<DebugTab> parts, final String title) throws IOException {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
writer.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n") writer.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n")
@ -265,24 +263,29 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
return value == null ? null : value.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;"); return value == null ? null : value.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
} }
protected static void appendJsonTable(final JsonGenerator gen, final Map<String, String> entries) protected static void appendJsonTable(JsonGenerator gen, final Map<String, String> entries)
throws IOException { throws IOException {
gen.writeStartObject(); if (entries == null || entries.isEmpty()) {
gen.writeNull();
for (Map.Entry<String, String> entry : entries.entrySet()) {
if (entry.getValue() != null) {
gen.writeStringField(entry.getKey(), entry.getValue());
} else { } else {
gen.writeNullField(entry.getKey()); gen.writeStartObject();
for (Map.Entry<String, String> entry : entries.entrySet()) {
gen.writeFieldName(entry.getKey());
if (entry.getValue() == null) {
gen.writeNull();
} else {
gen.writeString(entry.getValue());
} }
} }
gen.writeEndObject(); gen.writeEndObject();
} }
}
protected static void appendHtmlTable(final Writer writer, final Map<String, String> entries) throws IOException { protected static void appendHtmlTable(Writer writer, final Map<String, String> entries) throws IOException {
writer.append("<table>\n<thead>\n") writer.append("<table>\n<thead>\n")
.append("<tr><th class=\"name\">Name</th><th class=\"value\">Value</th></tr>\n") .append("<tr><th class=\"name\">Name</th><th class=\"value\">Value</th></tr>\n")
.append("</thead>\n<tbody>\n"); .append("</thead>\n<tbody>\n");
if (entries != null && !entries.isEmpty()) {
for (final Entry<String, String> entry : entries.entrySet()) { for (final Entry<String, String> entry : entries.entrySet()) {
writer.append("<tr><td class=\"name\">").append(entry.getKey()).append("</td>") writer.append("<tr><td class=\"name\">").append(entry.getKey()).append("</td>")
.append("<td class=\"value\">"); .append("<td class=\"value\">");
@ -293,6 +296,7 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
} }
writer.append("</td></tr>\n"); writer.append("</td></tr>\n");
} }
}
writer.append("</tbody>\n</table>\n"); writer.append("</tbody>\n</table>\n");
} }
} }

View File

@ -106,12 +106,12 @@ public class DebugTabBody implements DebugTab {
case XML: case XML:
writer.append("<pre class=\"code").append(" xml").append("\">\n"); writer.append("<pre class=\"code").append(" xml").append("\">\n");
writer.append(DebugResponseHelperImpl.escapeHtml(body)); writer.append(DebugResponseHelperImpl.escapeHtml(body));
writer.append("</pre>\n"); writer.append("\n</pre>\n");
break; break;
case JSON: case JSON:
writer.append("<pre class=\"code").append(" json").append("\">\n"); writer.append("<pre class=\"code").append(" json").append("\">\n");
writer.append(DebugResponseHelperImpl.escapeHtml(body)); writer.append(DebugResponseHelperImpl.escapeHtml(body));
writer.append("</pre>\n"); writer.append("\n</pre>\n");
break; break;
case IMAGE: case IMAGE:
writer.append("<img src=\"data:").append(response.getHeader(HttpHeader.CONTENT_TYPE)).append(";base64,") writer.append("<img src=\"data:").append(response.getHeader(HttpHeader.CONTENT_TYPE)).append(";base64,")
@ -122,7 +122,7 @@ public class DebugTabBody implements DebugTab {
default: default:
writer.append("<pre class=\"code").append("\">\n"); writer.append("<pre class=\"code").append("\">\n");
writer.append(DebugResponseHelperImpl.escapeHtml(body)); writer.append(DebugResponseHelperImpl.escapeHtml(body));
writer.append("</pre>\n"); writer.append("\n</pre>\n");
break; break;
} }
} }

View File

@ -85,7 +85,7 @@ public class DebugTabResponse implements DebugTab {
private Map<String, String> map(Map<String, List<String>> headers) { private Map<String, String> map(Map<String, List<String>> headers) {
Map<String, String> result = new HashMap<String, String>(); Map<String, String> result = new HashMap<String, String>();
for (Map.Entry<String, List<String>> entry : headers.entrySet()) { for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
if(entry.getValue().size() == 1) { if (entry.getValue().size() == 1) {
result.put(entry.getKey(), entry.getValue().get(0)); result.put(entry.getKey(), entry.getValue().get(0));
} else { } else {
result.put(entry.getKey(), entry.getValue().toString()); result.put(entry.getKey(), entry.getValue().toString());
@ -105,7 +105,7 @@ public class DebugTabResponse implements DebugTab {
if (response != null && response.getContent() != null) { if (response != null && response.getContent() != null) {
new DebugTabBody(response).appendHtml(writer); new DebugTabBody(response).appendHtml(writer);
} else { } else {
writer.append("<p>ODataLibrary: no response body</p>"); writer.append("<p>ODataLibrary: no response body</p>\n");
} }
} }
} }

View File

@ -89,7 +89,7 @@ public class DebugTabRuntime implements DebugTab {
private void appendRuntimeNode(final RuntimeNode node, final String draw, final boolean isLast, final Writer writer) private void appendRuntimeNode(final RuntimeNode node, final String draw, final boolean isLast, final Writer writer)
throws IOException { throws IOException {
if (node.className != null) { if (node.className != null) {
writer.append("<li>") writer.append("<li>\n")
.append("<span class=\"code\">") .append("<span class=\"code\">")
.append("<span class=\"draw\">").append(draw) .append("<span class=\"draw\">").append(draw)
.append(isLast ? "&#x2514;" : "&#x251C;").append("&#x2500;&nbsp;</span>") .append(isLast ? "&#x2514;" : "&#x251C;").append("&#x2500;&nbsp;</span>")

View File

@ -42,22 +42,14 @@ public class DebugTabServer implements DebugTab {
@Override @Override
public void appendJson(JsonGenerator gen) throws IOException { public void appendJson(JsonGenerator gen) throws IOException {
if (serverEnvironmentVariables != null && !serverEnvironmentVariables.isEmpty()) {
DebugResponseHelperImpl.appendJsonTable(gen, serverEnvironmentVariables); DebugResponseHelperImpl.appendJsonTable(gen, serverEnvironmentVariables);
} else {
gen.writeNull();
}
} }
@Override @Override
public void appendHtml(Writer writer) throws IOException { public void appendHtml(Writer writer) throws IOException {
final Package pack = DebugResponseHelperImpl.class.getPackage();
writer.append("<h2>Library Version</h2>\n") writer.append("<h2>Library Version</h2>\n")
.append("<p>").append(pack.getImplementationTitle()) .append("<p>").append(DebugResponseHelperImpl.getVersion()).append("</p>\n")
.append(" Version ").append(pack.getImplementationVersion()).append("</p>\n")
.append("<h2>Server Environment</h2>\n"); .append("<h2>Server Environment</h2>\n");
if (serverEnvironmentVariables != null && !serverEnvironmentVariables.isEmpty()) {
DebugResponseHelperImpl.appendHtmlTable(writer, serverEnvironmentVariables); DebugResponseHelperImpl.appendHtmlTable(writer, serverEnvironmentVariables);
} }
}
} }

View File

@ -19,12 +19,9 @@
package org.apache.olingo.server.core.debug; package org.apache.olingo.server.core.debug;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer; import java.io.Writer;
import java.util.List; import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriResource; import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.queryoption.CountOption; import org.apache.olingo.server.api.uri.queryoption.CountOption;
@ -38,9 +35,7 @@ import org.apache.olingo.server.api.uri.queryoption.SelectOption;
import org.apache.olingo.server.api.uri.queryoption.SkipOption; import org.apache.olingo.server.api.uri.queryoption.SkipOption;
import org.apache.olingo.server.api.uri.queryoption.TopOption; import org.apache.olingo.server.api.uri.queryoption.TopOption;
import org.apache.olingo.server.api.uri.queryoption.expression.Expression; import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
@ -63,11 +58,6 @@ public class DebugTabUri implements DebugTab {
@Override @Override
public void appendJson(JsonGenerator gen) throws IOException { public void appendJson(JsonGenerator gen) throws IOException {
if (uriInfo == null) {
gen.writeNull();
return;
}
gen.writeStartObject(); gen.writeStartObject();
if (uriInfo.getFormatOption() != null) { if (uriInfo.getFormatOption() != null) {
@ -233,7 +223,7 @@ public class DebugTabUri implements DebugTab {
boolean first = true; boolean first = true;
for (UriResource resourcePart : selectItem.getResourcePath().getUriResourceParts()) { for (UriResource resourcePart : selectItem.getResourcePath().getUriResourceParts()) {
if (!first) { if (!first) {
selectedProperty = selectedProperty + "/"; selectedProperty += "/";
} }
selectedProperty = resourcePart.toString(); selectedProperty = resourcePart.toString();
first = false; first = false;
@ -245,62 +235,12 @@ public class DebugTabUri implements DebugTab {
@Override @Override
public void appendHtml(final Writer writer) throws IOException { public void appendHtml(final Writer writer) throws IOException {
if (uriInfo == null) {
return;
}
writer.append("<h2>Uri Information</h2>\n") writer.append("<h2>Uri Information</h2>\n")
.append("<ul class=\"json\"><li>"); .append("<ul class=\"json\">\n<li>\n");
writer.append(getJsonString()); JsonGenerator json = new JsonFactory().createGenerator(writer)
writer.append("</li></ul>\n");
}
private String getJsonString() throws IOException {
CircleStreamBuffer csb = new CircleStreamBuffer();
IOException cachedException = null;
OutputStream outputStream = csb.getOutputStream();
try {
JsonGenerator json =
new JsonFactory().createGenerator(outputStream, JsonEncoding.UTF8)
.setPrettyPrinter(new DefaultPrettyPrinter()); .setPrettyPrinter(new DefaultPrettyPrinter());
appendJson(json); appendJson(json);
json.close(); json.close();
outputStream.close(); writer.append("\n</li>\n</ul>\n");
} catch (IOException e) {
throw e;
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
if (cachedException != null) {
throw cachedException;
} else {
throw e;
}
}
}
}
InputStream inputStream = csb.getInputStream();
try {
String jsonString = IOUtils.toString(inputStream);
inputStream.close();
return jsonString;
} catch (IOException e) {
throw e;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
if (cachedException != null) {
throw cachedException;
} else {
throw e;
}
}
}
}
} }
} }

View File

@ -61,17 +61,16 @@ public class ServerCoreDebugger {
} }
} }
public ODataResponse createDebugResponse(final HttpServletRequest request, final Exception exception, public ODataResponse createDebugResponse(final ODataRequest request, final ODataResponse response,
final ODataRequest odRequest, final ODataResponse odResponse, UriInfo uriInfo, final Exception exception, final UriInfo uriInfo, final Map<String, String> serverEnvironmentVariables) {
Map<String, String> serverEnvironmentVariables) {
//Failsafe so we do not generate unauthorized debug messages //Failsafe so we do not generate unauthorized debug messages
if(!isDebugMode){ if (!isDebugMode) {
return odResponse; return response;
} }
try { try {
DebugInformation debugInfo = DebugInformation debugInfo =
createDebugInformation(request, exception, odRequest, odResponse, uriInfo, serverEnvironmentVariables); createDebugInformation(request, response, exception, uriInfo, serverEnvironmentVariables);
return debugSupport.createDebugResponse(debugFormat, debugInfo); return debugSupport.createDebugResponse(debugFormat, debugInfo);
} catch (Exception e) { } catch (Exception e) {
@ -88,16 +87,15 @@ public class ServerCoreDebugger {
return odResponse; return odResponse;
} }
private DebugInformation createDebugInformation(final HttpServletRequest request, final Exception exception, private DebugInformation createDebugInformation(final ODataRequest request, final ODataResponse response,
final ODataRequest odRequest, final ODataResponse odResponse, UriInfo uriInfo, final Exception exception, final UriInfo uriInfo, final Map<String, String> serverEnvironmentVariables) {
Map<String, String> serverEnvironmentVaribles) {
DebugInformation debugInfo = new DebugInformation(); DebugInformation debugInfo = new DebugInformation();
debugInfo.setRequest(odRequest); debugInfo.setRequest(request);
debugInfo.setApplicationResponse(odResponse); debugInfo.setApplicationResponse(response);
debugInfo.setException(exception); debugInfo.setException(exception);
debugInfo.setServerEnvironmentVariables(serverEnvironmentVaribles); debugInfo.setServerEnvironmentVariables(serverEnvironmentVariables);
debugInfo.setUriInfo(uriInfo); debugInfo.setUriInfo(uriInfo);

View File

@ -18,41 +18,28 @@
*/ */
package org.apache.olingo.server.core.debug; package org.apache.olingo.server.core.debug;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import org.apache.commons.io.IOUtils;
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
public abstract class AbstractDebugTabTest { public abstract class AbstractDebugTabTest {
protected String createHtml(DebugTab tab) throws Exception { protected String createHtml(DebugTab tab) throws IOException {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
tab.appendHtml(writer); tab.appendHtml(writer);
writer.flush(); writer.flush();
byte[] bytes = writer.toString().getBytes("UTF-8"); return writer.toString();
return IOUtils.toString(new ByteArrayInputStream(bytes));
} }
protected String createJson(DebugTab requestTab) throws IOException { protected String createJson(DebugTab tab) throws IOException {
CircleStreamBuffer csb = new CircleStreamBuffer(); StringWriter writer = new StringWriter();
JsonGenerator gen = new JsonFactory().createGenerator(csb.getOutputStream(), JsonEncoding.UTF8); JsonGenerator gen = new JsonFactory().createGenerator(writer);
requestTab.appendJson(gen); tab.appendJson(gen);
gen.flush(); gen.flush();
gen.close(); gen.close();
csb.closeWrite(); writer.flush();
return IOUtils.toString(csb.getInputStream()); return writer.toString();
} }
protected void print(DebugTab tab) throws Exception{
System.out.println(createJson(tab));
System.out.println("---------------------------------------------------------");
System.out.println(createHtml(tab));
}
} }

View File

@ -28,10 +28,7 @@ public class DebugTabBodyTest extends AbstractDebugTabTest {
public void nullResponseMustNotLeadToException() throws Exception { public void nullResponseMustNotLeadToException() throws Exception {
DebugTabBody tab = new DebugTabBody(null); DebugTabBody tab = new DebugTabBody(null);
String expectedHtml = "<pre class=\"code\">\n"
+ "ODataLibrary: No body.</pre>\n";
assertEquals("null", createJson(tab)); assertEquals("null", createJson(tab));
assertEquals(expectedHtml, createHtml(tab)); assertEquals("<pre class=\"code\">\nODataLibrary: No body.\n</pre>\n", createHtml(tab));
} }
} }

View File

@ -42,7 +42,7 @@ public class DebugTabResponseTest extends AbstractDebugTabTest {
+ "</tbody>\n" + "</tbody>\n"
+ "</table>\n" + "</table>\n"
+ "<h2>Response Body</h2>\n" + "<h2>Response Body</h2>\n"
+ "<p>ODataLibrary: no response body</p>"; + "<p>ODataLibrary: no response body</p>\n";
assertEquals(expectedJson, createJson(tab)); assertEquals(expectedJson, createJson(tab));
assertEquals(expectedHtml, createHtml(tab)); assertEquals(expectedHtml, createHtml(tab));
@ -71,7 +71,7 @@ public class DebugTabResponseTest extends AbstractDebugTabTest {
+ "</tbody>\n" + "</tbody>\n"
+ "</table>\n" + "</table>\n"
+ "<h2>Response Body</h2>\n" + "<h2>Response Body</h2>\n"
+ "<p>ODataLibrary: no response body</p>"; + "<p>ODataLibrary: no response body</p>\n";
assertEquals(expectedJson, createJson(tab)); assertEquals(expectedJson, createJson(tab));
assertEquals(expectedHtml, createHtml(tab)); assertEquals(expectedHtml, createHtml(tab));
} }

View File

@ -18,7 +18,8 @@
*/ */
package org.apache.olingo.server.core.debug; package org.apache.olingo.server.core.debug;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -35,18 +36,17 @@ public class DebugTabServerTest extends AbstractDebugTabTest {
assertEquals("null", createJson(serverTab)); assertEquals("null", createJson(serverTab));
String html = createHtml(serverTab); String html = createHtml(serverTab);
assertTrue(html.startsWith("<h2>Library Version</h2>")); assertTrue(html.startsWith("<h2>Library Version</h2>"));
assertTrue(html.endsWith("<h2>Server Environment</h2>\n")); assertTrue(html.contains("<h2>Server Environment</h2>\n"));
} }
@Test @Test
public void initialServerInformationMustNotleadToException() throws Exception { public void initialServerInformationMustNotleadToException() throws Exception {
Map<String, String> env = Collections.emptyMap(); DebugTabServer serverTab = new DebugTabServer(Collections.<String, String> emptyMap());
DebugTabServer serverTab = new DebugTabServer(env);
assertEquals("null", createJson(serverTab)); assertEquals("null", createJson(serverTab));
String html = createHtml(serverTab); String html = createHtml(serverTab);
assertTrue(html.startsWith("<h2>Library Version</h2>")); assertTrue(html.startsWith("<h2>Library Version</h2>"));
assertTrue(html.endsWith("<h2>Server Environment</h2>\n")); assertTrue(html.contains("<h2>Server Environment</h2>\n"));
} }
@Test @Test

View File

@ -18,9 +18,10 @@
*/ */
package org.apache.olingo.server.core.debug; package org.apache.olingo.server.core.debug;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -30,6 +31,7 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.olingo.commons.api.ex.ODataRuntimeException; import org.apache.olingo.commons.api.ex.ODataRuntimeException;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataResponse; import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.debug.DebugInformation; import org.apache.olingo.server.api.debug.DebugInformation;
@ -44,11 +46,15 @@ public class ServerCoreDebuggerTest {
@Before @Before
public void setupDebugger() { public void setupDebugger() {
debugger = new ServerCoreDebugger(OData.newInstance()); debugger = new ServerCoreDebugger(OData.newInstance());
debugger.setDebugSupportProcessor(new LocalDebugProcessor()); DebugSupport processor = mock(DebugSupport.class);
when(processor.isUserAuthorized()).thenReturn(true);
when(processor.createDebugResponse(anyString(), any(DebugInformation.class)))
.thenThrow(new ODataRuntimeException("Test"));
debugger.setDebugSupportProcessor(processor);
} }
@Test @Test
public void standardIsDebugModeIsFlase() { public void standardIsDebugModeIsFalse() {
assertFalse(debugger.isDebugMode()); assertFalse(debugger.isDebugMode());
} }
@ -86,36 +92,20 @@ public class ServerCoreDebuggerTest {
} }
@Test @Test
public void testFailResponse() throws IOException { public void failResponse() throws IOException {
HttpServletRequest request = mock(HttpServletRequest.class); HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getParameter(DebugSupport.ODATA_DEBUG_QUERY_PARAMETER)).thenReturn(DebugSupport.ODATA_DEBUG_JSON); when(request.getParameter(DebugSupport.ODATA_DEBUG_QUERY_PARAMETER)).thenReturn(DebugSupport.ODATA_DEBUG_JSON);
debugger.resolveDebugMode(request); debugger.resolveDebugMode(request);
ODataResponse debugResponse = debugger.createDebugResponse(null, null, null, null, null, null); ODataResponse debugResponse = debugger.createDebugResponse(null, null, null, null, null);
assertEquals(500, debugResponse.getStatusCode()); assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), debugResponse.getStatusCode());
assertEquals("ODataLibrary: Could not assemble debug response.", IOUtils.toString(debugResponse.getContent())); assertEquals("ODataLibrary: Could not assemble debug response.", IOUtils.toString(debugResponse.getContent()));
} }
@Test @Test
public void noDebugModeCreateDebugResponseCallMustDoNothing() { public void noDebugModeCreateDebugResponseCallMustDoNothing() {
ODataResponse odResponse = new ODataResponse(); ODataResponse odResponse = new ODataResponse();
ODataResponse debugResponse = debugger.createDebugResponse(null, null, null, odResponse, null, null); ODataResponse debugResponse = debugger.createDebugResponse(null, odResponse, null, null, null);
assertTrue(odResponse == debugResponse); assertEquals(odResponse, debugResponse);
}
public class LocalDebugProcessor implements DebugSupport {
@Override
public void init(OData odata) {}
@Override
public boolean isUserAuthorized() {
return true;
}
@Override
public ODataResponse createDebugResponse(String debugFormat, DebugInformation debugInfo) {
throw new ODataRuntimeException("Test");
}
} }
} }