// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.sdk.internal.v8native;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.chromium.sdk.DebugEventListener;
import org.chromium.sdk.RelayOk;
import org.chromium.sdk.SyncCallback;
import org.chromium.sdk.internal.BaseCommandProcessor;
import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;
import org.chromium.sdk.internal.v8native.protocol.input.CommandResponse;
import org.chromium.sdk.internal.v8native.protocol.input.IncomingMessage;
import org.chromium.sdk.internal.v8native.protocol.input.V8ProtocolParserAccess;
import org.chromium.sdk.internal.v8native.protocol.output.DebuggerMessage;
import org.json.simple.JSONObject;
/**
* Sends JSON commands to V8 VM and handles responses. Command is sent
* via {@code V8CommandOutput}. Response is passed back to callback if it was provided.
* Also all responses and events are dispatched to group of dedicated processors.
*/
public class V8CommandProcessor implements V8CommandSender<DebuggerMessage, RuntimeException> {
/**
* A callback to handle V8 debugger responses.
*/
public interface V8HandlerCallback extends BaseCommandProcessor.Callback<CommandResponse> {
/**
* This method is invoked when a debugger command result has become
* available.
*
* @param response from the V8 debugger
*/
void messageReceived(CommandResponse response);
/**
* This method is invoked when a debugger command has failed.
*
* @param message containing the failure reason
*/
void failure(String message);
/** A no-op callback implementation. */
V8HandlerCallback NULL_CALLBACK = new V8HandlerCallback() {
public void failure(String message) {
}
public void messageReceived(CommandResponse response) {
}
};
}
/** The class logger. */
private static final Logger LOGGER = Logger.getLogger(V8CommandProcessor.class.getName());
private final V8CommandOutput messageOutput;
private final DefaultResponseHandler defaultResponseHandler;
private final DebugSession debugSession;
private final BaseCommandProcessor<Integer, DebuggerMessage, IncomingMessage, CommandResponse>
baseCommandProcessor;
public V8CommandProcessor(V8CommandOutput messageOutput,
DefaultResponseHandler defaultResponseHandler, DebugSession debugSession) {
this.messageOutput = messageOutput;
this.defaultResponseHandler = defaultResponseHandler;
this.debugSession = debugSession;
this.baseCommandProcessor =
new BaseCommandProcessor<Integer, DebuggerMessage, IncomingMessage, CommandResponse>(
new HandlerImpl());
}
@Override
public RelayOk sendV8CommandAsync(DebuggerMessage message, boolean isImmediate,
V8HandlerCallback v8HandlerCallback, SyncCallback syncCallback) {
return baseCommandProcessor.send(message, isImmediate, v8HandlerCallback, syncCallback);
}
public RelayOk runInDispatchThread(final Runnable callback, final SyncCallback syncCallback) {
Runnable innerRunnable = new Runnable() {
@Override public void run() {
RuntimeException exception = null;
try {
callback.run();
} catch (RuntimeException e) {
exception = e;
throw e;
} finally {
if (syncCallback != null) {
syncCallback.callbackDone(exception);
}
}
}
};
messageOutput.runInDispatchThread(innerRunnable);
return DISPATCH_THREAD_PROMISES_TO_CALL;
}
public void processIncomingJson(final JSONObject v8Json) {
IncomingMessage response;
try {
response = V8ProtocolParserAccess.get().parseIncomingMessage(v8Json);
} catch (JsonProtocolParseException e) {
LOGGER.log(Level.SEVERE, "JSON message does not conform to the protocol", e);
return;
}
baseCommandProcessor.processIncoming(response);
}
public void processEos() {
baseCommandProcessor.processEos();
}
private class HandlerImpl implements
BaseCommandProcessor.Handler<Integer, DebuggerMessage, IncomingMessage, CommandResponse> {
public Integer getUpdatedSeq(DebuggerMessage message) {
return message.getSeq();
}
public String getCommandName(DebuggerMessage message) {
return message.getCommand();
}
public void send(DebuggerMessage message, boolean isImmediate) {
V8CommandProcessor.this.messageOutput.send(message, isImmediate);
}
public CommandResponse parseWithSeq(IncomingMessage incoming) {
return incoming.asCommandResponse();
}
public Integer getSeq(CommandResponse incomingWithSeq) {
return (int) incomingWithSeq.requestSeq();
}
public void acceptNonSeq(IncomingMessage incoming) {
V8CommandProcessor.this.defaultResponseHandler.handleResponseWithHandler(incoming);
}
public void reportVmStatus(String currentRequest, int numberOfEnqueued) {
DebugEventListener.VmStatusListener statusListener =
V8CommandProcessor.this.debugSession.getDebugEventListener().getVmStatusListener();
if (statusListener == null) {
return;
}
}
}
private static final RelayOk DISPATCH_THREAD_PROMISES_TO_CALL = new RelayOk() {};
}