blob: 65bd617c790f70cce18fba1f842e7d998ab6bfb7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) 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:
* Soyatec - initial API and implementation
*******************************************************************************/
package org.eclipse.xwt.ui.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.pde.core.build.IBuild;
import org.eclipse.pde.core.build.IBuildEntry;
import org.eclipse.pde.core.build.IBuildModel;
import org.eclipse.pde.core.plugin.IPluginBase;
import org.eclipse.pde.core.plugin.IPluginLibrary;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.internal.core.bundle.WorkspaceBundleModel;
import org.eclipse.pde.internal.core.ibundle.IBundle;
import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
import org.osgi.framework.Constants;
/**
* @author jliu jin.liu@soyatec.com
*/
public class LibraryBuilder extends AbstractBuilder {
private String[] libraries;
public LibraryBuilder(IProject project, String[] libraries) {
super(project);
this.libraries = libraries;
}
public IStatus build() {
if (libraries == null || libraries.length == 0) {
return Status.CANCEL_STATUS;
}
try {
refreshLocal();
IBundlePluginModelBase model = (IBundlePluginModelBase) getModel();
IPluginBase pluginBase = model.getPluginBase();
WorkspaceBundleModel bundleModel = (WorkspaceBundleModel) model.getBundleModel();
synchronized (bundleModel) {
bundleModel.load();
boolean isNonEdit = bundleModel.isEditable();
if (!isNonEdit) {
bundleModel.setEditable(true);
}
for (String libPath : libraries) {
IPluginLibrary library = model.getPluginFactory().createLibrary();
library.setName(libPath.toString());
library.setExported(true);
pluginBase.add(library);
}
checkSourceRootEntry();
updateBuildProperties(new String[libraries.length], libraries, false);
updateJavaClasspathLibs(new String[libraries.length], libraries);
bundleModel.save();
if (!isNonEdit) {
bundleModel.setEditable(false);
}
}
buildClean();
} catch (CoreException e) {
error(e.getMessage());
}
return Status.OK_STATUS;
}
private void checkSourceRootEntry() {
IBundlePluginModelBase pluginModel = (IBundlePluginModelBase) getModel();
IPluginLibrary[] libraries = pluginModel.getPluginBase().getLibraries();
for (int i = 0; i < libraries.length; i++)
if (libraries[i].getName().equals(".")) //$NON-NLS-1$
return;
IBuildModel model = pluginModel.getBuildModel();
if (model == null)
return;
IBuildEntry[] entires = model.getBuild().getBuildEntries();
for (int i = 0; i < entires.length; i++) {
if (entires[i].getName().equals(IBuildPropertiesConstants.PROPERTY_SOURCE_PREFIX + '.')) {
IPluginLibrary library = pluginModel.getPluginFactory().createLibrary();
try {
library.setName("."); //$NON-NLS-1$
pluginModel.getPluginBase().add(library);
} catch (CoreException e) {
}
}
}
}
private IBuildModel getBuildModel() {
IBundlePluginModelBase pluginModel = (IBundlePluginModelBase) getModel();
if (pluginModel != null) {
return pluginModel.getBuildModel();
}
return null;
}
private void updateBuildProperties(final String[] oldPaths, final String[] newPaths, boolean modifySourceEntry) {
IBuildModel bmodel = getBuildModel();
if (bmodel == null)
return;
IBuild build = bmodel.getBuild();
IBuildEntry entry = build.getEntry(IBuildPropertiesConstants.PROPERTY_BIN_INCLUDES);
if (entry == null)
entry = bmodel.getFactory().createEntry(IBuildPropertiesConstants.PROPERTY_BIN_INCLUDES);
try {
// adding new entries
if (oldPaths[0] == null) {
for (int i = 0; i < newPaths.length; i++)
if (newPaths[i] != null) {
entry.addToken(newPaths[i]);
if (modifySourceEntry)
configureSourceBuildEntry(bmodel, null, newPaths[i]);
}
// removing entries
} else if (newPaths[0] == null) {
for (int i = 0; i < oldPaths.length; i++)
if (oldPaths[i] != null) {
entry.removeToken(oldPaths[i]);
if (modifySourceEntry)
configureSourceBuildEntry(bmodel, oldPaths[i], null);
}
if (entry.getTokens().length == 0)
build.remove(entry);
// rename entries
} else {
for (int i = 0; i < oldPaths.length; i++)
if (newPaths[i] != null && oldPaths[i] != null) {
entry.renameToken(oldPaths[i], newPaths[i]);
if (modifySourceEntry)
configureSourceBuildEntry(bmodel, oldPaths[i], newPaths[i]);
}
}
} catch (CoreException e) {
}
}
private void configureSourceBuildEntry(IBuildModel bmodel, String oldPath, String newPath) throws CoreException {
IBuild build = bmodel.getBuild();
IBuildEntry entry = build.getEntry(IBuildPropertiesConstants.PROPERTY_SOURCE_PREFIX + (oldPath != null ? oldPath : newPath));
try {
if (newPath != null) {
if (entry == null) {
IJavaProject jproject = JavaCore.create(project);
ArrayList tokens = new ArrayList();
IClasspathEntry[] entries = jproject.getRawClasspath();
for (int i = 0; i < entries.length; i++)
if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE)
tokens.add(entries[i].getPath().removeFirstSegments(1).addTrailingSeparator().toString());
if (tokens.size() == 0)
return;
entry = bmodel.getFactory().createEntry(IBuildPropertiesConstants.PROPERTY_SOURCE_PREFIX + newPath);
for (int i = 0; i < tokens.size(); i++)
entry.addToken((String) tokens.get(i));
build.add(entry);
} else
entry.setName(IBuildPropertiesConstants.PROPERTY_SOURCE_PREFIX + newPath);
} else if (entry != null && newPath == null)
build.remove(entry);
} catch (JavaModelException e) {
}
}
private void updateJavaClasspathLibs(String[] oldPaths, String[] newPaths) {
IJavaProject jproject = JavaCore.create(project);
try {
IClasspathEntry[] entries = jproject.getRawClasspath();
ArrayList toBeAdded = new ArrayList();
int index = -1;
entryLoop: for (int i = 0; i < entries.length; i++) {
if (entries[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
if (index == -1)
index = i;
// do not add the old paths (handling deletion/renaming)
IPath path = entries[i].getPath().removeFirstSegments(1).removeTrailingSeparator();
for (int j = 0; j < oldPaths.length; j++)
if (oldPaths[j] != null && path.equals(new Path(oldPaths[j]).removeTrailingSeparator()))
continue entryLoop;
} else if (entries[i].getEntryKind() == IClasspathEntry.CPE_CONTAINER)
if (index == -1)
index = i;
toBeAdded.add(entries[i]);
}
if (index == -1)
index = entries.length;
// add paths
for (int i = 0; i < newPaths.length; i++) {
if (newPaths[i] == null)
continue;
IClasspathEntry entry = JavaCore.newLibraryEntry(project.getFullPath().append(newPaths[i]), null, null, true);
if (!toBeAdded.contains(entry))
toBeAdded.add(index++, entry);
}
if (toBeAdded.size() == entries.length)
return;
IClasspathEntry[] updated = (IClasspathEntry[]) toBeAdded.toArray(new IClasspathEntry[toBeAdded.size()]);
jproject.setRawClasspath(updated, null);
} catch (JavaModelException e) {
}
}
public IStatus unbuild() {
if (libraries == null || libraries.length == 0) {
return warning("No library found.");
}
IPluginModelBase pluginModel = getModel();
IBundlePluginModelBase model = (IBundlePluginModelBase) pluginModel;
IPluginBase pluginBase = model.getPluginBase();
IPluginLibrary[] exists = pluginBase.getLibraries();
List<IPluginLibrary> libForRemove = new ArrayList<IPluginLibrary>();
for (IPluginLibrary pluginLibrary : exists) {
for (String libName : libraries) {
if (pluginLibrary.getName().equals(libName)) {
libForRemove.add(pluginLibrary);
}
}
}
if (libForRemove.isEmpty()) {
return warning("No library found.");
}
try {
refreshLocal();
WorkspaceBundleModel bundleModel = (WorkspaceBundleModel) model.getBundleModel();
synchronized (bundleModel) {
bundleModel.load();
boolean isNonEdit = bundleModel.isEditable();
if (!isNonEdit) {
bundleModel.setEditable(true);
}
String[] remove = new String[libForRemove.size()];
int i = 0;
IBundle bundle = bundleModel.getBundle();
for (IPluginLibrary pluginLibrary : libForRemove) {
pluginBase.remove(pluginLibrary);
String name = pluginLibrary.getName();
remove[i++] = name;
}
removeLibraries(bundle, remove);
bundleModel.save();
if (!isNonEdit) {
bundleModel.setEditable(false);
}
updateBuildProperties(remove, new String[remove.length], true);
updateJavaClasspathLibs(remove, new String[remove.length]);
}
buildClean();
} catch (CoreException e) {
error(e.getMessage());
}
return Status.OK_STATUS;
}
/**
* Fixed a bug of removing library from IPluginBase.remove(pluginLibrary), the bundle does not update at all.
*/
private void removeLibraries(IBundle bundle, String[] remove) {
String oldValue = bundle.getHeader(Constants.BUNDLE_CLASSPATH);
if (oldValue == null || oldValue.equals("")) {
return;
}
List<String> values = new ArrayList<String>();
StringTokenizer stk = new StringTokenizer(oldValue, ",");
while (stk.hasMoreTokens()) {
values.add(stk.nextToken().trim());
}
for (String r : remove) {
values.remove(r);
}
String newValue = null;
for (int i = 0; i < values.size(); i++) {
if (newValue == null) {
newValue = values.get(i);
} else {
newValue += "," + values.get(i);
}
}
bundle.setHeader(Constants.BUNDLE_CLASSPATH, newValue);
}
}