/******************************************************************************* * Copyright (c) 2004, 2010 QNX Software Systems 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: * QNX Software Systems - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.debug.internal.core.sourcelookup; import java.io.File; import java.io.IOException; import java.util.ArrayList; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.debug.core.CDebugCorePlugin; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.internal.core.model.ExternalTranslationUnit; import org.eclipse.cdt.internal.core.resources.ResourceLookup; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.sourcelookup.ISourceContainerType; import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; import org.eclipse.debug.core.sourcelookup.containers.AbstractSourceContainer; import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage; import com.ibm.icu.text.MessageFormat; /** * The source container that maps a backend path to the local filesystem path. */ public class MapEntrySourceContainer extends AbstractSourceContainer { /** * Unique identifier for the map entry source container type * (value <code>org.eclipse.cdt.debug.core.containerType.mapEntry</code>). */ public static final String TYPE_ID = CDebugCorePlugin.getUniqueIdentifier() + ".containerType.mapEntry"; //$NON-NLS-1$ private IPath fLocalPath; private IPath fBackendPath; /** * Constructor for MapEntrySourceContainer. */ public MapEntrySourceContainer() { fBackendPath = Path.EMPTY; fLocalPath = Path.EMPTY; } /** * Constructor for MapEntrySourceContainer. */ public MapEntrySourceContainer(IPath backend, IPath local) { fBackendPath = backend; fLocalPath = local; } /** * Create an IPath from a string which may be a Win32 path. <p> * <p> * ("new Path(...)" won't work in Unix when using a Win32 path: the backslash * separator and the device notation are completely munged.) * Copied from org.eclipse.cdt.debug.edc.internal.PathUtils * @param path * @return converted string */ public static IPath createPath(String path) { if (path == null) return null; if (path.contains("\\")) { //$NON-NLS-1$ // handle Windows slashes and canonicalize path = path.replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$ } // also check for device or UNC int firstSep = path.indexOf("/"); //$NON-NLS-1$ int idx = path.indexOf(":"); //$NON-NLS-1$ // ':' indicates a Windows device separator if it comes before // the first segment separator if (idx > 0 && (firstSep < 0 || idx < firstSep)) { String device = path.substring(0, idx + 1); path = path.substring(idx + 1); return new Path(path).setDevice(device); } else { // Cygwin or UNC path if (path.startsWith("//")) { //$NON-NLS-1$ String network; idx = path.indexOf("/", 2); //$NON-NLS-1$ if (idx > 0) { network = path.substring(0, idx); path = path.substring(idx); } else { network = path; path = ""; //$NON-NLS-1$ } return new Path(network, path).makeUNC(true); } } // fallthrough return new Path(path); } /* (non-Javadoc) * @see org.eclipse.debug.core.sourcelookup.ISourceContainer#findSourceElements(java.lang.String) */ public Object[] findSourceElements(String name) throws CoreException { IPath path = createPath(name); if (getBackendPath().isPrefixOf(path)) { path = path.removeFirstSegments(getBackendPath().segmentCount()); path = getLocalPath().append(path); IFile[] wsFiles = ResourceLookup.findFilesForLocation(path); ArrayList<IFile> list = new ArrayList<IFile>(); for (int j = 0; j < wsFiles.length; ++j) { if (wsFiles[j].exists()) { list.add(wsFiles[j]); if (!isFindDuplicates()) break; } } if (list.size() > 0) return list.toArray(); File file = path.toFile(); // The file is not already in the workspace so try to create an external translation unit for it. ISourceLookupDirector director = getDirector(); if (director != null && file.exists() && file.isFile()) { ILaunchConfiguration launchConfiguration = director.getLaunchConfiguration(); if (launchConfiguration != null) { String projectName = launchConfiguration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$ if (projectName.length() > 0) { ICProject project = CoreModel.getDefault().getCModel().getCProject(projectName); if (project != null) { String id; try { final IPath location= Path.fromOSString(file.getCanonicalPath()); id = CoreModel.getRegistedContentTypeId(project.getProject(), location.lastSegment()); return new ExternalTranslationUnit[] { new ExternalTranslationUnit(project, location, id) }; } catch (IOException e) { CDebugCorePlugin.log(e); } } } } } if (file.exists() && file.isFile()) { return new Object[] { new LocalFileStorage(file) }; } } return EMPTY; } /* (non-Javadoc) * @see org.eclipse.debug.core.sourcelookup.ISourceContainer#getName() */ public String getName() { return MessageFormat.format("{0} - {1}", new String[] { getBackendPath().toOSString(), getLocalPath().toOSString() }); //$NON-NLS-1$ } /* (non-Javadoc) * @see org.eclipse.debug.core.sourcelookup.ISourceContainer#getType() */ public ISourceContainerType getType() { return getSourceContainerType(TYPE_ID); } public IPath getLocalPath() { return fLocalPath; } public IPath getBackendPath() { return fBackendPath; } public void setLocalPath(IPath local) { fLocalPath = local; } public void setBackendPath(IPath backend) { fBackendPath = backend; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object o) { if (!(o instanceof MapEntrySourceContainer)) return false; MapEntrySourceContainer entry = (MapEntrySourceContainer)o; return (entry.getBackendPath().equals(getBackendPath()) && entry.getLocalPath().equals(getLocalPath())); } public MapEntrySourceContainer copy() { return new MapEntrySourceContainer(fBackendPath, fLocalPath); } }