blob: 3b6195398696fc63a3d46ca6396993c0603733ac [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2013 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.Map.Entry;
import java.util.List;
import java.util.zip.ZipException;
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.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.service.resolver.BundleDescription;
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.project.PDEProject;
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.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.team.core.*;
import org.eclipse.team.core.importing.provisional.IBundleImporter;
import org.eclipse.ui.*;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.wizards.datatransfer.*;
import org.osgi.framework.BundleException;
/**
* Imports one or more plug-ins into the workspace. There are three different
* ways to import a plugin: as binary, as binary with linked source,
* and as source.
*/
@SuppressWarnings("restriction")
// The IBundleImporter API is currently provisional
public class PluginImportOperation extends WorkspaceJob {
public static final int IMPORT_BINARY = 1;
public static final int IMPORT_BINARY_WITH_LINKS = 2;
public static final int IMPORT_WITH_SOURCE = 3;
public static final int IMPORT_FROM_REPOSITORY = 4;
private static final String DEFAULT_SOURCE_DIR = "src"; //$NON-NLS-1$
private static final String DEFAULT_LIBRARY_NAME = "."; //$NON-NLS-1$
private IPluginModelBase[] fModels;
private int fImportType;
private Hashtable<IProject, IClasspathEntry[]> fProjectClasspaths = new Hashtable<>();
/**
* Maps project ids to a List of IWorkingSets, the map is filled when determining what projects to delete
*/
private Map<String, List<IWorkingSet>> fProjectWorkingSets = new HashMap<>();
private boolean fForceAutobuild;
// used when importing from a repository
private Map<IBundleImporter, ScmUrlImportDescription[]> fImportDescriptions;
/**
* Used to find source locations when not found in default locations.
* Possibly <code>null</code>
*/
private SourceLocationManager fAlternateSource;
private boolean fPluginsAreInUse = false;
/**
* Constructor
* @param models models of plug-ins 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, boolean forceAutobuild) {
super(PDEUIMessages.ImportWizard_title);
fModels = models;
fImportType = importType;
fForceAutobuild = forceAutobuild;
}
/**
* Sets whether some of the plug-ins being imported are currently in use by a launched
* Eclipse instance. Setting this to true will force an additional check before deleting
* a plug-in.
* @param pluginsInUse
*/
public void setPluginsInUse(boolean pluginsInUse) {
fPluginsAreInUse = pluginsInUse;
}
/**
* Sets a source location manager to use to find source attachments. This should
* be specified when importing plug-ins that are not from the active target platform
* so source attachments can be found.
*
* @param alternate source location manager.
*/
public void setAlternateSource(SourceLocationManager alternate) {
fAlternateSource = alternate;
}
/**
* This custom message box class is used for warning the user about the projects that did not get imported.
* see bug 337730
*
* This class should get removed when Bug 346078 is fixed.
*
*/
private class NotImportedProjectsWarningDialog extends MessageDialog {
/**
* The list of the projects that did not get imported.
*/
private List<String> fNamesOfNotImportedProjects;
/**
* Creates a warning message dialog. The message area will contain the scrollable
* text box that will show the list of the projects supplied.
*
* @param warningMessage
* the warning message to be shown on the dialog.
* @param namesOfNotImportedProjects
* the list of the project names that did not get imported.
*/
public NotImportedProjectsWarningDialog(String warningMessage, List<String> namesOfNotImportedProjects) {
super(PlatformUI.getWorkbench().getModalDialogShellProvider().getShell(), PDEUIMessages.ImportWizard_title, null, warningMessage, MessageDialog.WARNING, new String[] {IDialogConstants.OK_LABEL}, 0);
fNamesOfNotImportedProjects = namesOfNotImportedProjects;
}
@Override
protected Control createCustomArea(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
Text projectText = new Text(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.READ_ONLY | SWT.BORDER);
projectText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint = convertWidthInCharsToPixels(60);
gd.heightHint = convertHeightInCharsToPixels(10);
projectText.setLayoutData(gd);
StringBuffer projectListBuffer = new StringBuffer();
for (Iterator<String> iterator = fNamesOfNotImportedProjects.iterator(); iterator.hasNext();) {
String project = iterator.next();
projectListBuffer.append(project).append('\n');
}
projectText.setText(projectListBuffer.toString());
return composite;
}
}
@Override
public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
try {
monitor.beginTask("", fModels.length + 5); //$NON-NLS-1$
MultiStatus multiStatus = new MultiStatus(PDEPlugin.getPluginId(), IStatus.OK, PDEUIMessages.ImportWizard_operation_multiProblem, null);
deleteConflictingProjects(multiStatus, new SubProgressMonitor(monitor, 2));
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
if (fImportType == IMPORT_FROM_REPOSITORY) {
final List<String> namesOfNotImportedProjects = new ArrayList<>();
Iterator<Entry<IBundleImporter, ScmUrlImportDescription[]>> iterator = fImportDescriptions.entrySet().iterator();
while (iterator.hasNext()) {
Entry<IBundleImporter, ScmUrlImportDescription[]> entry = iterator.next();
IBundleImporter importer = entry.getKey();
ScmUrlImportDescription[] descriptions = entry.getValue();
if (descriptions.length == 0)
continue;
IProject[] importedProjects = importer.performImport(descriptions, new SubProgressMonitor(monitor, descriptions.length));
if (importedProjects != null && importedProjects.length == descriptions.length)
continue;
ArrayList<String> namesOfImportedProjects = new ArrayList<>(importedProjects.length);
for (int i = 0; i < importedProjects.length; i++) {
namesOfImportedProjects.add(importedProjects[i].getName());
}
for (int i = 0; i < descriptions.length; i++) {
String projectName = descriptions[i].getProject();
if (!namesOfImportedProjects.contains(projectName)) {
namesOfNotImportedProjects.add(projectName);
}
}
}
if (namesOfNotImportedProjects.size() > 0) {
UIJob job = new UIJob(PDEUIMessages.PluginImportOperation_WarningDialogJob) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
String dialogMessage = namesOfNotImportedProjects.size() == 1 ? PDEUIMessages.PluginImportOperation_WarningDialogMessageSingular : PDEUIMessages.PluginImportOperation_WarningDialogMessagePlural;
NotImportedProjectsWarningDialog dialog = new NotImportedProjectsWarningDialog(dialogMessage, namesOfNotImportedProjects);
dialog.open();
return Status.OK_STATUS;
}
};
try {
job.schedule();
job.join();
} catch (InterruptedException e1) {
}
}
} else {
for (int i = 0; i < fModels.length; i++) {
monitor.setTaskName(NLS.bind(PDEUIMessages.PluginImportOperation_Importing_plugin, fModels[i].getPluginBase().getId()));
try {
importPlugin(fModels[i], fImportType, new SubProgressMonitor(monitor, 1));
} catch (CoreException e) {
multiStatus.merge(e.getStatus());
}
if (monitor.isCanceled()) {
try {
setClasspaths(new SubProgressMonitor(monitor, 3));
} catch (JavaModelException e) {
/* Do nothing as we are already cancelled */
}
return Status.CANCEL_STATUS;
}
}
monitor.setTaskName(PDEUIMessages.PluginImportOperation_Set_up_classpaths);
try {
setClasspaths(new SubProgressMonitor(monitor, 1));
} catch (JavaModelException e) {
multiStatus.merge(e.getStatus());
}
}
if (!ResourcesPlugin.getWorkspace().isAutoBuilding() && fForceAutobuild)
runBuildJob();
return multiStatus;
} finally {
monitor.done();
}
}
/**
* If there are existing projects in the workspace with the same symbolic name, open a dialog
* asking the user if they would like to delete those projects. The projects are deleted before
* the import continues so the individual imports can do a simple search for an allowed plug-in name.
*
* @param status the multi-status used to report problems
* @param monitor progress monitor, must not be <code>null</code>
*/
private void deleteConflictingProjects(MultiStatus status, IProgressMonitor monitor) {
monitor.beginTask("", 5); //$NON-NLS-1$
try {
IPluginModelBase[] workspacePlugins = PluginRegistry.getWorkspaceModels();
HashMap<String, ArrayList<IPluginModelBase>> workspacePluginMap = new HashMap<>();
for (int i = 0; i < workspacePlugins.length; i++) {
IPluginModelBase plugin = workspacePlugins[i];
if (plugin.getBundleDescription() != null) {
String symbolicName = plugin.getBundleDescription().getSymbolicName();
ArrayList<IPluginModelBase> pluginsWithSameSymbolicName = workspacePluginMap.get(symbolicName);
if (pluginsWithSameSymbolicName == null) {
pluginsWithSameSymbolicName = new ArrayList<>();
workspacePluginMap.put(symbolicName, pluginsWithSameSymbolicName);
}
pluginsWithSameSymbolicName.add(plugin);
}
}
monitor.worked(1);
final ArrayList<IPluginModelBase> conflictingPlugins = new ArrayList<>();
for (int i = 0; i < fModels.length; i++) {
if (fModels[i].getBundleDescription() == null) {
continue;
}
String symbolicName = fModels[i].getBundleDescription().getSymbolicName();
ArrayList<IPluginModelBase> plugins = workspacePluginMap.get(symbolicName);
if (plugins == null || plugins.size() == 0) {
continue;
}
if (!conflictingPlugins.containsAll(plugins)) {
conflictingPlugins.addAll(plugins);
}
}
monitor.worked(1);
final ArrayList<Object> overwriteProjectList = new ArrayList<>();
if (conflictingPlugins.size() > 0) {
UIJob job = new UIJob(PDEUIMessages.PluginImportOperation_OverwritePluginProjects) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
OverwriteProjectsSelectionDialog dialog = new OverwriteProjectsSelectionDialog(getDisplay().getActiveShell(), conflictingPlugins);
dialog.setBlockOnOpen(true);
if (dialog.open() == Window.OK) {
overwriteProjectList.addAll(Arrays.asList(dialog.getResult()));
return Status.OK_STATUS;
}
return Status.CANCEL_STATUS;
}
};
try {
job.schedule();
job.join();
} catch (InterruptedException e1) {
}
if (job.getResult() == null || !job.getResult().isOK()) {
monitor.setCanceled(true);
return;
}
monitor.worked(1);
// collect working set information
IWorkingSetManager wsManager = PlatformUI.getWorkbench().getWorkingSetManager();
IWorkingSet[] sets = wsManager.getAllWorkingSets();
for (int i = 0; i < sets.length; i++) {
IAdaptable[] contents = sets[i].getElements();
for (int j = 0; j < contents.length; j++) {
IResource resource = (IResource) contents[j].getAdapter(IResource.class);
if (resource instanceof IProject) {
// TODO For now just list everything in the map
String id = ((IProject) resource).getName();
List<IWorkingSet> workingSets = fProjectWorkingSets.get(id);
if (workingSets == null) {
workingSets = new ArrayList<>();
fProjectWorkingSets.put(id, workingSets);
}
workingSets.add(sets[i]);
}
}
}
//delete the selected projects
for (int i = 0; i < overwriteProjectList.size(); i++) {
IPluginModelBase plugin = (IPluginModelBase) overwriteProjectList.get(i);
monitor.setTaskName(NLS.bind(PDEUIMessages.PluginImportOperation_Importing_plugin, plugin.getPluginBase().getId()));
IProject project = plugin.getUnderlyingResource().getProject();
try {
if (RepositoryProvider.isShared(project))
RepositoryProvider.unmap(project);
if (!safeDeleteCheck(project, monitor)) {
status.add(new Status(IStatus.ERROR, PDEPlugin.getPluginId(), NLS.bind(PDEUIMessages.PluginImportOperation_could_not_delete_project, project.getName())));
}
boolean deleteContent = project.getWorkspace().getRoot().getLocation().equals(project.getLocation().removeLastSegments(1));
project.delete(deleteContent, true, monitor);
} catch (CoreException ex) {
status.add(new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.OK, NLS.bind(PDEUIMessages.PluginImportOperation_could_not_delete_project, project.getName()), ex));
}
}
monitor.worked(2);
} else {
monitor.worked(3);
}
} finally {
monitor.done();
}
}
/**
* 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 {
try {
monitor.beginTask("", fProjectClasspaths.size()); //$NON-NLS-1$
Enumeration<IProject> keys = fProjectClasspaths.keys();
while (keys.hasMoreElements()) {
IProject project = keys.nextElement();
IClasspathEntry[] classpath = fProjectClasspaths.get(project);
monitor.subTask(project.getName());
JavaCore.create(project).setRawClasspath(classpath, new SubProgressMonitor(monitor, 1));
}
} finally {
monitor.done();
}
}
/**
* 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 instructions instructions for how to import from repository
* @param monitor progress monitor
* @throws CoreException if a problem occurs while importing a plugin
*/
private void importPlugin(IPluginModelBase model, int importType, IProgressMonitor monitor) throws CoreException {
try {
monitor.beginTask("", 5); //$NON-NLS-1$
// Create the project or ask to overwrite if project exists
IProject project = createProject(model, new SubProgressMonitor(monitor, 1));
if (project == null) {
return;
}
// Target Weaving: if we are importing plug-ins in the runtime workbench from the host workbench, import everything as-is and return
// Target weaving will also break things when importing from a non-default target because the dev.properties changes the libraries to 'bin/' see bug 294005
if (Platform.inDevelopmentMode()) {
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()) {
PluginImportHelper.importContent(location, project.getFullPath(), FileSystemStructureProvider.INSTANCE, null, new SubProgressMonitor(monitor, 4));
return;
}
}
}
// Perform the import
Map<String, IPath> sourceMap = null;
if (importType == IMPORT_BINARY || (importType == IMPORT_WITH_SOURCE && !canFindSource(model))) {
sourceMap = importAsBinary(project, model, new SubProgressMonitor(monitor, 4));
} else if (importType == IMPORT_BINARY_WITH_LINKS) {
sourceMap = importAsBinaryWithLinks(project, model, new SubProgressMonitor(monitor, 4));
} else if (importType == IMPORT_WITH_SOURCE) {
importAsSource(project, model, new SubProgressMonitor(monitor, 4));
}
setProjectNatures(project, model);
// Set the classpath
if (project.hasNature(JavaCore.NATURE_ID) && project.findMember(".classpath") == null) //$NON-NLS-1$
fProjectClasspaths.put(project, ClasspathComputer.getClasspath(project, model, sourceMap, true, false));
} finally {
monitor.done();
}
}
/**
* 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 monitor progress monitor
* @return a mapping of libraries to source locations to use in the classpath
* @throws CoreException if there is a problem completing the import
*/
private Map<String, IPath> importAsBinary(IProject project, IPluginModelBase model, IProgressMonitor monitor) throws CoreException {
try {
monitor.beginTask("", 4); //$NON-NLS-1$
// Import the plug-in content
File srcFile = new File(model.getInstallLocation());
if (isJARd(model)) {
PluginImportHelper.copyArchive(srcFile, project.getFile(srcFile.getName()), new SubProgressMonitor(monitor, 1));
} else {
PluginImportHelper.importContent(new File(model.getInstallLocation()), project.getFullPath(), FileSystemStructureProvider.INSTANCE, null, new SubProgressMonitor(monitor, 1));
}
// Import source from known source locations
Map<String, IPath> sourceMap = importSourceArchives(project, model, IMPORT_BINARY, new SubProgressMonitor(monitor, 1));
// Import additional source files such as schema files for easy access, see bug 139161
importAdditionalSourceFiles(project, model, new SubProgressMonitor(monitor, 1));
// Extract the required bundle files and modify the imported manifest to have the correct classpath
importRequiredPluginFiles(project, model, new SubProgressMonitor(monitor, 1));
modifyBundleClasspathHeader(project, model);
// Mark the project as binary
RepositoryProvider.map(project, PDECore.BINARY_REPOSITORY_PROVIDER);
project.setPersistentProperty(PDECore.EXTERNAL_PROJECT_PROPERTY, PDECore.BINARY_PROJECT_VALUE);
return sourceMap;
} finally {
monitor.done();
}
}
/**
* Creates links to remote plugin and source locations and sets up the project
* @param project destination project of the import
* @param model model representing the plugin to import
* @param monitor progress monitor
* @return mapping of library name to path to source library (relative to project)
* @throws CoreException if there is a problem completing the import
*/
private Map<String, IPath> importAsBinaryWithLinks(IProject project, IPluginModelBase model, IProgressMonitor monitor) throws CoreException {
try {
monitor.beginTask("", 3); //$NON-NLS-1$
// Link the plug-in content
File srcFile = new File(model.getInstallLocation());
if (srcFile.isFile()) {
IFile dstFile = project.getFile(new Path(srcFile.getName()));
dstFile.createLink(srcFile.toURI(), IResource.NONE, new SubProgressMonitor(monitor, 1));
} else {
IFolder dstFile = project.getFolder(new Path(srcFile.getName()));
dstFile.createLink(srcFile.toURI(), IResource.NONE, new SubProgressMonitor(monitor, 1));
}
// Link source from known source locations
Map<String, IPath> sourceMap = importSourceArchives(project, model, IMPORT_BINARY_WITH_LINKS, new SubProgressMonitor(monitor, 1));
// Import additional source files such as schema files for easy access, see bug 139161
importAdditionalSourceFiles(project, model, new SubProgressMonitor(monitor, 1));
// Extract the required bundle files and modify the imported manifest to have the correct classpath
importRequiredPluginFiles(project, model, new SubProgressMonitor(monitor, 1));
modifyBundleClasspathHeader(project, model);
// Mark the project as binary
RepositoryProvider.map(project, PDECore.BINARY_REPOSITORY_PROVIDER);
project.setPersistentProperty(PDECore.EXTERNAL_PROJECT_PROPERTY, PDECore.BINARY_PROJECT_VALUE);
return sourceMap;
} finally {
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 {
try {
monitor.beginTask("", 4); //$NON-NLS-1$
// Extract the source, track build entries and package locations
WorkspaceBuildModel buildModel = new WorkspaceBuildModel(PDEProject.getBuildProperties(project));
Map<IPath, IPath> packageLocations = new HashMap<>(); // maps package path to a src folder
boolean sourceFound = extractSourceFolders(project, model, buildModel, packageLocations, new SubProgressMonitor(monitor, 1));
// If no source was found previously, check if there was a source folder (src) inside the binary plug-in
if (!sourceFound) {
sourceFound = handleInternalSource(model, buildModel, packageLocations);
}
// Extract additional non-java files from the source bundles
importAdditionalSourceFiles(project, model, new SubProgressMonitor(monitor, 1));
// Extract the binary plug-in (for non-class files)
// Use the package locations map to put files that belong in the package directory structure into the proper source directory
if (isJARd(model)) {
ZipFile zip = null;
try {
zip = new ZipFile(new File(model.getInstallLocation()));
ZipFileStructureProvider provider = new ZipFileStructureProvider(zip);
Map<IPath, List<Object>> collected = new HashMap<>();
PluginImportHelper.collectBinaryFiles(provider, provider.getRoot(), packageLocations, collected);
for (Iterator<IPath> iterator = collected.keySet().iterator(); iterator.hasNext();) {
IPath currentDestination = iterator.next();
IPath destination = project.getFullPath();
destination = destination.append(currentDestination);
PluginImportHelper.importContent(provider.getRoot(), destination, provider, collected.get(currentDestination), new NullProgressMonitor());
}
} finally {
if (zip != null) {
zip.close();
}
}
monitor.worked(1);
} else {
Map<IPath, List<Object>> collected = new HashMap<>();
File srcFile = new File(model.getInstallLocation());
PluginImportHelper.collectBinaryFiles(FileSystemStructureProvider.INSTANCE, srcFile, packageLocations, collected);
for (Iterator<IPath> iterator = collected.keySet().iterator(); iterator.hasNext();) {
IPath currentDestination = iterator.next();
IPath destination = project.getFullPath();
destination = destination.append(currentDestination);
PluginImportHelper.importContent(srcFile, destination, FileSystemStructureProvider.INSTANCE, collected.get(currentDestination), new NullProgressMonitor());
}
monitor.worked(1);
}
// If the source bundle had a pre-configured build.properties file, do not overwrite with the generated file (Bug 391801)
if (!PDEProject.getBuildProperties(project).exists()) {
configureBinIncludes(buildModel, model, project);
buildModel.save();
}
monitor.worked(1);
} catch (ZipException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
} finally {
monitor.done();
}
}
/**
* Creates the project to add to the workspace. If the project already exists in
* the workspace ask the user if it is ok to overwrite. Will return <code>null</code>
* if no project could be created for the import (i.e. the user chooses to not overwrite).
*
* @param model plug-in being imported
* @param monitor progress monitor
* @return the project to use or <code>null</code> if no project could be created/overwritten
* @throws TeamException if an existing project is shared and an error occurs disconnecting it
* @throws CoreException if an error occurs when working with the project
*/
private IProject createProject(IPluginModelBase model, IProgressMonitor monitor) throws TeamException, CoreException {
try {
monitor.beginTask("", 2); //$NON-NLS-1$
IProject project = findProject(model.getPluginBase().getId());
if (project.exists() || new File(project.getParent().getLocation().toFile(), project.getName()).exists()) {
project = PDEPlugin.getWorkspace().getRoot().getProject(model.getPluginBase().getId());
if (project.exists()) {
File installLocation = new File(model.getInstallLocation());
String projectName = installLocation.getName();
int jarIndex = projectName.toLowerCase().lastIndexOf(".jar"); //$NON-NLS-1$
if (jarIndex >= 0) {
projectName = projectName.substring(0, jarIndex);
}
project = PDEPlugin.getWorkspace().getRoot().getProject(projectName);
int index = 0;
while (project.exists() == true) {
index++;
project = PDEPlugin.getWorkspace().getRoot().getProject(projectName + '_' + index);
}
}
}
project.create(monitor);
if (!project.isOpen())
project.open(monitor);
// If we know that a previous project of the same name belonged to one or more working sets, add the new project to them
List<IWorkingSet> workingSets = fProjectWorkingSets.get(project.getName());
if (workingSets != null) {
for (Iterator<IWorkingSet> iterator = workingSets.iterator(); iterator.hasNext();) {
IWorkingSet ws = iterator.next();
IAdaptable newElement = project;
IAdaptable[] projectAdaptables = ws.adaptElements(new IAdaptable[] {project});
if (projectAdaptables.length > 0) {
newElement = projectAdaptables[0];
}
IAdaptable[] currentElements = ws.getElements();
IAdaptable[] newElements = new IAdaptable[currentElements.length + 1];
System.arraycopy(currentElements, 0, newElements, 0, currentElements.length);
newElements[currentElements.length] = newElement;
ws.setElements(newElements);
}
}
monitor.worked(1);
return project;
} finally {
monitor.done();
}
}
private IProject findProject(String id) {
IPluginModelBase model = PluginRegistry.findModel(id);
if (model != null) {
IResource resource = model.getUnderlyingResource();
if (resource != null && resource.exists()) {
return resource.getProject();
}
}
return PDEPlugin.getWorkspace().getRoot().getProject(id);
}
/**
* 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.
*
* @param project project to test
* @param monitor progress monitor
* @return true is it is safe to delete the project, false otherwise
*/
private boolean safeDeleteCheck(IProject project, IProgressMonitor monitor) {
if (!fPluginsAreInUse)
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;
}
/**
* Checks if we have a source location for the given model
* @param model model to lookup source for
* @return true if source was found for at least one library, false otherwise
*/
private boolean canFindSource(IPluginModelBase model) {
// Check the manager(s) for source
if (getSourceManager(model) != null) {
return true;
}
// Check for source inside the binary plug-in
ZipFile zip = null;
try {
IImportStructureProvider provider;
Object root;
if (isJARd(model)) {
zip = new ZipFile(new File(model.getInstallLocation()));
provider = new ZipFileStructureProvider(zip);
root = ((ZipFileStructureProvider) provider).getRoot();
} else {
provider = FileSystemStructureProvider.INSTANCE;
root = new File(model.getInstallLocation());
}
List<?> children = provider.getChildren(root);
for (Iterator<?> iterator = children.iterator(); iterator.hasNext();) {
String label = provider.getLabel(iterator.next());
if (label.equals(DEFAULT_SOURCE_DIR)) {
return true;
}
}
} catch (IOException e) {
// Do nothing, any other problems will be caught during binary import
} finally {
if (zip != null) {
try {
zip.close();
} catch (IOException e) {
}
}
}
return false;
}
/**
* Should be used inside this class rather than PDEPlugin.getSourceLocationManager as it checks if the alternate
* source manager has source for the given plug-in. The alternate source manager is set if we are importing from
* a location other than the active target platform. In that case we want to use source from the import location
* if available. If this method returns <code>null</code> no seperate source feature/bundle could be found. There
* may still be source stored internally in the plug-in.
*
* @return the most relevant source manager than contains source for the plug-in or <code>null</code> if no separate source could be found
*/
private SourceLocationManager getSourceManager(IPluginModelBase model) {
// Check the alternate source manager first
if (fAlternateSource != null) {
// Check for a source bundle
if (fAlternateSource.hasBundleManifestLocation(model.getPluginBase())) {
return fAlternateSource;
}
// Check for an old style source plug-in
String[] libraries = getLibraryNames(model);
for (int i = 0; i < libraries.length; i++) {
String zipName = ClasspathUtilCore.getSourceZipName(libraries[i]);
IPath srcPath = fAlternateSource.findSourcePath(model.getPluginBase(), new Path(zipName));
if (srcPath != null) {
return fAlternateSource;
}
}
}
// Check the pde default source manager second
SourceLocationManager manager = PDECore.getDefault().getSourceLocationManager();
// Check for a source bundle
if (manager.hasBundleManifestLocation(model.getPluginBase())) {
return manager;
}
// Check for an old style source plug-in
String[] libraries = getLibraryNames(model);
for (int i = 0; i < libraries.length; i++) {
String zipName = ClasspathUtilCore.getSourceZipName(libraries[i]);
IPath srcPath = manager.findSourcePath(model.getPluginBase(), new Path(zipName));
if (srcPath != null) {
return manager;
}
}
return null;
}
/**
* Starts a job that will build the workspace
*/
private void runBuildJob() {
Job buildJob = new Job(PDEUIMessages.CompilersConfigurationBlock_building) {
@Override
public boolean belongsTo(Object family) {
return ResourcesPlugin.FAMILY_AUTO_BUILD == family;
}
@Override
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();
}
/**
* Imports the source archives required by the project either by copying or linking, based on the mode
* constant that is passed to the method (IMPORT_BINARY or IMPORT_BINARY_WITH_LINKS).
* @param project project destination
* @param model model we are importing
* @param mode either IMPORT_BINARY (copies source) or MPORT_BINARY_WITH_LINKS (links source)
* @param monitor progress monitor
* @return mapping of library name to the source location
* @throws CoreException if there are problems importing an archive
*/
private Map<String, IPath> importSourceArchives(IProject project, IPluginModelBase model, int mode, IProgressMonitor monitor) throws CoreException {
String[] libraries = getLibraryNames(model);
try {
monitor.beginTask(PDEUIMessages.ImportWizard_operation_importingSource, libraries.length);
Map<String, IPath> sourceMap = new HashMap<>(libraries.length);
SourceLocationManager manager = getSourceManager(model);
if (manager != null) {
for (int i = 0; i < libraries.length; i++) {
String zipName = ClasspathUtilCore.getSourceZipName(libraries[i]);
IPluginBase pluginBase = model.getPluginBase();
// check default locations
IPath srcPath = manager.findSourcePath(pluginBase, new Path(zipName));
if (srcPath != null) {
zipName = srcPath.lastSegment();
IPath dstPath = new Path(zipName);
sourceMap.put(libraries[i], dstPath);
if (project.findMember(dstPath) == null) {
if (mode == IMPORT_BINARY) {
PluginImportHelper.copyArchive(new File(srcPath.toOSString()), project.getFile(dstPath), new SubProgressMonitor(monitor, 1));
} else if (mode == IMPORT_BINARY_WITH_LINKS) {
IFile dstFile = project.getFile(dstPath);
dstFile.createLink(srcPath, IResource.NONE, new SubProgressMonitor(monitor, 1));
}
}
}
}
}
return sourceMap;
} finally {
monitor.done();
}
}
/**
* Looks up the source locations for the plug-in and imports the source for each library. Each source root is
* extracted to a source folder in the project and a build model containing the source entries is returned.
*
* @param project destination project
* @param model plug-in being imported
* @param buildModel a workspace build model that entries for each created source folder will be added to
* @param packageLocations map that will be updated with package locations (package path to a source foldeR)
* @param monitor progress monitor
* @return whether a source location was found
* @throws CoreException if there is a problem extracting the source or creating a build entry
*/
private boolean extractSourceFolders(IProject project, IPluginModelBase model, WorkspaceBuildModel buildModel, Map<IPath, IPath> packageLocations, IProgressMonitor monitor) throws CoreException {
try {
String[] libraries = getLibraryNames(model);
monitor.beginTask(PDEUIMessages.ImportWizard_operation_importingSource, libraries.length);
SourceLocationManager manager = getSourceManager(model);
if (manager != null) {
// Check if we have new style individual source bundles
if (manager.hasBundleManifestLocation(model.getPluginBase())) {
File srcFile = manager.findSourcePlugin(model.getPluginBase());
Set<String> sourceRoots = manager.findSourceRoots(model.getPluginBase());
for (int i = 0; i < libraries.length; i++) {
if (libraries[i].equals(DEFAULT_LIBRARY_NAME)) {
// Need to pull out any java source that is not in another source root
IResource destination = project.getFolder(DEFAULT_SOURCE_DIR);
if (!destination.exists()) {
List<IPath> excludeFolders = new ArrayList<>(sourceRoots.size());
for (Iterator<String> iterator = sourceRoots.iterator(); iterator.hasNext();) {
String root = iterator.next();
if (!root.equals(DEFAULT_LIBRARY_NAME)) {
excludeFolders.add(new Path(root));
}
}
Set<IPath> collectedPackages = new HashSet<>();
PluginImportHelper.extractJavaSourceFromArchive(srcFile, excludeFolders, destination.getFullPath(), collectedPackages, new SubProgressMonitor(monitor, 1));
addBuildEntry(buildModel, "source." + DEFAULT_LIBRARY_NAME, DEFAULT_SOURCE_DIR + "/"); //$NON-NLS-1$ //$NON-NLS-2$
addPackageEntries(collectedPackages, new Path(DEFAULT_SOURCE_DIR), packageLocations);
}
} else if (sourceRoots.contains(getSourceDirName(libraries[i]))) {
IPath sourceDir = new Path(getSourceDirName(libraries[i]));
if (!project.getFolder(sourceDir).exists()) {
Set<IPath> collectedPackages = new HashSet<>();
PluginImportHelper.extractFolderFromArchive(srcFile, sourceDir, project.getFullPath(), collectedPackages, new SubProgressMonitor(monitor, 1));
addBuildEntry(buildModel, "source." + libraries[i], sourceDir.toString()); //$NON-NLS-1$
addPackageEntries(collectedPackages, sourceDir, packageLocations);
}
}
}
return true;
}
// Old style, zips in folders, determine the source zip name/location and extract it to the project
boolean sourceFound = false;
for (int i = 0; i < libraries.length; i++) {
String zipName = ClasspathUtilCore.getSourceZipName(libraries[i]);
IPath srcPath = manager.findSourcePath(model.getPluginBase(), new Path(zipName));
if (srcPath != null) {
sourceFound = true;
IPath dstPath = new Path(getSourceDirName(libraries[i]));
IResource destination = project.getFolder(dstPath);
if (!destination.exists()) {
Set<IPath> collectedPackages = new HashSet<>();
PluginImportHelper.extractArchive(new File(srcPath.toOSString()), destination.getFullPath(), collectedPackages, new SubProgressMonitor(monitor, 1));
addBuildEntry(buildModel, "source." + libraries[i], dstPath.toString()); //$NON-NLS-1$
addPackageEntries(collectedPackages, dstPath, packageLocations);
}
}
}
return sourceFound;
}
} finally {
monitor.done();
}
return false;
}
/**
* Looks inside the binary plug-in to see if source was packaged inside of a 'src' directory. If found, the build model and
* package locations are updated with the appropriate information. This method does not actually import the source as
* that is handled when the binary plug-in is extracted.
*
* @param model plug-in model being imported
* @param buildModel build model to update if source is found
* @param packageLocations package location map (package path to destination) to update if source is found
* @return true if source was found inside the binary plug-in, false otherwise
*
* @throws CoreException
* @throws ZipException
* @throws IOException
*/
private boolean handleInternalSource(IPluginModelBase model, WorkspaceBuildModel buildModel, Map<IPath, IPath> packageLocations) throws CoreException, ZipException, IOException {
IImportStructureProvider provider;
Object root;
IPath prefixPath;
IPath defaultSourcePath = new Path(DEFAULT_SOURCE_DIR);
ZipFile zip = null;
try {
if (isJARd(model)) {
zip = new ZipFile(new File(model.getInstallLocation()));
provider = new ZipFileStructureProvider(zip);
root = ((ZipFileStructureProvider) provider).getRoot();
prefixPath = defaultSourcePath;
} else {
provider = FileSystemStructureProvider.INSTANCE;
File rootFile = new File(model.getInstallLocation());
root = rootFile;
prefixPath = new Path(rootFile.getPath()).append(defaultSourcePath);
}
ArrayList<Object> collected = new ArrayList<>();
PluginImportHelper.collectResourcesFromFolder(provider, root, defaultSourcePath, collected);
if (collected.size() > 0) {
Set<IPath> packages = new HashSet<>();
PluginImportHelper.collectJavaPackages(provider, collected, prefixPath, packages);
addPackageEntries(packages, defaultSourcePath, packageLocations);
addBuildEntry(buildModel, "source." + DEFAULT_LIBRARY_NAME, DEFAULT_SOURCE_DIR + "/"); //$NON-NLS-1$ //$NON-NLS-2$
return true;
}
return false;
} finally {
if (zip != null) {
zip.close();
}
}
}
/**
* Adds a set of packages to the package location map. For each package in the given set
* an entry will be added to the map pointing to the destination. In additional, any parent
* package fragments that do not have entries in the map will be added (also pointing to the
* destination path).
*
* @param packages set of packages to add to the map
* @param destination the destination directory that the packages belong to
* @param packageLocations the map to add the entries to
*/
private void addPackageEntries(Set<IPath> packages, IPath destination, Map<IPath, IPath> packageLocations) {
for (Iterator<IPath> iterator = packages.iterator(); iterator.hasNext();) {
IPath currentPackage = iterator.next();
packageLocations.put(currentPackage, destination);
// Add package fragment locations
while (currentPackage.segmentCount() > 1) {
currentPackage = currentPackage.removeLastSegments(1);
if (packageLocations.containsKey(currentPackage)) {
break; // Don't overwrite existing entries, we assume that if one parent has an entry, all further parents already have an entry
}
packageLocations.put(currentPackage, destination);
}
}
}
/**
* Extracts any additional files and folders that exist in the source location
* @param project the destination project
* @param model the plugin being imported
* @param monitor progress monitor
* @throws CoreException is there is a problem importing the files
*/
private void importAdditionalSourceFiles(IProject project, IPluginModelBase model, SubProgressMonitor monitor) throws CoreException {
SourceLocationManager manager = getSourceManager(model);
if (manager != null) {
File sourceLocation = manager.findSourcePlugin(model.getPluginBase());
if (sourceLocation != null) {
if (sourceLocation.isFile()) {
ZipFile zip = null;
try {
zip = new ZipFile(sourceLocation);
ZipFileStructureProvider provider = new ZipFileStructureProvider(zip);
ArrayList<Object> collected = new ArrayList<>();
PluginImportHelper.collectNonJavaNonBuildFiles(provider, provider.getRoot(), collected);
PluginImportHelper.importContent(provider.getRoot(), project.getFullPath(), provider, collected, monitor);
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
} finally {
if (zip != null) {
try {
zip.close();
} catch (IOException e) {
}
}
}
} else {
ArrayList<Object> collected = new ArrayList<>();
PluginImportHelper.collectNonJavaNonBuildFiles(FileSystemStructureProvider.INSTANCE, sourceLocation, collected);
PluginImportHelper.importContent(sourceLocation, project.getFullPath(), FileSystemStructureProvider.INSTANCE, collected, monitor);
}
}
}
}
/**
* Imports files from the plug-in that are necessary to make the created project a plug-in project.
* Specifically the manifest and related file are extracted.
* @param project
* @param model
* @param monitor
* @throws CoreException if there is a problem importing the content
*/
private void importRequiredPluginFiles(IProject project, IPluginModelBase model, IProgressMonitor monitor) throws CoreException {
if (isJARd(model)) {
ZipFile zip = null;
try {
zip = new ZipFile(new File(model.getInstallLocation()));
ZipFileStructureProvider provider = new ZipFileStructureProvider(zip);
ArrayList<Object> collected = new ArrayList<>();
PluginImportHelper.collectRequiredBundleFiles(provider, provider.getRoot(), collected);
PluginImportHelper.importContent(provider.getRoot(), project.getFullPath(), provider, collected, monitor);
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
} finally {
if (zip != null) {
try {
zip.close();
} catch (IOException e) {
}
}
}
} else {
ArrayList<Object> collected = new ArrayList<>();
File file = new File(model.getInstallLocation());
PluginImportHelper.collectRequiredBundleFiles(FileSystemStructureProvider.INSTANCE, file, collected);
PluginImportHelper.importContent(file, project.getFullPath(), FileSystemStructureProvider.INSTANCE, collected, monitor);
}
}
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$
}
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<String, String> 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 = PluginImportHelper.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<String, String> getSourceDirectories(IBuild build) {
HashMap<String, String> 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;
}
/**
* Creates a model for an existing manifest file, replacing the classpath entry with the
* new location of the referenced library. Also removes any extra entries such as signing
* headers.
* @param project
* @param base
*/
private void modifyBundleClasspathHeader(IProject project, IPluginModelBase base) {
IFile file = PDEProject.getManifest(project);
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 boolean needsJavaNature(IProject project, IPluginModelBase model) {
// If there are class libraries we need a java nature
if (model.getPluginBase().getLibraries().length > 0)
return true;
// If the plug-in exports packages or requires an execution environment it has java code
BundleDescription desc = model.getBundleDescription();
if (desc != null) {
if (desc.getExecutionEnvironments().length > 0)
return true;
if (desc.getExportPackages().length > 0)
return true;
}
// If the build.properties file has a default source folder we need a java nature
IFile buildProperties = PDEProject.getBuildProperties(project);
if (buildProperties.exists()) {
WorkspaceBuildModel buildModel = new WorkspaceBuildModel(buildProperties);
buildModel.load();
IBuild build = buildModel.getBuild();
if (build != null) {
IBuildEntry buildEntry = build.getEntry("source.."); //$NON-NLS-1$
if (buildEntry != null) {
return true;
}
}
}
return false;
}
private void setProjectNatures(IProject project, IPluginModelBase model) throws CoreException {
IProjectDescription desc = project.getDescription();
if (!desc.hasNature(PDE.PLUGIN_NATURE)) {
CoreUtility.addNatureToProject(project, PDE.PLUGIN_NATURE, null);
}
if (!desc.hasNature(JavaCore.NATURE_ID) && needsJavaNature(project, model)) {
CoreUtility.addNatureToProject(project, JavaCore.NATURE_ID, null);
}
}
/**
* Gets the list of libraries from the model and returns an array of their expanded
* names. Will add the default library name if no libraries are specified.
*
* <p>If run in dev mode (target workbench), and the plug-in is in the host workspace
* the library names will be replaced with 'bin/'. See bug 294005.</p>
*
* @param model
* @return list of library names
*/
private String[] getLibraryNames(IPluginModelBase model) {
IPluginLibrary[] libraries = model.getPluginBase().getLibraries();
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < libraries.length; i++) {
list.add(ClasspathUtilCore.expandLibraryName(libraries[i].getName()));
}
if (libraries.length == 0 && isJARd(model))
list.add(DEFAULT_LIBRARY_NAME);
return list.toArray(new String[list.size()]);
}
/**
* Returns the standard source directory name for a library name.
* Used to get the source root name for a library as well as the
* standard destination name.
* @param libraryName
* @return source dir name
*/
private String getSourceDirName(String libraryName) {
int dot = libraryName.lastIndexOf('.');
return (dot != -1) ? libraryName.substring(0, dot) + DEFAULT_SOURCE_DIR : libraryName;
}
/**
* Returns whether the install location of the plug-in is a jar file or a folder
* @param model
* @return true if the install location is a jar, false if it is a folder
*/
private boolean isJARd(IPluginModelBase model) {
return new File(model.getInstallLocation()).isFile();
}
/**
* Sets the import descriptions to use when importing from a repository.
*
* @param descriptions map of {@link IBundleImporter} to arrays of {@link BundleImportDescription}.
*/
public void setImportDescriptions(Map<IBundleImporter, ScmUrlImportDescription[]> descriptions) {
fImportDescriptions = descriptions;
}
}