blob: e7e50f036faf0de41f72c8e5d611cc240b6e22d1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 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.pde.internal.ui.wizards.imports;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
import org.eclipse.osgi.service.environment.Constants;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.HostSpecification;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.core.build.IBuild;
import org.eclipse.pde.core.build.IBuildEntry;
import org.eclipse.pde.core.plugin.*;
import org.eclipse.pde.internal.core.*;
import org.eclipse.pde.internal.core.build.WorkspaceBuildModel;
import org.eclipse.pde.internal.core.bundle.WorkspaceBundleModel;
import org.eclipse.pde.internal.core.ibundle.IBundle;
import org.eclipse.pde.internal.core.natures.PDE;
import org.eclipse.pde.internal.core.util.CoreUtility;
import org.eclipse.pde.internal.ui.PDEPlugin;
import org.eclipse.pde.internal.ui.PDEUIMessages;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
import org.osgi.framework.BundleException;
/**
* Imports one or more plugins into the workspace. There are three different
* ways to import a plugin: as binary, as binary with linked source,
* and as source.
*/
public class PluginImportOperation extends JarImportOperation {
public static final int IMPORT_BINARY = 1;
public static final int IMPORT_BINARY_WITH_LINKS = 2;
public static final int IMPORT_WITH_SOURCE = 3;
private IPluginModelBase[] fModels;
private int fImportType;
private IImportQuery fReplaceQuery;
private Hashtable fProjectClasspaths = new Hashtable();
private boolean fForceAutobuild;
private IImportQuery fExecutionQuery;
private boolean fLaunchedConfigurations = false;
/**
* A list of plugins that were unable to be deleted
*/
private ArrayList fUnableToDeletePlugins;
public interface IImportQuery {
public static final int CANCEL = 0;
public static final int NO = 1;
public static final int YES = 2;
int doQuery(String message);
}
/**
* Constructor
* @param models models of plugins to import
* @param importType one of three types specified by constants, binary, binary with links, source
* @param replaceQuery defines what to do if the project already exists in the workspace
* @param executionQuery defines what to do if the project requires an unsupported execution environment
*/
public PluginImportOperation(IPluginModelBase[] models, int importType, IImportQuery replaceQuery, IImportQuery executionQuery) {
fModels = models;
fImportType = importType;
fReplaceQuery = replaceQuery;
fExecutionQuery = executionQuery;
fUnableToDeletePlugins = new ArrayList();
}
/**
* Constructor
* @param models models of plugins to import
* @param importType one of three types specified by constants, binary, binary with links, source
* @param replaceQuery defines what to do if the project already exists in the workspace
* @param executionQuery defines what to do if the project requires an unsupported execution environment
* @param forceAutobuild whether to force a build after the import
*/
public PluginImportOperation(IPluginModelBase[] models, int importType, IImportQuery replaceQuery, IImportQuery executionQuery, boolean forceAutobuild) {
this(models, importType, replaceQuery, executionQuery);
fForceAutobuild = forceAutobuild;
}
/* (non-Javadoc)
* @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
*/
public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
monitor.beginTask(PDEUIMessages.ImportWizard_operation_creating, fModels.length + 1);
try {
MultiStatus multiStatus = new MultiStatus(PDEPlugin.getPluginId(), IStatus.OK, PDEUIMessages.ImportWizard_operation_multiProblem, null);
for (int i = 0; i < fModels.length; i++) {
try {
importPlugin(fModels[i], new SubProgressMonitor(monitor, 1));
} catch (CoreException e) {
multiStatus.merge(e.getStatus());
}
if (monitor.isCanceled()) {
setClasspaths(new SubProgressMonitor(monitor, 1));
throw new OperationCanceledException();
}
}
setClasspaths(new SubProgressMonitor(monitor, 1));
if (!ResourcesPlugin.getWorkspace().isAutoBuilding() && fForceAutobuild)
runBuildJob();
if (!multiStatus.isOK())
throw new CoreException(multiStatus);
} finally {
monitor.done();
if (!fUnableToDeletePlugins.isEmpty()) {
final Display display = Display.getDefault();
display.syncExec(new Runnable() {
public void run() {
PluginImportFinishDialog dialog = new PluginImportFinishDialog(display.getActiveShell());
dialog.setTitle(PDEUIMessages.PluginImportInfoDialog_title);
dialog.setMessage(PDEUIMessages.PluginImportInfoDialog_message);
dialog.setInput(fUnableToDeletePlugins);
dialog.open();
}
});
}
}
}
/**
* Starts a job that will build the workspace
*/
private void runBuildJob() {
Job buildJob = new Job(PDEUIMessages.CompilersConfigurationBlock_building) {
public boolean belongsTo(Object family) {
return ResourcesPlugin.FAMILY_AUTO_BUILD == family;
}
protected IStatus run(IProgressMonitor monitor) {
try {
PDEPlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor);
} catch (CoreException e) {
}
return Status.OK_STATUS;
}
};
buildJob.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
buildJob.schedule();
}
/**
* Sets the raw classpath of projects that need to be updated
* @param monitor
* @throws JavaModelException if a classpath could not be set
*/
private void setClasspaths(IProgressMonitor monitor) throws JavaModelException {
monitor.beginTask("", fProjectClasspaths.size()); //$NON-NLS-1$
Enumeration keys = fProjectClasspaths.keys();
while (keys.hasMoreElements()) {
IProject project = (IProject) keys.nextElement();
IClasspathEntry[] classpath = (IClasspathEntry[]) fProjectClasspaths.get(project);
monitor.subTask(project.getName());
JavaCore.create(project).setRawClasspath(classpath, new SubProgressMonitor(monitor, 1));
}
}
/**
* This method starts the import of a specific plugin. Checks if the execution
* environment is supported and also checks if the project already exists and
* needs to be replaced.
* @param model model representing the plugin to import
* @param monitor progress monitor
* @throws CoreException if a problem occurs while importing a plugin
*/
private void importPlugin(IPluginModelBase model, IProgressMonitor monitor) throws CoreException {
String id = model.getPluginBase().getId();
monitor.beginTask(NLS.bind(PDEUIMessages.ImportWizard_operation_creating2, id), 6);
try {
BundleDescription desc = model.getBundleDescription();
if (desc != null) {
IExecutionEnvironmentsManager manager = JavaRuntime.getExecutionEnvironmentsManager();
String[] envs = desc.getExecutionEnvironments();
boolean found = false;
for (int i = 0; i < envs.length; i++) {
if (manager.getEnvironment(envs[i]) != null) {
found = true;
break;
}
}
if (envs.length > 0 && !found) {
String message = NLS.bind(PDEUIMessages.PluginImportOperation_executionEnvironment, id, envs[0]);
if (!queryExecutionEnvironment(message))
return;
}
}
IProject project = findProject(id);
if (project.exists() || new File(project.getParent().getLocation().toFile(), project.getName()).exists()) {
if (!queryReplace(project))
return;
if (RepositoryProvider.isShared(project))
RepositoryProvider.unmap(project);
if (!project.exists())
project.create(new SubProgressMonitor(monitor, 1));
if (!safeDeleteCheck(project, monitor)) {
fUnableToDeletePlugins.add(model);
return;
}
try {
project.delete(true, true, monitor);
} catch (CoreException e) {
fUnableToDeletePlugins.add(model);
return;
}
}
project.create(monitor);
if (!project.isOpen())
project.open(monitor);
monitor.worked(1);
if (Platform.inDevelopmentMode()) {
// if we are importing plug-ins in the runtime workbench from the host workbench, import everything as-is and return
File location = new File(model.getInstallLocation());
if (location.isDirectory()) {
File classpathFile = new File(location, ".classpath"); //$NON-NLS-1$
File projectFile = new File(location, ".project"); //$NON-NLS-1$
if (classpathFile.exists() && classpathFile.isFile() && projectFile.exists() && projectFile.isFile()) {
importContent(location, project.getFullPath(), FileSystemStructureProvider.INSTANCE, null, new SubProgressMonitor(monitor, 1));
return;
}
}
}
switch (fImportType) {
case IMPORT_BINARY :
importAsBinary(project, model, true, new SubProgressMonitor(monitor, 4));
break;
case IMPORT_BINARY_WITH_LINKS :
if (id.startsWith("org.eclipse.swt") && !isJARd(model)) { //$NON-NLS-1$
importAsBinary(project, model, true, monitor);
} else {
importAsBinaryWithLinks(project, model, new SubProgressMonitor(monitor, 4));
}
break;
case IMPORT_WITH_SOURCE :
if (isExempt(model)) {
importAsBinary(project, model, true, new SubProgressMonitor(monitor, 4));
} else {
importAsSource(project, model, new SubProgressMonitor(monitor, 4));
}
}
setProjectDescription(project, model);
if (project.hasNature(JavaCore.NATURE_ID) && project.findMember(".classpath") == null) //$NON-NLS-1$
fProjectClasspaths.put(project, ClasspathComputer.getClasspath(project, model, true, false));
} catch (CoreException e) {
PDEPlugin.logException(e);
} finally {
monitor.done();
}
}
// Returns the name of any projects the currently exist with same id and version. Otherwise it returns a default naming convention
protected String getProjectName(IPluginModelBase model) {
String id = model.getPluginBase().getId();
String version = model.getPluginBase().getVersion();
ModelEntry entry = PluginRegistry.findEntry(id);
if (entry != null) {
IPluginModelBase[] existingModels = entry.getWorkspaceModels();
for (int i = 0; i < existingModels.length; i++) {
String existingVersion = existingModels[i].getPluginBase().getVersion();
if (version.equals(existingVersion)) {
IResource res = existingModels[i].getUnderlyingResource();
if (res != null)
return res.getProject().getName();
}
}
}
return id + "_" + version; //$NON-NLS-1$
}
// returns true if it is safe to delete the project. It is not safe to delete if
// one of its libraries is locked by a running launch configuration.
private boolean safeDeleteCheck(IProject project, IProgressMonitor monitor) {
if (!fLaunchedConfigurations)
return true;
IPluginModelBase base = PluginRegistry.findModel(project);
if (base != null) {
IPluginLibrary[] libraries = base.getPluginBase().getLibraries();
for (int i = 0; i < libraries.length; i++) {
IResource res = project.findMember(libraries[i].getName());
if (res != null)
try {
if (!(ResourcesPlugin.getWorkspace().delete(new IResource[] {res}, true, monitor).isOK()))
return false;
} catch (CoreException e) {
return false;
}
}
}
return true;
}
/**
* Imports the contents of the plugin and adds links to the source location(s).
* @param project destination project of the import
* @param model model representing the plugin to import
* @param monitor progress monitor
* @throws CoreException if there is a problem completing the import
*/
private void importAsBinaryWithLinks(IProject project, IPluginModelBase model, IProgressMonitor monitor) throws CoreException {
if (isJARd(model)) {
extractJARdPlugin(project, model, monitor);
} else {
File installLocation = new File(model.getInstallLocation());
File[] items = installLocation.listFiles();
if (items != null) {
monitor.beginTask(PDEUIMessages.PluginImportOperation_linking, items.length + 1);
for (int i = 0; i < items.length; i++) {
File sourceFile = items[i];
String name = sourceFile.getName();
if (sourceFile.isDirectory()) {
project.getFolder(name).createLink(new Path(sourceFile.getPath()), IResource.NONE, new SubProgressMonitor(monitor, 1));
} else {
if (!name.equals(".project")) { //$NON-NLS-1$
project.getFile(name).createLink(new Path(sourceFile.getPath()), IResource.NONE, new SubProgressMonitor(monitor, 1));
} else {
// if the binary project with links has a .project file, copy it instead of linking (allows us to edit it)
ArrayList filesToImport = new ArrayList(1);
filesToImport.add(sourceFile);
importContent(installLocation, project.getFullPath(), FileSystemStructureProvider.INSTANCE, filesToImport, new SubProgressMonitor(monitor, 1));
}
}
}
}
linkSourceArchives(project, model, new SubProgressMonitor(monitor, 1));
}
try {
RepositoryProvider.map(project, PDECore.BINARY_REPOSITORY_PROVIDER);
} catch (TeamException e) {
}
}
/**
* Imports the contents of the plugin and imports source files as binary files that will not be compiled.
* @param project destination project of the import
* @param model model representing the plugin to import
* @param markAsBinary whether to mark the project as a binary project
* @param monitor progress monitor
* @throws CoreException if there is a problem completing the import
*/
private void importAsBinary(IProject project, IPluginModelBase model, boolean markAsBinary, IProgressMonitor monitor) throws CoreException {
monitor.beginTask("", 4); //$NON-NLS-1$
if (isJARd(model)) {
extractJARdPlugin(project, model, new SubProgressMonitor(monitor, 3));
} else {
importContent(new File(model.getInstallLocation()), project.getFullPath(), FileSystemStructureProvider.INSTANCE, null, new SubProgressMonitor(monitor, 1));
importSourceArchives(project, model, new SubProgressMonitor(monitor, 1));
// make sure all libraries have been imported
// if any are missing, check in fragments
IFragment[] fragments = getFragmentsFor(model);
IPluginLibrary[] libraries = model.getPluginBase().getLibraries();
IProgressMonitor fragmentMonitor = new SubProgressMonitor(monitor, 1);
fragmentMonitor.beginTask("", libraries.length); //$NON-NLS-1$
for (int i = 0; i < libraries.length; i++) {
String libraryName = libraries[i].getName();
if (ClasspathUtilCore.containsVariables(libraryName) && !project.exists(new Path(ClasspathUtilCore.expandLibraryName(libraryName)))) {
for (int j = 0; j < fragments.length; j++) {
importJarFromFragment(project, fragments[j], libraryName);
importSourceFromFragment(project, fragments[j], libraryName, new SubProgressMonitor(monitor, 1));
}
} else {
monitor.worked(1);
}
}
}
if (markAsBinary) {
project.setPersistentProperty(PDECore.EXTERNAL_PROJECT_PROPERTY, PDECore.BINARY_PROJECT_VALUE);
importAdditionalResources(project, model, new SubProgressMonitor(monitor, 1));
} else {
monitor.done();
}
}
/**
* Imports the contents of the plugin and imports source files to source folders that will be compiled.
* @param project destination project of the import
* @param model model representing the plugin to import
* @param monitor progress monitor
* @throws CoreException if there is a problem completing the import
*/
private void importAsSource(IProject project, IPluginModelBase model, SubProgressMonitor monitor) throws CoreException {
monitor.beginTask("", 4); //$NON-NLS-1$
importAsBinary(project, model, false, new SubProgressMonitor(monitor, 2));
List list = importAdditionalResources(project, model, new SubProgressMonitor(monitor, 1));
WorkspaceBuildModel buildModel = new WorkspaceBuildModel(project.getFile("build.properties")); //$NON-NLS-1$
if (!isJARd(model) || containsCode(new File(model.getInstallLocation()))) {
String[] libraries = getLibraryNames(model, false);
if (libraries.length == 0)
libraries = new String[] {"."}; //$NON-NLS-1$
for (int i = 0; i < libraries.length; i++) {
if (ClasspathUtilCore.containsVariables(libraries[i]))
continue;
String name = ClasspathUtilCore.expandLibraryName(libraries[i]);
IPath libraryPath = (name.equals(".") && isJARd(model)) //$NON-NLS-1$
? new Path(new File(model.getInstallLocation()).getName())
: new Path(name);
IResource jarFile = project.findMember(libraryPath);
if (jarFile != null) {
String srcName = ClasspathUtilCore.getSourceZipName(libraryPath.lastSegment());
IResource srcZip = jarFile.getProject().findMember(srcName);
if (srcZip == null) {
int extIndex = srcName.lastIndexOf('.');
if (extIndex != -1) {
srcZip = jarFile.getProject().findMember(srcName.substring(0, extIndex));
}
}
// srcZip == null if plug-in has embedded source
// if it jarred, all necessary files already in src folder
if (srcZip == null && libraries[i].equals(".") && !isJARd(model)) //$NON-NLS-1$
// if src does not exist (and returns null), then must not be plug-in with embedded source
srcZip = jarFile.getProject().findMember("src"); //$NON-NLS-1$
if (srcZip != null) {
String jarName = libraries[i].equals(".") ? "" : libraryPath.removeFileExtension().lastSegment(); //$NON-NLS-1$ //$NON-NLS-2$
String folder = addBuildEntry(buildModel, "source." + libraries[i], "src" + (jarName.length() == 0 ? "/" : "-" + jarName + "/")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
IFolder dest = jarFile.getProject().getFolder(folder);
if (srcZip instanceof IFolder) {
// if the source (srcZip) equals the destination folder (dest), then we don't want to delete/copy since every
// is already where it needs to be. This happens when importing source bundles in folder format declaring source with ext. point. (bug 214542)
if (!srcZip.equals(dest)) {
if (dest.exists()) {
dest.delete(true, null);
}
((IFolder) srcZip).move(dest.getFullPath(), true, new SubProgressMonitor(monitor, 1));
}
} else if (srcZip instanceof IFile) {
if (!dest.exists()) {
dest.create(true, true, null);
}
extractZipFile(srcZip.getLocation().toFile(), dest.getFullPath(), new SubProgressMonitor(monitor, 1));
srcZip.delete(true, null);
} else
monitor.worked(1);
if (jarFile instanceof IFile) {
if (isJARd(model)) {
extractJavaResources(jarFile.getLocation().toFile(), dest, new SubProgressMonitor(monitor, 1));
} else {
extractResources(jarFile.getLocation().toFile(), dest, new SubProgressMonitor(monitor, 1));
}
jarFile.delete(true, null);
} else {
moveBinaryContents((IContainer) jarFile, dest, new SubProgressMonitor(monitor, 1));
}
}
} else if (name.equals(".") && project.getFolder("src").exists()) { //$NON-NLS-1$ //$NON-NLS-2$
addBuildEntry(buildModel, "source..", "src/"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
configureBinIncludes(buildModel, model, project);
if (list.size() > 0)
configureSrcIncludes(buildModel, list);
buildModel.save();
}
/**
* Moves the binary files from the source container to the folder destination.
* Moves any file that isn't a .class file
* @param srcFolder container to move from
* @param dest folder to move to
* @param monitor progress monitor
*/
private void moveBinaryContents(IContainer srcFolder, IFolder dest, IProgressMonitor monitor) {
try {
// get all the folders for which we want to search
IResource[] children = dest.members();
ArrayList validFolders = new ArrayList();
for (int i = 0; i < children.length; i++)
if (children[i] instanceof IFolder) {
String folderName = children[i].getName();
IResource folder = srcFolder.findMember(folderName);
if (folder != null && folder instanceof IFolder)
validFolders.add(folder);
}
monitor.beginTask(new String(), validFolders.size());
ListIterator li = validFolders.listIterator();
while (li.hasNext()) {
IFolder folder = (IFolder) li.next();
int pathSegments = folder.getProjectRelativePath().segmentCount() - 1;
Stack stack = new Stack();
IResource[] resources = folder.members();
for (int i = 0; i < resources.length; i++)
stack.push(resources[i]);
while (!stack.isEmpty()) {
IResource res = (IResource) stack.pop();
if (res instanceof IFile) {
if (!res.getName().endsWith(".class")) { //$NON-NLS-1$
String pathName = res.getProjectRelativePath().removeFirstSegments(pathSegments).toString();
IFile destFile = dest.getFile(pathName);
if (!destFile.getParent().exists()) {
CoreUtility.createFolder((IFolder) destFile.getParent());
}
// file might exist if previous project was deleted without removing underlying resources
if (destFile.exists())
destFile.delete(true, null);
res.move(destFile.getFullPath(), true, null);
}
} else {
resources = ((IFolder) res).members();
for (int i = 0; i < resources.length; i++)
stack.push(resources[i]);
}
}
folder.delete(true, null);
monitor.worked(1);
}
} catch (CoreException e) {
}
}
/**
* Searches source locations for files to import to the new project, will ignore
* src.zip.
* @param project destination project of the import
* @param model model representing the plugin to import
* @param monitor progress monitor
* @return list of imported files
* @throws CoreException if there is a problem completing the import
*/
private List importAdditionalResources(IProject project, IPluginModelBase model, SubProgressMonitor monitor) throws CoreException {
SourceLocationManager manager = PDECore.getDefault().getSourceLocationManager();
File location = manager.findSourcePlugin(model.getPluginBase());
if (location != null) {
ArrayList list = new ArrayList();
if (location.isDirectory()) {
Object root = location;
File[] children = location.listFiles();
if (children != null) {
for (int i = 0; i < children.length; i++) {
String name = children[i].getName();
if (!project.exists(new Path(name)) && !"src.zip".equals(name)) { //$NON-NLS-1$
list.add(children[i]);
}
}
importContent(root, project.getFullPath(), FileSystemStructureProvider.INSTANCE, list, monitor);
ArrayList srcEntryList = new ArrayList(list.size());
for (ListIterator iterator = list.listIterator(); iterator.hasNext();) {
File current = (File) iterator.next();
String entry = current.getName();
if (current.isDirectory()) {
entry += "/"; //$NON-NLS-1$
}
srcEntryList.add(entry);
}
return srcEntryList;
}
} else if (location.isFile()) {
ZipFile zipFile = null;
try {
zipFile = new ZipFile(location);
ZipFileStructureProvider zipProvider = new ZipFileStructureProvider(zipFile);
Object root = zipProvider.getRoot();
collectAdditionalResources(zipProvider, root, list, project);
importContent(root, project.getFullPath(), zipProvider, list, monitor);
ArrayList srcEntryList = new ArrayList(list.size());
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
ZipEntry current = (ZipEntry) iterator.next();
String entry = current.getName();
srcEntryList.add(entry);
}
return srcEntryList;
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch (IOException e) {
}
}
}
}
}
return new ArrayList(0);
}
private void configureBinIncludes(WorkspaceBuildModel buildModel, IPluginModelBase model, IProject project) throws CoreException {
IBuild build = buildModel.getBuild(true);
IBuildEntry entry = build.getEntry("bin.includes"); //$NON-NLS-1$
HashMap libraryDirs = getSourceDirectories(build);
if (entry == null) {
entry = buildModel.getFactory().createEntry("bin.includes"); //$NON-NLS-1$
File location = new File(model.getInstallLocation());
if (location.isDirectory()) {
File[] files = location.listFiles();
for (int i = 0; i < files.length; i++) {
String token = files[i].getName();
if ((project.findMember(token) == null) && (build.getEntry(IBuildEntry.JAR_PREFIX + token) == null))
continue;
if (files[i].isDirectory()) {
token = token + "/"; //$NON-NLS-1$
if (libraryDirs.containsKey(token))
token = libraryDirs.get(token).toString();
}
entry.addToken(token);
}
} else {
String[] tokens = getTopLevelResources(location);
for (int i = 0; i < tokens.length; i++) {
IResource res = project.findMember(tokens[i]);
if ((res == null) && (build.getEntry(IBuildEntry.JAR_PREFIX + tokens[i]) == null))
continue;
if ((res instanceof IFolder) && (libraryDirs.containsKey(tokens[i])))
continue;
entry.addToken(tokens[i]);
}
}
buildModel.getBuild().add(entry);
}
}
private HashMap getSourceDirectories(IBuild build) {
HashMap set = new HashMap();
IBuildEntry[] entries = build.getBuildEntries();
for (int i = 0; i < entries.length; i++) {
String name = entries[i].getName();
if (name.startsWith(IBuildEntry.JAR_PREFIX)) {
name = name.substring(7);
String[] tokens = entries[i].getTokens();
for (int j = 0; j < tokens.length; j++) {
set.put(tokens[j], name);
}
}
}
return set;
}
private void configureSrcIncludes(WorkspaceBuildModel buildModel, List list) throws CoreException {
IBuildEntry entry = buildModel.getBuild(true).getEntry("src.includes"); //$NON-NLS-1$
if (entry == null) {
entry = buildModel.getFactory().createEntry("src.includes"); //$NON-NLS-1$
for (int i = 0; i < list.size(); i++) {
entry.addToken(list.get(i).toString());
}
buildModel.getBuild().add(entry);
}
}
private String addBuildEntry(WorkspaceBuildModel model, String key, String value) throws CoreException {
IBuild build = model.getBuild(true);
IBuildEntry entry = build.getEntry(key);
if (entry == null) {
entry = model.getFactory().createEntry(key);
entry.addToken(value);
build.add(entry);
}
String[] tokens = entry.getTokens();
return (tokens.length > 0) ? tokens[0] : "src/"; //$NON-NLS-1$
}
/**
* Creates links in the project to the source locations for the various libraries.
* If the source for all libraries is in a single bundle, one link is created
* @param project destination project of the import
* @param model model representing the plugin to import
* @param monitor progress monitor
* @throws CoreException if there is a problem completing the import
*/
private void linkSourceArchives(IProject project, IPluginModelBase model, IProgressMonitor monitor) throws CoreException {
String[] libraries = getLibraryNames(model, true);
monitor.beginTask(PDEUIMessages.ImportWizard_operation_copyingSource, libraries.length);
SourceLocationManager manager = PDECore.getDefault().getSourceLocationManager();
if (manager.hasBundleManifestLocation(model.getPluginBase())) {
IPath srcPath = manager.findSourcePath(model.getPluginBase(), null);
if (srcPath != null) {
// Source for all libraries is in the same bundle, just create one link to the source bundle
IPath path = new Path(project.getName() + "src.zip"); //$NON-NLS-1$
IFile srcFile = project.getFile(path.lastSegment());
if (!srcFile.exists()) {
srcFile.createLink(srcPath, IResource.NONE, new SubProgressMonitor(monitor, 1));
}
}
monitor.worked(libraries.length);
} else {
for (int i = 0; i < libraries.length; i++) {
String zipName = ClasspathUtilCore.getSourceZipName(libraries[i]);
IPath path = new Path(zipName);
if (project.findMember(path) == null) {
IPath srcPath = manager.findSourcePath(model.getPluginBase(), path);
if (srcPath != null) {
if ("src.zip".equals(zipName) && isJARd(model)) { //$NON-NLS-1$
path = new Path(ClasspathUtilCore.getSourceZipName(new File(model.getInstallLocation()).getName()));
}
IFile zipFile = project.getFile(path.lastSegment());
if (!zipFile.exists()) {
zipFile.createLink(srcPath, IResource.NONE, new SubProgressMonitor(monitor, 1));
}
}
}
monitor.worked(1);
}
}
monitor.done();
}
private void importSourceArchives(IProject project, IPluginModelBase model, IProgressMonitor monitor) throws CoreException {
String[] libraries = getLibraryNames(model, true);
monitor.beginTask(PDEUIMessages.ImportWizard_operation_copyingSource, libraries.length);
SourceLocationManager manager = PDECore.getDefault().getSourceLocationManager();
Set roots = null;
if (manager.hasBundleManifestLocation(model.getPluginBase()))
roots = manager.findSourceRoots(model.getPluginBase());
for (int i = 0; i < libraries.length; i++) {
String zipName = ClasspathUtilCore.getSourceZipName(libraries[i]);
IPath path = new Path(zipName);
if (project.findMember(path) == null) {
// if we are importing the source through a sourceBundle header...
if (roots != null) {
IPath sourceLocation = manager.findSourcePath(model.getPluginBase(), null);
String currentRoot = ".".equals(libraries[i]) ? "." : path.removeFileExtension().toString(); //$NON-NLS-1$ //$NON-NLS-2$
if (roots.contains(currentRoot)) {
if (".".equals(currentRoot)) { //$NON-NLS-1$
// Save to a special folder name based on the install location
IPath sourceName = getDefaultSourceNameForProject(model);
sourceName = sourceName.removeFileExtension();
IFolder dest = project.getFolder(sourceName);
if (!dest.exists()) {
dest.create(true, true, null);
}
// List all of the other source roots so they are not included when importing source from the root, ".", of the jar
Set allBundleRoots = manager.findAllSourceRootsInSourceLocation(model.getPluginBase());
List rootsToExclude = new ArrayList(allBundleRoots.size() - 1);
for (Iterator iterator2 = allBundleRoots.iterator(); iterator2.hasNext();) {
String rootString = (String) iterator2.next();
if (!".".equals(rootString)) { //$NON-NLS-1$
rootsToExclude.add(new Path(rootString));
}
}
// Extract folders containing java source
extractJavaSource(new File(sourceLocation.toOSString()), rootsToExclude, dest, monitor);
} else {
// Extract the specific library from it's folder
extractResourcesFromFolder(new File(sourceLocation.toOSString()), new Path(currentRoot), project, monitor);
}
}
} else {
IPath srcPath = manager.findSourcePath(model.getPluginBase(), path);
if (srcPath != null) {
if ("src.zip".equals(zipName) && isJARd(model)) { //$NON-NLS-1$
path = getDefaultSourceNameForProject(model);
}
importArchive(project, new File(srcPath.toOSString()), path);
}
}
}
monitor.worked(1);
}
monitor.done();
}
/**
* Creates a path representing a zip file that is named based on the plugin install location.
* Used to replace src.zip with a more unique and meaningful name.
* @param model model that the src.zip containg source for
* @return a new path describing the zip file
*/
private IPath getDefaultSourceNameForProject(IPluginModelBase model) {
return new Path(ClasspathUtilCore.getSourceZipName(new File(model.getInstallLocation()).getName()));
}
private String[] getLibraryNames(IPluginModelBase model, boolean expand) {
IPluginLibrary[] libraries = model.getPluginBase().getLibraries();
ArrayList list = new ArrayList();
for (int i = 0; i < libraries.length; i++) {
if (expand)
list.add(ClasspathUtilCore.expandLibraryName(libraries[i].getName()));
else
list.add(libraries[i].getName());
}
if (libraries.length == 0 && isJARd(model))
list.add("."); //$NON-NLS-1$
return (String[]) list.toArray(new String[list.size()]);
}
private void extractJARdPlugin(IProject project, IPluginModelBase model, IProgressMonitor monitor) throws CoreException {
ZipFile zipFile = null;
try {
zipFile = new ZipFile(model.getInstallLocation());
ZipFileStructureProvider provider = new ZipFileStructureProvider(zipFile);
if (!containsCode(provider)) {
extractZipFile(new File(model.getInstallLocation()), project.getFullPath(), monitor);
return;
}
ArrayList collected = new ArrayList();
collectNonJavaResources(provider, provider.getRoot(), collected);
importContent(provider.getRoot(), project.getFullPath(), provider, collected, monitor);
File file = new File(model.getInstallLocation());
if (hasEmbeddedSource(provider) && fImportType == IMPORT_WITH_SOURCE) {
collected = new ArrayList();
collectJavaFiles(provider, provider.getRoot(), collected);
importContent(provider.getRoot(), project.getFullPath(), provider, collected, monitor);
collected = new ArrayList();
collectJavaResources(provider, provider.getRoot(), collected);
importContent(provider.getRoot(), project.getFullPath().append("src"), provider, collected, monitor); //$NON-NLS-1$
} else {
if (fImportType == IMPORT_BINARY_WITH_LINKS) {
project.getFile(file.getName()).createLink(new Path(file.getAbsolutePath()), IResource.NONE, null);
} else {
importArchive(project, file, new Path(file.getName()));
}
if (!hasEmbeddedSource(provider)) {
if (fImportType == IMPORT_BINARY_WITH_LINKS) {
linkSourceArchives(project, model, new SubProgressMonitor(monitor, 1));
} else {
importSourceArchives(project, model, new SubProgressMonitor(monitor, 1));
}
}
}
if (fImportType != IMPORT_WITH_SOURCE) {
modifyBundleClasspathHeader(project, model);
} else {
removeSignedHeaders(project);
}
setPermissions(model, project);
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch (IOException e) {
}
}
}
}
private void modifyBundleClasspathHeader(IProject project, IPluginModelBase base) {
IFile file = project.getFile(JarFile.MANIFEST_NAME);
if (file.exists()) {
WorkspaceBundleModel bmodel = new WorkspaceBundleModel(file);
IBundle bundle = bmodel.getBundle();
String classpath = bundle.getHeader(org.osgi.framework.Constants.BUNDLE_CLASSPATH);
if (classpath == null) {
bundle.setHeader(org.osgi.framework.Constants.BUNDLE_CLASSPATH, ClasspathUtilCore.getFilename(base));
} else {
try {
ManifestElement[] elements = ManifestElement.parseHeader(org.osgi.framework.Constants.BUNDLE_CLASSPATH, classpath);
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < elements.length; i++) {
if (buffer.length() > 0) {
buffer.append(","); //$NON-NLS-1$
buffer.append(System.getProperty("line.separator")); //$NON-NLS-1$
buffer.append(" "); //$NON-NLS-1$
}
if (elements[i].getValue().equals(".")) //$NON-NLS-1$
buffer.append(ClasspathUtilCore.getFilename(base));
else
buffer.append(elements[i].getValue());
}
bundle.setHeader(org.osgi.framework.Constants.BUNDLE_CLASSPATH, buffer.toString());
} catch (BundleException e) {
}
}
bmodel.save();
}
}
private void removeSignedHeaders(IProject project) {
IFile file = project.getFile(JarFile.MANIFEST_NAME);
if (!file.exists())
return;
WorkspaceBundleModel model = new WorkspaceBundleModel(file);
model.save();
}
private IProject findProject(String id) {
IPluginModelBase model = PluginRegistry.findModel(id);
if (model != null) {
IResource resource = model.getUnderlyingResource();
if (resource != null)
return resource.getProject();
}
return PDEPlugin.getWorkspace().getRoot().getProject(id);
}
private boolean queryReplace(IProject project) throws OperationCanceledException {
switch (fReplaceQuery.doQuery(NLS.bind(PDEUIMessages.ImportWizard_messages_exists, project.getName()))) {
case IImportQuery.CANCEL :
throw new OperationCanceledException();
case IImportQuery.NO :
return false;
}
return true;
}
private boolean queryExecutionEnvironment(String message) throws OperationCanceledException {
switch (fExecutionQuery.doQuery(message)) {
case IImportQuery.CANCEL :
throw new OperationCanceledException();
case IImportQuery.NO :
return false;
}
return true;
}
private void setProjectDescription(IProject project, IPluginModelBase model) throws CoreException {
IProjectDescription desc = project.getDescription();
if (!desc.hasNature(PDE.PLUGIN_NATURE))
CoreUtility.addNatureToProject(project, PDE.PLUGIN_NATURE, null);
if (needsJavaNature(project, model) && !desc.hasNature(JavaCore.NATURE_ID))
CoreUtility.addNatureToProject(project, JavaCore.NATURE_ID, null);
}
private boolean needsJavaNature(IProject project, IPluginModelBase model) {
if (model.getPluginBase().getLibraries().length > 0)
return true;
BundleDescription desc = model.getBundleDescription();
if (desc != null) {
if (desc.getExportPackages().length > 0)
return true;
if (desc.getRequiredBundles().length > 0)
return true;
if (desc.getImportPackages().length > 0)
return true;
}
return false;
}
private boolean isExempt(IPluginModelBase model) {
String id = model.getPluginBase().getId();
if ("org.apache.ant".equals(id) //$NON-NLS-1$
|| "org.eclipse.osgi.util".equals(id) //$NON-NLS-1$
|| "org.eclipse.osgi.services".equals(id) //$NON-NLS-1$
|| "org.eclipse.core.runtime.compatibility.registry".equals(id)) //$NON-NLS-1$
return true;
if ("org.eclipse.swt".equals(id) && !isJARd(model)) //$NON-NLS-1$
return true;
return false;
}
private boolean isJARd(IPluginModelBase model) {
return new File(model.getInstallLocation()).isFile();
}
private void setPermissions(IPluginModelBase model, IProject project) {
try {
if (!Platform.getOS().equals(Constants.OS_WIN32) && model instanceof IFragmentModel) {
IFragment fragment = ((IFragmentModel) model).getFragment();
if ("org.eclipse.swt".equals(fragment.getPluginId())) { //$NON-NLS-1$
IResource[] children = project.members();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof IFile && isInterestingResource(children[i].getName())) {
Runtime.getRuntime().exec(new String[] {"chmod", "755", children[i].getLocation().toOSString()}).waitFor(); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
}
} catch (CoreException e) {
} catch (InterruptedException e) {
} catch (IOException e) {
}
}
private boolean isInterestingResource(String name) {
return name.endsWith(".jnilib") //$NON-NLS-1$
|| name.endsWith(".sl") //$NON-NLS-1$
|| name.endsWith(".a") //$NON-NLS-1$
|| name.indexOf(".so") != -1; //$NON-NLS-1$
}
private IFragment[] getFragmentsFor(IPluginModelBase model) {
ArrayList result = new ArrayList();
for (int i = 0; i < fModels.length; i++) {
if (fModels[i] instanceof IFragmentModel) {
HostSpecification spec = fModels[i].getBundleDescription().getHost();
BundleDescription host = spec == null ? null : (BundleDescription) spec.getSupplier();
if (model.getBundleDescription().equals(host)) {
result.add(((IFragmentModel) fModels[i]).getFragment());
}
}
}
return (IFragment[]) result.toArray(new IFragment[result.size()]);
}
private void importJarFromFragment(IProject project, IFragment fragment, String name) throws CoreException {
IPath jarPath = new Path(ClasspathUtilCore.expandLibraryName(name));
File jar = new File(fragment.getModel().getInstallLocation(), jarPath.toString());
if (jar.exists()) {
importArchive(project, jar, jarPath);
}
}
/**
* Imports the source for a library from a fragment.
* @param project destination project of the import
* @param fragment fragment to import the library from
* @param libraryName name of the library to import,
* @param monitor progress monitor
* @throws CoreException if there is a problem completing the import
*/
private void importSourceFromFragment(IProject project, IFragment fragment, String libraryName, IProgressMonitor monitor) throws CoreException {
try {
IPath jarPath = new Path(ClasspathUtilCore.expandLibraryName(libraryName));
String zipName = ClasspathUtilCore.getSourceZipName(jarPath.toString());
IPath path = new Path(zipName);
if (project.findMember(path) == null) {
SourceLocationManager manager = PDECore.getDefault().getSourceLocationManager();
IPath srcPath = manager.findSourcePath(fragment, path);
if (srcPath != null) {
if (manager.hasBundleManifestLocation(fragment)) {
// Extract the specific library from it's folder
extractResourcesFromFolder(new File(srcPath.toOSString()), path.removeFileExtension(), project, monitor);
} else {
importArchive(project, new File(srcPath.toOSString()), path);
}
}
}
} finally {
monitor.done();
}
}
protected void collectAdditionalResources(ZipFileStructureProvider provider, Object element, ArrayList collected, IProject project) {
collectAdditionalResources(provider, element, collected);
ListIterator li = collected.listIterator();
while (li.hasNext()) {
ZipEntry ze = (ZipEntry) li.next();
String name = ze.getName();
// only import the entries that don't already exist
if (project.findMember(name) != null) {
li.remove();
}
}
}
protected void collectNonJavaResources(ZipFileStructureProvider provider, Object element, ArrayList collected) {
super.collectNonJavaResources(provider, element, collected);
if (fImportType != IMPORT_WITH_SOURCE)
return;
// filter the resources we get back to include only relevant resource files
ListIterator li = collected.listIterator();
while (li.hasNext()) {
ZipEntry ze = (ZipEntry) li.next();
String name = ze.getName();
// filter out signature files - bug 175756
if (name.startsWith("META-INF/") && (name.endsWith(".RSA") || name.endsWith(".DSA") || name.endsWith(".SF"))) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
li.remove();
}
}
public void setLaunchedConfiguration(boolean launchedConfiguration) {
fLaunchedConfigurations = launchedConfiguration;
}
}