/*******************************************************************************
* 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.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
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.Messages;
import org.eclipse.buckminster.pde.PDEPlugin;
import org.eclipse.buckminster.pde.internal.EclipseImportReaderType;
import org.eclipse.buckminster.pde.internal.datatransfer.FileSystemStructureProvider;
import org.eclipse.buckminster.pde.internal.datatransfer.ZipFileStructureProvider;
import org.eclipse.buckminster.runtime.BuckminsterException;
import org.eclipse.buckminster.runtime.MonitorUtils;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.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.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
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.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.IFragment;
import org.eclipse.pde.core.plugin.IFragmentModel;
import org.eclipse.pde.core.plugin.IPluginLibrary;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.plugin.ModelEntry;
import org.eclipse.pde.internal.core.ClasspathComputer;
import org.eclipse.pde.internal.core.ClasspathUtilCore;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.SourceLocationManager;
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.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.osgi.framework.BundleException;
@SuppressWarnings("restriction")
public class PluginImportOperation extends JarImportOperation {
public static final int IMPORT_UNKNOWN = 0;
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 static final Method ClasspathComputer_getClasspath;
private static final boolean ClasspathComputer_is35;
private static final String GET_CLASSPATH = "getClasspath"; //$NON-NLS-1$
static {
Method getClasspath;
boolean is35 = false;
try {
getClasspath = ClasspathComputer.class.getDeclaredMethod(GET_CLASSPATH, IProject.class, IPluginModelBase.class, Map.class, boolean.class,
boolean.class);
is35 = true;
} catch (NoSuchMethodException e) {
try {
getClasspath = ClasspathComputer.class.getDeclaredMethod(GET_CLASSPATH, IProject.class, IPluginModelBase.class, boolean.class,
boolean.class);
} catch (NoSuchMethodException e1) {
throw new ExceptionInInitializerError(e);
}
} catch (SecurityException e) {
throw new ExceptionInInitializerError(e);
}
ClasspathComputer_getClasspath = getClasspath;
ClasspathComputer_is35 = is35;
}
public static void setClasspaths(IProgressMonitor monitor, Map<IProject, IClasspathEntry[]> classpaths) throws JavaModelException {
MonitorUtils.begin(monitor, classpaths.size());
try {
for (Map.Entry<IProject, IClasspathEntry[]> entry : classpaths.entrySet()) {
IClasspathEntry[] classpath = entry.getValue();
if (classpath != null)
JavaCore.create(entry.getKey()).setRawClasspath(classpath, MonitorUtils.subMonitor(monitor, 1));
}
} finally {
MonitorUtils.done(monitor);
}
}
private IProject project;
private EclipseImportReaderType classpathCollector;
private final IPath destination;
private final int importType;
private final IPluginModelBase model;
private final NodeQuery query;
public PluginImportOperation(IPluginModelBase model, NodeQuery query, IPath destination, int importType) {
this.model = model;
this.query = query;
this.importType = importType;
this.destination = destination;
}
/**
* 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 monitor
* progress monitor
* @throws CoreException
* if a problem occurs while importing a plugin
*/
public void importPlugin(IProgressMonitor monitor) throws CoreException {
MaterializationContext context = (MaterializationContext) query.getContext();
ComponentRequest request = query.getComponentRequest();
String projectName = request.getProjectName();
String id = model.getPluginBase().getId();
MonitorUtils.begin(monitor, NLS.bind(Messages.importing_plugin_0, id), 7);
try {
ConflictResolution conflictResolution = context.getMaterializationSpec().getConflictResolution(
WorkspaceInfo.getResolution(request, false));
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) {
// TODO: There's a misfit in execution environment. The
// AdvisorNode should have
// a way
// to handle this.
PDEPlugin.getLogger().info(NLS.bind(Messages.execution_env_misfit_skipping_plugin_0, id));
return;
}
}
IProject destProject = findProject(projectName);
if (destProject.exists()) {
switch (conflictResolution) {
case FAIL:
throw BuckminsterException.fromMessage(NLS.bind(Messages.project_0_already_exists, projectName));
case KEEP:
return;
default:
}
if (RepositoryProvider.isShared(destProject))
RepositoryProvider.unmap(destProject);
if (!destProject.exists())
destProject.create(MonitorUtils.subMonitor(monitor, 1));
destProject.delete(true, true, MonitorUtils.subMonitor(monitor, 1));
} else
MonitorUtils.worked(monitor, 1);
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IProjectDescription description = workspace.newProjectDescription(projectName);
FileUtils.prepareDestination(destination.toFile(), conflictResolution, MonitorUtils.subMonitor(monitor, 1));
if (!workspace.getRoot().getLocation().equals(destination.removeLastSegments(1)))
description.setLocation(destination);
destProject.create(description, MonitorUtils.subMonitor(monitor, 1));
destProject.open(MonitorUtils.subMonitor(monitor, 1));
project = destProject;
IProgressMonitor importMonitor = MonitorUtils.subMonitor(monitor, 4);
switch (importType) {
case IMPORT_BINARY:
importAsBinary(true, importMonitor);
break;
case IMPORT_BINARY_WITH_LINKS:
if (id.startsWith("org.eclipse.swt") && !isJARd()) //$NON-NLS-1$
importAsBinary(true, importMonitor);
else
importAsBinaryWithLinks(importMonitor);
break;
case IMPORT_WITH_SOURCE:
if (isExempt())
importAsBinary(true, importMonitor);
else
importAsSource(importMonitor);
}
setProjectDescription();
if (classpathCollector != null) {
if (project.hasNature(JavaCore.NATURE_ID) && project.findMember(".classpath") == null) //$NON-NLS-1$
classpathCollector.addProjectClasspath(project, getClasspath());
}
project.delete(false, true, MonitorUtils.subMonitor(monitor, 100));
} finally {
monitor.done();
}
}
@Override
public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
importPlugin(monitor);
MonitorUtils.testCancelStatus(monitor);
}
public void setClasspathCollector(EclipseImportReaderType classpathCollector) {
this.classpathCollector = classpathCollector;
}
protected void collectAdditionalResources(ZipFileStructureProvider provider, Object element, ArrayList<ZipEntry> collected, IProject p) {
collectAdditionalResources(provider, element, collected);
ListIterator<ZipEntry> li = collected.listIterator();
while (li.hasNext()) {
ZipEntry ze = li.next();
String name = ze.getName();
// only import the entries that don't already exist
if (p.findMember(name) != null) {
li.remove();
}
}
}
@SuppressWarnings("rawtypes")
@Override
protected void collectNonJavaResources(ZipFileStructureProvider provider, Object element, ArrayList collected) {
super.collectNonJavaResources(provider, element, collected);
// 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();
else if (importType == IMPORT_BINARY) {
if ("build.properties".equals(ze.getName())) //$NON-NLS-1$
li.remove();
}
}
}
private String addBuildEntry(WorkspaceBuildModel buildModel, String key, String value) throws CoreException {
IBuild build = buildModel.getBuild(true);
IBuildEntry entry = build.getEntry(key);
if (entry == null) {
entry = buildModel.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) 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 = 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 void configureSrcIncludes(WorkspaceBuildModel buildModel, List<String> 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));
buildModel.getBuild().add(entry);
}
}
private void extractJARdPlugin(IProgressMonitor monitor) throws CoreException {
try {
ZipFile zipFile = new ZipFile(model.getInstallLocation());
try {
ZipFileStructureProvider provider = new ZipFileStructureProvider(zipFile);
if (!containsCode(provider)) {
extractZipFile(new File(model.getInstallLocation()), project.getFullPath(), monitor);
return;
}
ArrayList<?> collected = new ArrayList<Object>();
collectNonJavaResources(provider, provider.getRoot(), collected);
importContent(provider.getRoot(), project.getFullPath(), provider, collected, monitor);
File file = new File(model.getInstallLocation());
if (hasEmbeddedSource(provider) && importType == IMPORT_WITH_SOURCE) {
collected = new ArrayList<Object>();
collectJavaFiles(provider, provider.getRoot(), collected);
importContent(provider.getRoot(), project.getFullPath(), provider, collected, monitor);
collected = new ArrayList<Object>();
collectJavaResources(provider, provider.getRoot(), collected);
importContent(provider.getRoot(), project.getFullPath().append("src"), provider, collected, monitor); //$NON-NLS-1$
} else {
if (importType == 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 (importType == IMPORT_BINARY_WITH_LINKS) {
linkSourceArchives(new SubProgressMonitor(monitor, 1));
} else {
importSourceArchives(new SubProgressMonitor(monitor, 1));
}
}
}
if (importType != IMPORT_WITH_SOURCE) {
modifyBundleClasspathHeader(model);
} else {
removeSignedHeaders();
}
setPermissions();
} finally {
zipFile.close();
}
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
}
}
private IProject findProject(String id) {
ModelEntry entry = PDECore.getDefault().getModelManager().findEntry(id);
if (entry != null) {
IPluginModelBase pluginModel = entry.getModel();
if (pluginModel != null) {
IResource resource = pluginModel.getUnderlyingResource();
if (resource != null)
return resource.getProject();
}
}
return ResourcesPlugin.getWorkspace().getRoot().getProject(id);
}
private IClasspathEntry[] getClasspath() throws CoreException {
try {
return (IClasspathEntry[]) (ClasspathComputer_is35 ? ClasspathComputer_getClasspath.invoke(null, project, model, null, Boolean.TRUE,
Boolean.FALSE) : ClasspathComputer_getClasspath.invoke(null, project, model, Boolean.TRUE, Boolean.FALSE));
} catch (Exception e) {
throw BuckminsterException.wrap(e);
}
}
/**
* 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() {
return new Path(ClasspathUtilCore.getSourceZipName(new File(model.getInstallLocation()).getName()));
}
private IFragment[] getFragmentsFor() {
// TODO: Need different solution for this. What search scope should
// be used when finding fragments?
return new IFragment[0];
}
private String[] getLibraryNames(boolean expand) {
IPluginLibrary[] libraries = model.getPluginBase().getLibraries();
int top = libraries.length;
if (top == 0 && isJARd())
return new String[] { "." }; //$NON-NLS-1$
String[] list = new String[top];
for (int i = 0; i < top; i++) {
list[i] = expand ? ClasspathUtilCore.expandLibraryName(libraries[i].getName()) : libraries[i].getName();
}
return list;
}
private HashMap<String, String> getSourceDirectories(IBuild build) {
HashMap<String, String> set = new HashMap<String, String>();
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;
}
/**
* Searches source locations for files to import to the new project, will
* ignore src.zip.
*
* @param monitor
* @return list of imported files
* @throws CoreException
* if there is a problem completing the import
*/
private List<String> importAdditionalResources(IProgressMonitor monitor) throws CoreException {
SourceLocationManager manager = PDECore.getDefault().getSourceLocationManager();
File location = manager.findSourcePlugin(model.getPluginBase());
if (location != null) {
if (location.isDirectory()) {
ArrayList<File> list = new ArrayList<File>();
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<String> srcEntryList = new ArrayList<String>(list.size());
for (ListIterator<File> iterator = list.listIterator(); iterator.hasNext();) {
File current = iterator.next();
String entry = current.getName();
if (current.isDirectory()) {
entry += "/"; //$NON-NLS-1$
}
srcEntryList.add(entry);
}
return srcEntryList;
}
} else if (location.isFile()) {
ArrayList<ZipEntry> list = new ArrayList<ZipEntry>();
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<String> srcEntryList = new ArrayList<String>(list.size());
for (Iterator<ZipEntry> iterator = list.iterator(); iterator.hasNext();) {
ZipEntry current = 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<String>(0);
}
/**
* Imports the contents of the plugin and imports source files as binary
* files that will not be compiled.
*
* @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(boolean markAsBinary, IProgressMonitor monitor) throws CoreException {
MonitorUtils.begin(monitor, 4);
if (isJARd()) {
extractJARdPlugin(MonitorUtils.subMonitor(monitor, 3));
} else {
importContent(new File(model.getInstallLocation()), project.getFullPath(), FileSystemStructureProvider.INSTANCE, null,
MonitorUtils.subMonitor(monitor, 1));
importSourceArchives(MonitorUtils.subMonitor(monitor, 1));
// make sure all libraries have been imported
// if any are missing, check in fragments
IFragment[] fragments = getFragmentsFor();
IPluginLibrary[] libraries = model.getPluginBase().getLibraries();
IProgressMonitor fragmentMonitor = MonitorUtils.subMonitor(monitor, 1);
MonitorUtils.begin(fragmentMonitor, libraries.length);
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(fragments[j], libraryName);
importSourceFromFragment(fragments[j], libraryName, MonitorUtils.subMonitor(monitor, 1));
}
} else {
MonitorUtils.worked(monitor, 1);
}
}
}
if (markAsBinary) {
project.setPersistentProperty(PDECore.EXTERNAL_PROJECT_PROPERTY, PDECore.BINARY_PROJECT_VALUE);
importAdditionalResources(MonitorUtils.subMonitor(monitor, 1));
} else
MonitorUtils.done(monitor);
}
/**
* Imports the contents of the plugin and adds links to the source
* location(s).
*
* @param monitor
* progress monitor
* @throws CoreException
* if there is a problem completing the import
*/
private void importAsBinaryWithLinks(IProgressMonitor monitor) throws CoreException {
if (isJARd()) {
extractJARdPlugin(monitor);
return;
}
File installLocation = new File(model.getInstallLocation());
File[] items = installLocation.listFiles();
if (items == null)
MonitorUtils.begin(monitor, Messages.linking_imported_plugin, 1);
else {
MonitorUtils.begin(monitor, Messages.linking_imported_plugin, 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, MonitorUtils.subMonitor(monitor, 1));
} else {
if (!name.equals(".project")) //$NON-NLS-1$
{
project.getFile(name).createLink(new Path(sourceFile.getPath()), IResource.NONE, MonitorUtils.subMonitor(monitor, 1));
} else {
// if the binary project with links has a .project file,
// copy it instead
// of linking (allows us to edit it)
ArrayList<File> filesToImport = new ArrayList<File>(1);
filesToImport.add(sourceFile);
importContent(installLocation, project.getFullPath(), FileSystemStructureProvider.INSTANCE, filesToImport,
new SubProgressMonitor(monitor, 1));
}
}
}
}
linkSourceArchives(MonitorUtils.subMonitor(monitor, 1));
MonitorUtils.done(monitor);
try {
RepositoryProvider.map(project, PDECore.BINARY_REPOSITORY_PROVIDER);
} catch (TeamException e) {
}
}
/**
* Imports the contents of the plugin and imports source files to source
* folders that will be compiled.
*
* @param monitor
* progress monitor
* @throws CoreException
* if there is a problem completing the import
*/
private void importAsSource(IProgressMonitor monitor) throws CoreException {
MonitorUtils.begin(monitor, 4);
importAsBinary(false, MonitorUtils.subMonitor(monitor, 2));
List<String> list = importAdditionalResources(MonitorUtils.subMonitor(monitor, 1));
WorkspaceBuildModel buildModel = new WorkspaceBuildModel(project.getFile("build.properties")); //$NON-NLS-1$
if (!isJARd() || containsCode(new File(model.getInstallLocation()))) {
String[] libraries = getLibraryNames(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()) //$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()) //$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()) {
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);
if (list.size() > 0)
configureSrcIncludes(buildModel, list);
buildModel.save();
}
private void importJarFromFragment(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);
}
private void importSourceArchives(IProgressMonitor monitor) throws CoreException {
String[] libraries = getLibraryNames(true);
if (libraries.length == 0)
return;
MonitorUtils.begin(monitor, Messages.copying_source, libraries.length);
SourceLocationManager manager = PDECore.getDefault().getSourceLocationManager();
Set<?> roots = null;
if (manager.hasBundleManifestLocation(model.getPluginBase()))
roots = manager.findSourceRoots(model.getPluginBase());
for (String library : libraries) {
String zipName = ClasspathUtilCore.getSourceZipName(library);
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(library) ? "." : 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();
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<IPath> rootsToExclude = new ArrayList<IPath>(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()) { //$NON-NLS-1$
path = getDefaultSourceNameForProject();
}
importArchive(project, new File(srcPath.toOSString()), path);
}
}
}
monitor.worked(1);
}
monitor.done();
}
private void importSourceFromFragment(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();
}
}
private boolean isExempt() {
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()) //$NON-NLS-1$
return true;
return false;
}
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 boolean isJARd() {
return new File(model.getInstallLocation()).isFile();
}
private void linkSourceArchives(IProgressMonitor monitor) throws CoreException {
String[] libraries = getLibraryNames(true);
monitor.beginTask(Messages.copying_imported_source, 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()) { //$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 modifyBundleClasspathHeader(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();
}
}
/**
* 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<IResource> validFolders = new ArrayList<IResource>();
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<IResource> li = validFolders.listIterator();
while (li.hasNext()) {
IFolder folder = (IFolder) li.next();
int pathSegments = folder.getProjectRelativePath().segmentCount() - 1;
Stack<IResource> stack = new Stack<IResource>();
IResource[] resources = folder.members();
for (int i = 0; i < resources.length; i++)
stack.push(resources[i]);
while (!stack.isEmpty()) {
IResource res = 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) {
}
}
private boolean needsJavaNature() {
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 void removeSignedHeaders() {
IFile file = project.getFile(JarFile.MANIFEST_NAME);
if (!file.exists())
return;
WorkspaceBundleModel bundleModel = new WorkspaceBundleModel(file);
bundleModel.save();
}
private void setPermissions() {
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 void setProjectDescription() throws CoreException {
IProjectDescription desc = project.getDescription();
if (!desc.hasNature(PDE.PLUGIN_NATURE))
CoreUtility.addNatureToProject(project, PDE.PLUGIN_NATURE, null);
if (needsJavaNature() && !desc.hasNature(JavaCore.NATURE_ID))
CoreUtility.addNatureToProject(project, JavaCore.NATURE_ID, null);
}
}