You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2015/08/04 16:25:46 UTC
[06/18] olingo-odata4 git commit: [OLINGO-731] Added html as debug
output and refactored structure
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java
new file mode 100644
index 0000000..43e9ba6
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java
@@ -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;", "&");
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabException.java
new file mode 100644
index 0000000..6bc69e4
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabException.java
@@ -0,0 +1,136 @@
+/*
+ * 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.olingo.server.api.ODataLibraryException;
+import org.apache.olingo.server.api.ODataLibraryException.ODataErrorMessage;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+/**
+ * Exception debug information.
+ */
+public class DebugTabException implements DebugTab {
+
+ private final Exception exception;
+
+ public DebugTabException(final Exception exception) {
+ this.exception = exception;
+ }
+
+ @Override
+ public String getName() {
+ return "Stacktrace";
+ }
+
+ @Override
+ public void appendJson(final JsonGenerator gen) throws IOException {
+ gen.writeStartObject();
+ gen.writeFieldName("exceptions");
+ gen.writeStartArray();
+ Throwable throwable = exception;
+ while (throwable != null) {
+ gen.writeStartObject();
+ gen.writeStringField("class", throwable.getClass().getCanonicalName());
+ gen.writeStringField("message", getMessageText(throwable));
+ gen.writeFieldName("invocation");
+ appendJsonStackTraceElement(gen, throwable.getStackTrace()[0]);
+ gen.writeEndObject();
+
+ // Get next exception in the cause list
+ throwable = throwable.getCause();
+ }
+ gen.writeEndArray();
+
+ gen.writeFieldName("stacktrace");
+ gen.writeStartArray();
+ for (final StackTraceElement stackTraceElement : exception.getStackTrace()) {
+ appendJsonStackTraceElement(gen, stackTraceElement);
+ }
+ gen.writeEndArray();
+
+ gen.writeEndObject();
+ }
+
+ private String getMessageText(final Throwable throwable) {
+ String message;
+ if (throwable instanceof ODataLibraryException) {
+ ODataLibraryException ex = (ODataLibraryException) throwable;
+ // We use the default locale
+ ODataErrorMessage translatedMessage = ex.getTranslatedMessage(null);
+ // We provide the best message we can
+ message = translatedMessage.getMessage() == null ? ex.getMessage() : translatedMessage.getMessage();
+ } else {
+ message = throwable.getMessage();
+ }
+ return message;
+ }
+
+ private void appendJsonStackTraceElement(final JsonGenerator gen, final StackTraceElement element)
+ throws IOException {
+ gen.writeStartObject();
+ gen.writeStringField("class", element.getClassName());
+ gen.writeStringField("method", element.getMethodName());
+ gen.writeStringField("line", Integer.toString(element.getLineNumber()));
+ gen.writeEndObject();
+ }
+
+ @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(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");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRequest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRequest.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRequest.java
new file mode 100644
index 0000000..8eba537
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRequest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.server.api.ODataRequest;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+/**
+ * Request debug information.
+ */
+public class DebugTabRequest implements DebugTab {
+
+ private final String method;
+ private final String uri;
+ private final String protocol;
+ private final Map<String, String> headers;
+
+ public DebugTabRequest(ODataRequest request) {
+ method = request.getMethod() == null ? "unkown" : request.getMethod().toString();
+ uri = request.getRawRequestUri() == null ? "unkown" : request.getRawRequestUri();
+ protocol = request.getProtocol() == null ? "unkown" : request.getProtocol();
+ // TODO: Should we really wrap the headers here or keep the original structure?
+ headers = wrapHeaders(request.getAllHeaders());
+ }
+
+ private Map<String, String> wrapHeaders(Map<String, List<String>> allHeaders) {
+ Map<String, String> localHeaders = new LinkedHashMap<String, String>();
+ for (Map.Entry<String, List<String>> entry : allHeaders.entrySet()) {
+ String value = null;
+ if (entry.getValue() != null) {
+ value = "";
+ boolean first = true;
+ for (String valuePart : entry.getValue()) {
+ if (!first) {
+ value = value + ", ";
+ }
+ value = value + valuePart;
+ }
+ }
+ localHeaders.put(entry.getKey(), value);
+ }
+ return localHeaders;
+ }
+
+ @Override
+ public void appendHtml(final Writer writer) throws IOException {
+ writer.append("<h2>Request Method</h2>\n")
+ .append("<p>").append(method).append("</p>\n")
+ .append("<h2>Request URI</h2>\n")
+ .append("<p>").append(DebugResponseHelperImpl.escapeHtml(uri.toString())).append("</p>\n")
+ .append("<h2>Request Protocol</h2>\n")
+ .append("<p>").append(protocol).append("</p>\n");
+ writer.append("<h2>Request Headers</h2>\n");
+ DebugResponseHelperImpl.appendHtmlTable(writer, headers);
+
+// .append("<table>\n<thead>\n")
+// .append("<tr><th class=\"name\">Name</th><th class=\"value\">Value</th></tr>\n")
+// .append("</thead>\n<tbody>\n");
+// for (final String name : headers.keySet()) {
+// for (final String value : headers.get(name)) {
+// if (value != null) {
+// writer.append("<tr><td class=\"name\">").append(name).append("</td>")
+// .append("<td class=\"value\">").append(DebugResponseHelperImpl.escapeHtml(value))
+// .append("</td></tr>\n");
+// }
+// }
+// }
+// writer.append("</tbody>\n</table>\n");
+ }
+
+ @Override
+ public String getName() {
+ return "Request";
+ }
+
+ @Override
+ public void appendJson(JsonGenerator gen) throws IOException {
+ gen.writeStartObject();
+ gen.writeStringField("method", method);
+
+ gen.writeStringField("uri", uri);
+
+ gen.writeStringField("protocol", protocol);
+
+ if (!headers.isEmpty()) {
+ gen.writeFieldName("headers");
+ DebugResponseHelperImpl.appendJsonTable(gen, headers);
+ }
+
+ gen.writeEndObject();
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabResponse.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabResponse.java
new file mode 100644
index 0000000..5cb153c
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabResponse.java
@@ -0,0 +1,89 @@
+/*
+ * 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 org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.ODataResponse;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+/**
+ * Response debug information.
+ */
+public class DebugTabResponse implements DebugTab {
+
+ private final ODataResponse response;
+ private final String serviceRoot;
+ private final HttpStatusCode status;
+ private final Map<String, String> headers;
+
+ public DebugTabResponse(final ODataResponse applicationResponse, final String serviceRoot) {
+ this.response = applicationResponse;
+ this.serviceRoot = serviceRoot;
+ status = HttpStatusCode.fromStatusCode(response.getStatusCode());
+ headers = response.getHeaders();
+ }
+
+ @Override
+ public String getName() {
+ return "Response";
+ }
+
+ @Override
+ public void appendJson(final JsonGenerator gen) throws IOException {
+ gen.writeStartObject();
+
+ if (status != null) {
+ gen.writeFieldName("status");
+ gen.writeStartObject();
+ gen.writeStringField("code", Integer.toString(status.getStatusCode()));
+ gen.writeStringField("info", status.getInfo());
+ gen.writeEndObject();
+ }
+
+ if (headers != null && !headers.isEmpty()) {
+ gen.writeFieldName("headers");
+ DebugResponseHelperImpl.appendJsonTable(gen, headers);
+ }
+
+ gen.writeFieldName("body");
+ new DebugTabBody(response, serviceRoot).appendJson(gen);
+
+ gen.writeEndObject();
+ }
+
+ @Override
+ public void appendHtml(final Writer writer) throws IOException {
+ writer.append("<h2>Status Code</h2>\n")
+ .append("<p>").append(Integer.toString(status.getStatusCode())).append(' ')
+ .append(status.getInfo()).append("</p>\n")
+ .append("<h2>Response Headers</h2>\n");
+ DebugResponseHelperImpl.appendHtmlTable(writer, headers);
+ writer.append("<h2>Response Body</h2>\n");
+ if (response.getContent() != null) {
+ new DebugTabBody(response, serviceRoot).appendHtml(writer);
+ } else {
+ writer.append("<p>ODataLibrary: no response body</p>");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRuntime.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRuntime.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRuntime.java
new file mode 100644
index 0000000..312b4cd
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRuntime.java
@@ -0,0 +1,181 @@
+/*
+ * 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.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.olingo.server.api.debug.RuntimeMeasurement;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+/**
+ * Runtime debug information.
+ */
+public class DebugTabRuntime implements DebugTab {
+
+ private final RuntimeNode rootNode;
+
+ public DebugTabRuntime(List<RuntimeMeasurement> runtimeInformation) {
+ rootNode = new RuntimeNode();
+ for (final RuntimeMeasurement runtimeMeasurement : runtimeInformation) {
+ rootNode.add(runtimeMeasurement);
+ }
+ rootNode.combineRuntimeMeasurements();
+ }
+
+ @Override
+ public String getName() {
+ return "Runtime";
+ }
+
+ @Override
+ public void appendJson(JsonGenerator gen) throws IOException {
+ appendJsonChildren(gen, rootNode);
+ }
+
+ private void appendJsonChildren(JsonGenerator gen, RuntimeNode node) throws IOException {
+ gen.writeStartArray();
+ for (RuntimeNode child : node.children) {
+ appendJsonNode(gen, child);
+ }
+ gen.writeEndArray();
+ }
+
+ private void appendJsonNode(JsonGenerator gen, RuntimeNode node) throws IOException {
+ gen.writeStartObject();
+ gen.writeStringField("class", node.className);
+ gen.writeStringField("method ", node.methodName);
+
+ if (node.timeStopped == 0) {
+ gen.writeNullField("duration");
+ } else {
+ gen.writeStringField("duration", Long.toString((node.timeStopped - node.timeStarted) / 1000));
+ gen.writeStringField("unit", "µs");
+ }
+
+ if (!node.children.isEmpty()) {
+ gen.writeFieldName("children");
+ appendJsonChildren(gen, node);
+ }
+
+ gen.writeEndObject();
+ }
+
+ @Override
+ public void appendHtml(final Writer writer) throws IOException {
+ appendRuntimeNode(rootNode, "", true, writer);
+ }
+
+ private void appendRuntimeNode(final RuntimeNode node, final String draw, final boolean isLast, final Writer writer)
+ throws IOException {
+ if (node.className != null) {
+ writer.append("<li>")
+ .append("<span class=\"code\">")
+ .append("<span class=\"draw\">").append(draw)
+ .append(isLast ? "└" : "├").append("─ </span>")
+ .append("<span class=\"class\">").append(node.className).append("</span>.")
+ .append("<span class=\"method\">").append(node.methodName).append("(…)")
+ .append("</span></span>");
+ long time = node.timeStopped == 0 ? 0 : (node.timeStopped - node.timeStarted) / 1000;
+ writer.append("<span class=\"").append(time == 0 ? "null" : "numeric")
+ .append("\" title=\"").append(time == 0 ? "Stop time missing" : "Gross duration")
+ .append("\">").append(time == 0 ? "unfinished" : Long.toString(time) + " µs")
+ .append("</span>\n");
+ }
+ if (!node.children.isEmpty()) {
+ writer.append("<ol class=\"tree\">\n");
+ for (final RuntimeNode childNode : node.children) {
+ appendRuntimeNode(childNode,
+ node.className == null ? draw : draw + (isLast ? " " : "│") + " ",
+ node.children.indexOf(childNode) == node.children.size() - 1,
+ writer);
+ }
+ writer.append("</ol>\n");
+ }
+ if (node.className != null) {
+ writer.append("</li>\n");
+ }
+ }
+
+ private class RuntimeNode {
+
+ protected String className;
+ protected String methodName;
+ protected long timeStarted;
+ protected long timeStopped;
+ protected List<RuntimeNode> children = new ArrayList<RuntimeNode>();
+
+ protected RuntimeNode() {
+ timeStarted = 0;
+ timeStopped = Long.MAX_VALUE;
+ }
+
+ private RuntimeNode(final RuntimeMeasurement runtimeMeasurement) {
+ className = runtimeMeasurement.getClassName();
+ methodName = runtimeMeasurement.getMethodName();
+ timeStarted = runtimeMeasurement.getTimeStarted();
+ timeStopped = runtimeMeasurement.getTimeStopped();
+ }
+
+ protected boolean add(final RuntimeMeasurement runtimeMeasurement) {
+ if (timeStarted <= runtimeMeasurement.getTimeStarted()
+ && timeStopped != 0 && timeStopped >= runtimeMeasurement.getTimeStopped()) {
+ for (RuntimeNode candidate : children) {
+ if (candidate.add(runtimeMeasurement)) {
+ return true;
+ }
+ }
+ children.add(new RuntimeNode(runtimeMeasurement));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Combines runtime measurements with identical class names and method
+ * names into one measurement, assuming that they originate from a loop
+ * or a similar construct where a summary measurement has been intended.
+ */
+ protected void combineRuntimeMeasurements() {
+ RuntimeNode preceding = null;
+ for (Iterator<RuntimeNode> iterator = children.iterator(); iterator.hasNext();) {
+ final RuntimeNode child = iterator.next();
+ if (preceding != null
+ && preceding.timeStopped != 0 && child.timeStopped != 0
+ && preceding.timeStopped <= child.timeStarted
+ && preceding.children.isEmpty() && child.children.isEmpty()
+ && preceding.methodName.equals(child.methodName)
+ && preceding.className.equals(child.className)) {
+ preceding.timeStarted = child.timeStarted - (preceding.timeStopped - preceding.timeStarted);
+ preceding.timeStopped = child.timeStopped;
+
+ iterator.remove();
+ } else {
+ preceding = child;
+ child.combineRuntimeMeasurements();
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabServer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabServer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabServer.java
new file mode 100644
index 0000000..4eb95ba
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabServer.java
@@ -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);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java
new file mode 100644
index 0000000..5c50c0f
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java
@@ -0,0 +1,232 @@
+/*
+ * 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.olingo.server.api.uri.UriInfo;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+
+/**
+ * URI parser debug information.
+ */
+public class DebugTabUri implements DebugTab {
+
+ private UriInfo uriInfo;
+
+ public DebugTabUri(UriInfo uriInfo) {
+ this.uriInfo = uriInfo;
+ }
+
+ @Override
+ public String getName() {
+ return "URI";
+ }
+
+ @Override
+ public void appendJson(JsonGenerator jsonGenerator) throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void appendHtml(Writer writer) throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+// private final UriInfo uriInfo;
+// private final FilterExpression filter;
+// private final OrderByExpression orderBy;
+// private final ExpandSelectTreeNodeImpl expandSelectTree;
+// private final ExpressionParserException exception;
+//
+// public DebugInfoUri(final UriInfo uriInfo, final ExpressionParserException exception) {
+// this.uriInfo = uriInfo;
+// filter = uriInfo == null ? null : uriInfo.getFilter();
+// orderBy = uriInfo == null ? null : uriInfo.getOrderBy();
+// expandSelectTree = uriInfo == null ? null : getExpandSelect();
+// this.exception = exception;
+// }
+//
+// private ExpandSelectTreeNodeImpl getExpandSelect() {
+// try {
+// return uriInfo.getExpand().isEmpty() && uriInfo.getSelect().isEmpty() ? null :
+// new ExpandSelectTreeCreator(uriInfo.getSelect(), uriInfo.getExpand()).create();
+// } catch (final EdmException e) {
+// return null;
+// }
+// }
+// @Override
+// public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
+// jsonStreamWriter.beginObject();
+//
+// if (exception != null && exception.getFilterTree() != null) {
+// jsonStreamWriter.name("error")
+// .beginObject()
+// .namedStringValue("expression", exception.getFilterTree().getUriLiteral())
+// .endObject();
+// if (filter != null || orderBy != null || expandSelectTree != null) {
+// jsonStreamWriter.separator();
+// }
+// }
+//
+// if (filter != null) {
+// String filterString;
+// try {
+// filterString = (String) filter.accept(new JsonVisitor());
+// } catch (final ExceptionVisitExpression e) {
+// filterString = null;
+// } catch (final ODataApplicationException e) {
+// filterString = null;
+// }
+// jsonStreamWriter.name("filter").unquotedValue(filterString);
+// if (orderBy != null || expandSelectTree != null) {
+// jsonStreamWriter.separator();
+// }
+// }
+//
+// if (orderBy != null) {
+// String orderByString;
+// try {
+// orderByString = (String) orderBy.accept(new JsonVisitor());
+// } catch (final ExceptionVisitExpression e) {
+// orderByString = null;
+// } catch (final ODataApplicationException e) {
+// orderByString = null;
+// }
+// jsonStreamWriter.name("orderby").unquotedValue(orderByString);
+// if (expandSelectTree != null) {
+// jsonStreamWriter.separator();
+// }
+// }
+//
+// if (expandSelectTree != null) {
+// jsonStreamWriter.name("expandSelect").unquotedValue(expandSelectTree.toJsonString());
+// }
+//
+// jsonStreamWriter.endObject();
+// }
+//
+// @Override
+// public void appendHtml(final Writer writer) throws IOException {
+// if (exception != null && exception.getFilterTree() != null) {
+// writer.append("<h2>Expression Information</h2>\n")
+// .append("<pre class=\"code\">").append(exception.getFilterTree().getUriLiteral())
+// .append("</pre>\n");
+// // TODO: filter error position, filter tokens, filter tree
+// }
+// if (filter != null) {
+// writer.append("<h2>Filter</h2>\n")
+// .append("<ul class=\"expr\"><li>");
+// appendExpression(filter.getExpression(), writer);
+// writer.append("</li></ul>\n");
+// }
+// if (orderBy != null) {
+// writer.append("<h2>Orderby</h2>\n")
+// .append(orderBy.getOrdersCount() == 1 ? "<ul" : "<ol").append(" class=\"expr\">\n");
+// for (final OrderExpression order : orderBy.getOrders()) {
+// writer.append("<li>");
+// appendExpression(order.getExpression(), writer);
+// final ExpressionKind kind = order.getExpression().getKind();
+// if (kind == ExpressionKind.PROPERTY || kind == ExpressionKind.LITERAL) {
+// writer.append("<br />");
+// }
+// writer.append("<span class=\"order\">")
+// .append(order.getSortOrder().toString())
+// .append("</span></li>\n");
+// }
+// writer.append(orderBy.getOrdersCount() == 1 ? "</ul" : "</ol").append(">\n");
+// }
+// if (expandSelectTree != null) {
+// writer.append("<h2>Expand/Select</h2>\n");
+// appendExpandSelect(expandSelectTree, writer);
+// }
+// }
+//
+// private void appendExpression(final CommonExpression expression, final Writer writer) throws IOException {
+// final ExpressionKind kind = expression.getKind();
+// writer.append("<span class=\"kind\">")
+// .append(kind.toString())
+// .append("</span> <span class=\"literal\">")
+// .append(kind == ExpressionKind.MEMBER ? ((MemberExpression) expression).getProperty().getUriLiteral() :
+// expression.getUriLiteral())
+// .append("</span>, type <span class=\"type\">")
+// .append(expression.getEdmType().toString())
+// .append("</span>");
+// if (kind == ExpressionKind.UNARY) {
+// writer.append("<ul class=\"expr\"><li>");
+// appendExpression(((UnaryExpression) expression).getOperand(), writer);
+// writer.append("</li></ul>");
+// } else if (kind == ExpressionKind.BINARY) {
+// writer.append("<ol class=\"expr\"><li>");
+// appendExpression(((BinaryExpression) expression).getLeftOperand(), writer);
+// writer.append("</li><li>");
+// appendExpression(((BinaryExpression) expression).getRightOperand(), writer);
+// writer.append("</li></ol>");
+// } else if (kind == ExpressionKind.METHOD) {
+// final MethodExpression methodExpression = (MethodExpression) expression;
+// if (methodExpression.getParameterCount() > 0) {
+// writer.append("<ol class=\"expr\">");
+// for (final CommonExpression parameter : methodExpression.getParameters()) {
+// writer.append("<li>");
+// appendExpression(parameter, writer);
+// writer.append("</li>");
+// }
+// writer.append("</ol>");
+// }
+// } else if (kind == ExpressionKind.MEMBER) {
+// writer.append("<ul class=\"expr\"><li>");
+// appendExpression(((MemberExpression) expression).getPath(), writer);
+// writer.append("</li></ul>");
+// }
+// }
+//
+// private void appendExpandSelect(final ExpandSelectTreeNode expandSelect, final Writer writer) throws IOException {
+// writer.append("<ul class=\"expand\">\n")
+// .append("<li>");
+// if (expandSelect.isAll()) {
+// writer.append("all properties");
+// } else {
+// for (final EdmProperty property : expandSelect.getProperties()) {
+// try {
+// writer.append("property <span class=\"prop\">")
+// .append(property.getName())
+// .append("</span><br />");
+// } catch (final EdmException e) {}
+// }
+// }
+// writer.append("</li>\n");
+// if (!expandSelect.getLinks().isEmpty()) {
+// for (final String name : expandSelect.getLinks().keySet()) {
+// writer.append("<li>link <span class=\"link\">").append(name).append("</span>");
+// final ExpandSelectTreeNode link = expandSelect.getLinks().get(name);
+// if (link != null) {
+// writer.append('\n');
+// appendExpandSelect(link, writer);
+// }
+// writer.append("</li>\n");
+// }
+// }
+// writer.append("</ul>\n");
+// }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ServerCoreDebugger.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ServerCoreDebugger.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ServerCoreDebugger.java
new file mode 100644
index 0000000..fcf611d
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ServerCoreDebugger.java
@@ -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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
index 0b5922c..8b74a88 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
@@ -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.edmx.EdmxReference;
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.processor.TechnicalActionProcessor;
import org.apache.olingo.server.tecsvc.processor.TechnicalBatchProcessor;
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
index 236c1b7..5b347d1 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
@@ -6,9 +6,9 @@
* 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
@@ -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.ServiceDocumentProcessor;
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.EdmTechProvider;
import org.junit.Test;
@@ -233,7 +234,8 @@ public class ODataHandlerTest {
request.setMethod(HttpMethod.GET);
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);
assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode());
}
@@ -720,7 +722,7 @@ public class ODataHandlerTest {
final ServiceMetadata metadata = odata.createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference> emptyList());
- ODataHandler handler = new ODataHandler(odata, metadata);
+ ODataHandler handler = new ODataHandler(odata, metadata, new ServerCoreDebugger(odata));
if (processor != null) {
handler.register(processor);