/******************************************************************************* * Copyright (c) 2008, 2012 Nokia 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: * Nokia - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.debug.internal.core.executables; import java.io.File; import java.io.IOException; import java.util.ArrayList; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.IBinaryParser; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.debug.core.CDebugCorePlugin; import org.eclipse.cdt.debug.core.executables.Executable; import org.eclipse.cdt.debug.core.executables.ExecutablesManager; import org.eclipse.cdt.debug.core.executables.IExecutableImporter; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.core.runtime.content.IContentTypeManager; import org.eclipse.core.runtime.content.IContentTypeSettings; import org.eclipse.debug.core.DebugPlugin; public class StandardExecutableImporter implements IExecutableImporter { public static final String DEBUG_PROJECT_ID = "org.eclipse.cdt.debug"; //$NON-NLS-1$ /* * (non-Javadoc) * * @see org.eclipse.cdt.debug.core.executables.IExecutableImporter#importExecutables(java.lang.String[], * org.eclipse.core.runtime.IProgressMonitor) */ @Override public boolean importExecutables(String[] fileNames, IProgressMonitor monitor) { monitor.beginTask("Import Executables", fileNames.length); //$NON-NLS-1$ IProject exeProject = null; boolean checkProject = false; boolean handled = false; // Weed out existing ones for (String path : fileNames) { try { path = new File(path).getCanonicalPath(); } catch (IOException e1) { } if (AllowImport(Path.fromOSString(path))) { if (!checkProject) { // See if the default project exists String defaultProjectName = "Executables"; //$NON-NLS-1$ ICProject cProject = CoreModel.getDefault().getCModel().getCProject(defaultProjectName); if (cProject.exists()) { exeProject = cProject.getProject(); } else { final String[] ignoreList = { ".project", //$NON-NLS-1$ ".cdtproject", //$NON-NLS-1$ ".cproject", //$NON-NLS-1$ ".cdtbuild", //$NON-NLS-1$ ".settings", //$NON-NLS-1$ }; IWorkspace workspace = ResourcesPlugin.getWorkspace(); IProject newProjectHandle = workspace.getRoot().getProject(defaultProjectName); int projectSuffix = 2; while (newProjectHandle.exists()){ newProjectHandle = workspace.getRoot().getProject(defaultProjectName + projectSuffix); projectSuffix++; } IProjectDescription description = workspace.newProjectDescription(newProjectHandle.getName()); description.setLocation(null); IFileStore store; try { store = EFS.getStore(workspace.getRoot().getLocationURI()); store = store.getChild(newProjectHandle.getName()); for (String deleteName : ignoreList) { IFileStore projFile = store.getChild(deleteName); projFile.delete(EFS.NONE, new NullProgressMonitor()); } IFileStore[] children = store.childStores(EFS.NONE, new NullProgressMonitor()); for (IFileStore fileStore : children) { if (fileStore.fetchInfo().isDirectory()) fileStore.delete(EFS.NONE, new NullProgressMonitor()); } exeProject = CCorePlugin.getDefault().createCProject(description, newProjectHandle, null, DEBUG_PROJECT_ID); } catch (OperationCanceledException e) { DebugPlugin.log( e ); } catch (CoreException e) { DebugPlugin.log( e ); } } checkProject = true; } importExecutable(exeProject, path); handled = true; } monitor.worked(1); if (monitor.isCanceled()) { break; } } monitor.done(); return handled; } public boolean AllowImport(IPath path) { return (!ExecutablesManager.getExecutablesManager().executableExists(path)); } private IContainer createFromRoot(IProject exeProject, IPath path) throws CoreException { int segmentCount = path.segmentCount() - 1; IContainer currentFolder = exeProject; for (int i = 0; i < segmentCount; i++) { currentFolder = currentFolder.getFolder(new Path(path.segment(i))); if (!currentFolder.exists()) { ((IFolder) currentFolder).create(IResource.VIRTUAL | IResource.DERIVED, true, new NullProgressMonitor()); } } return currentFolder; } private void importExecutable(IProject exeProject, String path) { IPath location = Path.fromOSString(path); String executableName = location.toFile().getName(); try { IContainer fileContainer = createFromRoot(exeProject, location); Path exectuableFilePath = new Path(executableName); IFile exeFile = fileContainer.getFile(exectuableFilePath); if (!exeFile.exists() && validateBinaryParsers(exeProject, new File(path))) { ensureBinaryType(exectuableFilePath); exeFile.createLink(location, 0, null); } } catch (CoreException e) { CDebugCorePlugin.log(e); } } private void ensureBinaryType(IPath exectuableFilePath) { if (Executable.isBinaryFile(exectuableFilePath)) return; String ext = exectuableFilePath.getFileExtension(); if (ext != null) { // add the extension to the content type manager as a binary final IContentTypeManager ctm = Platform.getContentTypeManager(); final IContentType ctbin = ctm.getContentType(CCorePlugin.CONTENT_TYPE_BINARYFILE); try { ctbin.addFileSpec(ext, IContentTypeSettings.FILE_EXTENSION_SPEC); } catch (CoreException e) { CDebugCorePlugin.log(e); } } } private boolean isExtensionVisible(IExtension ext) { IConfigurationElement[] elements = ext.getConfigurationElements(); for (IConfigurationElement element : elements) { IConfigurationElement[] children = element.getChildren("filter"); //$NON-NLS-1$ for (int j = 0; j < children.length; j++) { String name = children[j].getAttribute("name"); //$NON-NLS-1$ if (name != null && name.equals("visibility")) { //$NON-NLS-1$ String value = children[j].getAttribute("value"); //$NON-NLS-1$ if (value != null && value.equals("private")) { //$NON-NLS-1$ return false; } } } return true; } return false; // invalid extension definition (must have at least // cextension elements) } private IBinaryParser instantiateBinaryParser(IExtension ext) { IBinaryParser parser = null; IConfigurationElement[] elements = ext.getConfigurationElements(); for (int i = 0; i < elements.length; i++) { IConfigurationElement[] children = elements[i].getChildren("run"); //$NON-NLS-1$ for (int j = 0; j < children.length; j++) { try { parser = (IBinaryParser) children[j].createExecutableExtension("class"); //$NON-NLS-1$ } catch (CoreException e) { CDebugCorePlugin.log(e); } } } return parser; } private boolean validateBinaryParsers(IProject exeProject, File file) { IExtension[] binaryParserExtensions; IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.BINARY_PARSER_SIMPLE_ID); if (point != null) { IExtension[] exts = point.getExtensions(); ArrayList<IExtension> extensionsInUse = new ArrayList<IExtension>(); for (int i = 0; i < exts.length; i++) { if (isExtensionVisible(exts[i])) { extensionsInUse.add(exts[i]); } } binaryParserExtensions = extensionsInUse.toArray(new IExtension[extensionsInUse.size()]); for (int i = 0; i < binaryParserExtensions.length; i++) { IBinaryParser parser = instantiateBinaryParser(binaryParserExtensions[i]); if (isBinary(file, parser)) { String parserID = binaryParserExtensions[i].getUniqueIdentifier(); // Make sure the project has this parser ICProjectDescription pd = CCorePlugin.getDefault().getProjectDescription(exeProject); try { boolean existsAlready = false; ICConfigExtensionReference[] parsers = pd.getDefaultSettingConfiguration().get(CCorePlugin.BINARY_PARSER_UNIQ_ID); for (ICConfigExtensionReference configExtensionReference : parsers) { if (configExtensionReference.getID().equals(parserID)) { existsAlready = true; break; } } if (!existsAlready) { pd.getDefaultSettingConfiguration().create(CCorePlugin.BINARY_PARSER_UNIQ_ID, parserID); CCorePlugin.getDefault().setProjectDescription(exeProject, pd, true, new NullProgressMonitor()); } } catch (CoreException e) { } return true; } } } return false; } private boolean isBinary(File file, IBinaryParser parser) { if (parser != null) { try { IBinaryParser.IBinaryFile bin = parser.getBinary(new Path(file.getAbsolutePath())); return bin != null && (bin.getType() == IBinaryParser.IBinaryFile.EXECUTABLE || bin.getType() == IBinaryParser.IBinaryFile.SHARED); } catch (IOException e) { return false; } } else return false; } @Override public int getPriority(String[] fileNames) { return NORMAL_PRIORITY; } }