/*******************************************************************************
* Copyright (c) 2005 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
*******************************************************************************/
package org.eclipse.buckminster.pde.internal.imports;
import java.io.File;
import java.util.List;
import org.eclipse.buckminster.core.cspec.model.ComponentRequest;
import org.eclipse.buckminster.core.helpers.FileUtils;
import org.eclipse.buckminster.core.materializer.MaterializationContext;
import org.eclipse.buckminster.core.metadata.WorkspaceInfo;
import org.eclipse.buckminster.core.mspec.ConflictResolution;
import org.eclipse.buckminster.core.resolver.NodeQuery;
import org.eclipse.buckminster.pde.IPDEConstants;
import org.eclipse.buckminster.pde.Messages;
import org.eclipse.buckminster.pde.internal.EclipseImportReaderType;
import org.eclipse.buckminster.pde.internal.datatransfer.IImportStructureProvider;
import org.eclipse.buckminster.pde.internal.datatransfer.ImportOperation;
import org.eclipse.buckminster.pde.internal.dialogs.IOverwriteQuery;
import org.eclipse.buckminster.runtime.BuckminsterException;
import org.eclipse.buckminster.runtime.MonitorUtils;
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.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.core.build.IBuildEntry;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.build.WorkspaceBuildModel;
import org.eclipse.pde.internal.core.ifeature.IFeatureInstallHandler;
import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
@SuppressWarnings("restriction")
public class FeatureImportOperation implements IWorkspaceRunnable {
private final IFeatureModel model;
private final NodeQuery query;
private final EclipseImportReaderType classpathCollector;
private final boolean binary;
private final IWorkspaceRoot root;
private final IPath destination;
/**
* @param models
* @param targetPath
* a parent of external project or null
* @param replaceQuery
*/
public FeatureImportOperation(EclipseImportReaderType classpathCollector, IFeatureModel model, NodeQuery query, IPath destination, boolean binary) {
this.classpathCollector = classpathCollector;
this.model = model;
this.binary = binary;
this.query = query;
this.root = ResourcesPlugin.getWorkspace().getRoot();
this.destination = destination;
}
/*
* @see IWorkspaceRunnable#run(IProgressMonitor)
*/
@Override
public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
createProject(monitor);
MonitorUtils.testCancelStatus(monitor);
}
private void createBuildProperties(IProject project) {
IFile file = project.getFile("build.properties"); //$NON-NLS-1$
if (file.exists())
return;
WorkspaceBuildModel buildModel = new WorkspaceBuildModel(file);
IBuildEntry ientry = buildModel.getFactory().createEntry("bin.includes"); //$NON-NLS-1$
try {
IResource[] res = project.members();
for (int i = 0; i < res.length; i++) {
String path = res[i].getProjectRelativePath().toString();
if (!path.equals(".project")) //$NON-NLS-1$
ientry.addToken(path);
}
buildModel.getBuild().add(ientry);
buildModel.save();
} catch (CoreException e) {
}
}
private void createProject(IProgressMonitor monitor) throws CoreException {
MaterializationContext context = (MaterializationContext) query.getContext();
ComponentRequest request = query.getComponentRequest();
String projectName = request.getProjectName();
monitor.beginTask(NLS.bind(Messages.importing_feature_0, projectName), 100);
IProject project = root.getProject(projectName);
try {
ConflictResolution conflictResolution = context.getMaterializationSpec().getConflictResolution(
WorkspaceInfo.getResolution(request, false));
if (project.exists()) {
switch (conflictResolution) {
case FAIL:
throw BuckminsterException.fromMessage(NLS.bind(Messages.project_0_already_exists, projectName));
case KEEP:
return;
default:
}
// Overwrite, i.e. remove current contents.
//
project.delete(true, true, MonitorUtils.subMonitor(monitor, 10));
try {
RepositoryProvider.unmap(project);
} catch (TeamException e) {
}
} else
MonitorUtils.worked(monitor, 10);
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IProjectDescription description = workspace.newProjectDescription(projectName);
FileUtils.prepareDestination(destination.toFile(), conflictResolution, MonitorUtils.subMonitor(monitor, 10));
description.setLocation(destination);
project.create(description, MonitorUtils.subMonitor(monitor, 5));
project.open(MonitorUtils.subMonitor(monitor, 5));
File featureDir = new File(model.getInstallLocation());
importContent(featureDir, project.getFullPath(), org.eclipse.buckminster.pde.internal.datatransfer.FileSystemStructureProvider.INSTANCE,
null, MonitorUtils.subMonitor(monitor, 50));
IFolder folder = project.getFolder("META-INF"); //$NON-NLS-1$
if (folder.exists())
folder.delete(true, null);
if (binary) {
// Mark this project so that we can show image overlay
// using the label decorator
project.setPersistentProperty(PDECore.EXTERNAL_PROJECT_PROPERTY, PDECore.BINARY_PROJECT_VALUE);
}
createBuildProperties(project);
setProjectNatures(project, model, MonitorUtils.subMonitor(monitor, 20));
if (project.hasNature(JavaCore.NATURE_ID))
classpathCollector.addProjectClasspath(project, getClasspath(project, model));
project.delete(false, true, MonitorUtils.subMonitor(monitor, 100));
} finally {
monitor.done();
}
}
private IClasspathEntry[] getClasspath(IProject project, IFeatureModel featureModel) throws JavaModelException {
IClasspathEntry jreCPEntry = JavaCore.newContainerEntry(new Path("org.eclipse.jdt.launching.JRE_CONTAINER")); //$NON-NLS-1$
String libName = featureModel.getFeature().getInstallHandler().getLibrary();
IClasspathEntry handlerCPEntry = JavaCore.newLibraryEntry(project.getFullPath().append(libName), null, null);
return new IClasspathEntry[] { jreCPEntry, handlerCPEntry };
}
private void importContent(Object source, IPath destPath, IImportStructureProvider provider, List<?> filesToImport, IProgressMonitor monitor)
throws CoreException {
IOverwriteQuery overwrite = new IOverwriteQuery() {
@Override
public String queryOverwrite(String file) {
return ALL;
}
};
ImportOperation op = new ImportOperation(destPath, source, provider, overwrite);
op.setCreateContainerStructure(false);
if (filesToImport != null)
op.setFilesToImport(filesToImport);
IStatus status = op.runInWorkspace(monitor);
if (status == Status.CANCEL_STATUS || monitor.isCanceled())
throw new OperationCanceledException(status.getMessage());
if (status.getSeverity() == IStatus.ERROR)
throw new CoreException(status);
}
private boolean needsJavaNature(IFeatureModel featureModel) {
IFeatureInstallHandler handler = featureModel.getFeature().getInstallHandler();
if (handler == null)
return false;
String libName = handler.getLibrary();
if (libName == null || libName.length() == 0)
return false;
File lib = new File(featureModel.getInstallLocation(), libName);
return lib.exists();
}
private void setProjectNatures(IProject project, IFeatureModel model, IProgressMonitor monitor) throws CoreException {
IProjectDescription desc = project.getDescription();
if (needsJavaNature(model))
desc.setNatureIds(new String[] { JavaCore.NATURE_ID, IPDEConstants.FEATURE_NATURE });
else
desc.setNatureIds(new String[] { IPDEConstants.FEATURE_NATURE });
project.setDescription(desc, monitor);
}
}