blob: de5171fa984fed87a780a695ce48f3e25ca25c68 [file]
/*
* 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.netbeans.modules.debugger.jpda.projectsui;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.swing.Action;
import javax.swing.SwingUtilities;
import org.netbeans.api.debugger.DebuggerEngine;
import org.netbeans.api.debugger.DebuggerManager;
import org.netbeans.api.debugger.jpda.ClassLoadUnloadBreakpoint;
import org.netbeans.api.debugger.jpda.ExceptionBreakpoint;
import org.netbeans.api.debugger.jpda.FieldBreakpoint;
import org.netbeans.api.debugger.jpda.JPDABreakpoint;
import org.netbeans.api.debugger.jpda.LineBreakpoint;
import org.netbeans.api.debugger.jpda.MethodBreakpoint;
import org.netbeans.api.debugger.jpda.ThreadBreakpoint;
import org.netbeans.api.java.classpath.GlobalPathRegistry;
import org.netbeans.modules.debugger.jpda.projects.EditorContextSupport;
import org.netbeans.modules.debugger.jpda.projects.SourcePathProviderImpl;
import org.netbeans.spi.debugger.DebuggerServiceRegistration;
import org.netbeans.spi.debugger.jpda.SourcePathProvider;
import org.netbeans.spi.viewmodel.Models;
import org.netbeans.spi.viewmodel.NodeActionsProvider;
import org.netbeans.spi.viewmodel.NodeActionsProviderFilter;
import org.netbeans.spi.viewmodel.UnknownTypeException;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.URLMapper;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
/**
* @author Martin Entlicher
*/
@DebuggerServiceRegistration(path="BreakpointsView", types=NodeActionsProviderFilter.class)
public class BreakpointsActionsProvider implements NodeActionsProviderFilter {
private static final Action GO_TO_SOURCE_ACTION = Models.createAction (
loc("CTL_Breakpoint_GoToSource_Label"), // NOI18N
new Models.ActionPerformer () {
@Override
public boolean isEnabled (Object node) {
return true;
}
@Override
public void perform (Object[] nodes) {
goToSource ((JPDABreakpoint) nodes [0]);
}
},
Models.MULTISELECTION_TYPE_EXACTLY_ONE
);
private static String loc(String key) {
return NbBundle.getMessage(BreakpointsActionsProvider.class, key);
}
@Override
public Action[] getActions (NodeActionsProvider original, Object node)
throws UnknownTypeException {
if (!(node instanceof JPDABreakpoint) || node instanceof ThreadBreakpoint) {
return original.getActions (node);
}
Action[] oas = original.getActions (node);
Action[] as = new Action [oas.length + 2];
as [0] = GO_TO_SOURCE_ACTION;
as [1] = null;
System.arraycopy (oas, 0, as, 2, oas.length);
return as;
}
@Override
public void performDefaultAction (NodeActionsProvider original, Object node) throws UnknownTypeException {
if (node instanceof JPDABreakpoint && !(node instanceof ThreadBreakpoint)) {
goToSource ((JPDABreakpoint) node);
} else {
original.performDefaultAction (node);
}
}
private static void goToSource (JPDABreakpoint b) {
String url;
int lineNumber;
Future futureLineNumber = null;
if (b instanceof LineBreakpoint) {
LineBreakpoint lb = (LineBreakpoint) b;
url = lb.getURL();
lineNumber = lb.getLineNumber();
if (lineNumber < 1) {
lineNumber = 1;
}
} else if (b instanceof FieldBreakpoint) {
FieldBreakpoint fb = (FieldBreakpoint) b;
String fieldName = fb.getFieldName();
String className = fb.getClassName ();
FileObject fo = getFileObject(getRelativePath (className));
if (fo == null) {
return ;
}
url = fo.toURL ().toString ();
Future<Integer> fi = EditorContextSupport.getFieldLineNumber (
fo,
className,
fieldName
);
if (fi.isDone()) {
try {
lineNumber = fi.get();
} catch (InterruptedException ex) {
lineNumber = 1;
} catch (ExecutionException ex) {
Exceptions.printStackTrace(ex);
lineNumber = 1;
}
} else {
futureLineNumber = fi;
lineNumber = -1;
}
} else if (b instanceof MethodBreakpoint) {
MethodBreakpoint mb = (MethodBreakpoint) b;
String methodName = mb.getMethodName();
String[] classFilters = mb.getClassFilters();
if (classFilters.length < 1) {
return ;
}
String className = classFilters[0];
FileObject fo = getFileObject(getRelativePath (className));
if (fo == null) {
return ;
}
url = fo.toURL ().toString ();
Future<int[]> fi = EditorContextSupport.getMethodLineNumbers(
fo,
className,
mb.getClassExclusionFilters(),
methodName,
mb.getMethodSignature()
);
if (fi.isDone()) {
int[] lineNumbers;
try {
lineNumbers = fi.get();
if (lineNumbers.length == 0) {
lineNumber = 1;
} else {
lineNumber = lineNumbers[0];
}
} catch (InterruptedException ex) {
lineNumber = 1;
} catch (ExecutionException ex) {
Exceptions.printStackTrace(ex);
lineNumber = 1;
}
} else {
futureLineNumber = fi;
lineNumber = -1;
}
} else if (b instanceof ExceptionBreakpoint) {
ExceptionBreakpoint eb = (ExceptionBreakpoint) b;
String className = eb.getExceptionClassName();
FileObject fo = getFileObject(getRelativePath (className));
if (fo == null) {
return ;
}
url = fo.toURL ().toString ();
// TODO: EditorContextImpl.getClassLineNumber(fo, className);
lineNumber = 1;
} else if (b instanceof ClassLoadUnloadBreakpoint) {
ClassLoadUnloadBreakpoint cb = (ClassLoadUnloadBreakpoint) b;
String[] classNames = cb.getClassFilters();
if (classNames.length == 0) {
return;
}
String className = classNames[0];
FileObject fo = getFileObject(getRelativePath (className));
if (fo == null) {
return ;
}
url = fo.toURL ().toString ();
// TODO: EditorContextImpl.getClassLineNumber(fo, className);
lineNumber = 1;
} else {
return;
}
if (futureLineNumber != null) {
final Future future = futureLineNumber;
final String u = url;
RequestProcessor.getDefault().post(new Runnable() {
@Override
public void run() {
try {
Object lineObj = future.get();
final int line;
if (lineObj instanceof Integer) {
line = (Integer) lineObj;
} else {
int[] lines = (int[]) lineObj;
if (lines.length == 0) {
line = 1;
} else {
line = lines[0];
}
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
EditorContextImpl.showSourceLine (
u,
line,
null
);
}
});
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
Exceptions.printStackTrace(ex);
}
}
});
return ;
}
EditorContextImpl.showSourceLine (
url,
lineNumber,
null
);
}
private static FileObject getFileObject(String classRelPath) {
DebuggerEngine engine = DebuggerManager.getDebuggerManager ().getCurrentEngine();
if (engine != null) {
SourcePathProvider sp = engine.lookupFirst(null, SourcePathProvider.class);
if (sp != null) {
String url = sp.getURL(classRelPath, false);
if (url == null) {
url = sp.getURL(classRelPath, true);
}
if (url != null) {
try {
FileObject fo = URLMapper.findFileObject(new URL(url));
if (fo != null) {
return fo;
}
} catch (MalformedURLException ex) {
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
}
}
}
}
classRelPath = SourcePathProviderImpl.normalize(classRelPath);
FileObject fo = GlobalPathRegistry.getDefault().findResource(classRelPath);
return fo;
}
private static String getRelativePath (String className) {
int i = className.indexOf ('$');
if (i > 0) {
className = className.substring (0, i);
}
String sourceName = className.replace
('.', '/') + ".java";
return sourceName;
}
}