blob: 1a8955574cdbacb545e155a6a480dc7322eb7fae [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.internal.core;
import java.io.*;
import java.net.URL;
import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jdt.core.*;
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.build.WorkspaceBuildModel;
public class ClasspathHelper {
private static final String DOT = "."; //$NON-NLS-1$
public static String getDevEntriesProperties(String fileName, boolean checkExcluded) {
File file = new File(fileName);
if (!file.exists()) {
File directory = file.getParentFile();
if (directory != null && (!directory.exists() || directory.isFile())) {
directory.mkdirs();
}
}
Properties properties = new Properties();
// account for cascading workspaces
TargetWeaver.weaveDevProperties(properties);
IPluginModelBase[] models = PluginRegistry.getWorkspaceModels();
for (int i = 0; i < models.length; i++) {
String id = models[i].getPluginBase().getId();
if (id == null)
continue;
String entry = writeEntry(getDevPaths(models[i], checkExcluded, null));
if (entry.length() > 0) {
String currentValue = (String) properties.get(id);
if (!entry.equals(currentValue)) {
if (currentValue != null)
entry = currentValue.concat(",").concat(entry); //$NON-NLS-1$
properties.put(id, entry);
}
}
}
properties.put("@ignoredot@", "true"); //$NON-NLS-1$ //$NON-NLS-2$
FileOutputStream stream = null;
try {
stream = new FileOutputStream(fileName);
properties.store(stream, ""); //$NON-NLS-1$
stream.flush();
return new URL("file:" + fileName).toString(); //$NON-NLS-1$
} catch (IOException e) {
PDECore.logException(e);
} finally {
try {
if (stream != null)
stream.close();
} catch (IOException e) {
}
}
return getDevEntries(checkExcluded);
}
public static String getDevEntriesProperties(String fileName, Map map) {
File file = new File(fileName);
if (!file.exists()) {
File directory = file.getParentFile();
if (directory != null && (!directory.exists() || directory.isFile())) {
directory.mkdirs();
}
}
Properties properties = new Properties();
// account for cascading workspaces
TargetWeaver.weaveDevProperties(properties);
Iterator iter = map.values().iterator();
while (iter.hasNext()) {
IPluginModelBase model = (IPluginModelBase) iter.next();
if (model.getUnderlyingResource() != null) {
String entry = writeEntry(getDevPaths(model, true, map));
if (entry.length() > 0) {
String id = model.getPluginBase().getId();
String currentValue = (String) properties.get(id);
if (!entry.equals(currentValue)) {
if (currentValue != null)
entry = currentValue.concat(",").concat(entry); //$NON-NLS-1$
properties.put(id, entry);
}
}
}
}
properties.put("@ignoredot@", "true"); //$NON-NLS-1$ //$NON-NLS-2$
FileOutputStream stream = null;
try {
stream = new FileOutputStream(fileName);
properties.store(stream, ""); //$NON-NLS-1$
stream.flush();
return new URL("file:" + fileName).toString(); //$NON-NLS-1$
} catch (IOException e) {
PDECore.logException(e);
} finally {
try {
if (stream != null)
stream.close();
} catch (IOException e) {
}
}
return getDevEntries(true);
}
private static String getDevEntries(boolean checkExcluded) {
IPluginModelBase[] models = PluginRegistry.getWorkspaceModels();
ArrayList list = new ArrayList();
for (int i = 0; i < models.length; i++) {
String id = models[i].getPluginBase().getId();
if (id == null || id.trim().length() == 0)
continue;
IPath[] paths = getDevPaths(models[i], checkExcluded, null);
for (int j = 0; j < paths.length; j++) {
list.add(paths[j]);
}
}
String entry = writeEntry((IPath[]) list.toArray(new IPath[list.size()]));
return entry.length() > 0 ? entry : "bin"; //$NON-NLS-1$
}
private static String writeEntry(IPath[] paths) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < paths.length; i++) {
buffer.append(paths[i].toString());
if (i < paths.length - 1)
buffer.append(","); //$NON-NLS-1$
}
return buffer.toString();
}
// TODO remove - no longer used after bug 217870
public static Dictionary getDevDictionary(IPluginModelBase model) {
if (model.getUnderlyingResource() == null)
return null;
String id = model.getPluginBase().getId();
if (id == null || id.trim().length() == 0)
return null;
IPath[] paths = getDevPaths(model, false, null);
String entry = writeEntry(paths);
Hashtable map = new Hashtable(2);
map.put("@ignoredot@", "true"); //$NON-NLS-1$ //$NON-NLS-2$
map.put(id, entry.length() > 0 ? entry : "bin"); //$NON-NLS-1$
return map;
}
// creates a map whose key is a Path to the source directory/jar and the value is a Path output directory or jar.
private static Map getClasspathMap(IProject project, boolean checkExcluded, boolean onlyJarsIfLinked, boolean absolutePaths) throws JavaModelException {
List excluded = getFoldersToExclude(project, checkExcluded);
IJavaProject jProject = JavaCore.create(project);
HashMap map = new HashMap();
IClasspathEntry[] entries = jProject.getRawClasspath();
for (int i = 0; i < entries.length; i++) {
// most of the paths we get will be project relative, so we need to make the paths relative
// we will have problems adding an "absolute" path that is workspace relative
IPath output = null, source = null;
if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
source = entries[i].getPath();
output = entries[i].getOutputLocation();
if (output == null)
output = jProject.getOutputLocation();
} else if (entries[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
source = entries[i].getPath();
output = entries[i].getPath();
if (source.segmentCount() == 1)
source = new Path(DOT);
}
if (output != null && !excluded.contains(output)) {
IResource file = project.findMember(output.removeFirstSegments(1));
// make the path either relative or absolute
if (file != null) {
boolean isLinked = file.isLinked(IResource.CHECK_ANCESTORS);
if (entries[i].getEntryKind() != IClasspathEntry.CPE_SOURCE && !isLinked && onlyJarsIfLinked)
continue;
output = (isLinked || absolutePaths) ? file.getLocation().makeAbsolute() : output.makeRelative();
} else
continue;
ArrayList list = (ArrayList) map.get(source);
if (list == null)
list = new ArrayList();
list.add(output);
map.put(source, list);
}
}
return map;
}
// find the corresponding paths for a library name. Searches for source folders first, but includes any libraries on the buildpath with the same name
private static IPath[] findLibrary(String libName, IProject project, Map classpathMap, IBuild build) {
ArrayList paths = new ArrayList();
IBuildEntry entry = (build != null) ? build.getEntry(IBuildEntry.JAR_PREFIX + libName) : null;
if (entry != null) {
String[] resources = entry.getTokens();
for (int j = 0; j < resources.length; j++) {
IResource res = project.findMember(resources[j]);
if (res != null) {
ArrayList list = (ArrayList) classpathMap.get(res.getFullPath());
if (list != null) {
ListIterator li = list.listIterator();
while (li.hasNext())
paths.add(li.next());
}
}
}
}
// search for a library that exists in jar form on the buildpath
IPath path = null;
if (libName.equals(DOT))
path = new Path(DOT);
else {
IResource res = project.findMember(libName);
if (res != null)
path = res.getFullPath();
}
ArrayList list = (ArrayList) classpathMap.get(path);
if (list != null) {
ListIterator li = list.listIterator();
while (li.hasNext())
paths.add(li.next());
}
return (IPath[]) paths.toArray(new IPath[paths.size()]);
}
private static IPath[] getDevPaths(IPluginModelBase model, boolean checkExcluded, Map pluginsMap) {
ArrayList result = new ArrayList();
IProject project = model.getUnderlyingResource().getProject();
IPluginBase base = model.getPluginBase();
IPluginLibrary[] libraries = base.getLibraries();
try {
if (project.hasNature(JavaCore.NATURE_ID)) {
Map classpathMap = getClasspathMap(project, checkExcluded, !base.getId().equals(PDECore.getDefault().getModelManager().getSystemBundleId()), false);
IFile file = project.getFile("build.properties"); //$NON-NLS-1$
boolean searchBuild = file.exists();
if (searchBuild) {
WorkspaceBuildModel bModel = new WorkspaceBuildModel(file);
IBuild build = bModel.getBuild();
// if it is a custom build, act like there is no build.properties (add everything)
IBuildEntry entry = build.getEntry("custom"); //$NON-NLS-1$
if (entry != null)
searchBuild = false;
else {
if (libraries.length == 0) {
IPath[] paths = findLibrary(DOT, project, classpathMap, build);
for (int j = 0; j < paths.length; j++)
addPath(result, project, paths[j]);
} else {
for (int i = 0; i < libraries.length; i++) {
IPath[] paths = findLibrary(libraries[i].getName(), project, classpathMap, build);
if (paths.length == 0 && !libraries[i].getName().equals(DOT)) {
paths = findLibraryFromFragments(libraries[i].getName(), model, checkExcluded, pluginsMap);
}
for (int j = 0; j < paths.length; j++)
addPath(result, project, paths[j]);
}
}
}
}
if (!searchBuild) {
// if no build.properties, add all output folders
Iterator it = classpathMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
ArrayList list = (ArrayList) entry.getValue();
ListIterator li = list.listIterator();
while (li.hasNext())
addPath(result, project, (IPath) li.next());
}
}
}
} catch (JavaModelException e) {
} catch (CoreException e) {
}
return (IPath[]) result.toArray(new IPath[result.size()]);
}
// looks for fragments for a plug-in. Then searches the fragments for a specific library. Will return paths which are absolute (required by runtime)
private static IPath[] findLibraryFromFragments(String libName, IPluginModelBase model, boolean checkExcluded, Map plugins) {
IFragmentModel[] frags = PDEManager.findFragmentsFor(model);
for (int i = 0; i < frags.length; i++) {
if (plugins != null && !plugins.containsKey(frags[i].getBundleDescription().getSymbolicName()))
continue;
// look in project first
if (frags[i].getUnderlyingResource() != null) {
try {
IProject project = frags[i].getUnderlyingResource().getProject();
Map classpathMap = getClasspathMap(project, checkExcluded, false, true);
IFile file = project.getFile("build.properties"); //$NON-NLS-1$
IBuild build = null;
if (file.exists()) {
WorkspaceBuildModel bModel = new WorkspaceBuildModel(file);
build = bModel.getBuild();
}
IPath[] paths = findLibrary(libName, project, classpathMap, build);
if (paths.length > 0)
return paths;
} catch (JavaModelException e) {
continue;
}
// if external plugin, look in child directories for library
} else {
File file = new File(frags[i].getInstallLocation());
if (file.isDirectory()) {
file = new File(file, libName);
if (file.exists())
return new IPath[] {new Path(file.getPath())};
}
}
}
return new IPath[0];
}
private static void addPath(ArrayList result, IProject project, IPath path) {
IPath resultPath = null;
if (path.isAbsolute())
resultPath = path;
else if (path.segmentCount() > 0 && path.segment(0).equals(project.getName())) {
path = path.removeFirstSegments(1);
if (path.segmentCount() == 0)
resultPath = new Path(DOT);
else {
IResource resource = project.findMember(path);
if (resource != null)
resultPath = path;
}
}
if (resultPath != null && !result.contains(resultPath))
result.add(resultPath);
}
private static List getFoldersToExclude(IProject project, boolean checkExcluded) {
ArrayList list = new ArrayList();
if (checkExcluded) {
IEclipsePreferences pref = new ProjectScope(project).getNode(PDECore.PLUGIN_ID);
if (pref != null) {
String binExcludes = pref.get(ICoreConstants.SELFHOSTING_BIN_EXCLUDES, ""); //$NON-NLS-1$
StringTokenizer tokenizer = new StringTokenizer(binExcludes, ","); //$NON-NLS-1$
while (tokenizer.hasMoreTokens()) {
list.add(new Path(tokenizer.nextToken().trim()));
}
}
}
return list;
}
}