001: /*******************************************************************************
002: * Copyright (c) 2000, 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.builders;
011:
012: import java.util.Vector;
013:
014: import org.eclipse.osgi.util.NLS;
015: import org.eclipse.pde.core.plugin.IPlugin;
016: import org.eclipse.pde.core.plugin.IPluginImport;
017: import org.eclipse.pde.core.plugin.IPluginModel;
018: import org.eclipse.pde.core.plugin.IPluginModelBase;
019: import org.eclipse.pde.core.plugin.PluginRegistry;
020: import org.eclipse.pde.internal.core.PDECoreMessages;
021:
022: public class DependencyLoopFinder {
023:
024: public static DependencyLoop[] findLoops(IPlugin root) {
025: return findLoops(root, null);
026: }
027:
028: public static DependencyLoop[] findLoops(IPlugin root,
029: IPlugin[] candidates) {
030: return findLoops(root, candidates, false);
031: }
032:
033: public static DependencyLoop[] findLoops(IPlugin root,
034: IPlugin[] candidates, boolean onlyCandidates) {
035: Vector loops = new Vector();
036:
037: Vector path = new Vector();
038: findLoops(loops, path, root, candidates, onlyCandidates,
039: new Vector());
040: return (DependencyLoop[]) loops
041: .toArray(new DependencyLoop[loops.size()]);
042: }
043:
044: private static void findLoops(Vector loops, Vector path,
045: IPlugin subroot, IPlugin[] candidates,
046: boolean onlyCandidates, Vector exploredPlugins) {
047: if (path.size() > 0) {
048: // test the path so far
049: // is the subroot the same as root - if yes, that's it
050:
051: IPlugin root = (IPlugin) path.elementAt(0);
052: if (isEquivalent(root, subroot)) {
053: // our loop!!
054: DependencyLoop loop = new DependencyLoop();
055: loop.setMembers((IPlugin[]) path
056: .toArray(new IPlugin[path.size()]));
057: int no = loops.size() + 1;
058: loop
059: .setName(NLS
060: .bind(
061: PDECoreMessages.Builders_DependencyLoopFinder_loopName,
062: ("" + no))); //$NON-NLS-1$
063: loops.add(loop);
064: return;
065: }
066: // is the subroot the same as any other node?
067: // if yes, abort - local loop that is not ours
068: for (int i = 1; i < path.size(); i++) {
069: IPlugin node = (IPlugin) path.elementAt(i);
070: if (isEquivalent(subroot, node)) {
071: // local loop
072: return;
073: }
074: }
075: }
076: Vector newPath = path.size() > 0 ? ((Vector) path.clone())
077: : path;
078: newPath.add(subroot);
079:
080: if (!onlyCandidates) {
081: IPluginImport[] iimports = subroot.getImports();
082: for (int i = 0; i < iimports.length; i++) {
083: IPluginImport iimport = iimports[i];
084: String id = iimport.getId();
085: //Be paranoid
086: if (id == null)
087: continue;
088: if (!exploredPlugins.contains(id)) {
089: // is plugin in list of non loop yielding plugins
090: //Commenting linear lookup - was very slow
091: //when called from here. We will use
092: //model manager instead because it
093: //has a hash table lookup that is much faster.
094: //IPlugin child = PDECore.getDefault().findPlugin(id);
095: IPlugin child = findPlugin(id);
096: if (child != null) {
097: // number of loops before traversing plugin
098: int oldLoopSize = loops.size();
099:
100: findLoops(loops, newPath, child, null, false,
101: exploredPlugins);
102:
103: // number of loops after traversing plugin
104: int newLoopsSize = loops.size();
105:
106: if (oldLoopSize == newLoopsSize) {// no change in number of loops
107: // no loops from going to this node, skip next time
108: exploredPlugins.add(id);
109: }
110: }
111: }
112:
113: }
114:
115: }
116: if (candidates != null) {
117: for (int i = 0; i < candidates.length; i++) {
118: IPlugin candidate = candidates[i];
119:
120: // number of loops before traversing plugin
121: int oldLoopSize = loops.size();
122:
123: findLoops(loops, newPath, candidate, null, false,
124: exploredPlugins);
125:
126: // number of loops after traversing plugin
127: int newLoopsSize = loops.size();
128:
129: if (oldLoopSize == newLoopsSize) { // no change in number of loops
130: // no loops from going to this node, skip next time
131: exploredPlugins.add(candidate.getId());
132: }
133: }
134: }
135:
136: }
137:
138: private static IPlugin findPlugin(String id) {
139: IPluginModelBase childModel = PluginRegistry.findModel(id);
140: if (childModel == null || !(childModel instanceof IPluginModel))
141: return null;
142: return (IPlugin) childModel.getPluginBase();
143: }
144:
145: private static boolean isEquivalent(IPlugin left, IPlugin right) {
146: return left.getId().equals(right.getId());
147: }
148: }
|