blob: 095b4ece288900bbf82d1ebbd1cfbbca7995ba03 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2015 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
* Code 9 Corporation - ongoing enhancements
* Les Jones <lesojones@gamil.com> - bug 205361
*******************************************************************************/
package org.eclipse.pde.internal.ui.wizards.tools;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.eclipse.pde.core.IBaseModel;
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.WorkspaceBundlePluginModel;
import org.eclipse.pde.internal.core.ibundle.IBundle;
import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
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.core.util.IdUtil;
import org.eclipse.pde.internal.ui.PDEPlugin;
import org.eclipse.pde.internal.ui.PDEUIMessages;
import org.eclipse.pde.internal.ui.util.ModelModification;
import org.eclipse.pde.internal.ui.util.PDEModelUtility;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.osgi.framework.Constants;
/**
* Operation to convert a normal workspace project into a plug-in project. This
* code has, in the main, been refactored (copied with little or no amendment)
* from org.eclipse.pde.internal.ui.wizards.tool.ConvertedProjectsPage.
*/
public class ConvertProjectToPluginOperation extends WorkspaceModifyOperation {
private IProject[] projectsToConvert;
private boolean enableApiAnalysis;
private String fLibraryName;
private String[] fSrcEntries;
private String[] fLibEntries;
/**
* Workspace operation to convert the specified project into a plug-in
* project.
*
* @param theProjectsToConvert The project to be converted.
* @param enableApiAnalysis Whether to set up API Tooling analysis on the projects
*/
public ConvertProjectToPluginOperation(IProject[] theProjectsToConvert, boolean enableApiAnalysis) {
this.projectsToConvert = theProjectsToConvert;
this.enableApiAnalysis = enableApiAnalysis;
}
/**
* Convert a normal java project into a plug-in project.
*
* @param monitor
* Progress monitor
*/
@Override
protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException {
try {
monitor.beginTask(PDEUIMessages.ConvertedProjectWizard_converting, projectsToConvert.length);
for (int i = 0; i < projectsToConvert.length; i++) {
IProject projectToConvert = projectsToConvert[i];
convertProject(projectToConvert, monitor);
monitor.worked(1);
}
} catch (CoreException e) {
PDEPlugin.logException(e);
} finally {
monitor.done();
}
}
private void convertProject(IProject projectToConvert, IProgressMonitor monitor) throws CoreException {
// Do early checks to make sure we can get out fast if we're not setup
// properly
if (projectToConvert == null || !projectToConvert.exists()) {
return;
}
// Nature check - do we need to do anything at all?
if (projectToConvert.hasNature(PDE.PLUGIN_NATURE)) {
return;
}
CoreUtility.addNatureToProject(projectToConvert, PDE.PLUGIN_NATURE, monitor);
// Setup API Tooling, which requires the java nature
if (enableApiAnalysis) {
if (!projectToConvert.hasNature(JavaCore.NATURE_ID)) {
CoreUtility.addNatureToProject(projectToConvert, JavaCore.NATURE_ID, monitor);
}
CoreUtility.addNatureToProject(projectToConvert, "org.eclipse.pde.api.tools.apiAnalysisNature", monitor); //$NON-NLS-1$
}
loadClasspathEntries(projectToConvert, monitor);
loadLibraryName(projectToConvert);
createManifestFile(PDEProject.getManifest(projectToConvert), monitor);
IFile buildFile = PDEProject.getBuildProperties(projectToConvert);
if (!buildFile.exists()) {
WorkspaceBuildModel model = new WorkspaceBuildModel(buildFile);
IBuild build = model.getBuild(true);
IBuildEntry entry = model.getFactory().createEntry(IBuildEntry.BIN_INCLUDES);
if (PDEProject.getPluginXml(projectToConvert).exists())
entry.addToken(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR);
if (PDEProject.getManifest(projectToConvert).exists())
entry.addToken(ICoreConstants.MANIFEST_FOLDER_NAME);
for (int i = 0; i < fLibEntries.length; i++) {
entry.addToken(fLibEntries[i]);
}
if (fSrcEntries.length > 0) {
entry.addToken(fLibraryName);
IBuildEntry source = model.getFactory().createEntry(IBuildEntry.JAR_PREFIX + fLibraryName);
for (int i = 0; i < fSrcEntries.length; i++) {
source.addToken(fSrcEntries[i]);
}
build.add(source);
}
if (entry.getTokens().length > 0)
build.add(entry);
model.save();
}
}
private void loadClasspathEntries(IProject project, IProgressMonitor monitor) {
IJavaProject javaProject = JavaCore.create(project);
IClasspathEntry[] currentClassPath = new IClasspathEntry[0];
ArrayList<String> sources = new ArrayList<>();
ArrayList<String> libraries = new ArrayList<>();
try {
currentClassPath = javaProject.getRawClasspath();
} catch (JavaModelException e) {
}
for (int i = 0; i < currentClassPath.length; i++) {
int contentType = currentClassPath[i].getEntryKind();
if (contentType == IClasspathEntry.CPE_SOURCE) {
String relativePath = getRelativePath(currentClassPath[i], project);
if (relativePath.equals("")) { //$NON-NLS-1$
sources.add("."); //$NON-NLS-1$
} else {
sources.add(relativePath + "/"); //$NON-NLS-1$
}
} else if (contentType == IClasspathEntry.CPE_LIBRARY) {
String path = getRelativePath(currentClassPath[i], project);
if (path.length() > 0)
libraries.add(path);
else
libraries.add("."); //$NON-NLS-1$
}
}
fSrcEntries = sources.toArray(new String[sources.size()]);
fLibEntries = libraries.toArray(new String[libraries.size()]);
IClasspathEntry[] classPath = new IClasspathEntry[currentClassPath.length + 1];
System.arraycopy(currentClassPath, 0, classPath, 0, currentClassPath.length);
classPath[classPath.length - 1] = ClasspathComputer.createContainerEntry();
try {
javaProject.setRawClasspath(classPath, monitor);
} catch (JavaModelException e) {
}
}
private String getRelativePath(IClasspathEntry cpe, IProject project) {
IPath path = project.getFile(cpe.getPath()).getProjectRelativePath();
return path.removeFirstSegments(1).toString();
}
private void loadLibraryName(IProject project) {
if (isOldTarget() || (fLibEntries.length > 0 && fSrcEntries.length > 0)) {
String libName = project.getName();
int i = libName.lastIndexOf("."); //$NON-NLS-1$
if (i != -1)
libName = libName.substring(i + 1);
fLibraryName = libName + ".jar"; //$NON-NLS-1$
} else {
fLibraryName = "."; //$NON-NLS-1$
}
}
private void organizeExports(final IProject project) {
PDEModelUtility.modifyModel(new ModelModification(PDEProject.getManifest(project)) {
@Override
protected void modifyModel(IBaseModel model, IProgressMonitor monitor) throws CoreException {
if (!(model instanceof IBundlePluginModelBase))
return;
OrganizeManifest.organizeExportPackages(((IBundlePluginModelBase) model).getBundleModel().getBundle(), project, true, true);
}
}, null);
}
private String createInitialName(String id) {
int loc = id.lastIndexOf('.');
if (loc == -1)
return id;
StringBuffer buf = new StringBuffer(id.substring(loc + 1));
buf.setCharAt(0, Character.toUpperCase(buf.charAt(0)));
return buf.toString();
}
private void createManifestFile(IFile file, IProgressMonitor monitor) throws CoreException {
WorkspaceBundlePluginModel model = new WorkspaceBundlePluginModel(file, null);
model.load();
IBundle pluginBundle = model.getBundleModel().getBundle();
String pluginId = pluginBundle.getHeader(Constants.BUNDLE_SYMBOLICNAME);
String pluginName = pluginBundle.getHeader(Constants.BUNDLE_NAME);
String pluginVersion = pluginBundle.getHeader(Constants.BUNDLE_VERSION);
boolean missingInfo = (pluginId == null || pluginName == null || pluginVersion == null);
// If no ID exists, create one
if (pluginId == null) {
pluginId = IdUtil.getValidId(file.getProject().getName());
}
// At this point, the plug-in ID is not null
// If no version number exists, create one
if (pluginVersion == null) {
pluginVersion = "1.0.0.qualifier"; //$NON-NLS-1$
}
// If no name exists, create one using the non-null pluginID
if (pluginName == null) {
pluginName = createInitialName(pluginId);
}
pluginBundle.setHeader(Constants.BUNDLE_SYMBOLICNAME, pluginId);
pluginBundle.setHeader(Constants.BUNDLE_VERSION, pluginVersion);
pluginBundle.setHeader(Constants.BUNDLE_NAME, pluginName);
if (missingInfo) {
IPluginModelFactory factory = model.getPluginFactory();
IPluginBase base = model.getPluginBase();
if (fLibraryName != null && !fLibraryName.equals(".")) { //$NON-NLS-1$
IPluginLibrary library = factory.createLibrary();
library.setName(fLibraryName);
library.setExported(true);
base.add(library);
}
for (int i = 0; i < fLibEntries.length; i++) {
IPluginLibrary library = factory.createLibrary();
library.setName(fLibEntries[i]);
library.setExported(true);
base.add(library);
}
if (TargetPlatformHelper.getTargetVersion() >= 3.1)
pluginBundle.setHeader(Constants.BUNDLE_MANIFESTVERSION, "2"); //$NON-NLS-1$
}
model.save();
monitor.done();
organizeExports(file.getProject());
}
private boolean isOldTarget() {
return TargetPlatformHelper.getTargetVersion() < 3.1;
}
}