/*******************************************************************************
* Copyright (c) 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - Jeff Briggs, Henry Hughes, Ryan Morse
*******************************************************************************/
package org.eclipse.linuxtools.internal.systemtap.ui.ide.views;
import java.io.File;
import java.net.URI;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.linuxtools.internal.systemtap.ui.ide.IDEPlugin;
import org.eclipse.linuxtools.internal.systemtap.ui.ide.Localization;
import org.eclipse.linuxtools.internal.systemtap.ui.ide.actions.KernelSourceAction;
import org.eclipse.linuxtools.internal.systemtap.ui.ide.preferences.IDEPreferenceConstants;
import org.eclipse.linuxtools.internal.systemtap.ui.ide.preferences.PathPreferencePage;
import org.eclipse.linuxtools.profiling.launch.IRemoteFileProxy;
import org.eclipse.linuxtools.profiling.launch.RemoteProxyManager;
import org.eclipse.linuxtools.systemtap.graphing.ui.widgets.ExceptionErrorDialog;
import org.eclipse.linuxtools.systemtap.structures.KernelSourceTree;
import org.eclipse.linuxtools.systemtap.structures.TreeNode;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
/**
* The Kernel Source Browser module for the SystemTap GUI. This browser provides a list of kernel source
* files and allows the user to open those files in an editor in order to place probes in arbitrary locations.
* @author Henry Hughes
* @author Ryan Morse
*/
public class KernelBrowserView extends BrowserView {
public static final String ID = "org.eclipse.linuxtools.internal.systemtap.ui.ide.views.KernelBrowserView"; //$NON-NLS-1$
private class KernelRefreshJob extends Job {
private boolean remote;
private URI kernelLocationURI;
private IRemoteFileProxy proxy;
private String kernelSource;
public KernelRefreshJob(boolean remote, URI kernelLocationURI, IRemoteFileProxy proxy, String kernelSource) {
super(Localization.getString("KernelBrowserView.RefreshingKernelSource")); //$NON-NLS-1$
this.remote = remote;
this.kernelLocationURI = kernelLocationURI;
this.proxy = proxy;
this.kernelSource = kernelSource;
}
@Override
public IStatus run(IProgressMonitor monitor) {
IPreferenceStore p = IDEPlugin.getDefault().getPreferenceStore();
KernelSourceTree kst = new KernelSourceTree();
String excluded[] = p.getString(IDEPreferenceConstants.P_EXCLUDED_KERNEL_SOURCE).split(File.pathSeparator);
if (remote) {
try {
kst.buildKernelTree(kernelLocationURI, excluded, proxy, monitor);
} catch (CoreException e) {
ExceptionErrorDialog.openError(Localization.getString("KernelBrowserView.CouldNotInitializeTree"), e); //$NON-NLS-1$
}
} else {
kst.buildKernelTree(kernelSource, excluded);
}
if (monitor.isCanceled()) {
setViewerInput(null);
return Status.CANCEL_STATUS;
}
setViewerInput(kst.getTree());
monitor.done();
return Status.OK_STATUS;
}
}
/**
* Creates the UI on the given <code>Composite</code>
*/
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
refresh();
makeActions();
}
@Override
protected void makeActions() {
doubleClickAction = new KernelSourceAction(getSite().getWorkbenchWindow(), this);
viewer.addDoubleClickListener(doubleClickAction);
IDEPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(propertyChangeListener);
}
@Override
protected Image getEntryImage(TreeNode treeObj) {
if (treeObj.toString().equals(
Localization.getString("KernelBrowserView.NoKernelSourceFound"))) { //$NON-NLS-1$
return null;
}
if (treeObj.toString().lastIndexOf('.') != -1) {
String item = treeObj.getData().toString();
if (item.endsWith(".c")) { //$NON-NLS-1$
return IDEPlugin.getImageDescriptor("icons/files/file_c.gif").createImage(); //$NON-NLS-1$
}
if (item.endsWith(".h")) { //$NON-NLS-1$
return IDEPlugin.getImageDescriptor("icons/files/file_h.gif").createImage(); //$NON-NLS-1$
}
return IDEPlugin.getImageDescriptor("icons/vars/var_unk.gif").createImage(); //$NON-NLS-1$
}
return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);
}
/**
* Updates the kernel source displayed to the user with the new kernel source tree. Usually
* a response to the user changing the preferences related to the kernel source location, requiring
* that the application update the kernel source information.
*/
@Override
public void refresh() {
displayLoadingMessage();
IPreferenceStore p = IDEPlugin.getDefault().getPreferenceStore();
String kernelSource = p.getString(IDEPreferenceConstants.P_KERNEL_SOURCE);
if (kernelSource == null || kernelSource.length() < 1) {
displayMessage(Localization.getString("KernelBrowserView.NoKernelSourceFound")); //$NON-NLS-1$
return;
}
String localOrRemote = p.getString(IDEPreferenceConstants.P_REMOTE_LOCAL_KERNEL_SOURCE);
URI kernelLocationURI = null;
IRemoteFileProxy proxy = null;
boolean remote = localOrRemote.equals(PathPreferencePage.REMOTE);
if (remote) {
boolean error = false;
try {
kernelLocationURI = IDEPlugin.getDefault().createRemoteUri(kernelSource);
if (kernelLocationURI == null) {
error = true;
} else {
proxy = RemoteProxyManager.getInstance().getFileProxy(kernelLocationURI);
if (!validateProxy(proxy, kernelSource)) {
error = true;
}
}
} catch (CoreException e2) {
error = true;
}
if (error) {
displayMessage(Localization.getString("KernelBrowserView.KernelSourceDirNotFound")); //$NON-NLS-1$
return;
}
}
KernelRefreshJob refreshJob = new KernelRefreshJob(remote, kernelLocationURI, proxy, kernelSource);
refreshJob.setPriority(Job.SHORT);
refreshJob.schedule();
}
private boolean validateProxy(IRemoteFileProxy proxy, String kernelSource) {
if (proxy == null) {
return false;
}
IFileStore fs = proxy.getResource(kernelSource);
if (fs == null) {
return false;
}
IFileInfo info = fs.fetchInfo();
if (info == null) {
return false;
}
if (!info.exists()) {
return false;
}
return true;
}
/**
* A <code>IPropertyChangeListener</code> that detects changes to the Kernel Source location
* and runs the <code>updateKernelSourceTree</code> method.
*/
private final IPropertyChangeListener propertyChangeListener = event -> {
if (event.getProperty().equals(IDEPreferenceConstants.P_KERNEL_SOURCE) ||
event.getProperty().equals(IDEPreferenceConstants.P_REMOTE_LOCAL_KERNEL_SOURCE) ||
event.getProperty().equals(IDEPreferenceConstants.P_EXCLUDED_KERNEL_SOURCE)) {
refresh();
}
};
@Override
public void dispose() {
IDEPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(propertyChangeListener);
super.dispose();
}
}