| /******************************************************************************* |
| * Copyright (c) 2005, 2009 IBM Corporation and others. |
| * 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 - initial API and implementation |
| * QNX Software System |
| * Sergey Prigogin, Google - https://bugs.eclipse.org/bugs/show_bug.cgi?id=13221 |
| * Ed Swartz (Nokia) |
| * Anton Leherbauer (Wind River Systems) |
| *******************************************************************************/ |
| |
| package org.eclipse.ptp.internal.rdt.ui.editor; |
| |
| import java.io.File; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| |
| import org.eclipse.cdt.core.CCorePlugin; |
| import org.eclipse.cdt.core.model.CModelException; |
| import org.eclipse.cdt.core.model.IInclude; |
| import org.eclipse.cdt.core.parser.ExtendedScannerInfo; |
| import org.eclipse.cdt.core.parser.IExtendedScannerInfo; |
| import org.eclipse.cdt.core.parser.IScannerInfo; |
| import org.eclipse.cdt.core.parser.IScannerInfoProvider; |
| import org.eclipse.cdt.internal.core.resources.ResourceLookup; |
| import org.eclipse.cdt.internal.ui.CPluginImages; |
| import org.eclipse.cdt.internal.ui.dialogs.ElementListSelectionDialog; |
| import org.eclipse.cdt.internal.ui.util.EditorUtility; |
| import org.eclipse.cdt.ui.CUIPlugin; |
| import org.eclipse.cdt.utils.PathUtil; |
| import org.eclipse.core.filesystem.EFS; |
| import org.eclipse.core.filesystem.IFileStore; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.jface.viewers.ILabelProvider; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.ISelectionProvider; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.LabelProvider; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.ptp.rdt.core.RDTLog; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.widgets.MessageBox; |
| |
| /** |
| * Action to open an include file from the Outline view |
| * @author vkong |
| * |
| */ |
| public class OpenIncludeAction extends |
| org.eclipse.cdt.internal.ui.editor.OpenIncludeAction { |
| |
| private static final String PREFIX= "OpenIncludeAction."; //$NON-NLS-1$ |
| |
| private static final String DIALOG_TITLE= PREFIX + "dialog.title"; //$NON-NLS-1$ |
| private static final String DIALOG_MESSAGE= PREFIX + "dialog.message"; //$NON-NLS-1$ |
| |
| private ISelectionProvider fSelectionProvider; |
| |
| public OpenIncludeAction(ISelectionProvider provider) { |
| super(provider); |
| setDescription(CUIPlugin.getResourceString(PREFIX + "description")); //$NON-NLS-1$ |
| setToolTipText(CUIPlugin.getResourceString(PREFIX + "tooltip")); //$NON-NLS-1$ |
| |
| CPluginImages.setImageDescriptors(this, CPluginImages.T_LCL, CPluginImages.IMG_MENU_OPEN_INCLUDE); |
| |
| fSelectionProvider= provider; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.internal.ui.editor.OpenIncludeAction#run() |
| */ |
| @Override |
| public void run() { |
| IInclude include= getIncludeStatement(fSelectionProvider.getSelection()); |
| if (include == null) { |
| return; |
| } |
| try { |
| ArrayList<URI> filesFound = new ArrayList<URI>(4); |
| IResource res = include.getUnderlyingResource(); //the resource that contains this include |
| String fullFileName= include.getFullFileName(); //the full path, if there is one |
| |
| if (fullFileName != null) { |
| IPath fullPath= new Path(fullFileName); |
| if (fullPath.isAbsolute() && fullPath.toFile().exists()) { //local |
| filesFound.add(fullPath.toFile().toURI()); |
| } |
| if (filesFound.isEmpty()) { |
| //remote: get host information and try again |
| URI locationURI = include.getLocationURI(); //the location of the innermost file enclosing this include |
| URI includeURI = replacePath(locationURI, fullFileName); |
| |
| IFileStore fileStore = EFS.getStore(includeURI); |
| if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) { |
| filesFound.add(includeURI); |
| } |
| } |
| } |
| |
| if (filesFound.isEmpty() && res != null) { |
| boolean isSystemInclude = include.isStandard(); |
| IProject proj = res.getProject(); |
| String includeName = include.getElementName(); |
| URI locationURI = include.getLocationURI(); //the location of the innermost file enclosing this include |
| |
| // Search in the scannerInfo information |
| IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(proj); |
| if (provider != null) { |
| IScannerInfo info = provider.getScannerInformation(res); |
| // XXXX this should fall back to project by itself |
| if (info == null) { |
| info = provider.getScannerInformation(proj); |
| } |
| if (info != null) { |
| IExtendedScannerInfo scanInfo = new ExtendedScannerInfo(info); |
| |
| if (!isSystemInclude) { |
| IPath pathURI = new Path(locationURI.toString()); |
| // search in current directory |
| if (pathURI != null) { |
| String currentDir= pathURI.removeLastSegments(1).toOSString(); |
| findFile(new String[] { currentDir }, includeName, filesFound); |
| } |
| if (filesFound.isEmpty()) { |
| // search in "..." include directories |
| String[] localIncludePaths = scanInfo.getLocalIncludePath(); |
| String[] includePaths = new String[localIncludePaths.length]; |
| for (int i = 0; i < localIncludePaths.length; i++) { |
| includePaths[i] = locationURI.getScheme() + "://" + locationURI.getHost() + new String(localIncludePaths[i]); //$NON-NLS-1$ |
| } |
| findFile(includePaths, includeName, filesFound); |
| } |
| } |
| |
| if (filesFound.isEmpty()) { |
| // search in <...> include directories |
| String[] includePaths = scanInfo.getIncludePaths(); //these include paths do not have host information |
| String[] newIncludePaths = new String[includePaths.length]; |
| for (int i = 0; i < includePaths.length; i++) { |
| newIncludePaths[i] = locationURI.getScheme() + "://" + locationURI.getHost() + new String(includePaths[i]); //$NON-NLS-1$ |
| } |
| findFile(newIncludePaths, includeName, filesFound); |
| } |
| } |
| |
| if (filesFound.isEmpty()) { |
| // Fall back and search the project |
| IResource resource = include.getCProject().getProject().findMember(include.getElementName()); |
| if (!isSystemInclude && resource != null && resource instanceof IFile) |
| filesFound.add(resource.getLocationURI()); |
| } |
| } |
| } |
| Object fileToOpen; |
| int nElementsFound= filesFound.size(); |
| if (nElementsFound == 0) { |
| noElementsFound(); |
| fileToOpen= null; |
| } else if (nElementsFound == 1) { |
| fileToOpen= filesFound.get(0); |
| } else { |
| fileToOpen= chooseFile(filesFound); |
| } |
| |
| if (fileToOpen != null) |
| EditorUtility.openInEditor((URI)fileToOpen, include.getCProject()); |
| |
| } catch (CModelException e) { |
| CUIPlugin.log(e.getStatus()); |
| } catch (CoreException e) { |
| CUIPlugin.log(e.getStatus()); |
| } |
| } |
| |
| /** |
| * |
| */ |
| private void noElementsFound() { |
| MessageBox errorMsg = new MessageBox(CUIPlugin.getActiveWorkbenchShell(), SWT.ICON_ERROR | SWT.OK); |
| errorMsg.setText(CUIPlugin.getResourceString("OpenIncludeAction.error")); //$NON-NLS-1$ |
| errorMsg.setMessage (CUIPlugin.getResourceString("OpenIncludeAction.error.description")); //$NON-NLS-1$ |
| errorMsg.open(); |
| } |
| |
| private boolean isInProject(IPath path) { |
| return getWorkspaceRoot().getFileForLocation(path) != null; |
| } |
| |
| /** |
| * Returns the path as is, if it points to a workspace resource. If the path |
| * does not point to a workspace resource, but there are linked workspace |
| * resources pointing to it, returns the paths of these resources. |
| * Otherwise, returns the path as is. |
| */ |
| private IPath[] resolveIncludeLink(IPath path) { |
| if (!isInProject(path)) { |
| IFile[] files = ResourceLookup.findFilesForLocation(path); |
| if (files.length > 0) { |
| IPath[] paths = new IPath[files.length]; |
| for (int i = 0; i < files.length; i++) { |
| paths[i] = files[i].getFullPath(); |
| } |
| return paths; |
| } |
| } |
| |
| return new IPath[] { path }; |
| } |
| |
| private IWorkspaceRoot getWorkspaceRoot() { |
| return ResourcesPlugin.getWorkspace().getRoot(); |
| } |
| |
| private void findFile(String[] includePaths, String name, ArrayList<URI> list) |
| throws CoreException { |
| // in case it is an absolute path and it's local |
| IPath includeFile= new Path(name); |
| if (includeFile.isAbsolute()) { |
| includeFile = PathUtil.getCanonicalPath(includeFile); |
| if (includeFile.toFile().exists()) { |
| list.add(includeFile.toFile().toURI()); |
| return; |
| } |
| } |
| HashSet<IPath> foundSet = new HashSet<IPath>(); |
| for (String includePath : includePaths) { |
| IPath path = PathUtil.getCanonicalPath(new Path(includePath).append(includeFile)); |
| //local case: |
| File file = path.toFile(); |
| if (file.exists()) { |
| IPath[] paths = resolveIncludeLink(path); |
| for (IPath p : paths) { |
| if (foundSet.add(p)) { |
| list.add(p.toFile().toURI()); |
| } |
| } |
| } else { //remote case include paths: |
| try { |
| URI uri = new URI(path.toPortableString()); |
| IFileStore fileStore = EFS.getStore(uri); |
| if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) { |
| list.add(uri); |
| } |
| } catch (URISyntaxException e) { |
| RDTLog.logError(e); |
| } |
| } |
| } |
| } |
| |
| private Object chooseFile(ArrayList<URI> filesFound) { |
| ILabelProvider renderer= new LabelProvider() { |
| @Override |
| public String getText(Object element) { |
| if (element instanceof URI) { |
| URI uri= (URI)element; |
| IPath path = new Path(uri.getPath()); |
| return path.lastSegment() + " - " + path.toString(); //$NON-NLS-1$ |
| } |
| return super.getText(element); |
| } |
| }; |
| |
| ElementListSelectionDialog dialog= new ElementListSelectionDialog(CUIPlugin.getActiveWorkbenchShell(), renderer, false, false); |
| dialog.setTitle(CUIPlugin.getResourceString(DIALOG_TITLE)); |
| dialog.setMessage(CUIPlugin.getResourceString(DIALOG_MESSAGE)); |
| dialog.setElements(filesFound); |
| |
| if (dialog.open() == Window.OK) { |
| return (IFile)((IPath) dialog.getSelectedElement()).toFile(); |
| } |
| return null; |
| } |
| |
| private static IInclude getIncludeStatement(ISelection sel) { |
| if (!sel.isEmpty() && sel instanceof IStructuredSelection) { |
| List<?> list= ((IStructuredSelection)sel).toList(); |
| if (list.size() == 1) { |
| Object element= list.get(0); |
| if (element instanceof IInclude) { |
| return (IInclude)element; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Replaces the path portion of the given URI. |
| */ |
| private URI replacePath(URI u, String path) { |
| try { |
| return new URI(u.getScheme(), u.getUserInfo(), u.getHost(), u.getPort(), |
| path, // replaced! |
| u.getQuery(),u.getFragment()); |
| } catch (URISyntaxException e) { |
| RDTLog.logError(e); |
| return null; |
| } |
| } |
| |
| } |