/******************************************************************************* * Author: Markus Barchfeld * * Copyright (c) 2004 RubyPeople. * * This file is part of the Ruby Development Tools (RDT) plugin for eclipse. RDT * is subject to the "Common Public License (CPL) v 1.0". You may not use RDT * except in compliance with the License. For further information see * org.rubypeople.rdt/rdt.license. This source code is based on * org.eclipse.jdt.internal.debug.ui.console.JavaConsoleTracker / * * /******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Common Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/cpl-v10.html * * Contributors: IBM Corporation - initial API and implementation ******************************************************************************/ package org.rubypeople.rdt.internal.debug.ui.console; import java.io.File; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.ui.console.IConsole; import org.eclipse.debug.ui.console.IConsoleLineTracker; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IRegion; import org.eclipse.ui.console.IHyperlink; import org.rubypeople.rdt.internal.ui.RubyPlugin; import org.rubypeople.rdt.internal.ui.util.StackTraceLine; import org.rubypeople.rdt.launching.IRubyLaunchConfigurationConstants; /** * Provides links for stack traces, eg: /data/EMAILTOSMSBRIDGE/configFile.rb:1:in `require': No such file to load -- * inifile (LoadError) from /data/EMAILTOSMSBRIDGE/configFile.rb:1 from /data/EMAILTOSMSBRIDGE/fetchmail.rb:2:in * `require' from /data/EMAILTOSMSBRIDGE/fetchmail.rb:2 from /data/EMAILTOSMSBRIDGE/startEmailToSms.rb:1:in `require' * from /data/EMAILTOSMSBRIDGE/startEmailToSms.rb:1 */ public class RubyConsoleTracker implements IConsoleLineTracker { public interface FileExistanceChecker { boolean fileExists(String filename); } public static class StandardFileExistanceChecker implements FileExistanceChecker { public boolean fileExists(String filename) { File file = new File(filename); if (file.exists()) return true; IPath path = new Path(filename); if (!path.isValidPath(filename)) { return false; } try { IFile iFile = ResourcesPlugin.getWorkspace().getRoot().getFile(path); if (iFile != null) return iFile.exists(); } catch (IllegalArgumentException e) { return false; } return false; } } private final FileExistanceChecker existanceChecker; public RubyConsoleTracker() { this(new StandardFileExistanceChecker()); } public RubyConsoleTracker(FileExistanceChecker existance) { this.existanceChecker = existance; } /** * The console associated with this line tracker */ protected IConsole fConsole; private ILaunch fLastLaunch; private IProject fProject; /** * @see org.eclipse.debug.ui.console.IConsoleLineTracker#init(org.eclipse.debug.ui.console.IConsole) */ public void init(IConsole pConsole) { fConsole = pConsole; } /** * @see org.eclipse.debug.ui.console.IConsoleLineTracker#lineAppended(org.eclipse.jface.text.IRegion) */ public void lineAppended(IRegion line) { try { int prefix = 0; String text = getText(line); while (StackTraceLine.isTraceLine(text)) { StackTraceLine stackTraceLine = new StackTraceLine(text, getProject()); if (!existanceChecker.fileExists(stackTraceLine.getFilename())) return; IHyperlink link = new RubyStackTraceHyperlink(fConsole, stackTraceLine); fConsole.addLink(link, line.getOffset() + prefix + stackTraceLine.offset(), stackTraceLine.length()); prefix = stackTraceLine.offset() + stackTraceLine.length(); int substring = stackTraceLine.offset() + stackTraceLine.length(); if (text.length() < substring - 1) { text = ""; } else { text = text.substring(substring); if (text.startsWith(":in `require':")) { text = text.substring(14); prefix += 14; } } } } catch (BadLocationException e) { } } protected IProject getProject() { if (fLastLaunch == null || (fConsole.getProcess() != null && !fLastLaunch.equals(fConsole.getProcess().getLaunch()))) { if (fConsole.getProcess() == null) return null; fLastLaunch = fConsole.getProcess().getLaunch(); String projectName = null; try { if (fConsole.getProcess() != null && fConsole.getProcess().getLaunch() != null && fConsole.getProcess().getLaunch().getLaunchConfiguration() != null) projectName = fConsole.getProcess().getLaunch().getLaunchConfiguration().getAttribute( IRubyLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null); } catch (Exception e) { RubyPlugin.log(e); } if (projectName == null) return null; fProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); } return fProject; } protected String getText(IRegion line) throws BadLocationException { return fConsole.getDocument().get(line.getOffset(), line.getLength()); } /** * @see org.eclipse.debug.ui.console.IConsoleLineTracker#dispose() */ public void dispose() { fConsole = null; } }