001: /*******************************************************************************
002: * Copyright (c) 2003, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.core;
011:
012: import java.io.File;
013: import java.io.FileOutputStream;
014: import java.io.IOException;
015: import java.net.URL;
016: import java.util.ArrayList;
017: import java.util.Dictionary;
018: import java.util.HashMap;
019: import java.util.Hashtable;
020: import java.util.Iterator;
021: import java.util.List;
022: import java.util.ListIterator;
023: import java.util.Map;
024: import java.util.Properties;
025: import java.util.StringTokenizer;
026:
027: import org.eclipse.core.resources.IFile;
028: import org.eclipse.core.resources.IProject;
029: import org.eclipse.core.resources.IResource;
030: import org.eclipse.core.resources.ProjectScope;
031: import org.eclipse.core.runtime.CoreException;
032: import org.eclipse.core.runtime.IPath;
033: import org.eclipse.core.runtime.Path;
034: import org.eclipse.core.runtime.preferences.IEclipsePreferences;
035: import org.eclipse.jdt.core.IClasspathEntry;
036: import org.eclipse.jdt.core.IJavaProject;
037: import org.eclipse.jdt.core.JavaCore;
038: import org.eclipse.jdt.core.JavaModelException;
039: import org.eclipse.pde.core.build.IBuild;
040: import org.eclipse.pde.core.build.IBuildEntry;
041: import org.eclipse.pde.core.plugin.IFragmentModel;
042: import org.eclipse.pde.core.plugin.IPluginBase;
043: import org.eclipse.pde.core.plugin.IPluginLibrary;
044: import org.eclipse.pde.core.plugin.IPluginModelBase;
045: import org.eclipse.pde.core.plugin.PluginRegistry;
046: import org.eclipse.pde.internal.core.build.WorkspaceBuildModel;
047:
048: public class ClasspathHelper {
049:
050: private static final String DOT = "."; //$NON-NLS-1$
051:
052: public static String getDevEntriesProperties(String fileName,
053: boolean checkExcluded) {
054: File file = new File(fileName);
055: if (!file.exists()) {
056: File directory = file.getParentFile();
057: if (directory != null
058: && (!directory.exists() || directory.isFile())) {
059: directory.mkdirs();
060: }
061: }
062: Properties properties = new Properties();
063: IPluginModelBase[] models = PluginRegistry.getWorkspaceModels();
064: for (int i = 0; i < models.length; i++) {
065: String id = models[i].getPluginBase().getId();
066: if (id == null)
067: continue;
068: String entry = writeEntry(getDevPaths(models[i],
069: checkExcluded, null));
070: if (entry.length() > 0)
071: properties.put(id, entry);
072: }
073: properties.put("@ignoredot@", "true"); //$NON-NLS-1$ //$NON-NLS-2$
074:
075: FileOutputStream stream = null;
076: try {
077: stream = new FileOutputStream(fileName);
078: properties.store(stream, ""); //$NON-NLS-1$
079: stream.flush();
080: return new URL("file:" + fileName).toString(); //$NON-NLS-1$
081: } catch (IOException e) {
082: PDECore.logException(e);
083: } finally {
084: try {
085: if (stream != null)
086: stream.close();
087: } catch (IOException e) {
088: }
089: }
090: return getDevEntries(checkExcluded);
091: }
092:
093: public static String getDevEntriesProperties(String fileName,
094: Map map) {
095: File file = new File(fileName);
096: if (!file.exists()) {
097: File directory = file.getParentFile();
098: if (directory != null
099: && (!directory.exists() || directory.isFile())) {
100: directory.mkdirs();
101: }
102: }
103: Properties properties = new Properties();
104: Iterator iter = map.values().iterator();
105: while (iter.hasNext()) {
106: IPluginModelBase model = (IPluginModelBase) iter.next();
107: if (model.getUnderlyingResource() != null) {
108: String entry = writeEntry(getDevPaths(model, true, map));
109: if (entry.length() > 0)
110: properties
111: .put(model.getPluginBase().getId(), entry);
112: }
113: }
114: properties.put("@ignoredot@", "true"); //$NON-NLS-1$ //$NON-NLS-2$
115:
116: FileOutputStream stream = null;
117: try {
118: stream = new FileOutputStream(fileName);
119: properties.store(stream, ""); //$NON-NLS-1$
120: stream.flush();
121: return new URL("file:" + fileName).toString(); //$NON-NLS-1$
122: } catch (IOException e) {
123: PDECore.logException(e);
124: } finally {
125: try {
126: if (stream != null)
127: stream.close();
128: } catch (IOException e) {
129: }
130: }
131: return getDevEntries(true);
132: }
133:
134: public static String getDevEntries(boolean checkExcluded) {
135: IPluginModelBase[] models = PluginRegistry.getWorkspaceModels();
136: ArrayList list = new ArrayList();
137: for (int i = 0; i < models.length; i++) {
138: String id = models[i].getPluginBase().getId();
139: if (id == null || id.trim().length() == 0)
140: continue;
141: IPath[] paths = getDevPaths(models[i], checkExcluded, null);
142: for (int j = 0; j < paths.length; j++) {
143: list.add(paths[j]);
144: }
145: }
146: String entry = writeEntry((IPath[]) list.toArray(new IPath[list
147: .size()]));
148: return entry.length() > 0 ? entry : "bin"; //$NON-NLS-1$
149: }
150:
151: private static String writeEntry(IPath[] paths) {
152: StringBuffer buffer = new StringBuffer();
153: for (int i = 0; i < paths.length; i++) {
154: buffer.append(paths[i].toString());
155: if (i < paths.length - 1)
156: buffer.append(","); //$NON-NLS-1$
157: }
158: return buffer.toString();
159: }
160:
161: public static Dictionary getDevDictionary(IPluginModelBase model) {
162: if (model.getUnderlyingResource() == null)
163: return null;
164:
165: String id = model.getPluginBase().getId();
166: if (id == null || id.trim().length() == 0)
167: return null;
168: IPath[] paths = getDevPaths(model, false, null);
169: String entry = writeEntry(paths);
170: Hashtable map = new Hashtable(2);
171: map.put("@ignoredot@", "true"); //$NON-NLS-1$ //$NON-NLS-2$
172: map.put(id, entry.length() > 0 ? entry : "bin"); //$NON-NLS-1$
173: return map;
174: }
175:
176: // creates a map whose key is a Path to the source directory/jar and the value is a Path output directory or jar.
177: private static Map getClasspathMap(IProject project,
178: boolean checkExcluded, boolean onlyJarsIfLinked,
179: boolean absolutePaths) throws JavaModelException {
180: List excluded = getFoldersToExclude(project, checkExcluded);
181: IJavaProject jProject = JavaCore.create(project);
182: HashMap map = new HashMap();
183: IClasspathEntry[] entries = jProject.getRawClasspath();
184: for (int i = 0; i < entries.length; i++) {
185: // most of the paths we get will be project relative, so we need to make the paths relative
186: // we will have problems adding an "absolute" path that is workspace relative
187: IPath output = null, source = null;
188: if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
189: source = entries[i].getPath();
190: output = entries[i].getOutputLocation();
191: if (output == null)
192: output = jProject.getOutputLocation();
193: } else if (entries[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
194: source = entries[i].getPath();
195: output = entries[i].getPath();
196: if (source.segmentCount() == 1)
197: source = new Path(DOT);
198: }
199: if (output != null && !excluded.contains(output)) {
200: IResource file = project.findMember(output
201: .removeFirstSegments(1));
202: // make the path either relative or absolute
203: if (file != null) {
204: boolean isLinked = file
205: .isLinked(IResource.CHECK_ANCESTORS);
206: if (entries[i].getEntryKind() != IClasspathEntry.CPE_SOURCE
207: && !isLinked && onlyJarsIfLinked)
208: continue;
209: output = (isLinked || absolutePaths) ? file
210: .getLocation().makeAbsolute() : output
211: .makeRelative();
212: } else
213: continue;
214: ArrayList list = (ArrayList) map.get(source);
215: if (list == null)
216: list = new ArrayList();
217: list.add(output);
218: map.put(source, list);
219: }
220: }
221: return map;
222: }
223:
224: // find the corresponding paths for a library name. Searches for source folders first, but includes any libraries on the buildpath with the same name
225: private static IPath[] findLibrary(String libName,
226: IProject project, Map classpathMap, IBuild build) {
227: ArrayList paths = new ArrayList();
228: IBuildEntry entry = (build != null) ? build
229: .getEntry(IBuildEntry.JAR_PREFIX + libName) : null;
230: if (entry != null) {
231: String[] resources = entry.getTokens();
232: for (int j = 0; j < resources.length; j++) {
233: IResource res = project.findMember(resources[j]);
234: if (res != null) {
235: ArrayList list = (ArrayList) classpathMap.get(res
236: .getFullPath());
237: if (list != null) {
238: ListIterator li = list.listIterator();
239: while (li.hasNext())
240: paths.add(li.next());
241: }
242: }
243: }
244: }
245:
246: // search for a library that exists in jar form on the buildpath
247: IPath path = null;
248: if (libName.equals(DOT))
249: path = new Path(DOT);
250: else {
251: IResource res = project.findMember(libName);
252: if (res != null)
253: path = res.getFullPath();
254: }
255:
256: ArrayList list = (ArrayList) classpathMap.get(path);
257: if (list != null) {
258: ListIterator li = list.listIterator();
259: while (li.hasNext())
260: paths.add(li.next());
261: }
262: return (IPath[]) paths.toArray(new IPath[paths.size()]);
263: }
264:
265: private static IPath[] getDevPaths(IPluginModelBase model,
266: boolean checkExcluded, Map pluginsMap) {
267: ArrayList result = new ArrayList();
268: IProject project = model.getUnderlyingResource().getProject();
269: IPluginBase base = model.getPluginBase();
270: IPluginLibrary[] libraries = base.getLibraries();
271: try {
272: if (project.hasNature(JavaCore.NATURE_ID)) {
273: Map classpathMap = getClasspathMap(project,
274: checkExcluded, !base.getId().equals(
275: "org.eclipse.osgi"), false); //$NON-NLS-1$
276: IFile file = project.getFile("build.properties"); //$NON-NLS-1$
277: boolean searchBuild = file.exists();
278: if (searchBuild) {
279: WorkspaceBuildModel bModel = new WorkspaceBuildModel(
280: file);
281: IBuild build = bModel.getBuild();
282: // if it is a custom build, act like there is no build.properties (add everything)
283: IBuildEntry entry = build.getEntry("custom"); //$NON-NLS-1$
284: if (entry != null)
285: searchBuild = false;
286: else {
287: if (libraries.length == 0) {
288: IPath[] paths = findLibrary(DOT, project,
289: classpathMap, build);
290: for (int j = 0; j < paths.length; j++)
291: addPath(result, project, paths[j]);
292: } else {
293: for (int i = 0; i < libraries.length; i++) {
294: IPath[] paths = findLibrary(
295: libraries[i].getName(),
296: project, classpathMap, build);
297: if (paths.length == 0
298: && !libraries[i].getName()
299: .equals(DOT)) {
300: paths = findLibraryFromFragments(
301: libraries[i].getName(),
302: model, checkExcluded,
303: pluginsMap);
304: }
305: for (int j = 0; j < paths.length; j++)
306: addPath(result, project, paths[j]);
307: }
308: }
309: }
310: }
311: if (!searchBuild) {
312: // if no build.properties, add all output folders
313: Iterator it = classpathMap.entrySet().iterator();
314: while (it.hasNext()) {
315: Map.Entry entry = (Map.Entry) it.next();
316: ArrayList list = (ArrayList) entry.getValue();
317: ListIterator li = list.listIterator();
318: while (li.hasNext())
319: addPath(result, project, (IPath) li.next());
320: }
321: }
322: }
323: } catch (JavaModelException e) {
324: } catch (CoreException e) {
325: }
326: return (IPath[]) result.toArray(new IPath[result.size()]);
327: }
328:
329: // looks for fragments for a plug-in. Then searches the fragments for a specific library. Will return paths which are absolute (required by runtime)
330: private static IPath[] findLibraryFromFragments(String libName,
331: IPluginModelBase model, boolean checkExcluded, Map plugins) {
332: IFragmentModel[] frags = PDEManager.findFragmentsFor(model);
333: for (int i = 0; i < frags.length; i++) {
334: if (plugins != null
335: && !plugins.containsKey(frags[i]
336: .getBundleDescription().getSymbolicName()))
337: continue;
338: // look in project first
339: if (frags[i].getUnderlyingResource() != null) {
340: try {
341: IProject project = frags[i].getUnderlyingResource()
342: .getProject();
343: Map classpathMap = getClasspathMap(project,
344: checkExcluded, false, true);
345: IFile file = project.getFile("build.properties"); //$NON-NLS-1$
346: IBuild build = null;
347: if (file.exists()) {
348: WorkspaceBuildModel bModel = new WorkspaceBuildModel(
349: file);
350: build = bModel.getBuild();
351: }
352: IPath[] paths = findLibrary(libName, project,
353: classpathMap, build);
354: if (paths.length > 0)
355: return paths;
356:
357: } catch (JavaModelException e) {
358: continue;
359: }
360: // if external plugin, look in child directories for library
361: } else {
362: File file = new File(frags[i].getInstallLocation());
363: if (file.isDirectory()) {
364: file = new File(file, libName);
365: if (file.exists())
366: return new IPath[] { new Path(file.getPath()) };
367: }
368: }
369: }
370: return new IPath[0];
371: }
372:
373: private static void addPath(ArrayList result, IProject project,
374: IPath path) {
375: IPath resultPath = null;
376: if (path.isAbsolute())
377: resultPath = path;
378: else if (path.segmentCount() > 0
379: && path.segment(0).equals(project.getName())) {
380: path = path.removeFirstSegments(1);
381: if (path.segmentCount() == 0)
382: resultPath = new Path(DOT);
383: else {
384: IResource resource = project.findMember(path);
385: if (resource != null)
386: resultPath = path;
387: }
388: }
389:
390: if (resultPath != null && !result.contains(resultPath))
391: result.add(resultPath);
392: }
393:
394: private static List getFoldersToExclude(IProject project,
395: boolean checkExcluded) {
396: ArrayList list = new ArrayList();
397: if (checkExcluded) {
398: IEclipsePreferences pref = new ProjectScope(project)
399: .getNode(PDECore.PLUGIN_ID);
400: if (pref != null) {
401: String binExcludes = pref.get(
402: ICoreConstants.SELFHOSTING_BIN_EXCLUDES, ""); //$NON-NLS-1$
403: StringTokenizer tokenizer = new StringTokenizer(
404: binExcludes, ","); //$NON-NLS-1$
405: while (tokenizer.hasMoreTokens()) {
406: list.add(new Path(tokenizer.nextToken().trim()));
407: }
408: }
409: }
410: return list;
411: }
412:
413: }
|