[OLINGO-731] Added html as debug output and refactored structure
This commit is contained in:
parent
010d94f7f7
commit
3dae763f35
|
@ -31,7 +31,7 @@ import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||||
public class ODataResponse {
|
public class ODataResponse {
|
||||||
|
|
||||||
private int statusCode = HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode();
|
private int statusCode = HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode();
|
||||||
private Map<String, String> headers = new HashMap<String, String>();
|
private final Map<String, String> headers = new HashMap<String, String>();
|
||||||
private InputStream content;
|
private InputStream content;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* 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.olingo.server.api.debug;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.olingo.server.api.ODataRequest;
|
||||||
|
import org.apache.olingo.server.api.ODataResponse;
|
||||||
|
import org.apache.olingo.server.api.uri.UriInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class contains all information necessary to construct a debug response.
|
||||||
|
*/
|
||||||
|
public class DebugInformation {
|
||||||
|
|
||||||
|
private ODataRequest request;
|
||||||
|
private ODataResponse applicationResponse;
|
||||||
|
private UriInfo uriInfo;
|
||||||
|
private Exception exception;
|
||||||
|
private Map<String, String> serverEnvironmentVaribles;
|
||||||
|
private List<RuntimeMeasurement> runtimeInformation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will return the ODataRequest the library created. This request will never be null but might be filled
|
||||||
|
* incompletely if there has been an exception during the request parsing.
|
||||||
|
* @return the ODataRequest the library built
|
||||||
|
*/
|
||||||
|
public ODataRequest getRequest() {
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequest(ODataRequest request) {
|
||||||
|
this.request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will return the ODataResponse which was filled by the Application or the library in an exception case.
|
||||||
|
* The response might be null or might not be filled completely.
|
||||||
|
* @return the response filled by the application
|
||||||
|
*/
|
||||||
|
public ODataResponse getApplicationResponse() {
|
||||||
|
return applicationResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationResponse(ODataResponse applicationResponse) {
|
||||||
|
this.applicationResponse = applicationResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URI Info object the library created during URI parsing. Might be null if there was an exception during URI
|
||||||
|
* parsing.
|
||||||
|
* @return the URI Info Object
|
||||||
|
*/
|
||||||
|
public UriInfo getUriInfo() {
|
||||||
|
return uriInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUriInfo(UriInfo uriInfo) {
|
||||||
|
this.uriInfo = uriInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will return any exception that was thrown from the application or library. Will be null if there was no
|
||||||
|
* exception.
|
||||||
|
* @return an exception if thrown.
|
||||||
|
*/
|
||||||
|
public Exception getException() {
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setException(Exception exception) {
|
||||||
|
this.exception = exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map containing information about the runtime environment. Depending on the servlet or webserver used this map
|
||||||
|
* might contain different information. Will never be null but might be empty.
|
||||||
|
* @return environment variables
|
||||||
|
*/
|
||||||
|
public Map<String, String> getServerEnvironmentVaribles() {
|
||||||
|
return serverEnvironmentVaribles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServerEnvironmentVaribles(Map<String, String> serverEnvironmentVaribles) {
|
||||||
|
this.serverEnvironmentVaribles = serverEnvironmentVaribles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will return all runtime information which was collected inside the library. Might be null if no data
|
||||||
|
* could be collected.
|
||||||
|
* @return runtime information collected by the library
|
||||||
|
*/
|
||||||
|
public List<RuntimeMeasurement> getRuntimeInformation() {
|
||||||
|
return runtimeInformation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRuntimeInformation(List<RuntimeMeasurement> runtimeInformation) {
|
||||||
|
this.runtimeInformation = runtimeInformation;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,10 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.olingo.server.api.debug;
|
package org.apache.olingo.server.api.debug;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.olingo.server.api.ODataRequest;
|
|
||||||
import org.apache.olingo.server.api.ODataResponse;
|
import org.apache.olingo.server.api.ODataResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,6 +34,5 @@ public interface DebugResponseHelper {
|
||||||
* @param runtimeInformation
|
* @param runtimeInformation
|
||||||
* @return the debug response or the raw application response in case an exception occurred.
|
* @return the debug response or the raw application response in case an exception occurred.
|
||||||
*/
|
*/
|
||||||
ODataResponse createDebugResponse(ODataRequest request, ODataResponse applicationResponse, Exception exception,
|
ODataResponse createDebugResponse(DebugInformation debugInfo);
|
||||||
Map<String, String> serverEnvironmentVaribles, List<RuntimeMeasurement> runtimeInformation);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.olingo.server.api.debug;
|
package org.apache.olingo.server.api.debug;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.olingo.server.api.OData;
|
import org.apache.olingo.server.api.OData;
|
||||||
import org.apache.olingo.server.api.ODataRequest;
|
|
||||||
import org.apache.olingo.server.api.ODataResponse;
|
import org.apache.olingo.server.api.ODataResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,8 +31,11 @@ public interface DebugSupport {
|
||||||
public static final String ODATA_DEBUG_HTML = "html";
|
public static final String ODATA_DEBUG_HTML = "html";
|
||||||
public static final String ODATA_DEBUG_DOWNLOAD = "download";
|
public static final String ODATA_DEBUG_DOWNLOAD = "download";
|
||||||
|
|
||||||
|
//TODO:JavaDoc
|
||||||
void init(OData odata);
|
void init(OData odata);
|
||||||
|
|
||||||
|
boolean isUserAuthorized();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method should create a debug response and deliver it back to the Olingo library. This method MUST NEVER throw
|
* This method should create a debug response and deliver it back to the Olingo library. This method MUST NEVER throw
|
||||||
* an exception.
|
* an exception.
|
||||||
|
@ -46,7 +45,6 @@ public interface DebugSupport {
|
||||||
* @param exception which has been thrown. Might be null in case there was no exception
|
* @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
|
* @return a new debug response which will be send to the client
|
||||||
*/
|
*/
|
||||||
ODataResponse createDebugResponse(String debugFormat, ODataRequest request, ODataResponse response,
|
ODataResponse createDebugResponse(String debugFormat, DebugInformation debugInfo);
|
||||||
Exception exception, Map<String, String> serverEnvironmentVaribles, List<RuntimeMeasurement> runtimeInformation);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.olingo.server.api.debug;
|
package org.apache.olingo.server.api.debug;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.olingo.server.api.OData;
|
import org.apache.olingo.server.api.OData;
|
||||||
import org.apache.olingo.server.api.ODataRequest;
|
|
||||||
import org.apache.olingo.server.api.ODataResponse;
|
import org.apache.olingo.server.api.ODataResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,18 +34,21 @@ public class DefaultDebugSupport implements DebugSupport {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ODataResponse createDebugResponse(String debugFormat, ODataRequest request, ODataResponse applicationResponse,
|
public boolean isUserAuthorized() {
|
||||||
Exception exception, Map<String, String> serverEnvironmentVaribles, List<RuntimeMeasurement> runtimeInformation) {
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ODataResponse createDebugResponse(String debugFormat, DebugInformation debugInfo) {
|
||||||
// Check if debugFormat is supported by the library
|
// Check if debugFormat is supported by the library
|
||||||
if (DebugSupport.ODATA_DEBUG_JSON.equalsIgnoreCase(debugFormat)
|
if (DebugSupport.ODATA_DEBUG_JSON.equalsIgnoreCase(debugFormat)
|
||||||
|| DebugSupport.ODATA_DEBUG_HTML.equalsIgnoreCase(debugFormat)
|
|| DebugSupport.ODATA_DEBUG_HTML.equalsIgnoreCase(debugFormat)
|
||||||
|| DebugSupport.ODATA_DEBUG_DOWNLOAD.equalsIgnoreCase(debugFormat)) {
|
|| DebugSupport.ODATA_DEBUG_DOWNLOAD.equalsIgnoreCase(debugFormat)) {
|
||||||
return odata.createDebugResponseHelper(debugFormat).createDebugResponse(request, applicationResponse, exception,
|
return odata.createDebugResponseHelper(debugFormat).createDebugResponse(debugInfo);
|
||||||
serverEnvironmentVaribles, runtimeInformation);
|
|
||||||
} else {
|
} else {
|
||||||
// Debug format is not supported by the library by default so in order to avoid an exception we will just give
|
// Debug format is not supported by the library by default so in order to avoid an exception we will just give
|
||||||
// back the original response from the application.
|
// back the original response from the application.
|
||||||
return applicationResponse;
|
return debugInfo.getApplicationResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ import org.apache.olingo.server.api.serializer.CustomContentTypeSupport;
|
||||||
import org.apache.olingo.server.api.serializer.RepresentationType;
|
import org.apache.olingo.server.api.serializer.RepresentationType;
|
||||||
import org.apache.olingo.server.api.serializer.SerializerException;
|
import org.apache.olingo.server.api.serializer.SerializerException;
|
||||||
import org.apache.olingo.server.api.uri.UriInfo;
|
import org.apache.olingo.server.api.uri.UriInfo;
|
||||||
|
import org.apache.olingo.server.core.debug.ServerCoreDebugger;
|
||||||
import org.apache.olingo.server.core.uri.parser.Parser;
|
import org.apache.olingo.server.core.uri.parser.Parser;
|
||||||
import org.apache.olingo.server.core.uri.parser.UriParserException;
|
import org.apache.olingo.server.core.uri.parser.UriParserException;
|
||||||
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
|
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
|
||||||
|
@ -54,15 +55,18 @@ public class ODataHandler {
|
||||||
private final OData odata;
|
private final OData odata;
|
||||||
private final ServiceMetadata serviceMetadata;
|
private final ServiceMetadata serviceMetadata;
|
||||||
private final List<Processor> processors = new LinkedList<Processor>();
|
private final List<Processor> processors = new LinkedList<Processor>();
|
||||||
|
private final ServerCoreDebugger debugger;
|
||||||
|
|
||||||
private CustomContentTypeSupport customContentTypeSupport;
|
private CustomContentTypeSupport customContentTypeSupport;
|
||||||
private CustomETagSupport customETagSupport;
|
private CustomETagSupport customETagSupport;
|
||||||
|
|
||||||
private UriInfo uriInfo;
|
private UriInfo uriInfo;
|
||||||
private Exception lastThrownException;
|
private Exception lastThrownException;
|
||||||
|
|
||||||
public ODataHandler(final OData server, final ServiceMetadata serviceMetadata) {
|
public ODataHandler(final OData server, final ServiceMetadata serviceMetadata, ServerCoreDebugger debugger) {
|
||||||
odata = server;
|
odata = server;
|
||||||
this.serviceMetadata = serviceMetadata;
|
this.serviceMetadata = serviceMetadata;
|
||||||
|
this.debugger = debugger;
|
||||||
|
|
||||||
register(new DefaultRedirectProcessor());
|
register(new DefaultRedirectProcessor());
|
||||||
register(new DefaultProcessor());
|
register(new DefaultProcessor());
|
||||||
|
@ -192,4 +196,8 @@ public class ODataHandler {
|
||||||
public Exception getLastThrownException() {
|
public Exception getLastThrownException() {
|
||||||
return lastThrownException;
|
return lastThrownException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UriInfo getUriInfo(){
|
||||||
|
return uriInfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,19 +35,19 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
import org.apache.olingo.commons.api.ODataRuntimeException;
|
import org.apache.olingo.commons.api.ODataRuntimeException;
|
||||||
import org.apache.olingo.commons.api.http.HttpHeader;
|
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||||
import org.apache.olingo.commons.api.http.HttpMethod;
|
import org.apache.olingo.commons.api.http.HttpMethod;
|
||||||
import org.apache.olingo.server.api.ODataServerError;
|
|
||||||
import org.apache.olingo.server.api.OData;
|
import org.apache.olingo.server.api.OData;
|
||||||
import org.apache.olingo.server.api.ODataHttpHandler;
|
import org.apache.olingo.server.api.ODataHttpHandler;
|
||||||
|
import org.apache.olingo.server.api.ODataLibraryException;
|
||||||
import org.apache.olingo.server.api.ODataRequest;
|
import org.apache.olingo.server.api.ODataRequest;
|
||||||
import org.apache.olingo.server.api.ODataResponse;
|
import org.apache.olingo.server.api.ODataResponse;
|
||||||
import org.apache.olingo.server.api.ODataLibraryException;
|
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.debug.RuntimeMeasurement;
|
|
||||||
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.api.serializer.SerializerException;
|
||||||
|
import org.apache.olingo.server.core.debug.ServerCoreDebugger;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -56,99 +56,52 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ODataHttpHandlerImpl.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ODataHttpHandlerImpl.class);
|
||||||
|
|
||||||
private final ODataHandler handler;
|
private final ODataHandler handler;
|
||||||
private final OData odata;
|
private final ServerCoreDebugger debugger;
|
||||||
|
|
||||||
private int split = 0;
|
private int split = 0;
|
||||||
|
|
||||||
// debug stuff
|
|
||||||
private final List<RuntimeMeasurement> runtimeInformation = new ArrayList<RuntimeMeasurement>();
|
|
||||||
private DebugSupport debugSupport;
|
|
||||||
private String debugFormat;
|
|
||||||
private boolean isDebugMode = false;
|
|
||||||
|
|
||||||
public ODataHttpHandlerImpl(final OData odata, final ServiceMetadata serviceMetadata) {
|
public ODataHttpHandlerImpl(final OData odata, final ServiceMetadata serviceMetadata) {
|
||||||
this.odata = odata;
|
debugger = new ServerCoreDebugger(odata);
|
||||||
handler = new ODataHandler(odata, serviceMetadata);
|
handler = new ODataHandler(odata, serviceMetadata, debugger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(final HttpServletRequest request, final HttpServletResponse response) {
|
public void process(final HttpServletRequest request, final HttpServletResponse response) {
|
||||||
|
ODataRequest odRequest = new ODataRequest();
|
||||||
Exception exception = null;
|
Exception exception = null;
|
||||||
ODataRequest odRequest = null;
|
|
||||||
ODataResponse odResponse;
|
ODataResponse odResponse;
|
||||||
resolveDebugMode(request);
|
debugger.resolveDebugMode(request);
|
||||||
int processMethodHandel = startRuntimeMeasurement("ODataHttpHandlerImpl", "process");
|
|
||||||
|
|
||||||
|
int processMethodHandel = debugger.startRuntimeMeasurement("ODataHttpHandlerImpl", "process");
|
||||||
try {
|
try {
|
||||||
odRequest = new ODataRequest();
|
int requestHandel = debugger.startRuntimeMeasurement("ODataHttpHandlerImpl", "fillODataRequest");
|
||||||
int requestHandel = startRuntimeMeasurement("ODataHttpHandlerImpl", "fillODataRequest");
|
|
||||||
fillODataRequest(odRequest, request, split);
|
fillODataRequest(odRequest, request, split);
|
||||||
stopRuntimeMeasurement(requestHandel);
|
debugger.stopRuntimeMeasurement(requestHandel);
|
||||||
|
|
||||||
int responseHandel = startRuntimeMeasurement("ODataHandler", "process");
|
int responseHandel = debugger.startRuntimeMeasurement("ODataHandler", "process");
|
||||||
odResponse = handler.process(odRequest);
|
odResponse = handler.process(odRequest);
|
||||||
stopRuntimeMeasurement(responseHandel);
|
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);
|
||||||
}
|
}
|
||||||
stopRuntimeMeasurement(processMethodHandel);
|
debugger.stopRuntimeMeasurement(processMethodHandel);
|
||||||
|
|
||||||
if (isDebugMode) {
|
if (debugger.isDebugMode()) {
|
||||||
debugSupport.init(odata);
|
Map<String, String> serverEnvironmentVaribles = createEnvironmentVariablesMap(request);
|
||||||
// TODO: Should we be more careful here with response assignement in order to not loose the original response?
|
|
||||||
// TODO: How should we react to exceptions here?
|
|
||||||
if (exception == null) {
|
if (exception == null) {
|
||||||
// This is to ensure that we have access to the thrown OData Exception
|
// This is to ensure that we have access to the thrown OData Exception
|
||||||
// TODO: Should we make this hack
|
|
||||||
exception = handler.getLastThrownException();
|
exception = handler.getLastThrownException();
|
||||||
}
|
}
|
||||||
Map<String, String> serverEnvironmentVaribles = createEnvironmentVariablesMap(request);
|
|
||||||
|
|
||||||
odResponse =
|
odResponse =
|
||||||
debugSupport.createDebugResponse(debugFormat, odRequest, odResponse, exception, serverEnvironmentVaribles,
|
debugger.createDebugResponse(request, exception, odRequest, odResponse, handler.getUriInfo(),
|
||||||
runtimeInformation);
|
serverEnvironmentVaribles);
|
||||||
}
|
}
|
||||||
|
|
||||||
convertToHttp(response, odResponse);
|
convertToHttp(response, odResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveDebugMode(HttpServletRequest request) {
|
|
||||||
if (debugSupport != null) {
|
|
||||||
// Should we read the parameter from the servlet here and ignore multiple parameters?
|
|
||||||
debugFormat = request.getParameter(DebugSupport.ODATA_DEBUG_QUERY_PARAMETER);
|
|
||||||
// Debug format is present and we have a debug support processor registered so we are in debug mode
|
|
||||||
isDebugMode = debugFormat != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int startRuntimeMeasurement(final String className, final String methodName) {
|
|
||||||
if (isDebugMode) {
|
|
||||||
int handleId = runtimeInformation.size();
|
|
||||||
|
|
||||||
final RuntimeMeasurement measurement = new RuntimeMeasurement();
|
|
||||||
measurement.setTimeStarted(System.nanoTime());
|
|
||||||
measurement.setClassName(className);
|
|
||||||
measurement.setMethodName(methodName);
|
|
||||||
|
|
||||||
runtimeInformation.add(measurement);
|
|
||||||
|
|
||||||
return handleId;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopRuntimeMeasurement(final int handle) {
|
|
||||||
if (isDebugMode && handle < runtimeInformation.size()) {
|
|
||||||
long stopTime = System.nanoTime();
|
|
||||||
RuntimeMeasurement runtimeMeasurement = runtimeInformation.get(handle);
|
|
||||||
if (runtimeMeasurement != null) {
|
|
||||||
runtimeMeasurement.setTimeStopped(stopTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, String> createEnvironmentVariablesMap(HttpServletRequest request) {
|
private Map<String, String> createEnvironmentVariablesMap(HttpServletRequest request) {
|
||||||
LinkedHashMap<String, String> environment = new LinkedHashMap<String, String>();
|
LinkedHashMap<String, String> environment = new LinkedHashMap<String, String>();
|
||||||
environment.put("authType", request.getAuthType());
|
environment.put("authType", request.getAuthType());
|
||||||
|
@ -350,6 +303,6 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(final DebugSupport debugSupport) {
|
public void register(final DebugSupport debugSupport) {
|
||||||
this.debugSupport = debugSupport;
|
debugger.setDebugSupportProcessor(debugSupport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,150 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.olingo.server.core.debug;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Writer;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.olingo.commons.api.http.HttpHeader;
|
|
||||||
import org.apache.olingo.server.api.ODataResponse;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response body debug information.
|
|
||||||
*/
|
|
||||||
public class DebugInfoBody implements DebugInfo {
|
|
||||||
|
|
||||||
private static enum ResponseContent {JSON, XML, TEXT, IMAGE};
|
|
||||||
|
|
||||||
private final ODataResponse response;
|
|
||||||
private final ResponseContent responseContent;
|
|
||||||
|
|
||||||
//private final String serviceRoot;
|
|
||||||
// private final boolean isXml;
|
|
||||||
// private final boolean isJson;
|
|
||||||
// private final boolean isText;
|
|
||||||
// private final boolean isImage;
|
|
||||||
|
|
||||||
public DebugInfoBody(final ODataResponse response, final String serviceRoot) {
|
|
||||||
this.response = response;
|
|
||||||
// TODO: make header case insensitive
|
|
||||||
final String contentType = response.getHeaders().get(HttpHeader.CONTENT_TYPE);
|
|
||||||
//TODO: Differentiate better
|
|
||||||
if (contentType != null) {
|
|
||||||
responseContent = ResponseContent.JSON;
|
|
||||||
} else {
|
|
||||||
responseContent = ResponseContent.TEXT;
|
|
||||||
}
|
|
||||||
// isXml = contentType.contains("xml");
|
|
||||||
// isJson = !isXml && contentType.startsWith(HttpContentType.APPLICATION_JSON);
|
|
||||||
// isText = isXml || isJson || contentType.startsWith("text/")
|
|
||||||
// || contentType.startsWith(HttpContentType.APPLICATION_HTTP)
|
|
||||||
// || contentType.startsWith(HttpContentType.MULTIPART_MIXED);
|
|
||||||
// isImage = !isText && contentType.startsWith("image/");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "Body";
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
@Override
|
|
||||||
public void appendJson(final JsonGenerator gen) throws IOException {
|
|
||||||
gen.writeString(getContentString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getContentString() {
|
|
||||||
try {
|
|
||||||
String contentString;
|
|
||||||
switch (responseContent) {
|
|
||||||
case IMAGE:
|
|
||||||
//TODO: DecodeString as base 64
|
|
||||||
contentString = "Currently not supported";
|
|
||||||
break;
|
|
||||||
case JSON:
|
|
||||||
case XML:
|
|
||||||
case TEXT:
|
|
||||||
default:
|
|
||||||
// TODO: Remove IOUtils from core dependency
|
|
||||||
contentString = IOUtils.toString(response.getContent(), "UTF-8");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return contentString;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return "Could not parse Body for Debug Output";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void appendHtml(final Writer writer) throws IOException {
|
|
||||||
// final String body = getContentString();
|
|
||||||
// if (isImage) {
|
|
||||||
// writer.append("<img src=\"data:").append(response.getContentHeader()).append(";base64,")
|
|
||||||
// .append(body)
|
|
||||||
// .append("\" />\n");
|
|
||||||
// } else {
|
|
||||||
// writer.append("<pre class=\"code").append(isXml ? " xml" : isJson ? " json" : "").append("\">\n")
|
|
||||||
// .append(isXml || isJson ?
|
|
||||||
// addLinks(ODataDebugResponseWrapper.escapeHtml(isXml ? formatXml(body) : formatJson(body)), isXml) :
|
|
||||||
// ODataDebugResponseWrapper.escapeHtml(body))
|
|
||||||
// .append("</pre>\n");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private String formatXml(final String xml) throws IOException {
|
|
||||||
// try {
|
|
||||||
// Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
|
||||||
// transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
|
||||||
// transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
|
||||||
// StreamResult outputTarget = new StreamResult(new StringWriter());
|
|
||||||
// transformer.transform(new StreamSource(new StringReader(xml)), outputTarget);
|
|
||||||
// return outputTarget.getWriter().toString();
|
|
||||||
// } catch (final TransformerException e) {
|
|
||||||
// return xml;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private String formatJson(final String json) {
|
|
||||||
// return new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create().toJson(new JsonParser().parse(json));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private String addLinks(final String source, final boolean isXml) {
|
|
||||||
// final String debugOption = ODataDebugResponseWrapper.ODATA_DEBUG_QUERY_PARAMETER + "="
|
|
||||||
// + ODataDebugResponseWrapper.ODATA_DEBUG_HTML;
|
|
||||||
// final String urlPattern = "("
|
|
||||||
// + (isXml ? "(?:href|src|base)=" : "\"(?:uri|media_src|edit_media|__next)\":\\p{Space}*")
|
|
||||||
// + "\")(.+?)\"";
|
|
||||||
// return (isXml ? source.replaceAll("(xmlns(?::\\p{Alnum}+)?=\")(.+?)\"", "$1<span class=\"ns\">$2</span>\"") :
|
|
||||||
// source)
|
|
||||||
// .replaceAll(urlPattern, "$1<a href=\"" + serviceRoot + "$2?" + debugOption + "\">$2</a>\"")
|
|
||||||
// .replaceAll("(<a href=\"" + Pattern.quote(serviceRoot) + ')' + Pattern.quote(serviceRoot), "$1")
|
|
||||||
// .replaceAll("<a href=\"(.+?)\\?(.+?)\\?" + debugOption, "<a href=\"$1?$2&" + debugOption)
|
|
||||||
// .replaceAll("&amp;", "&");
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void appendHtml(Writer writer) throws IOException {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.olingo.server.core.debug;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server debug information.
|
|
||||||
*/
|
|
||||||
public class DebugInfoServer implements DebugInfo {
|
|
||||||
|
|
||||||
private final Map<String, String> serverEnvironmentVaribles;
|
|
||||||
|
|
||||||
public DebugInfoServer(Map<String, String> serverEnvironmentVaribles) {
|
|
||||||
this.serverEnvironmentVaribles = serverEnvironmentVaribles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "Environment";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void appendJson(JsonGenerator gen) throws IOException {
|
|
||||||
DebugResponseHelperImpl.appendJsonTable(gen, serverEnvironmentVaribles);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void appendHtml(Writer writer) throws IOException {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// private final Map<String, String> environment;
|
|
||||||
//
|
|
||||||
// public DebugInfoServer(final HttpServletRequest httpServletRequest) {
|
|
||||||
// environment = new TreeMap<String, String>();
|
|
||||||
// environment.put("authType", httpServletRequest.getAuthType());
|
|
||||||
// environment.put("localAddr", httpServletRequest.getLocalAddr());
|
|
||||||
// environment.put("localName", httpServletRequest.getLocalName());
|
|
||||||
// addInt("localPort", httpServletRequest.getLocalPort());
|
|
||||||
// environment.put("pathInfo", httpServletRequest.getPathInfo());
|
|
||||||
// environment.put("pathTranslated", httpServletRequest.getPathTranslated());
|
|
||||||
// environment.put("remoteAddr", httpServletRequest.getRemoteAddr());
|
|
||||||
// environment.put("remoteHost", httpServletRequest.getRemoteHost());
|
|
||||||
// addInt("remotePort", httpServletRequest.getRemotePort());
|
|
||||||
// environment.put("remoteUser", httpServletRequest.getRemoteUser());
|
|
||||||
// environment.put("scheme", httpServletRequest.getScheme());
|
|
||||||
// environment.put("serverName", httpServletRequest.getServerName());
|
|
||||||
// addInt("serverPort", httpServletRequest.getServerPort());
|
|
||||||
// environment.put("servletPath", httpServletRequest.getServletPath());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public void appendHtml(final Writer writer) throws IOException {
|
|
||||||
// final Package pack = ODataDebugResponseWrapper.class.getPackage();
|
|
||||||
// writer.append("<h2>Library Version</h2>\n")
|
|
||||||
// .append("<p>").append(pack.getImplementationTitle())
|
|
||||||
// .append(" Version ").append(pack.getImplementationVersion()).append("</p>\n")
|
|
||||||
// .append("<h2>Server Environment</h2>\n");
|
|
||||||
// ODataDebugResponseWrapper.appendHtmlTable(writer, environment);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private void addInt(final String name, final int number) {
|
|
||||||
// environment.put(name, number == 0 ? null : Integer.toString(number));
|
|
||||||
// }
|
|
||||||
}
|
|
|
@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -32,8 +33,8 @@ import org.apache.olingo.commons.api.ODataRuntimeException;
|
||||||
import org.apache.olingo.commons.api.format.ContentType;
|
import org.apache.olingo.commons.api.format.ContentType;
|
||||||
import org.apache.olingo.commons.api.http.HttpHeader;
|
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||||
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||||
import org.apache.olingo.server.api.ODataRequest;
|
|
||||||
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.DebugResponseHelper;
|
import org.apache.olingo.server.api.debug.DebugResponseHelper;
|
||||||
import org.apache.olingo.server.api.debug.DebugSupport;
|
import org.apache.olingo.server.api.debug.DebugSupport;
|
||||||
import org.apache.olingo.server.api.debug.RuntimeMeasurement;
|
import org.apache.olingo.server.api.debug.RuntimeMeasurement;
|
||||||
|
@ -62,12 +63,9 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ODataResponse createDebugResponse(ODataRequest request, ODataResponse applicationResponse,
|
public ODataResponse createDebugResponse(DebugInformation debugInfo) {
|
||||||
Exception exception, Map<String, String> serverEnvironmentVaribles, List<RuntimeMeasurement> runtimeInformation) {
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final List<DebugInfo> parts =
|
final List<DebugTab> parts = createParts(debugInfo);
|
||||||
createParts(request, applicationResponse, exception, serverEnvironmentVaribles, runtimeInformation);
|
|
||||||
|
|
||||||
ODataResponse response = new ODataResponse();
|
ODataResponse response = new ODataResponse();
|
||||||
String contentTypeString;
|
String contentTypeString;
|
||||||
|
@ -78,7 +76,9 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
|
||||||
+ new Date().toString().replace(' ', '_').replace(':', '.') + ".html");
|
+ new Date().toString().replace(' ', '_').replace(':', '.') + ".html");
|
||||||
// Download is the same as html except for the above header
|
// Download is the same as html except for the above header
|
||||||
case HTML:
|
case HTML:
|
||||||
body = wrapInHtml(parts);
|
String title = debugInfo.getRequest() == null ?
|
||||||
|
"V4 Service" : "V4 Service: " + debugInfo.getRequest().getRawODataPath();
|
||||||
|
body = wrapInHtml(parts, title);
|
||||||
contentTypeString = ContentType.TEXT_HTML.toContentTypeString();
|
contentTypeString = ContentType.TEXT_HTML.toContentTypeString();
|
||||||
break;
|
break;
|
||||||
case JSON:
|
case JSON:
|
||||||
|
@ -93,65 +93,58 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// Should not happen
|
// Should not happen. In case it does the library will deliver a default response. So no handling here.
|
||||||
// TODO: Check what we can do here.
|
|
||||||
throw new ODataRuntimeException(e);
|
throw new ODataRuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<DebugInfo> createParts(ODataRequest request, ODataResponse applicationResponse, Exception exception,
|
private List<DebugTab> createParts(DebugInformation debugInfo) {
|
||||||
Map<String, String> serverEnvironmentVaribles, List<RuntimeMeasurement> runtimeInformation) {
|
List<DebugTab> parts = new ArrayList<DebugTab>();
|
||||||
List<DebugInfo> parts = new ArrayList<DebugInfo>();
|
|
||||||
|
|
||||||
// request
|
// request
|
||||||
parts.add(new DebugInfoRequest(request));
|
parts.add(new DebugTabRequest(debugInfo.getRequest()));
|
||||||
|
|
||||||
// response
|
// response
|
||||||
// TODO: Check service URI
|
parts.add(new DebugTabResponse(debugInfo.getApplicationResponse(), debugInfo.getRequest().getRawBaseUri()));
|
||||||
parts.add(new DebugInfoResponse(applicationResponse, request.getRawBaseUri()));
|
|
||||||
|
|
||||||
// server
|
// server
|
||||||
|
Map<String, String> serverEnvironmentVaribles = debugInfo.getServerEnvironmentVaribles();
|
||||||
if (serverEnvironmentVaribles != null && !serverEnvironmentVaribles.isEmpty()) {
|
if (serverEnvironmentVaribles != null && !serverEnvironmentVaribles.isEmpty()) {
|
||||||
parts.add(new DebugInfoServer(serverEnvironmentVaribles));
|
parts.add(new DebugTabServer(serverEnvironmentVaribles));
|
||||||
}
|
}
|
||||||
|
|
||||||
// // URI
|
// TODO:Enable URIDebugInfo
|
||||||
// Throwable candidate = exception;
|
// URI
|
||||||
// while (candidate != null && !(candidate instanceof ExpressionParserException)) {
|
// if (uriInfo != null && (uriInfo.getFilterOption() != null || uriInfo.getOrderByOption() != null
|
||||||
// candidate = candidate.getCause();
|
// || uriInfo.getExpandOption() != null || uriInfo.getSelectOption() != null)) {
|
||||||
|
// parts.add(new DebugInfoUri(uriInfo));
|
||||||
// }
|
// }
|
||||||
// final ExpressionParserException expressionParserException = (ExpressionParserException) candidate;
|
|
||||||
// if (uriInfo != null
|
// runtime measurements
|
||||||
// && (uriInfo.getFilter() != null || uriInfo.getOrderBy() != null
|
List<RuntimeMeasurement> runtimeInformation = debugInfo.getRuntimeInformation();
|
||||||
// || !uriInfo.getExpand().isEmpty() || !uriInfo.getSelect().isEmpty())
|
|
||||||
// || expressionParserException != null && expressionParserException.getFilterTree() != null) {
|
|
||||||
// parts.add(new DebugInfoUri(uriInfo, expressionParserException));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // runtime measurements
|
|
||||||
if (runtimeInformation != null && !runtimeInformation.isEmpty()) {
|
if (runtimeInformation != null && !runtimeInformation.isEmpty()) {
|
||||||
parts.add(new DebugInfoRuntime(runtimeInformation));
|
parts.add(new DebugTabRuntime(runtimeInformation));
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// // exceptions
|
// exceptions
|
||||||
if (exception != null) {
|
if (debugInfo.getException() != null) {
|
||||||
parts.add(new DebugInfoException(exception));
|
parts.add(new DebugTabException(debugInfo.getException()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream wrapInJson(final List<DebugInfo> parts) throws IOException {
|
private InputStream wrapInJson(final List<DebugTab> parts) throws IOException {
|
||||||
CircleStreamBuffer csb = new CircleStreamBuffer();
|
CircleStreamBuffer csb = new CircleStreamBuffer();
|
||||||
JsonGenerator gen = new JsonFactory().createGenerator(csb.getOutputStream(), JsonEncoding.UTF8);
|
JsonGenerator gen = new JsonFactory().createGenerator(csb.getOutputStream(), JsonEncoding.UTF8);
|
||||||
|
|
||||||
gen.writeStartObject();
|
gen.writeStartObject();
|
||||||
DebugInfo requestInfo = parts.get(0);
|
DebugTab requestInfo = parts.get(0);
|
||||||
// TODO: Should we really translate to lower case here?
|
// TODO: Should we really translate to lower case here?
|
||||||
gen.writeFieldName(requestInfo.getName().toLowerCase(Locale.ROOT));
|
gen.writeFieldName(requestInfo.getName().toLowerCase(Locale.ROOT));
|
||||||
requestInfo.appendJson(gen);
|
requestInfo.appendJson(gen);
|
||||||
|
|
||||||
DebugInfo responseInfo = parts.get(1);
|
DebugTab responseInfo = parts.get(1);
|
||||||
gen.writeFieldName(responseInfo.getName().toLowerCase(Locale.ROOT));
|
gen.writeFieldName(responseInfo.getName().toLowerCase(Locale.ROOT));
|
||||||
responseInfo.appendJson(gen);
|
responseInfo.appendJson(gen);
|
||||||
|
|
||||||
|
@ -163,7 +156,7 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
|
||||||
} else {
|
} else {
|
||||||
gen.writeNullField("version");
|
gen.writeNullField("version");
|
||||||
}
|
}
|
||||||
for (DebugInfo part : parts.subList(2, parts.size())) {
|
for (DebugTab part : parts.subList(2, parts.size())) {
|
||||||
gen.writeFieldName(part.getName().toLowerCase(Locale.ROOT));
|
gen.writeFieldName(part.getName().toLowerCase(Locale.ROOT));
|
||||||
part.appendJson(gen);
|
part.appendJson(gen);
|
||||||
}
|
}
|
||||||
|
@ -171,76 +164,72 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
|
||||||
|
|
||||||
gen.writeEndObject();
|
gen.writeEndObject();
|
||||||
gen.close();
|
gen.close();
|
||||||
|
csb.close();
|
||||||
|
|
||||||
return csb.getInputStream();
|
return csb.getInputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream wrapInHtml(final List<DebugInfo> parts) throws IOException {
|
private InputStream wrapInHtml(final List<DebugTab> parts, String title) throws IOException {
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
// PathInfo pathInfo = null;
|
|
||||||
// try {
|
writer.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n")
|
||||||
// pathInfo = context.getPathInfo();
|
.append(" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n")
|
||||||
// } catch (final ODataException e) {}
|
.append("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n")
|
||||||
//
|
.append("<head>\n")
|
||||||
// writer.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n")
|
.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n")
|
||||||
// .append(" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n")
|
.append("<title>")
|
||||||
// .append("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n")
|
.append(escapeHtml(title))
|
||||||
// .append("<head>\n")
|
.append("</title>\n")
|
||||||
// .append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n")
|
.append("<style type=\"text/css\">\n")
|
||||||
// .append("<title>")
|
.append("body { font-family: Arial, sans-serif; font-size: 13px;\n")
|
||||||
// .append(pathInfo == null ? "" :
|
.append(" line-height: 16px; margin: 0;\n")
|
||||||
// escapeHtml(pathInfo.getServiceRoot().relativize(pathInfo.getRequestUri()).getPath()))
|
.append(" background-color: #eeeeee; color: #333333; }\n")
|
||||||
// .append("</title>\n")
|
.append(".header { float: left; }\n")
|
||||||
// .append("<style type=\"text/css\">\n")
|
.append(".header a { line-height: 22px; padding: 10px 18px;\n")
|
||||||
// .append("body { font-family: Arial, sans-serif; font-size: 13px;\n")
|
.append(" text-decoration: none; color: #333333; }\n")
|
||||||
// .append(" line-height: 16px; margin: 0;\n")
|
.append(":target, .header:nth-last-child(2) { background-color: #cccccc; }\n")
|
||||||
// .append(" background-color: #eeeeee; color: #333333; }\n")
|
.append(":target ~ .header:nth-last-child(2) { background-color: inherit; }\n")
|
||||||
// .append(".header { float: left; }\n")
|
.append(".header:focus, .header:hover,\n")
|
||||||
// .append(".header a { line-height: 22px; padding: 10px 18px;\n")
|
.append(" .header:nth-last-child(2):focus, .header:nth-last-child(2):hover\n")
|
||||||
// .append(" text-decoration: none; color: #333333; }\n")
|
.append(" { background-color: #999999; }\n")
|
||||||
// .append(":target, .header:nth-last-child(2) { background-color: #cccccc; }\n")
|
.append(".section { position: absolute; top: 42px; min-width: 100%;\n")
|
||||||
// .append(":target ~ .header:nth-last-child(2) { background-color: inherit; }\n")
|
.append(" padding-top: 18px; border-top: 1px solid #dddddd; }\n")
|
||||||
// .append(".header:focus, .header:hover,\n")
|
.append(".section > * { margin-left: 18px; }\n")
|
||||||
// .append(" .header:nth-last-child(2):focus, .header:nth-last-child(2):hover\n")
|
.append(":target + .section, .section:last-child { display: block; }\n")
|
||||||
// .append(" { background-color: #999999; }\n")
|
.append(".section, :target + .section ~ .section { display: none; }\n")
|
||||||
// .append(".section { position: absolute; top: 42px; min-width: 100%;\n")
|
.append("h1 { font-size: 18px; font-weight: normal; margin: 10px 0; }\n")
|
||||||
// .append(" padding-top: 18px; border-top: 1px solid #dddddd; }\n")
|
.append("h2 { font-size: 15px; }\n")
|
||||||
// .append(".section > * { margin-left: 18px; }\n")
|
.append("h2:not(:first-child) { margin-top: 2em; }\n")
|
||||||
// .append(":target + .section, .section:last-child { display: block; }\n")
|
.append("table { border-collapse: collapse; border-spacing: 0;\n")
|
||||||
// .append(".section, :target + .section ~ .section { display: none; }\n")
|
.append(" margin-top: 1.5em; }\n")
|
||||||
// .append("h1 { font-size: 18px; font-weight: normal; margin: 10px 0; }\n")
|
.append("table, thead { border-width: 1px 0; border-style: solid;\n")
|
||||||
// .append("h2 { font-size: 15px; }\n")
|
.append(" border-color: #dddddd; text-align: left; }\n")
|
||||||
// .append("h2:not(:first-child) { margin-top: 2em; }\n")
|
.append("th.name, td.name { padding: 1ex 2em 1ex 0; }\n")
|
||||||
// .append("table { border-collapse: collapse; border-spacing: 0;\n")
|
.append("tbody > tr:hover { background-color: #cccccc; }\n")
|
||||||
// .append(" margin-top: 1.5em; }\n")
|
.append(".code { font-family: \"Courier New\", monospace; }\n")
|
||||||
// .append("table, thead { border-width: 1px 0; border-style: solid;\n")
|
.append(".code, .tree li { line-height: 15px; }\n")
|
||||||
// .append(" border-color: #dddddd; text-align: left; }\n")
|
.append(".code a { text-decoration: underline; color: #666666; }\n")
|
||||||
// .append("th.name, td.name { padding: 1ex 2em 1ex 0; }\n")
|
.append(".xml .ns { font-style: italic; color: #999999; }\n")
|
||||||
// .append("tbody > tr:hover { background-color: #cccccc; }\n")
|
.append("ul, .tree { list-style-type: none; }\n")
|
||||||
// .append(".code { font-family: \"Courier New\", monospace; }\n")
|
.append("div > ul.expr, div > .expand, .tree { padding-left: 0; }\n")
|
||||||
// .append(".code, .tree li { line-height: 15px; }\n")
|
.append(".expr, .expand, .null, .numeric { padding-left: 1.5em; }\n")
|
||||||
// .append(".code a { text-decoration: underline; color: #666666; }\n")
|
.append("</style>\n")
|
||||||
// .append(".xml .ns { font-style: italic; color: #999999; }\n")
|
.append("</head>\n")
|
||||||
// .append("ul, .tree { list-style-type: none; }\n")
|
.append("<body>\n");
|
||||||
// .append("div > ul.expr, div > .expand, .tree { padding-left: 0; }\n")
|
char count = '0';
|
||||||
// .append(".expr, .expand, .null, .numeric { padding-left: 1.5em; }\n")
|
for (final DebugTab part : parts) {
|
||||||
// .append("</style>\n")
|
writer.append("<div class=\"header\" id=\"sec").append(++count).append("\">\n")
|
||||||
// .append("</head>\n")
|
.append("<h1><a href=\"#sec").append(count).append("\">")
|
||||||
// .append("<body>\n");
|
.append(part.getName())
|
||||||
// char count = '0';
|
.append("</a></h1>\n")
|
||||||
// for (final DebugInfo part : parts) {
|
.append("</div>\n")
|
||||||
// writer.append("<div class=\"header\" id=\"sec").append(++count).append("\">\n")
|
.append("<div class=\"section\">\n");
|
||||||
// .append("<h1><a href=\"#sec").append(count).append("\">")
|
part.appendHtml(writer);
|
||||||
// .append(part.getName())
|
writer.append("</div>\n");
|
||||||
// .append("</a></h1>\n")
|
}
|
||||||
// .append("</div>\n")
|
writer.append("</body>\n")
|
||||||
// .append("<div class=\"section\">\n");
|
.append("</html>\n")
|
||||||
// part.appendHtml(writer);
|
.close();
|
||||||
// writer.append("</div>\n");
|
|
||||||
// }
|
|
||||||
// writer.append("</body>\n")
|
|
||||||
// .append("</html>\n")
|
|
||||||
// .close();
|
|
||||||
byte[] bytes = writer.toString().getBytes("UTF-8");
|
byte[] bytes = writer.toString().getBytes("UTF-8");
|
||||||
return new ByteArrayInputStream(bytes);
|
return new ByteArrayInputStream(bytes);
|
||||||
}
|
}
|
||||||
|
@ -262,21 +251,21 @@ public class DebugResponseHelperImpl implements DebugResponseHelper {
|
||||||
}
|
}
|
||||||
gen.writeEndObject();
|
gen.writeEndObject();
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// protected static void appendHtmlTable(final Writer writer, final Map<String, String> entries) throws IOException {
|
protected static void appendHtmlTable(final 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");
|
||||||
// for (final String name : entries.keySet()) {
|
for (final String name : entries.keySet()) {
|
||||||
// final String value = entries.get(name);
|
final String value = entries.get(name);
|
||||||
// if (value != null) {
|
if (value != null) {
|
||||||
// writer.append("<tr><td class=\"name\">").append(name).append("</td>")
|
writer.append("<tr><td class=\"name\">").append(name).append("</td>")
|
||||||
// .append("<td class=\"value\">")
|
.append("<td class=\"value\">")
|
||||||
// .append(ODataDebugResponseWrapper.escapeHtml(value))
|
.append(escapeHtml(value))
|
||||||
// .append("</td></tr>\n");
|
.append("</td></tr>\n");
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// writer.append("</tbody>\n</table>\n");
|
writer.append("</tbody>\n</table>\n");
|
||||||
// }
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
/**
|
/**
|
||||||
* Debug information.
|
* Debug information.
|
||||||
*/
|
*/
|
||||||
public interface DebugInfo {
|
public interface DebugTab {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the name of this debug information part, useful as title.
|
* Gets the name of this debug information part, useful as title.
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* 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.olingo.server.core.debug;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||||
|
import org.apache.olingo.server.api.ODataResponse;
|
||||||
|
import org.apache.olingo.server.api.debug.DebugSupport;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response body debug information.
|
||||||
|
*/
|
||||||
|
public class DebugTabBody implements DebugTab {
|
||||||
|
|
||||||
|
private static enum ResponseContent {
|
||||||
|
JSON, XML, TEXT, IMAGE
|
||||||
|
};
|
||||||
|
|
||||||
|
private final ODataResponse response;
|
||||||
|
private final ResponseContent responseContent;
|
||||||
|
|
||||||
|
private final String serviceRoot;
|
||||||
|
|
||||||
|
// private final boolean isXml;
|
||||||
|
// private final boolean isJson;
|
||||||
|
// private final boolean isText;
|
||||||
|
// private final boolean isImage;
|
||||||
|
|
||||||
|
public DebugTabBody(final ODataResponse response, final String serviceRoot) {
|
||||||
|
this.response = response;
|
||||||
|
this.serviceRoot = serviceRoot;
|
||||||
|
final String contentType = response.getHeaders().get(HttpHeader.CONTENT_TYPE);
|
||||||
|
// TODO: Differentiate better
|
||||||
|
if (contentType != null) {
|
||||||
|
responseContent = ResponseContent.JSON;
|
||||||
|
} else {
|
||||||
|
responseContent = ResponseContent.TEXT;
|
||||||
|
}
|
||||||
|
// isXml = contentType.contains("xml");
|
||||||
|
// isJson = !isXml && contentType.startsWith(HttpContentType.APPLICATION_JSON);
|
||||||
|
// isText = isXml || isJson || contentType.startsWith("text/")
|
||||||
|
// || contentType.startsWith(HttpContentType.APPLICATION_HTTP)
|
||||||
|
// || contentType.startsWith(HttpContentType.MULTIPART_MIXED);
|
||||||
|
// isImage = !isText && contentType.startsWith("image/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Body";
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
@Override
|
||||||
|
public void appendJson(final JsonGenerator gen) throws IOException {
|
||||||
|
if (response.getContent() == null) {
|
||||||
|
gen.writeNull();
|
||||||
|
} else {
|
||||||
|
gen.writeString(getContentString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getContentString() {
|
||||||
|
try {
|
||||||
|
String contentString;
|
||||||
|
switch (responseContent) {
|
||||||
|
case IMAGE:
|
||||||
|
// TODO: DecodeString as base 64
|
||||||
|
contentString = "Currently not supported";
|
||||||
|
break;
|
||||||
|
case JSON:
|
||||||
|
case XML:
|
||||||
|
case TEXT:
|
||||||
|
default:
|
||||||
|
// TODO: Remove IOUtils from core dependency
|
||||||
|
contentString = IOUtils.toString(response.getContent(), "UTF-8");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return contentString;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return "Could not parse Body for Debug Output";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendHtml(final Writer writer) throws IOException {
|
||||||
|
|
||||||
|
final String body = response.getContent() == null ? "ODataLibrary: null body." : getContentString();
|
||||||
|
switch (responseContent) {
|
||||||
|
case XML:
|
||||||
|
writer.append("<pre class=\"code").append("xml").append("\">\n");
|
||||||
|
writer.append(addLinks(DebugResponseHelperImpl.escapeHtml(body)));
|
||||||
|
writer.append("</pre>\n");
|
||||||
|
break;
|
||||||
|
case JSON:
|
||||||
|
writer.append("<pre class=\"code").append("json").append("\">\n");
|
||||||
|
writer.append(addLinks(DebugResponseHelperImpl.escapeHtml(body)));
|
||||||
|
writer.append("</pre>\n");
|
||||||
|
break;
|
||||||
|
case IMAGE:
|
||||||
|
// Make header query case insensitive
|
||||||
|
writer.append("<img src=\"data:").append(response.getHeaders().get(HttpHeader.CONTENT_TYPE)).append(";base64,")
|
||||||
|
.append(body)
|
||||||
|
.append("\" />\n");
|
||||||
|
break;
|
||||||
|
case TEXT:
|
||||||
|
default:
|
||||||
|
writer.append("<pre class=\"code").append("").append("\">\n");
|
||||||
|
writer.append(DebugResponseHelperImpl.escapeHtml(body));
|
||||||
|
writer.append("</pre>\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String addLinks(final String source) {
|
||||||
|
final String debugOption = DebugSupport.ODATA_DEBUG_QUERY_PARAMETER + "=" + DebugSupport.ODATA_DEBUG_HTML;
|
||||||
|
final String urlPattern = "("
|
||||||
|
+ (responseContent == ResponseContent.XML ?
|
||||||
|
"(?:href|src|base)=" : "\"(?:uri|media_src|edit_media|__next)\":\\p{Space}*")
|
||||||
|
+ "\")(.+?)\"";
|
||||||
|
return (responseContent == ResponseContent.XML ?
|
||||||
|
source.replaceAll("(xmlns(?::\\p{Alnum}+)?=\")(.+?)\"", "$1<span class=\"ns\">$2</span>\"") : source)
|
||||||
|
.replaceAll(urlPattern, "$1<a href=\"" + serviceRoot + "$2?" + debugOption + "\">$2</a>\"")
|
||||||
|
.replaceAll("(<a href=\"" + Pattern.quote(serviceRoot) + ')' + Pattern.quote(serviceRoot), "$1")
|
||||||
|
.replaceAll("<a href=\"(.+?)\\?(.+?)\\?" + debugOption, "<a href=\"$1?$2&" + debugOption)
|
||||||
|
.replaceAll("&amp;", "&");
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,11 +29,11 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
/**
|
/**
|
||||||
* Exception debug information.
|
* Exception debug information.
|
||||||
*/
|
*/
|
||||||
public class DebugInfoException implements DebugInfo {
|
public class DebugTabException implements DebugTab {
|
||||||
|
|
||||||
private final Exception exception;
|
private final Exception exception;
|
||||||
|
|
||||||
public DebugInfoException(final Exception exception) {
|
public DebugTabException(final Exception exception) {
|
||||||
this.exception = exception;
|
this.exception = exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ public class DebugInfoException implements DebugInfo {
|
||||||
while (throwable != null) {
|
while (throwable != null) {
|
||||||
gen.writeStartObject();
|
gen.writeStartObject();
|
||||||
gen.writeStringField("class", throwable.getClass().getCanonicalName());
|
gen.writeStringField("class", throwable.getClass().getCanonicalName());
|
||||||
gen.writeStringField("message", getMessage(throwable));
|
gen.writeStringField("message", getMessageText(throwable));
|
||||||
gen.writeFieldName("invocation");
|
gen.writeFieldName("invocation");
|
||||||
appendJsonStackTraceElement(gen, throwable.getStackTrace()[0]);
|
appendJsonStackTraceElement(gen, throwable.getStackTrace()[0]);
|
||||||
gen.writeEndObject();
|
gen.writeEndObject();
|
||||||
|
@ -71,7 +71,7 @@ public class DebugInfoException implements DebugInfo {
|
||||||
gen.writeEndObject();
|
gen.writeEndObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getMessage(final Throwable throwable) {
|
private String getMessageText(final Throwable throwable) {
|
||||||
String message;
|
String message;
|
||||||
if (throwable instanceof ODataLibraryException) {
|
if (throwable instanceof ODataLibraryException) {
|
||||||
ODataLibraryException ex = (ODataLibraryException) throwable;
|
ODataLibraryException ex = (ODataLibraryException) throwable;
|
||||||
|
@ -95,48 +95,42 @@ public class DebugInfoException implements DebugInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendHtml(Writer writer) throws IOException {
|
public void appendHtml(final Writer writer) throws IOException {
|
||||||
// TODO Auto-generated method stub
|
appendException(exception, writer);
|
||||||
|
writer.append("<h2>Stacktrace</h2>\n");
|
||||||
|
int count = 0;
|
||||||
|
for (final StackTraceElement stackTraceElement : exception.getStackTrace()) {
|
||||||
|
appendStackTraceElement(stackTraceElement, ++count == 1, count == exception.getStackTrace().length, writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendException(final Throwable throwable, final Writer writer) throws IOException {
|
||||||
|
if (throwable.getCause() != null) {
|
||||||
|
appendException(throwable.getCause(), writer);
|
||||||
|
}
|
||||||
|
final StackTraceElement details = throwable.getStackTrace()[0];
|
||||||
|
writer.append("<h2>").append(throwable.getClass().getCanonicalName()).append("</h2>\n")
|
||||||
|
.append("<p>")
|
||||||
|
.append(DebugResponseHelperImpl.escapeHtml(getMessageText(throwable)))
|
||||||
|
.append("</p>\n");
|
||||||
|
appendStackTraceElement(details, true, true, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendStackTraceElement(final StackTraceElement stackTraceElement,
|
||||||
|
final boolean isFirst, final boolean isLast, final Writer writer) throws IOException {
|
||||||
|
if (isFirst) {
|
||||||
|
writer.append("<table>\n<thead>\n")
|
||||||
|
.append("<tr>\n<th class=\"name\">Class</th>\n")
|
||||||
|
.append("<th class=\"name\">Method</th>\n")
|
||||||
|
.append("<th class=\"value\">Line number in class</th>\n</tr>\n")
|
||||||
|
.append("</thead>\n<tbody>\n");
|
||||||
|
}
|
||||||
|
writer.append("<tr>\n<td class=\"name\">").append(stackTraceElement.getClassName()).append("</td>\n")
|
||||||
|
.append("<td class=\"name\">").append(stackTraceElement.getMethodName()).append("</td>\n")
|
||||||
|
.append("<td class=\"value\">").append(Integer.toString(stackTraceElement.getLineNumber()))
|
||||||
|
.append("</td>\n</tr>\n");
|
||||||
|
if (isLast) {
|
||||||
|
writer.append("</tbody>\n</table>\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void appendHtml(final Writer writer) throws IOException {
|
|
||||||
// appendException(exception, writer);
|
|
||||||
// writer.append("<h2>Stacktrace</h2>\n");
|
|
||||||
// int count = 0;
|
|
||||||
// for (final StackTraceElement stackTraceElement : exception.getStackTrace()) {
|
|
||||||
// appendStackTraceElement(stackTraceElement, ++count == 1, count == exception.getStackTrace().length, writer);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private void appendException(final Throwable throwable, final Writer writer) throws IOException {
|
|
||||||
// if (throwable.getCause() != null) {
|
|
||||||
// appendException(throwable.getCause(), writer);
|
|
||||||
// }
|
|
||||||
// final StackTraceElement details = throwable.getStackTrace()[0];
|
|
||||||
// writer.append("<h2>").append(throwable.getClass().getCanonicalName()).append("</h2>\n")
|
|
||||||
// .append("<p>")
|
|
||||||
// .append(ODataDebugResponseWrapper.escapeHtml(getMessageText(throwable)))
|
|
||||||
// .append("</p>\n");
|
|
||||||
// appendStackTraceElement(details, true, true, writer);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private void appendStackTraceElement(final StackTraceElement stackTraceElement,
|
|
||||||
// final boolean isFirst, final boolean isLast, final Writer writer) throws IOException {
|
|
||||||
// if (isFirst) {
|
|
||||||
// writer.append("<table>\n<thead>\n")
|
|
||||||
// .append("<tr>\n<th class=\"name\">Class</th>\n")
|
|
||||||
// .append("<th class=\"name\">Method</th>\n")
|
|
||||||
// .append("<th class=\"value\">Line number in class</th>\n</tr>\n")
|
|
||||||
// .append("</thead>\n<tbody>\n");
|
|
||||||
// }
|
|
||||||
// writer.append("<tr>\n<td class=\"name\">").append(stackTraceElement.getClassName()).append("</td>\n")
|
|
||||||
// .append("<td class=\"name\">").append(stackTraceElement.getMethodName()).append("</td>\n")
|
|
||||||
// .append("<td class=\"value\">").append(Integer.toString(stackTraceElement.getLineNumber()))
|
|
||||||
// .append("</td>\n</tr>\n");
|
|
||||||
// if (isLast) {
|
|
||||||
// writer.append("</tbody>\n</table>\n");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
|
@ -20,7 +20,7 @@ package org.apache.olingo.server.core.debug;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -31,14 +31,14 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
/**
|
/**
|
||||||
* Request debug information.
|
* Request debug information.
|
||||||
*/
|
*/
|
||||||
public class DebugInfoRequest implements DebugInfo {
|
public class DebugTabRequest implements DebugTab {
|
||||||
|
|
||||||
private final String method;
|
private final String method;
|
||||||
private final String uri;
|
private final String uri;
|
||||||
private final String protocol;
|
private final String protocol;
|
||||||
private final Map<String, String> headers;
|
private final Map<String, String> headers;
|
||||||
|
|
||||||
public DebugInfoRequest(ODataRequest request) {
|
public DebugTabRequest(ODataRequest request) {
|
||||||
method = request.getMethod() == null ? "unkown" : request.getMethod().toString();
|
method = request.getMethod() == null ? "unkown" : request.getMethod().toString();
|
||||||
uri = request.getRawRequestUri() == null ? "unkown" : request.getRawRequestUri();
|
uri = request.getRawRequestUri() == null ? "unkown" : request.getRawRequestUri();
|
||||||
protocol = request.getProtocol() == null ? "unkown" : request.getProtocol();
|
protocol = request.getProtocol() == null ? "unkown" : request.getProtocol();
|
||||||
|
@ -47,7 +47,7 @@ public class DebugInfoRequest implements DebugInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> wrapHeaders(Map<String, List<String>> allHeaders) {
|
private Map<String, String> wrapHeaders(Map<String, List<String>> allHeaders) {
|
||||||
Map<String, String> localHeaders = new HashMap<String, String>();
|
Map<String, String> localHeaders = new LinkedHashMap<String, String>();
|
||||||
for (Map.Entry<String, List<String>> entry : allHeaders.entrySet()) {
|
for (Map.Entry<String, List<String>> entry : allHeaders.entrySet()) {
|
||||||
String value = null;
|
String value = null;
|
||||||
if (entry.getValue() != null) {
|
if (entry.getValue() != null) {
|
||||||
|
@ -60,19 +60,22 @@ public class DebugInfoRequest implements DebugInfo {
|
||||||
value = value + valuePart;
|
value = value + valuePart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
localHeaders.put(entry.getKey(), value);
|
||||||
}
|
}
|
||||||
return localHeaders;
|
return localHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendHtml(final Writer writer) throws IOException {
|
public void appendHtml(final Writer writer) throws IOException {
|
||||||
// writer.append("<h2>Request Method</h2>\n")
|
writer.append("<h2>Request Method</h2>\n")
|
||||||
// .append("<p>").append(method).append("</p>\n")
|
.append("<p>").append(method).append("</p>\n")
|
||||||
// .append("<h2>Request URI</h2>\n")
|
.append("<h2>Request URI</h2>\n")
|
||||||
// .append("<p>").append(DebugResponseHelperImpl.escapeHtml(uri.toString())).append("</p>\n")
|
.append("<p>").append(DebugResponseHelperImpl.escapeHtml(uri.toString())).append("</p>\n")
|
||||||
// .append("<h2>Request Protocol</h2>\n")
|
.append("<h2>Request Protocol</h2>\n")
|
||||||
// .append("<p>").append(protocol).append("</p>\n");
|
.append("<p>").append(protocol).append("</p>\n");
|
||||||
// writer.append("<h2>Request Headers</h2>\n")
|
writer.append("<h2>Request Headers</h2>\n");
|
||||||
|
DebugResponseHelperImpl.appendHtmlTable(writer, headers);
|
||||||
|
|
||||||
// .append("<table>\n<thead>\n")
|
// .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");
|
|
@ -30,14 +30,14 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
/**
|
/**
|
||||||
* Response debug information.
|
* Response debug information.
|
||||||
*/
|
*/
|
||||||
public class DebugInfoResponse implements DebugInfo {
|
public class DebugTabResponse implements DebugTab {
|
||||||
|
|
||||||
private final ODataResponse response;
|
private final ODataResponse response;
|
||||||
private final String serviceRoot;
|
private final String serviceRoot;
|
||||||
private final HttpStatusCode status;
|
private final HttpStatusCode status;
|
||||||
private final Map<String, String> headers;
|
private final Map<String, String> headers;
|
||||||
|
|
||||||
public DebugInfoResponse(final ODataResponse applicationResponse, final String serviceRoot) {
|
public DebugTabResponse(final ODataResponse applicationResponse, final String serviceRoot) {
|
||||||
this.response = applicationResponse;
|
this.response = applicationResponse;
|
||||||
this.serviceRoot = serviceRoot;
|
this.serviceRoot = serviceRoot;
|
||||||
status = HttpStatusCode.fromStatusCode(response.getStatusCode());
|
status = HttpStatusCode.fromStatusCode(response.getStatusCode());
|
||||||
|
@ -67,21 +67,23 @@ public class DebugInfoResponse implements DebugInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
gen.writeFieldName("body");
|
gen.writeFieldName("body");
|
||||||
new DebugInfoBody(response, serviceRoot).appendJson(gen);
|
new DebugTabBody(response, serviceRoot).appendJson(gen);
|
||||||
|
|
||||||
gen.writeEndObject();
|
gen.writeEndObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendHtml(final Writer writer) throws IOException {
|
public void appendHtml(final Writer writer) throws IOException {
|
||||||
// writer.append("<h2>Status Code</h2>\n")
|
writer.append("<h2>Status Code</h2>\n")
|
||||||
// .append("<p>").append(Integer.toString(status.getStatusCode())).append(' ')
|
.append("<p>").append(Integer.toString(status.getStatusCode())).append(' ')
|
||||||
// .append(status.getInfo()).append("</p>\n")
|
.append(status.getInfo()).append("</p>\n")
|
||||||
// .append("<h2>Response Headers</h2>\n");
|
.append("<h2>Response Headers</h2>\n");
|
||||||
// ODataDebugResponseWrapper.appendHtmlTable(writer, headers);
|
DebugResponseHelperImpl.appendHtmlTable(writer, headers);
|
||||||
// if (response.getContentHeader() != null && response.getEntity() != null) {
|
writer.append("<h2>Response Body</h2>\n");
|
||||||
// writer.append("<h2>Response Body</h2>\n");
|
if (response.getContent() != null) {
|
||||||
// new DebugInfoBody(response, serviceRoot).appendHtml(writer);
|
new DebugTabBody(response, serviceRoot).appendHtml(writer);
|
||||||
// }
|
} else {
|
||||||
|
writer.append("<p>ODataLibrary: no response body</p>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,11 +31,11 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
/**
|
/**
|
||||||
* Runtime debug information.
|
* Runtime debug information.
|
||||||
*/
|
*/
|
||||||
public class DebugInfoRuntime implements DebugInfo {
|
public class DebugTabRuntime implements DebugTab {
|
||||||
|
|
||||||
private final RuntimeNode rootNode;
|
private final RuntimeNode rootNode;
|
||||||
|
|
||||||
public DebugInfoRuntime(List<RuntimeMeasurement> runtimeInformation) {
|
public DebugTabRuntime(List<RuntimeMeasurement> runtimeInformation) {
|
||||||
rootNode = new RuntimeNode();
|
rootNode = new RuntimeNode();
|
||||||
for (final RuntimeMeasurement runtimeMeasurement : runtimeInformation) {
|
for (final RuntimeMeasurement runtimeMeasurement : runtimeInformation) {
|
||||||
rootNode.add(runtimeMeasurement);
|
rootNode.add(runtimeMeasurement);
|
||||||
|
@ -82,44 +82,39 @@ public class DebugInfoRuntime implements DebugInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendHtml(Writer writer) throws IOException {
|
public void appendHtml(final Writer writer) throws IOException {
|
||||||
// TODO Auto-generated method stub
|
appendRuntimeNode(rootNode, "", true, writer);
|
||||||
//
|
}
|
||||||
// @Override
|
|
||||||
// public void appendHtml(final Writer writer) throws IOException {
|
private void appendRuntimeNode(final RuntimeNode node, final String draw, final boolean isLast, final Writer writer)
|
||||||
// appendRuntimeNode(rootNode, "", true, writer);
|
throws IOException {
|
||||||
// }
|
if (node.className != null) {
|
||||||
//
|
writer.append("<li>")
|
||||||
// private void appendRuntimeNode(final RuntimeNode node, final String draw, final boolean isLast, final Writer writer)
|
.append("<span class=\"code\">")
|
||||||
// throws IOException {
|
.append("<span class=\"draw\">").append(draw)
|
||||||
// if (node.className != null) {
|
.append(isLast ? "└" : "├").append("─ </span>")
|
||||||
// writer.append("<li>")
|
.append("<span class=\"class\">").append(node.className).append("</span>.")
|
||||||
// .append("<span class=\"code\">")
|
.append("<span class=\"method\">").append(node.methodName).append("(…)")
|
||||||
// .append("<span class=\"draw\">").append(draw)
|
.append("</span></span>");
|
||||||
// .append(isLast ? "└" : "├").append("─ </span>")
|
long time = node.timeStopped == 0 ? 0 : (node.timeStopped - node.timeStarted) / 1000;
|
||||||
// .append("<span class=\"class\">").append(node.className).append("</span>.")
|
writer.append("<span class=\"").append(time == 0 ? "null" : "numeric")
|
||||||
// .append("<span class=\"method\">").append(node.methodName).append("(…)")
|
.append("\" title=\"").append(time == 0 ? "Stop time missing" : "Gross duration")
|
||||||
// .append("</span></span>");
|
.append("\">").append(time == 0 ? "unfinished" : Long.toString(time) + " µs")
|
||||||
// long time = node.timeStopped == 0 ? 0 : (node.timeStopped - node.timeStarted) / 1000;
|
.append("</span>\n");
|
||||||
// writer.append("<span class=\"").append(time == 0 ? "null" : "numeric")
|
}
|
||||||
// .append("\" title=\"").append(time == 0 ? "Stop time missing" : "Gross duration")
|
if (!node.children.isEmpty()) {
|
||||||
// .append("\">").append(time == 0 ? "unfinished" : Long.toString(time) + " µs")
|
writer.append("<ol class=\"tree\">\n");
|
||||||
// .append("</span>\n");
|
for (final RuntimeNode childNode : node.children) {
|
||||||
// }
|
appendRuntimeNode(childNode,
|
||||||
// if (!node.children.isEmpty()) {
|
node.className == null ? draw : draw + (isLast ? " " : "│") + " ",
|
||||||
// writer.append("<ol class=\"tree\">\n");
|
node.children.indexOf(childNode) == node.children.size() - 1,
|
||||||
// for (final RuntimeNode childNode : node.children) {
|
writer);
|
||||||
// appendRuntimeNode(childNode,
|
}
|
||||||
// node.className == null ? draw : draw + (isLast ? " " : "│") + " ",
|
writer.append("</ol>\n");
|
||||||
// node.children.indexOf(childNode) == node.children.size() - 1,
|
}
|
||||||
// writer);
|
if (node.className != null) {
|
||||||
// }
|
writer.append("</li>\n");
|
||||||
// writer.append("</ol>\n");
|
}
|
||||||
// }
|
|
||||||
// if (node.className != null) {
|
|
||||||
// writer.append("</li>\n");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RuntimeNode {
|
private class RuntimeNode {
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* 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.olingo.server.core.debug;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server debug information.
|
||||||
|
*/
|
||||||
|
public class DebugTabServer implements DebugTab {
|
||||||
|
|
||||||
|
private final Map<String, String> serverEnvironmentVaribles;
|
||||||
|
|
||||||
|
public DebugTabServer(Map<String, String> serverEnvironmentVaribles) {
|
||||||
|
this.serverEnvironmentVaribles = serverEnvironmentVaribles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Environment";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendJson(JsonGenerator gen) throws IOException {
|
||||||
|
DebugResponseHelperImpl.appendJsonTable(gen, serverEnvironmentVaribles);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendHtml(Writer writer) throws IOException {
|
||||||
|
final Package pack = DebugResponseHelperImpl.class.getPackage();
|
||||||
|
writer.append("<h2>Library Version</h2>\n")
|
||||||
|
.append("<p>").append(pack.getImplementationTitle())
|
||||||
|
.append(" Version ").append(pack.getImplementationVersion()).append("</p>\n")
|
||||||
|
.append("<h2>Server Environment</h2>\n");
|
||||||
|
DebugResponseHelperImpl.appendHtmlTable(writer, serverEnvironmentVaribles);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,18 +21,25 @@ package org.apache.olingo.server.core.debug;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
|
||||||
|
import org.apache.olingo.server.api.uri.UriInfo;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URI parser debug information.
|
* URI parser debug information.
|
||||||
*/
|
*/
|
||||||
public class DebugInfoUri implements DebugInfo {
|
public class DebugTabUri implements DebugTab {
|
||||||
|
|
||||||
|
private UriInfo uriInfo;
|
||||||
|
|
||||||
|
public DebugTabUri(UriInfo uriInfo) {
|
||||||
|
this.uriInfo = uriInfo;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
// TODO Auto-generated method stub
|
return "URI";
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -69,12 +76,6 @@ public class DebugInfoUri implements DebugInfo {
|
||||||
// return null;
|
// return null;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public String getName() {
|
|
||||||
// return "URI";
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
// @Override
|
||||||
// public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
|
// public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
|
||||||
// jsonStreamWriter.beginObject();
|
// jsonStreamWriter.beginObject();
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* 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.olingo.server.core.debug;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.olingo.commons.api.format.ContentType;
|
||||||
|
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||||
|
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||||
|
import org.apache.olingo.server.api.OData;
|
||||||
|
import org.apache.olingo.server.api.ODataRequest;
|
||||||
|
import org.apache.olingo.server.api.ODataResponse;
|
||||||
|
import org.apache.olingo.server.api.debug.DebugInformation;
|
||||||
|
import org.apache.olingo.server.api.debug.DebugSupport;
|
||||||
|
import org.apache.olingo.server.api.debug.RuntimeMeasurement;
|
||||||
|
import org.apache.olingo.server.api.uri.UriInfo;
|
||||||
|
|
||||||
|
public class ServerCoreDebugger {
|
||||||
|
|
||||||
|
private final List<RuntimeMeasurement> runtimeInformation = new ArrayList<RuntimeMeasurement>();
|
||||||
|
private final OData odata;
|
||||||
|
|
||||||
|
private boolean isDebugMode = false;
|
||||||
|
private DebugSupport debugSupport;
|
||||||
|
private String debugFormat;
|
||||||
|
|
||||||
|
public ServerCoreDebugger(OData odata) {
|
||||||
|
this.odata = odata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resolveDebugMode(HttpServletRequest request) {
|
||||||
|
if (debugSupport != null) {
|
||||||
|
// Should we read the parameter from the servlet here and ignore multiple parameters?
|
||||||
|
debugFormat = request.getParameter(DebugSupport.ODATA_DEBUG_QUERY_PARAMETER);
|
||||||
|
if (debugFormat != null) {
|
||||||
|
debugSupport.init(odata);
|
||||||
|
isDebugMode = debugSupport.isUserAuthorized();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ODataResponse createDebugResponse(final HttpServletRequest request, final Exception exception,
|
||||||
|
final ODataRequest odRequest, final ODataResponse odResponse, UriInfo uriInfo,
|
||||||
|
Map<String, String> serverEnvironmentVaribles) {
|
||||||
|
try {
|
||||||
|
DebugInformation debugInfo =
|
||||||
|
createDebugInformation(request, exception, odRequest, odResponse, uriInfo, serverEnvironmentVaribles);
|
||||||
|
|
||||||
|
return debugSupport.createDebugResponse(debugFormat, debugInfo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return createFailResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ODataResponse createFailResponse() {
|
||||||
|
ODataResponse odResponse = new ODataResponse();
|
||||||
|
odResponse.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
|
||||||
|
odResponse.setHeader(HttpHeader.CONTENT_TYPE, ContentType.TEXT_PLAIN.toContentTypeString());
|
||||||
|
InputStream content = new ByteArrayInputStream("ODataLibrary: Could not assemble debug response.".getBytes());
|
||||||
|
odResponse.setContent(content);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DebugInformation createDebugInformation(final HttpServletRequest request, final Exception exception,
|
||||||
|
final ODataRequest odRequest, final ODataResponse odResponse, UriInfo uriInfo,
|
||||||
|
Map<String, String> serverEnvironmentVaribles) {
|
||||||
|
DebugInformation debugInfo = new DebugInformation();
|
||||||
|
debugInfo.setRequest(odRequest);
|
||||||
|
debugInfo.setApplicationResponse(odResponse);
|
||||||
|
|
||||||
|
debugInfo.setException(exception);
|
||||||
|
|
||||||
|
debugInfo.setServerEnvironmentVaribles(serverEnvironmentVaribles);
|
||||||
|
|
||||||
|
debugInfo.setUriInfo(uriInfo);
|
||||||
|
|
||||||
|
debugInfo.setRuntimeInformation(runtimeInformation);
|
||||||
|
return debugInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int startRuntimeMeasurement(final String className, final String methodName) {
|
||||||
|
if (isDebugMode) {
|
||||||
|
int handleId = runtimeInformation.size();
|
||||||
|
|
||||||
|
final RuntimeMeasurement measurement = new RuntimeMeasurement();
|
||||||
|
measurement.setTimeStarted(System.nanoTime());
|
||||||
|
measurement.setClassName(className);
|
||||||
|
measurement.setMethodName(methodName);
|
||||||
|
|
||||||
|
runtimeInformation.add(measurement);
|
||||||
|
|
||||||
|
return handleId;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopRuntimeMeasurement(final int handle) {
|
||||||
|
if (isDebugMode && handle < runtimeInformation.size()) {
|
||||||
|
long stopTime = System.nanoTime();
|
||||||
|
RuntimeMeasurement runtimeMeasurement = runtimeInformation.get(handle);
|
||||||
|
if (runtimeMeasurement != null) {
|
||||||
|
runtimeMeasurement.setTimeStopped(stopTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugSupportProcessor(DebugSupport debugSupport) {
|
||||||
|
this.debugSupport = debugSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDebugMode() {
|
||||||
|
return isDebugMode;
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,6 @@ import org.apache.olingo.server.api.ServiceMetadata;
|
||||||
import org.apache.olingo.server.api.debug.DefaultDebugSupport;
|
import org.apache.olingo.server.api.debug.DefaultDebugSupport;
|
||||||
import org.apache.olingo.server.api.edmx.EdmxReference;
|
import org.apache.olingo.server.api.edmx.EdmxReference;
|
||||||
import org.apache.olingo.server.api.edmx.EdmxReferenceInclude;
|
import org.apache.olingo.server.api.edmx.EdmxReferenceInclude;
|
||||||
import org.apache.olingo.server.tecsvc.async.TechnicalAsyncService;
|
|
||||||
import org.apache.olingo.server.tecsvc.data.DataProvider;
|
import org.apache.olingo.server.tecsvc.data.DataProvider;
|
||||||
import org.apache.olingo.server.tecsvc.processor.TechnicalActionProcessor;
|
import org.apache.olingo.server.tecsvc.processor.TechnicalActionProcessor;
|
||||||
import org.apache.olingo.server.tecsvc.processor.TechnicalBatchProcessor;
|
import org.apache.olingo.server.tecsvc.processor.TechnicalBatchProcessor;
|
||||||
|
|
|
@ -77,6 +77,7 @@ import org.apache.olingo.server.api.processor.ReferenceCollectionProcessor;
|
||||||
import org.apache.olingo.server.api.processor.ReferenceProcessor;
|
import org.apache.olingo.server.api.processor.ReferenceProcessor;
|
||||||
import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
|
import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
|
||||||
import org.apache.olingo.server.api.uri.UriInfo;
|
import org.apache.olingo.server.api.uri.UriInfo;
|
||||||
|
import org.apache.olingo.server.core.debug.ServerCoreDebugger;
|
||||||
import org.apache.olingo.server.tecsvc.provider.ContainerProvider;
|
import org.apache.olingo.server.tecsvc.provider.ContainerProvider;
|
||||||
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
|
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -233,7 +234,8 @@ public class ODataHandlerTest {
|
||||||
request.setMethod(HttpMethod.GET);
|
request.setMethod(HttpMethod.GET);
|
||||||
request.setRawODataPath("EdmException");
|
request.setRawODataPath("EdmException");
|
||||||
|
|
||||||
final ODataResponse response = new ODataHandler(odata, serviceMetadata).process(request);
|
final ODataResponse response =
|
||||||
|
new ODataHandler(odata, serviceMetadata, new ServerCoreDebugger(odata)).process(request);
|
||||||
assertNotNull(response);
|
assertNotNull(response);
|
||||||
assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode());
|
assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode());
|
||||||
}
|
}
|
||||||
|
@ -720,7 +722,7 @@ public class ODataHandlerTest {
|
||||||
final ServiceMetadata metadata = odata.createServiceMetadata(
|
final ServiceMetadata metadata = odata.createServiceMetadata(
|
||||||
new EdmTechProvider(), Collections.<EdmxReference> emptyList());
|
new EdmTechProvider(), Collections.<EdmxReference> emptyList());
|
||||||
|
|
||||||
ODataHandler handler = new ODataHandler(odata, metadata);
|
ODataHandler handler = new ODataHandler(odata, metadata, new ServerCoreDebugger(odata));
|
||||||
|
|
||||||
if (processor != null) {
|
if (processor != null) {
|
||||||
handler.register(processor);
|
handler.register(processor);
|
||||||
|
|
Loading…
Reference in New Issue