/*
* Copyright (c) 2013, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html
*
* 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 com.google.dart.tools.debug.core.server;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IRegisterGroup;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IVariable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* A pseudo stack frame for the current isolate. This frame will be able to enumerate all the
* libraries in the current isolate, and each library's top-level variables.
*/
public class ServerDebugIsolateFrame extends ServerDebugElement implements IStackFrame {
/**
* This IValueRetriever implementation retrieves the top-level variables for a library given a
* VmLibraryRef.
*/
static class LibraryVariableRetriever implements IValueRetriever {
private final ServerDebugTarget target;
private final VmIsolate isolate;
private final VmLibraryRef libraryRef;
LibraryVariableRetriever(ServerDebugTarget target, VmIsolate isolate, VmLibraryRef libraryRef) {
this.target = target;
this.isolate = isolate;
this.libraryRef = libraryRef;
}
@Override
public String getDisplayName() {
return "";
}
@Override
public List<IVariable> getVariables() {
final CountDownLatch latch = new CountDownLatch(1);
final List<IVariable> vars = new ArrayList<IVariable>();
try {
target.getConnection().getLibraryProperties(
isolate,
libraryRef.getId(),
new VmCallback<VmLibrary>() {
@Override
public void handleResult(VmResult<VmLibrary> result) {
if (!result.isError()) {
for (VmVariable var : result.getResult().getGlobals()) {
vars.add(new ServerDebugVariable(target, var));
}
}
latch.countDown();
}
});
} catch (IOException e1) {
latch.countDown();
}
try {
latch.await();
} catch (InterruptedException e) {
}
return vars;
}
@Override
public boolean hasVariables() {
return true;
}
}
private static String getNameFor(String libraryUrl) {
// Return 'bar.dart' for 'file:///foo/.../bar.dart.
if (libraryUrl.startsWith("file:") && libraryUrl.indexOf('/') != -1) {
return "file:" + libraryUrl.substring(libraryUrl.lastIndexOf('/') + 1);
}
return libraryUrl;
}
private ServerDebugThread thread;
List<IVariable> variables;
public ServerDebugIsolateFrame(ServerDebugThread thread) {
super(thread.getTarget());
this.thread = thread;
}
@Override
public boolean canResume() {
return thread.canResume();
}
@Override
public boolean canStepInto() {
return thread.canStepInto();
}
@Override
public boolean canStepOver() {
return thread.canStepOver();
}
@Override
public boolean canStepReturn() {
return thread.canStepReturn();
}
@Override
public boolean canSuspend() {
return thread.canSuspend();
}
@Override
public boolean canTerminate() {
return thread.canTerminate();
}
@Override
public int getCharEnd() throws DebugException {
// not called
return 0;
}
@Override
public int getCharStart() throws DebugException {
// not called
return 0;
}
@Override
public int getLineNumber() throws DebugException {
// not called
return 0;
}
@Override
public String getName() throws DebugException {
return thread.getName();
}
@Override
public IRegisterGroup[] getRegisterGroups() throws DebugException {
return null;
}
@Override
public IThread getThread() {
return thread;
}
@Override
public IVariable[] getVariables() throws DebugException {
if (variables == null) {
variables = new ArrayList<IVariable>();
final CountDownLatch latch = new CountDownLatch(1);
try {
getConnection().getLibraries(thread.getIsolate(), new VmCallback<List<VmLibraryRef>>() {
@Override
public void handleResult(VmResult<List<VmLibraryRef>> result) {
if (!result.isError() && result.getResult() != null) {
List<VmLibraryRef> libraries = new ArrayList<VmLibraryRef>(result.getResult());
Collections.sort(libraries);
for (VmLibraryRef ref : libraries) {
ServerDebugVariable variable = new ServerDebugVariable(
getTarget(),
getNameFor(ref.getUrl()),
new LibraryVariableRetriever(getTarget(), thread.getIsolate(), ref));
variable.setIsLibraryObject(true);
variables.add(variable);
}
}
latch.countDown();
}
});
} catch (IOException e) {
latch.countDown();
}
try {
latch.await();
} catch (InterruptedException e) {
}
}
return variables.toArray(new IVariable[variables.size()]);
}
@Override
public boolean hasRegisterGroups() throws DebugException {
return false;
}
@Override
public boolean hasVariables() throws DebugException {
return true;
}
@Override
public boolean isStepping() {
return thread.isStepping();
}
@Override
public boolean isSuspended() {
return thread.isSuspended();
}
@Override
public boolean isTerminated() {
return thread.isTerminated();
}
@Override
public void resume() throws DebugException {
thread.resume();
}
@Override
public void stepInto() throws DebugException {
thread.stepInto();
}
@Override
public void stepOver() throws DebugException {
thread.stepOver();
}
@Override
public void stepReturn() throws DebugException {
thread.stepReturn();
}
@Override
public void suspend() throws DebugException {
thread.suspend();
}
@Override
public void terminate() throws DebugException {
thread.terminate();
}
}