blob: 232693ec593202ae2351521311182d6f6fa5459b [file] [log] [blame]
/*
* 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.groovy.debug;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.codehaus.groovy.ast.ASTNode;
import org.netbeans.api.debugger.jpda.JPDABreakpoint;
import org.netbeans.api.debugger.jpda.LineBreakpoint;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.modules.groovy.editor.api.ASTUtils;
import org.netbeans.modules.groovy.editor.api.AstPath;
import org.netbeans.modules.groovy.editor.api.parser.GroovyLanguage;
import org.netbeans.modules.groovy.editor.api.parser.GroovyParserResult;
import org.netbeans.modules.parsing.api.ParserManager;
import org.netbeans.modules.parsing.api.ResultIterator;
import org.netbeans.modules.parsing.api.Source;
import org.netbeans.modules.parsing.api.UserTask;
import org.netbeans.modules.parsing.spi.ParseException;
import org.netbeans.spi.debugger.jpda.BreakpointStratifier;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider;
/**
* Modifies breakpoints to adapt to the Groovy stratum.
*
* @author Martin Janicek
*/
@ServiceProvider(service = BreakpointStratifier.class)
public final class GroovyBreakpointStratifier implements BreakpointStratifier {
public final static String GROOVY_STRATUM = "Groovy"; //NOI18N
private static final Logger LOGGER = Logger.getLogger(GroovyBreakpointStratifier.class.getName());
public GroovyBreakpointStratifier() {
}
/**
* Creates a new breakpoint for the given parameters.
*
* @param url a url
* @param lineNumber a line number
* @return a new breakpoint for given parameters
*/
@Override
@Messages("CTL_Default_Print_Text=Breakpoint reached at line {lineNumber} in {groovyName} by thread {threadName}.")
public void stratify(JPDABreakpoint breakpoint) {
if (breakpoint instanceof LineBreakpoint) {
LineBreakpoint lb = (LineBreakpoint) breakpoint;
String url = lb.getURL();
FileObject fo = getFileObjectFromUrl(url);
if (fo != null && GroovyLanguage.GROOVY_MIME_TYPE.equals(fo.getMIMEType())) {
int lineNumber = lb.getLineNumber();
String groovyName = fo.getNameExt();
String pt = Bundle.CTL_Default_Print_Text();
String printText = pt.replace("{groovyName}", (groovyName != null) ? groovyName : "?"); // NOI18N
String groovyPath = getGroovyPath(url, fo);
lb.setStratum(GROOVY_STRATUM);
lb.setSourceName(groovyName);
lb.setSourcePath(groovyPath);
lb.setPreferredClassName(findGroovyClassName(groovyPath, fo, lineNumber));
lb.setPrintText(printText);
}
}
}
private static FileObject getFileObjectFromUrl(String url) {
FileObject fo = null;
try {
fo = URLMapper.findFileObject(new URL(url));
} catch (MalformedURLException e) {
//noop
}
return fo;
}
private static String findGroovyClassName(String relativePath, FileObject fo, int lineNumber) {
Source source = Source.create(fo);
String[] className = new String[] { null };
try {
ParserManager.parse(Collections.singleton(source), new UserTask() {
public @Override void run(ResultIterator resultIterator) throws Exception {
GroovyParserResult result = ASTUtils.getParseResult(resultIterator.getParserResult());
ASTNode root = ASTUtils.getRoot(result);
AstPath path = new AstPath(root, lineNumber, 0);
className[0] = ASTUtils.getFqnName(path);
}
});
} catch (ParseException ex) {
}
if (className[0] != null) {
return className[0];
} else {
return getClassFilter(relativePath);
}
}
private static String getClassFilter(String relativePath) {
if (relativePath == null) {
return "";
}
int dot = relativePath.lastIndexOf('.');
if (dot > 0) {
relativePath = relativePath.substring(0, dot);
}
return relativePath.replace('/', '.') + "*";
}
private static String getGroovyPath(String url, FileObject fo) {
if (fo != null) {
String relativePath;
ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE);
if (cp != null) {
FileObject root = cp.findOwnerRoot(fo);
if (root != null) {
relativePath = FileUtil.getRelativePath(root, fo);
} else {
// Suppose the current folder
relativePath = fo.getNameExt();
}
} else {
LOGGER.log(Level.FINE, "No classpath for {0}", url);
// Suppose the current folder
relativePath = fo.getNameExt();
return relativePath;
}
return relativePath;
}
return url;
}
}