/*******************************************************************************
* Copyright (c) 2005, 2010 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
* Andrew Ferguson (Symbian)
* Markus Schorn (Wind River Systems)
* Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.testplugin;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.zip.ZipFile;
import junit.framework.Assert;
import org.eclipse.cdt.core.CCProjectNature;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CProjectNature;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IArchive;
import org.eclipse.cdt.core.model.IArchiveContainer;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.core.model.IBinaryContainer;
import org.eclipse.cdt.core.model.ICContainer;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ISourceRoot;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.core.settings.model.TestCfgDataProvider;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
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.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
import org.osgi.framework.Bundle;
/**
* Helper methods to set up a ICProject.
*/
public class CProjectHelper {
private final static IOverwriteQuery OVERWRITE_QUERY= new IOverwriteQuery() {
public String queryOverwrite(String file) {
return ALL;
}
};
public static ICProject createCProject(final String projectName, String binFolderName) throws CoreException {
return createCCProject(projectName, binFolderName, null);
}
/**
* Creates a ICProject.
*/
public static ICProject createCProject(final String projectName, String binFolderName, final String indexerID) throws CoreException {
final IWorkspace ws = ResourcesPlugin.getWorkspace();
final ICProject newProject[] = new ICProject[1];
ws.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
IWorkspaceRoot root = ws.getRoot();
IProject project = root.getProject(projectName);
if (indexerID != null) {
IndexerPreferences.set(project, IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG, "true");
IndexerPreferences.set(project, IndexerPreferences.KEY_INDEXER_ID, indexerID);
}
if (!project.exists()) {
project.create(null);
} else {
project.refreshLocal(IResource.DEPTH_INFINITE, null);
}
if (!project.isOpen()) {
project.open(null);
}
if (!project.hasNature(CProjectNature.C_NATURE_ID)) {
String projectId = CTestPlugin.PLUGIN_ID + ".TestProject";
addNatureToProject(project, CProjectNature.C_NATURE_ID, null);
CCorePlugin.getDefault().mapCProjectOwner(project, projectId, false);
}
addDefaultBinaryParser(project);
newProject[0] = CCorePlugin.getDefault().getCoreModel().create(project);
}
}, null);
return newProject[0];
}
/**
* Add the default binary parser if no binary parser configured.
*
* @param project
* @throws CoreException
*/
public static boolean addDefaultBinaryParser(IProject project) throws CoreException {
ICConfigExtensionReference[] binaryParsers= CCorePlugin.getDefault().getDefaultBinaryParserExtensions(project);
if (binaryParsers == null || binaryParsers.length == 0) {
ICProjectDescription desc= CCorePlugin.getDefault().getProjectDescription(project);
if (desc == null) {
return false;
}
desc.getDefaultSettingConfiguration().create(CCorePlugin.BINARY_PARSER_UNIQ_ID, CCorePlugin.DEFAULT_BINARY_PARSER_UNIQ_ID);
CCorePlugin.getDefault().setProjectDescription(project, desc);
}
return true;
}
/**
* Creates a ICProject.
*/
public static ICProject createNewStileCProject(final String projectName, final String indexerID) throws CoreException {
return createNewStileCProject(projectName, indexerID, false);
}
/**
* Creates a ICProject.
*/
public static ICProject createNewStileCProject(final String projectName, String providerId, final String indexerID) throws CoreException {
return createNewStileCProject(projectName, providerId, indexerID, false);
}
/**
* Creates a ICProject.
*/
public static ICProject createNewStileCProject(final String projectName, final String indexerID, boolean markCreating) throws CoreException {
return createNewStileCProject(projectName, null, indexerID, markCreating);
}
/**
* Creates a ICProject.
*/
public static ICProject createNewStileCProject(final String projectName, String cfgProviderId, final String indexerID, final boolean markCreating) throws CoreException {
final IWorkspace ws = ResourcesPlugin.getWorkspace();
final ICProject newProject[] = new ICProject[1];
if(cfgProviderId == null)
cfgProviderId = TestCfgDataProvider.PROVIDER_ID;
final String finalCfgProviderId = cfgProviderId;
ws.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
IWorkspaceRoot root = ws.getRoot();
IProject project = root.getProject(projectName);
if (indexerID != null) {
IndexerPreferences.set(project, IndexerPreferences.KEY_INDEXER_ID, indexerID);
}
if (!project.exists()) {
project.create(null);
} else {
project.refreshLocal(IResource.DEPTH_INFINITE, null);
}
if (!project.isOpen()) {
project.open(null);
}
if (!project.hasNature(CProjectNature.C_NATURE_ID)) {
addNatureToProject(project, CProjectNature.C_NATURE_ID, null);
ICConfigurationDescription prefCfg = CCorePlugin.getDefault().getPreferenceConfiguration(finalCfgProviderId);
ICProjectDescriptionManager mngr = CCorePlugin.getDefault().getProjectDescriptionManager();
ICProjectDescription projDes = mngr.createProjectDescription(project, false, markCreating);
projDes.createConfiguration(CDataUtil.genId(null), CDataUtil.genId("test"), prefCfg);
mngr.setProjectDescription(project, projDes);
// CCorePlugin.getDefault().mapCProjectOwner(project, projectId, false);
}
addDefaultBinaryParser(project);
newProject[0] = CCorePlugin.getDefault().getCoreModel().create(project);
}
}, null);
return newProject[0];
}
private static String getMessage(IStatus status) {
StringBuffer message = new StringBuffer("[");
message.append(status.getMessage());
if (status.isMultiStatus()) {
IStatus children[] = status.getChildren();
for( int i = 0; i < children.length; i++) {
message.append(getMessage(children[i]));
}
}
message.append("]");
return message.toString();
}
public static ICProject createCCProject(final String projectName, final String binFolderName) throws CoreException {
return createCCProject(projectName, binFolderName, null);
}
public static ICProject createCCProject(final String projectName, final String binFolderName, final String indexerID) throws CoreException {
final IWorkspace ws = ResourcesPlugin.getWorkspace();
final ICProject newProject[] = new ICProject[1];
ws.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
ICProject cproject = createCProject(projectName, binFolderName, indexerID);
if (!cproject.getProject().hasNature(CCProjectNature.CC_NATURE_ID)) {
addNatureToProject(cproject.getProject(), CCProjectNature.CC_NATURE_ID, null);
}
newProject[0] = cproject;
}
}, null);
return newProject[0];
}
/**
* Removes a ICProject.
*/
public static void delete(ICProject cproject) {
try {
cproject.getProject().delete(true, true, null);
} catch (CoreException e) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
} finally {
try {
System.gc();
System.runFinalization();
cproject.getProject().delete(true, true, null);
} catch (CoreException e2) {
Assert.fail(getMessage(e2.getStatus()));
}
}
}
}
/**
* Adds a folder container to a ICProject.
*/
public static ICContainer addCContainer(ICProject cproject, String containerName) throws CoreException {
IProject project = cproject.getProject();
ICContainer container = null;
if (containerName == null || containerName.length() == 0) {
ICContainer[] conts = cproject.getSourceRoots();
if (conts.length > 0) {
container = conts[0];
}
} else {
IFolder folder = project.getFolder(containerName);
if (!folder.exists()) {
folder.create(false, true, null);
}
container = CoreModel.getDefault().create(folder);
}
return container;
}
/**
* Adds a folder container to a ICProject and imports all files contained in the given Zip file.
*/
public static ICContainer addCContainerWithImport(ICProject cproject, String containerName, ZipFile zipFile)
throws InvocationTargetException, CoreException {
ICContainer root = addCContainer(cproject, containerName);
importFilesFromZip(zipFile, root.getPath(), null);
return root;
}
/**
* Removes a folder from a ICProject.
*/
public static void removeCContainer(ICProject cproject, String containerName) throws CoreException {
IFolder folder = cproject.getProject().getFolder(containerName);
folder.delete(true, null);
}
/**
* Attempts to find an archive with the given name in the workspace
*/
public static IArchive findArchive(ICProject testProject, String name) throws CModelException {
int x;
IArchive[] myArchives;
IArchiveContainer archCont;
/***************************************************************************************************************************
* Since ArchiveContainer.getArchives does not wait until all the archives in the project have been parsed before returning
* the list, we have to do a sync ArchiveContainer.getChildren first to make sure we find all the archives.
*/
archCont = testProject.getArchiveContainer();
myArchives = archCont.getArchives();
if (myArchives.length < 1)
return (null);
for (x = 0; x < myArchives.length; x++) {
if (myArchives[x].getElementName().equals(name))
return (myArchives[x]);
}
return (null);
}
/**
* Attempts to find a binary with the given name in the workspace
*/
public static IBinary findBinary(ICProject testProject, String name) throws CModelException {
IBinaryContainer binCont;
int x;
IBinary[] myBinaries;
binCont = testProject.getBinaryContainer();
myBinaries = binCont.getBinaries();
if (myBinaries.length < 1)
return (null);
for (x = 0; x < myBinaries.length; x++) {
if (myBinaries[x].getElementName().equals(name))
return (myBinaries[x]);
}
return (null);
}
/**
* Attempts to find an object with the given name in the workspace
*/
public static IBinary findObject(ICProject testProject, String name) throws CModelException {
ICElement[] sourceRoots = testProject.getChildren();
for (int i = 0; i < sourceRoots.length; i++) {
ISourceRoot root = (ISourceRoot) sourceRoots[i];
ICElement[] myElements = root.getChildren();
for (int x = 0; x < myElements.length; x++) {
if (myElements[x].getElementName().equals(name)) {
if (myElements[x] instanceof IBinary) {
return ((IBinary) myElements[x]);
}
}
}
}
return null;
}
/**
* Attempts to find a TranslationUnit with the given name in the workspace
* @throws InterruptedException
*/
public static ITranslationUnit findTranslationUnit(ICProject testProject, String name) throws CModelException, InterruptedException {
for (int j=0; j<20; j++) {
ICElement[] sourceRoots = testProject.getChildren();
for (int i = 0; i < sourceRoots.length; i++) {
ISourceRoot root = (ISourceRoot) sourceRoots[i];
ICElement[] myElements = root.getChildren();
for (int x = 0; x < myElements.length; x++) {
if (myElements[x].getElementName().equals(name)) {
if (myElements[x] instanceof ITranslationUnit) {
return ((ITranslationUnit) myElements[x]);
}
}
}
}
Thread.sleep(100);
}
return null;
}
/**
* Attempts to find an element with the given name in the workspace
*/
public static ICElement findElement(ICProject testProject, String name) throws CModelException {
ICElement[] sourceRoots = testProject.getChildren();
for (int i = 0; i < sourceRoots.length; i++) {
ISourceRoot root = (ISourceRoot) sourceRoots[i];
ICElement[] myElements = root.getChildren();
for (int x = 0; x < myElements.length; x++) {
if (myElements[x].getElementName().equals(name)) {
return myElements[x];
}
}
}
return null;
}
public static void addNatureToProject(IProject proj, String natureId, IProgressMonitor monitor) throws CoreException {
IProjectDescription description = proj.getDescription();
String[] prevNatures = description.getNatureIds();
String[] newNatures = new String[prevNatures.length + 1];
System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
newNatures[prevNatures.length] = natureId;
description.setNatureIds(newNatures);
proj.setDescription(description, monitor);
}
private static void importFilesFromZip(ZipFile srcZipFile, IPath destPath, IProgressMonitor monitor)
throws InvocationTargetException {
ZipFileStructureProvider structureProvider = new ZipFileStructureProvider(srcZipFile);
try {
ImportOperation op = new ImportOperation(destPath, structureProvider.getRoot(), structureProvider,
OVERWRITE_QUERY);
op.run(monitor);
} catch (InterruptedException e) {
// should not happen
}
}
public static void importSourcesFromPlugin(ICProject project, Bundle bundle, String sources) throws CoreException {
try {
String baseDir= FileLocator.toFileURL(FileLocator.find(bundle, new Path(sources), null)).getFile();
ImportOperation importOp = new ImportOperation(project.getProject().getFullPath(),
new File(baseDir), FileSystemStructureProvider.INSTANCE, OVERWRITE_QUERY);
importOp.setCreateContainerStructure(false);
importOp.run(new NullProgressMonitor());
}
catch (Exception e) {
throw new CoreException(new Status(IStatus.ERROR, CTestPlugin.PLUGIN_ID, 0, "Import Interrupted", e));
}
}
/**
* @return the location of a newly created directory in temporary area.
* Note that cleanup should be done with {@link ResourceHelper#cleanUp()}.
* @throws IOException
* @throws CoreException
*/
public static File freshDir() throws IOException, CoreException {
IPath folderPath = ResourceHelper.createTemporaryFolder();
File folder = new File(folderPath.toOSString());
Assert.assertTrue(folder.exists());
Assert.assertTrue(folder.isDirectory());
Assert.assertTrue(folder.canWrite());
return folder;
}
}