KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > pde > internal > ui > editor > contentassist > ManifestContentAssistProcessor


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.pde.internal.ui.editor.contentassist;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.Comparator JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.StringTokenizer JavaDoc;
21
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.jdt.core.IJavaProject;
24 import org.eclipse.jdt.core.IPackageFragment;
25 import org.eclipse.jdt.core.JavaCore;
26 import org.eclipse.jdt.core.search.IJavaSearchConstants;
27 import org.eclipse.jdt.launching.JavaRuntime;
28 import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
29 import org.eclipse.jface.resource.ImageDescriptor;
30 import org.eclipse.jface.text.BadLocationException;
31 import org.eclipse.jface.text.IDocument;
32 import org.eclipse.jface.text.IRegion;
33 import org.eclipse.jface.text.ITextViewer;
34 import org.eclipse.jface.text.contentassist.ContentAssistEvent;
35 import org.eclipse.jface.text.contentassist.ICompletionListener;
36 import org.eclipse.jface.text.contentassist.ICompletionProposal;
37 import org.eclipse.osgi.service.resolver.BundleDescription;
38 import org.eclipse.osgi.service.resolver.ExportPackageDescription;
39 import org.eclipse.osgi.util.ManifestElement;
40 import org.eclipse.pde.core.IBaseModel;
41 import org.eclipse.pde.core.plugin.IPluginModelBase;
42 import org.eclipse.pde.core.plugin.ModelEntry;
43 import org.eclipse.pde.core.plugin.PluginRegistry;
44 import org.eclipse.pde.internal.core.ICoreConstants;
45 import org.eclipse.pde.internal.core.ibundle.IBundleModel;
46 import org.eclipse.pde.internal.core.util.HeaderMap;
47 import org.eclipse.pde.internal.core.util.PDEJavaHelper;
48 import org.eclipse.pde.internal.ui.PDEPluginImages;
49 import org.eclipse.pde.internal.ui.editor.PDEFormEditor;
50 import org.eclipse.pde.internal.ui.editor.PDESourcePage;
51 import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor;
52 import org.eclipse.pde.internal.ui.util.ImageOverlayIcon;
53 import org.eclipse.pde.internal.ui.util.PDEJavaHelperUI;
54 import org.eclipse.swt.graphics.Image;
55 import org.osgi.framework.BundleException;
56 import org.osgi.framework.Constants;
57 import org.osgi.framework.Version;
58
59 public class ManifestContentAssistProcessor extends TypePackageCompletionProcessor implements ICompletionListener {
60     
61     protected PDESourcePage fSourcePage;
62     private IJavaProject fJP;
63     
64     // if we order the headers alphabetically in the array, there is no need to sort and we can save time
65
private static final String JavaDoc[] fHeader = {
66         Constants.BUNDLE_ACTIVATOR,
67         Constants.BUNDLE_ACTIVATIONPOLICY,
68         Constants.BUNDLE_CATEGORY,
69         Constants.BUNDLE_CLASSPATH,
70         Constants.BUNDLE_CONTACTADDRESS,
71         Constants.BUNDLE_COPYRIGHT,
72         Constants.BUNDLE_DESCRIPTION,
73         Constants.BUNDLE_DOCURL,
74         Constants.BUNDLE_LOCALIZATION,
75         Constants.BUNDLE_MANIFESTVERSION,
76         Constants.BUNDLE_NAME,
77         Constants.BUNDLE_NATIVECODE,
78         Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT,
79         Constants.BUNDLE_SYMBOLICNAME,
80         Constants.BUNDLE_UPDATELOCATION,
81         Constants.BUNDLE_VENDOR,
82         Constants.BUNDLE_VERSION,
83         Constants.DYNAMICIMPORT_PACKAGE,
84         ICoreConstants.ECLIPSE_BUDDY_POLICY,
85         ICoreConstants.ECLIPSE_GENERIC_CAPABILITY,
86         ICoreConstants.ECLIPSE_GENERIC_REQUIRED,
87         ICoreConstants.ECLIPSE_LAZYSTART,
88         Constants.EXPORT_PACKAGE,
89         ICoreConstants.PLATFORM_FILTER,
90         ICoreConstants.ECLIPSE_REGISTER_BUDDY,
91         ICoreConstants.EXPORT_SERVICE,
92         Constants.IMPORT_PACKAGE,
93         ICoreConstants.IMPORT_SERVICE,
94         Constants.REQUIRE_BUNDLE,
95         Constants.FRAGMENT_HOST
96     };
97     
98     private static final String JavaDoc BAUMAN = "Brian Bauman"; //$NON-NLS-1$
99
private static final String JavaDoc ANISZCZYK = "Chris Aniszczyk"; //$NON-NLS-1$
100
private static final String JavaDoc LASOCKI_BICZYSKO = "Janek Lasocki-Biczysko"; //$NON-NLS-1$
101
private static final String JavaDoc PAWLOWSKI = "Mike Pawlowski"; //$NON-NLS-1$
102
private static final String JavaDoc MELHEM = "Wassim Melhem"; //$NON-NLS-1$
103

104     private static final String JavaDoc[] fNames = {
105         BAUMAN,
106         ANISZCZYK,
107         LASOCKI_BICZYSKO,
108         PAWLOWSKI,
109         MELHEM
110     };
111     
112     protected static final short
113     F_TYPE_HEADER = 0, // header proposal
114
F_TYPE_PKG = 1, // package proposal
115
F_TYPE_BUNDLE = 2, // bundle proposal
116
F_TYPE_CLASS = 3, // class proposal
117
F_TYPE_DIRECTIVE = 4, // directive proposal
118
F_TYPE_ATTRIBUTE = 5, // attribute proposal
119
F_TYPE_VALUE = 6, // value of attribute or directive proposal
120
F_TYPE_EXEC_ENV = 7, // value of execution env., added since we use a unique icon for exec envs.
121

122     F_TOTAL_TYPES = 8;
123     
124     private final Image[] fImages = new Image[F_TOTAL_TYPES];
125     
126     private static final String JavaDoc[] fExecEnvs;
127     static {
128         IExecutionEnvironment[] envs = JavaRuntime.getExecutionEnvironmentsManager().getExecutionEnvironments();
129         fExecEnvs = new String JavaDoc[envs.length];
130         for (int i = 0; i < envs.length; i++)
131             fExecEnvs[i] = envs[i].getId();
132         Arrays.sort(fExecEnvs, new Comparator JavaDoc() {
133             public int compare(Object JavaDoc o1, Object JavaDoc o2) {
134                 return ((String JavaDoc)o1).compareToIgnoreCase((String JavaDoc)o2);
135             }
136         });
137     }
138     
139     Map JavaDoc fHeaders;
140         
141     public ManifestContentAssistProcessor(PDESourcePage sourcePage) {
142         fSourcePage = sourcePage;
143     }
144
145     public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
146             int offset) {
147         IDocument doc = fSourcePage.getDocumentProvider().getDocument(fSourcePage.getInputContext().getInput());
148         if (fHeaders == null) {
149             parseDocument(doc);
150         }
151         try {
152             int lineNum = doc.getLineOfOffset(offset);
153             int lineStart = doc.getLineOffset(lineNum);
154             return computeCompletionProposals(doc, lineStart, offset);
155         } catch (BadLocationException e) {
156         }
157         return null;
158     }
159     
160     protected final void parseDocument(IDocument doc) {
161         fHeaders = new HeaderMap();
162         int numLines = doc.getNumberOfLines();
163         int offset = 0;
164         for (int i = 0; i < numLines; i++) {
165             try {
166                 IRegion line = doc.getLineInformation(i);
167                 String JavaDoc value = doc.get(offset, line.getOffset() + line.getLength() - offset);
168                 if (value.indexOf(':') != value.lastIndexOf(':')|| i == (numLines - 1)) {
169                     value = doc.get(offset, line.getOffset() - offset - 1).trim();
170                     int index = value.indexOf(':');
171                     String JavaDoc header = (index == -1) ? value : value.substring(0, index);
172                     try {
173                         if (value.endsWith(",")) //$NON-NLS-1$
174
value = value.substring(0, value.length() - 1);
175                         ManifestElement[] elems = ManifestElement.parseHeader(header, value.substring(index + 1));
176                         if (shouldStoreSet(header)) {
177                             HashSet JavaDoc set = new HashSet JavaDoc((4/3) * elems.length + 1);
178                             for (int j = 0; j < elems.length; j++)
179                                 set.add(elems[j].getValue());
180                             fHeaders.put(header, set);
181                         } else
182                             fHeaders.put(header, elems);
183                     } catch (BundleException e) {
184                     }
185                     offset = line.getOffset();
186                 }
187             } catch (BadLocationException e) {
188             }
189         }
190     }
191     
192     protected final boolean shouldStoreSet(String JavaDoc header) {
193         return header.equalsIgnoreCase(Constants.IMPORT_PACKAGE) || header.equalsIgnoreCase(Constants.EXPORT_PACKAGE) ||
194             header.equalsIgnoreCase(Constants.REQUIRE_BUNDLE) || header.equalsIgnoreCase(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
195     }
196     
197     protected ICompletionProposal[] computeCompletionProposals(IDocument doc, int startOffset, int offset) {
198         try {
199             if (!isHeader(doc, startOffset, offset))
200                 return computeValue(doc, startOffset, offset);
201             return computeHeader(doc.get(startOffset, offset - startOffset), startOffset, offset);
202         } catch (BadLocationException e) {
203         }
204         return new ICompletionProposal[0];
205     }
206     
207     protected final boolean isHeader(IDocument doc, int startOffset, int offset) throws BadLocationException {
208         String JavaDoc value = doc.get(startOffset, offset - startOffset);
209         if (value.indexOf(':') != -1)
210             return false;
211         for (--startOffset; startOffset >= 0; --startOffset) {
212             char ch = doc.getChar(startOffset);
213             if (!Character.isWhitespace(ch))
214                 return ch != ',' && ch != ':' && ch != ';';
215         }
216         return true;
217     }
218     
219     protected ICompletionProposal[] computeHeader(String JavaDoc currentValue, int startOffset, int offset) {
220         ArrayList JavaDoc completions = new ArrayList JavaDoc();
221         IBaseModel model = fSourcePage.getInputContext().getModel();
222         int length = fHeader.length;
223         if (model instanceof IBundleModel && !((IBundleModel)model).isFragmentModel())
224             --length;
225         for (int i = 0; i < fHeader.length; i++) {
226             if (fHeader[i].regionMatches(true, 0, currentValue, 0, currentValue.length()) && fHeaders.get(fHeader[i]) == null) {
227                 TypeCompletionProposal proposal = new TypeCompletionProposal(fHeader[i] + ": ", getImage(F_TYPE_HEADER), //$NON-NLS-1$
228
fHeader[i], startOffset, currentValue.length());
229                 proposal.setAdditionalProposalInfo(getJavaDoc(fHeader[i]));
230                 completions.add(proposal); //$NON-NLS-1$
231
}
232         }
233         return (ICompletionProposal[]) completions.toArray(new ICompletionProposal[completions.size()]);
234     }
235     
236     protected ICompletionProposal[] computeValue(IDocument doc, int startOffset, int offset) throws BadLocationException {
237         String JavaDoc value = doc.get(startOffset, offset - startOffset);
238         int lineNum = doc.getLineOfOffset(startOffset) - 1;
239         int index;
240         while((index = value.indexOf(':')) == -1 || ((value.length() - 1 != index) && (value.charAt(index + 1 ) == '='))) {
241             int startLine = doc.getLineOffset(lineNum);
242             value = doc.get(startLine, offset-startLine);
243             lineNum--;
244         }
245                 
246         int length = value.length();
247         if (value.regionMatches(true, 0, Constants.IMPORT_PACKAGE, 0, Math.min(length, Constants.IMPORT_PACKAGE.length())))
248             return handleImportPackageCompletion(value.substring(Constants.IMPORT_PACKAGE.length() + 1), offset);
249         if (value.regionMatches(true, 0, Constants.FRAGMENT_HOST, 0, Math.min(length, Constants.FRAGMENT_HOST.length())))
250             return handleFragmentHostCompletion(value.substring(Constants.FRAGMENT_HOST.length() + 1), offset);
251         if (value.regionMatches(true, 0, Constants.REQUIRE_BUNDLE, 0, Math.min(length, Constants.REQUIRE_BUNDLE.length())))
252             return handleRequireBundleCompletion(value.substring(Constants.REQUIRE_BUNDLE.length() + 1), offset);
253         if (value.regionMatches(true, 0, Constants.EXPORT_PACKAGE, 0, Math.min(length, Constants.EXPORT_PACKAGE.length())))
254             return handleExportPackageCompletion(value.substring(Constants.EXPORT_PACKAGE.length() + 1), offset);
255         if (value.regionMatches(true, 0, Constants.BUNDLE_ACTIVATOR, 0, Math.min(length, Constants.BUNDLE_ACTIVATOR.length())))
256             return handleBundleActivatorCompletion(removeLeadingSpaces(value.substring(Constants.BUNDLE_ACTIVATOR.length() + 1)), offset);
257         if (value.regionMatches(true, 0, Constants.BUNDLE_SYMBOLICNAME, 0, Math.min(length, Constants.BUNDLE_SYMBOLICNAME.length())))
258             return handleBundleSymbolicNameCompletion(value.substring(Constants.BUNDLE_SYMBOLICNAME.length() + 1), offset);
259         if (value.regionMatches(true, 0, Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT, 0,
260                 Math.min(length, Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT.length())))
261             return handleRequiredExecEnv(value.substring(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT.length() + 1), offset);
262         if (value.regionMatches(true, 0, ICoreConstants.ECLIPSE_LAZYSTART, 0, Math.min(length, ICoreConstants.ECLIPSE_LAZYSTART.length())))
263             return handleTrueFalseValue(value.substring(ICoreConstants.ECLIPSE_LAZYSTART.length() + 1), offset);
264         if (value.regionMatches(true, 0, Constants.BUNDLE_NAME, 0, Math.min(length, Constants.BUNDLE_NAME.length())))
265             return handleBundleNameCompletion(value.substring(Constants.BUNDLE_NAME.length() + 1), offset);
266         if (value.regionMatches(true, 0, Constants.BUNDLE_ACTIVATIONPOLICY, 0, Math.min(length, Constants.BUNDLE_ACTIVATIONPOLICY.length())))
267             return handleBundleActivationPolicyCompletion(value.substring(Constants.BUNDLE_ACTIVATIONPOLICY.length() + 1), offset);
268         if (value.regionMatches(true, 0, ICoreConstants.ECLIPSE_BUDDY_POLICY, 0, Math.min(length, ICoreConstants.ECLIPSE_BUDDY_POLICY.length())))
269             return handleBuddyPolicyCompletion(value.substring(ICoreConstants.ECLIPSE_BUDDY_POLICY.length() + 1), offset);
270         return new ICompletionProposal[0];
271     }
272     
273     /*
274      * Easter Egg
275      */

276     protected ICompletionProposal[] handleBundleNameCompletion(String JavaDoc currentValue, int offset) {
277         currentValue = removeLeadingSpaces(currentValue);
278         int length = currentValue.length();
279         
280         // only show when there is no bundle name
281
if(length == 0) {
282             return new ICompletionProposal[] {
283                     new TypeCompletionProposal(BAUMAN, null, BAUMAN, offset - length, length),
284                     new TypeCompletionProposal(ANISZCZYK, null, ANISZCZYK, offset - length, length),
285                     new TypeCompletionProposal(LASOCKI_BICZYSKO, null, LASOCKI_BICZYSKO, offset - length, length),
286                     new TypeCompletionProposal(PAWLOWSKI, null, PAWLOWSKI, offset - length, length),
287                     new TypeCompletionProposal(MELHEM, null, MELHEM, offset - length, length)
288             };
289         }
290         
291         // only show when we are trying to complete a name
292
for (int i = 0; i < fNames.length; i++) {
293             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(currentValue, " "); //$NON-NLS-1$
294
while (tokenizer.hasMoreTokens()) {
295                 String JavaDoc token = tokenizer.nextToken();
296                 if (fNames[i].regionMatches(true, 0, token, 0, token.length())) {
297                     return new ICompletionProposal[] {
298                             new TypeCompletionProposal(
299                                     fNames[i], null, fNames[i], offset - token.length(), token.length())
300                     };
301                 }
302             }
303         }
304         return new ICompletionProposal[0];
305     }
306
307     protected ICompletionProposal[] handleImportPackageCompletion(String JavaDoc currentValue, int offset) {
308         int comma = currentValue.lastIndexOf(',');
309         int semicolon = currentValue.lastIndexOf(';');
310         String JavaDoc value = comma != -1 ? currentValue.substring(comma + 1) : currentValue;
311         if (comma > semicolon || comma == semicolon) {
312             HashSet JavaDoc set = (HashSet JavaDoc) fHeaders.get(Constants.IMPORT_PACKAGE);
313             if (set == null)
314                 set = parseHeaderForValues(currentValue, offset);
315             HashSet JavaDoc importedBundles = (HashSet JavaDoc) fHeaders.get(Constants.REQUIRE_BUNDLE);
316             if (importedBundles == null) importedBundles = new HashSet JavaDoc(0);
317             value = removeLeadingSpaces(value);
318             int length = value.length();
319             set.remove(value);
320             ArrayList JavaDoc completions = new ArrayList JavaDoc();
321             IPluginModelBase[] bases = PluginRegistry.getActiveModels();
322             
323             for (int j = 0; j < bases.length; j++) { // Remove any packages already imported through Require-Bundle
324
BundleDescription desc = bases[j].getBundleDescription();
325                 if (desc == null || importedBundles.contains(desc.getSymbolicName()))
326                     continue;
327                 ExportPackageDescription[] expPkgs = desc.getExportPackages();
328                 for (int i = 0; i < expPkgs.length; i++) {
329                     String JavaDoc pkgName = expPkgs[i].getName();
330                     if (pkgName.regionMatches(true, 0, value, 0, length) && !set.contains(pkgName)) {
331                         completions.add(new TypeCompletionProposal(pkgName, getImage(F_TYPE_PKG), pkgName, offset - length, length));
332                         set.add(pkgName);
333                     }
334                 }
335             }
336             ICompletionProposal[] proposals = (ICompletionProposal[]) completions.toArray(new ICompletionProposal[completions.size()]);
337             sortCompletions(proposals);
338             return proposals;
339         }
340         int equals = currentValue.lastIndexOf('=');
341         if (equals == -1 || semicolon > equals) {
342             String JavaDoc[] validAtts = new String JavaDoc[] {Constants.RESOLUTION_DIRECTIVE, Constants.VERSION_ATTRIBUTE};
343             Integer JavaDoc[] validTypes = new Integer JavaDoc[] {new Integer JavaDoc(F_TYPE_DIRECTIVE), new Integer JavaDoc(F_TYPE_ATTRIBUTE)};
344             return handleAttrsAndDirectives(value, initializeNewList(validAtts), initializeNewList(validTypes), offset);
345         }
346         String JavaDoc attributeValue = removeLeadingSpaces(currentValue.substring(semicolon + 1));
347         if (Constants.RESOLUTION_DIRECTIVE.regionMatches(true, 0, attributeValue, 0, Constants.RESOLUTION_DIRECTIVE.length()))
348             return matchValueCompletion(currentValue.substring(equals + 1), new String JavaDoc[] {
349                 Constants.RESOLUTION_MANDATORY, Constants.RESOLUTION_OPTIONAL} , new int[] {F_TYPE_VALUE, F_TYPE_VALUE}, offset, "RESOLUTION_"); //$NON-NLS-1$
350
if (Constants.VERSION_ATTRIBUTE.regionMatches(true, 0, attributeValue, 0, Constants.VERSION_ATTRIBUTE.length())) {
351             value = removeLeadingSpaces(currentValue.substring(equals + 1));
352             if (value.length() == 0)
353                 return new ICompletionProposal[] {new TypeCompletionProposal("\"\"", getImage(F_TYPE_VALUE), "\"\"", offset, 0)}; //$NON-NLS-1$ //$NON-NLS-2$
354
}
355         return new ICompletionProposal[0];
356     }
357     
358     private ICompletionProposal[] handleXFriendsCompletion(String JavaDoc value, final int offset) {
359         ManifestElement[] elems = (ManifestElement[])fHeaders.get(Constants.BUNDLE_SYMBOLICNAME);
360         HashSet JavaDoc set = new HashSet JavaDoc();
361         if (elems != null && elems.length > 0)
362             set.add(elems[0].getValue());
363         value = removeLeadingSpaces(value);
364         if (value.length() == 0)
365             return new ICompletionProposal[] {new TypeCompletionProposal("\"\"", getImage(F_TYPE_VALUE), "\"\"", offset, 0)}; //$NON-NLS-1$ //$NON-NLS-2$
366
if (value.charAt(0) == '"')
367             value = value.substring(1);
368         int index = value.lastIndexOf(',');
369         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(value, ","); //$NON-NLS-1$
370
while (tokenizer.hasMoreTokens())
371             set.add(tokenizer.nextToken());
372         return handleBundleCompletions(value.substring((index == -1) ? 0 : index + 1), set, F_TYPE_VALUE, offset, true);
373     }
374     
375     protected ICompletionProposal[] handleFragmentHostCompletion(String JavaDoc currentValue, int offset) {
376         int index = currentValue.lastIndexOf(';');
377         if (index == -1) {
378             HashMap JavaDoc completions = new HashMap JavaDoc();
379             IPluginModelBase base = PluginRegistry.findModel(((ManifestEditor)fSourcePage.getEditor()).getCommonProject());
380             BundleDescription desc = base.getBundleDescription();
381             String JavaDoc currentId = desc != null ? desc.getSymbolicName() : null;
382
383             String JavaDoc pluginStart = removeLeadingSpaces(currentValue);
384             int length = pluginStart.length();
385             IPluginModelBase [] bases = PluginRegistry.getActiveModels();
386             for (int i = 0; i < bases.length; i++) {
387                 desc = bases[i].getBundleDescription();
388                 if (desc != null && desc.getHost() == null) {
389                     String JavaDoc pluginID = bases[i].getBundleDescription().getSymbolicName();
390                     if (!completions.containsKey(pluginID) && pluginID.regionMatches(true, 0, pluginStart, 0, length) && !pluginID.equals(currentId))
391                         completions.put(pluginID, new TypeCompletionProposal(pluginID, getImage(F_TYPE_BUNDLE), pluginID, offset - length, length));
392                 }
393             }
394             return (ICompletionProposal[]) completions.values().toArray(new ICompletionProposal[completions.size()]);
395         }
396         int equals = currentValue.lastIndexOf('=');
397         if (equals == -1 || index > equals)
398             return matchValueCompletion(removeLeadingSpaces(currentValue.substring(index + 1)), new String JavaDoc[] {
399                 Constants.BUNDLE_VERSION_ATTRIBUTE }, new int[] {F_TYPE_ATTRIBUTE}, offset);
400         String JavaDoc attributeValue = removeLeadingSpaces(currentValue.substring(index + 1));
401         if (Constants.BUNDLE_VERSION_ATTRIBUTE.regionMatches(true, 0, attributeValue, 0, Constants.BUNDLE_VERSION_ATTRIBUTE.length())) {
402             return getBundleVersionCompletions(currentValue.substring(0, index).trim(), removeLeadingSpaces(currentValue.substring(equals + 1)), offset);
403         }
404         return new ICompletionProposal[0];
405     }
406     
407     protected ICompletionProposal[] handleRequireBundleCompletion(String JavaDoc currentValue, int offset) {
408         int comma = currentValue.lastIndexOf(',');
409         int semicolon = currentValue.lastIndexOf(';');
410         String JavaDoc value = comma != -1 ? currentValue.substring(comma + 1) : currentValue;
411         if (comma > semicolon || comma == semicolon) {
412             HashSet JavaDoc set = (HashSet JavaDoc) fHeaders.get(Constants.REQUIRE_BUNDLE);
413             if (set == null)
414                 set = parseHeaderForValues(currentValue, offset);
415             return handleBundleCompletions(value, set, F_TYPE_BUNDLE, offset, false);
416         }
417         int equals = currentValue.lastIndexOf('=');
418         if (equals == -1 || semicolon > equals) {
419             String JavaDoc[] validAttrs = new String JavaDoc[] {Constants.BUNDLE_VERSION_ATTRIBUTE, Constants.RESOLUTION_DIRECTIVE, Constants.VISIBILITY_DIRECTIVE};
420             Integer JavaDoc[] validTypes = new Integer JavaDoc[] {new Integer JavaDoc(F_TYPE_ATTRIBUTE), new Integer JavaDoc(F_TYPE_DIRECTIVE), new Integer JavaDoc(F_TYPE_DIRECTIVE)};
421             return handleAttrsAndDirectives(value, initializeNewList(validAttrs), initializeNewList(validTypes), offset);
422         }
423         String JavaDoc attributeValue = removeLeadingSpaces(currentValue.substring(semicolon + 1));
424         if (Constants.VISIBILITY_DIRECTIVE.regionMatches(true, 0, attributeValue, 0, Constants.VISIBILITY_DIRECTIVE.length()))
425             return matchValueCompletion(currentValue.substring(equals + 1), new String JavaDoc[] {
426                 Constants.VISIBILITY_PRIVATE, Constants.VISIBILITY_REEXPORT}, new int[] {F_TYPE_VALUE, F_TYPE_VALUE}, offset, "VISIBILITY_"); //$NON-NLS-1$
427
if (Constants.RESOLUTION_DIRECTIVE.regionMatches(true, 0, attributeValue, 0, Constants.RESOLUTION_DIRECTIVE.length()))
428             return matchValueCompletion(currentValue.substring(equals + 1), new String JavaDoc[] {
429                 Constants.RESOLUTION_MANDATORY, Constants.RESOLUTION_OPTIONAL} , new int[] {F_TYPE_VALUE, F_TYPE_VALUE}, offset, "RESOLUTION_"); //$NON-NLS-1$
430
if (Constants.BUNDLE_VERSION_ATTRIBUTE.regionMatches(true, 0, attributeValue, 0, Constants.RESOLUTION_DIRECTIVE.length())) {
431             String JavaDoc pluginId = removeLeadingSpaces(currentValue.substring((comma == -1) ? 0 : comma + 1, semicolon));
432             return getBundleVersionCompletions(pluginId, removeLeadingSpaces(currentValue.substring(equals + 1)), offset);
433         }
434         return new ICompletionProposal[0];
435     }
436     
437     private ICompletionProposal[] getBundleVersionCompletions(String JavaDoc pluginID, String JavaDoc existingValue, int offset) {
438         ModelEntry entry = PluginRegistry.findEntry(pluginID);
439         if (entry != null) {
440             IPluginModelBase[] hosts = entry.getActiveModels();
441             ArrayList JavaDoc proposals = new ArrayList JavaDoc(hosts.length);
442             for (int i = 0; i < hosts.length; i++) {
443                 String JavaDoc proposalValue = getVersionProposal(hosts[i]);
444                 if (proposalValue.regionMatches(0, existingValue, 0, existingValue.length()))
445                     proposals.add(new TypeCompletionProposal(proposalValue.substring(existingValue.length()),
446                             getImage(F_TYPE_VALUE), proposalValue, offset, 0));
447             }
448             return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]);
449         } else if (existingValue.length() == 0)
450             return new ICompletionProposal[] {new TypeCompletionProposal("\"\"", getImage(F_TYPE_VALUE), "\"\"", offset, 0)}; //$NON-NLS-1$ //$NON-NLS-2$
451
return new ICompletionProposal[0];
452     }
453     
454     private String JavaDoc getVersionProposal(IPluginModelBase base) {
455         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("\""); //$NON-NLS-1$
456
BundleDescription desc = base.getBundleDescription();
457         if (desc != null) {
458             Version version = desc.getVersion();
459             buffer.append(version.getMajor());
460             buffer.append('.');
461             buffer.append(version.getMinor());
462             buffer.append('.');
463             buffer.append(version.getMicro());
464         } else {
465             char[] chars = base.getPluginBase().getVersion().toCharArray();
466             int periodCount = 0;
467             for (int i = 0; i < chars.length; i++) {
468                 if (chars[i] == '.') {
469                     if (periodCount == 2)
470                         break;
471                     ++periodCount;
472                 }
473                 buffer.append(chars[i]);
474             }
475         }
476         return buffer.append('\"').toString();
477     }
478     
479     private ICompletionProposal[] handleBundleCompletions(String JavaDoc value, Collection JavaDoc doNotInclude, int type, int offset, boolean includeFragments) {
480         value = removeLeadingSpaces(value);
481         int length = value.length();
482         doNotInclude.remove(value);
483         ArrayList JavaDoc completions = new ArrayList JavaDoc();
484         IPluginModelBase [] bases = PluginRegistry.getActiveModels();
485         for (int i = 0; i < bases.length; i++) {
486             BundleDescription desc = bases[i].getBundleDescription();
487             if (desc != null) {
488                 if (!includeFragments && desc.getHost() != null)
489                     continue;
490                 String JavaDoc bundleId = desc.getSymbolicName();
491                 if (bundleId.regionMatches(true, 0, value, 0, value.length()) &&
492                         !doNotInclude.contains(bundleId))
493                     completions.add(new TypeCompletionProposal(bundleId, getImage(type), bundleId, offset - length, length));
494             }
495         }
496         return (ICompletionProposal[]) completions.toArray(new ICompletionProposal[completions.size()]);
497     }
498     
499     protected ICompletionProposal[] handleExportPackageCompletion(String JavaDoc currentValue, int offset) {
500         int comma = currentValue.lastIndexOf(',');
501         int semicolon = currentValue.lastIndexOf(';');
502         ArrayList JavaDoc list = new ArrayList JavaDoc();
503         if (!insideQuotes(currentValue) && comma > semicolon || comma == semicolon) {
504             String JavaDoc value = comma != -1 ? currentValue.substring(comma + 1) : currentValue;
505             HashSet JavaDoc set = (HashSet JavaDoc) fHeaders.get(Constants.EXPORT_PACKAGE);
506             if (set == null)
507                 set = parseHeaderForValues(currentValue, offset);
508             value = removeLeadingSpaces(value);
509             int length = value.length();
510             IProject proj = ((PDEFormEditor)fSourcePage.getEditor()).getCommonProject();
511             if (proj != null) {
512                 IJavaProject jp = JavaCore.create(proj);
513                 IPackageFragment[] frags = PDEJavaHelper.getPackageFragments(jp, set, false);
514                 for (int i = 0; i < frags.length; i++) {
515                     String JavaDoc name = frags[i].getElementName();
516                     if (name.regionMatches(true, 0, value, 0, length))
517                         list.add(new TypeCompletionProposal(name, getImage(F_TYPE_PKG), name, offset - length, length));
518                 }
519             }
520         } else {
521             String JavaDoc value = currentValue;
522             if (comma > 0) {
523                 do {
524                     String JavaDoc prefix = currentValue.substring(0, comma);
525                     if (!insideQuotes(prefix)) {
526                         value = currentValue.substring(comma + 1);
527                         break;
528                     }
529                     comma = currentValue.lastIndexOf(',', comma - 1);
530                 } while (comma > 0);
531             }
532             int equals = currentValue.lastIndexOf('=');
533             if (equals == -1 || semicolon > equals) {
534                 String JavaDoc[] validAttrs = new String JavaDoc[] {Constants.VERSION_ATTRIBUTE, ICoreConstants.INTERNAL_DIRECTIVE,
535                         ICoreConstants.FRIENDS_DIRECTIVE};
536                 Integer JavaDoc[] validTypes = new Integer JavaDoc[] {new Integer JavaDoc(F_TYPE_ATTRIBUTE), new Integer JavaDoc(F_TYPE_DIRECTIVE), new Integer JavaDoc(F_TYPE_DIRECTIVE)};
537                 return handleAttrsAndDirectives(value, initializeNewList(validAttrs), initializeNewList(validTypes), offset);
538             }
539             String JavaDoc attributeValue = removeLeadingSpaces(currentValue.substring(semicolon + 1));
540             if (ICoreConstants.FRIENDS_DIRECTIVE.regionMatches(true, 0, attributeValue, 0, ICoreConstants.FRIENDS_DIRECTIVE.length()))
541                 return handleXFriendsCompletion(currentValue.substring(equals + 1), offset);
542             if (ICoreConstants.INTERNAL_DIRECTIVE.regionMatches(true, 0, attributeValue, 0, ICoreConstants.INTERNAL_DIRECTIVE.length()))
543                 return handleTrueFalseValue(currentValue.substring(equals + 1), offset);
544             if (Constants.VERSION_ATTRIBUTE.regionMatches(true, 0, attributeValue, 0, Constants.VERSION_ATTRIBUTE.length())) {
545                 value = removeLeadingSpaces(currentValue.substring(equals + 1));
546                 if (value.length() == 0)
547                     return new ICompletionProposal[] {new TypeCompletionProposal("\"\"", getImage(F_TYPE_VALUE), "\"\"", offset, 0)}; //$NON-NLS-1$ //$NON-NLS-2$
548
}
549         }
550         return (ICompletionProposal[]) list.toArray(new ICompletionProposal[list.size()]);
551     }
552     
553     protected ICompletionProposal[] handleBundleActivatorCompletion(final String JavaDoc currentValue, final int offset) {
554         ArrayList JavaDoc completions = new ArrayList JavaDoc();
555         IProject project = ((PDEFormEditor)fSourcePage.getEditor()).getCommonProject();
556         int startOffset = offset - currentValue.length();
557         generateTypePackageProposals(currentValue, project, completions, startOffset, IJavaSearchConstants.CLASS);
558         ICompletionProposal[] proposals = (ICompletionProposal[]) completions.toArray(new ICompletionProposal[completions.size()]);
559         sortCompletions(proposals);
560         return proposals;
561     }
562     
563     protected ICompletionProposal[] handleBundleSymbolicNameCompletion(String JavaDoc currentValue, int offset) {
564         int semicolon = currentValue.indexOf(';');
565         if (semicolon != -1) {
566             int equals = currentValue.indexOf('=');
567             if (equals == -1) {
568                 String JavaDoc attribute = currentValue.substring(semicolon + 1);
569                 attribute = removeLeadingSpaces(attribute);
570                 Object JavaDoc o = fHeaders.get(Constants.BUNDLE_MANIFESTVERSION);
571                 int type = (o == null || o.toString().equals("1")) ? F_TYPE_ATTRIBUTE : F_TYPE_DIRECTIVE;//$NON-NLS-1$
572
if (Constants.SINGLETON_DIRECTIVE.regionMatches(true, 0, attribute, 0, attribute.length())) {
573                     int length = attribute.length();
574                     TypeCompletionProposal proposal = new TypeCompletionProposal(Constants.SINGLETON_DIRECTIVE + ":=", //$NON-NLS-1$
575
getImage(type), Constants.SINGLETON_DIRECTIVE, offset - length, length);
576                     proposal.setAdditionalProposalInfo(getJavaDoc("SINGLETON_DIRECTIVE")); //$NON-NLS-1$
577
return new ICompletionProposal[] {proposal};
578                 }
579             } else if (equals > semicolon)
580                 return handleTrueFalseValue(currentValue.substring(equals + 1), offset);
581         }
582         return new ICompletionProposal[0];
583     }
584
585     protected ICompletionProposal[] handleBundleActivationPolicyCompletion(final String JavaDoc currentValue, final int offset) {
586         int comma = currentValue.lastIndexOf(',');
587         int semicolon = currentValue.lastIndexOf(';');
588         if (!insideQuotes(currentValue) && comma > semicolon || comma == semicolon) {
589             String JavaDoc value = removeLeadingSpaces(currentValue);
590             String JavaDoc lazyValue = "lazy"; //$NON-NLS-1$
591
int length = value.length();
592             if (lazyValue.regionMatches(0, value, 0, length))
593                 return new ICompletionProposal[] {new TypeCompletionProposal(lazyValue, null, lazyValue, offset - length, length)};
594         }
595         return new ICompletionProposal[0];
596     }
597         
598     protected ICompletionProposal[] handleBuddyPolicyCompletion(String JavaDoc currentValue, int offset) {
599         String JavaDoc value = removeLeadingSpaces(currentValue);
600         // values from bug 178517 comment #7
601
ArrayList JavaDoc validValues = initializeNewList(new String JavaDoc[] {"dependent", "global", "registered", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
602
"app", "ext", "boot", "parent"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
603
ArrayList JavaDoc types = initializeNewList(new Object JavaDoc[] {new Integer JavaDoc(F_TYPE_VALUE), new Integer JavaDoc(F_TYPE_VALUE), new Integer JavaDoc(F_TYPE_VALUE),
604                 new Integer JavaDoc(F_TYPE_VALUE), new Integer JavaDoc(F_TYPE_VALUE), new Integer JavaDoc(F_TYPE_VALUE), new Integer JavaDoc(F_TYPE_VALUE)});
605         return handleAttrsAndDirectives(value, validValues, types, offset);
606     }
607     
608     protected ICompletionProposal[] handleRequiredExecEnv(String JavaDoc currentValue, int offset) {
609         int comma = currentValue.lastIndexOf(',');
610         if (comma != -1)
611             currentValue = currentValue.substring(comma + 1);
612         currentValue = removeLeadingSpaces(currentValue);
613         ArrayList JavaDoc completions = new ArrayList JavaDoc();
614         HashSet JavaDoc set = (HashSet JavaDoc)fHeaders.get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
615         if (set == null) set = new HashSet JavaDoc(0);
616         int length = currentValue.length();
617         for (int i = 0; i < fExecEnvs.length; i++)
618             if (fExecEnvs[i].regionMatches(true, 0, currentValue, 0, length) &&
619                     !set.contains(fExecEnvs[i]))
620                 completions.add(new TypeCompletionProposal(fExecEnvs[i], getImage(F_TYPE_EXEC_ENV), fExecEnvs[i], offset - length, length));
621         return (ICompletionProposal[]) completions.toArray(new ICompletionProposal[completions.size()]);
622     }
623     
624     protected ICompletionProposal[] handleTrueFalseValue(String JavaDoc currentValue, int offset) {
625         currentValue = removeLeadingSpaces(currentValue);
626         int length = currentValue.length();
627         if (length == 0)
628             return new ICompletionProposal[] {
629                 new TypeCompletionProposal("true", getImage(F_TYPE_VALUE), "true", offset, 0), //$NON-NLS-1$ //$NON-NLS-2$
630
new TypeCompletionProposal("false", getImage(F_TYPE_VALUE), "false", offset, 0) //$NON-NLS-1$ //$NON-NLS-2$
631
};
632         else if (length < 5 && "true".regionMatches(true, 0, currentValue, 0, length)) //$NON-NLS-1$
633
return new ICompletionProposal[] {
634                 new TypeCompletionProposal("true", getImage(F_TYPE_VALUE), "true", offset - length, length) //$NON-NLS-1$ //$NON-NLS-2$
635
};
636         else if (length < 6 && "false".regionMatches(true, 0, currentValue, 0, length)) //$NON-NLS-1$
637
return new ICompletionProposal[] {
638                 new TypeCompletionProposal("false", getImage(F_TYPE_VALUE), "false", offset - length, length) //$NON-NLS-1$ //$NON-NLS-2$
639
};
640         return new ICompletionProposal[0];
641     }
642     
643     protected ICompletionProposal[] matchValueCompletion(String JavaDoc value, String JavaDoc[] attrs, int[] types, int offset) {
644         return matchValueCompletion(value, attrs, types, offset, ""); //$NON-NLS-1$
645
}
646     
647     protected ICompletionProposal[] matchValueCompletion(String JavaDoc value, String JavaDoc[] attrs, int[] types, int offset, String JavaDoc prefixCostant) {
648         ArrayList JavaDoc list = new ArrayList JavaDoc();
649         int length = value.length();
650         TypeCompletionProposal proposal = null;
651         for (int i = 0; i < attrs.length; i++)
652             if (attrs[i].regionMatches(true, 0, value, 0, length)) {
653                 if (types[i] == F_TYPE_ATTRIBUTE) {
654                     proposal = new TypeCompletionProposal(attrs[i] + "=", getImage(F_TYPE_ATTRIBUTE), attrs[i], offset - length, length); //$NON-NLS-1$
655
proposal.setAdditionalProposalInfo(getJavaDoc(attrs[i] + "_ATTRIBUTE")); //$NON-NLS-1$
656
} else if (types[i] == F_TYPE_DIRECTIVE) {
657                     proposal = new TypeCompletionProposal(attrs[i] + ":=", getImage(F_TYPE_DIRECTIVE), attrs[i], offset - length, length); //$NON-NLS-1$
658
proposal.setAdditionalProposalInfo(getJavaDoc(attrs[i] + "_DIRECTIVE")); //$NON-NLS-1$
659
} else {
660                     proposal = new TypeCompletionProposal(attrs[i], getImage(types[i]), attrs[i], offset - length, length);
661                     proposal.setAdditionalProposalInfo(getJavaDoc(prefixCostant + attrs[i]));
662                 }
663                 list.add(proposal);
664             }
665         return (ICompletionProposal[]) list.toArray(new ICompletionProposal[list.size()]);
666     }
667     
668     protected ICompletionProposal[] handleAttrsAndDirectives(String JavaDoc value, ArrayList JavaDoc attrs, ArrayList JavaDoc types, int offset) {
669         String JavaDoc fullValue = findFullLine(value, offset, false);
670         int semicolon = value.lastIndexOf(';');
671         value = removeLeadingSpaces(value.substring(semicolon + 1));
672         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(fullValue, ";"); //$NON-NLS-1$
673
tokenizer.nextToken();
674         while (tokenizer.hasMoreTokens()) {
675             String JavaDoc tokenValue = removeLeadingSpaces(tokenizer.nextToken());
676             int index = tokenValue.indexOf('=');
677             if (index == -1)
678                 continue;
679             if (tokenValue.charAt(index - 1) == ':')
680                 --index;
681             tokenValue = tokenValue.substring(0, index);
682             int indexOfObject = attrs.indexOf(tokenValue);
683             if (indexOfObject >= 0) {
684                 attrs.remove(indexOfObject);
685                 types.remove(indexOfObject);
686             }
687         }
688         return matchValueCompletion(value, (String JavaDoc[])attrs.toArray(new String JavaDoc[attrs.size()]), toIntArray(types), offset);
689     }
690     
691     private HashSet JavaDoc parseHeaderForValues(String JavaDoc currentValue, int offset) {
692         HashSet JavaDoc set = new HashSet JavaDoc();
693         String JavaDoc fullValue = findFullLine(currentValue, offset, true);
694         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(fullValue, ","); //$NON-NLS-1$
695
while(tokenizer.hasMoreTokens()) {
696             String JavaDoc pkgValue = tokenizer.nextToken();
697             int index = pkgValue.indexOf(';');
698             set.add(index == -1 ? pkgValue.trim() : pkgValue.substring(0, index).trim());
699         }
700         return set;
701     }
702     
703     private String JavaDoc findFullLine(String JavaDoc value, int offset, boolean entireHeader) {
704         IDocument doc = fSourcePage.getDocumentProvider().getDocument(fSourcePage.getInputContext().getInput());
705         try {
706             int line = doc.getLineOfOffset(offset);
707             String JavaDoc newValue = ""; //$NON-NLS-1$
708
int startOfLine = 0;
709             int colon = -1;
710             do {
711                 startOfLine = doc.getLineOffset(line);
712                 newValue = doc.get(offset, doc.getLineLength(line) - offset + startOfLine);
713                 ++line;
714                 colon = newValue.lastIndexOf(':');
715             } while ((colon == -1 || (newValue.length() > colon && newValue.charAt(colon + 1) == '=')) &&
716                     (entireHeader || newValue.indexOf(',') == -1) && !(doc.getNumberOfLines() == line));
717             if (colon > 0 && newValue.charAt(colon +1) != '=') {
718                 newValue = doc.get(offset, startOfLine - 1 - offset);
719             } else {
720                 int comma = newValue.indexOf(',');
721                 newValue = (comma != -1) ? newValue.substring(0, comma) : newValue;
722             }
723             return value.concat(newValue);
724         } catch (BadLocationException e) {
725         }
726         return ""; //$NON-NLS-1$
727
}
728     
729     private int[] toIntArray(ArrayList JavaDoc list) {
730         int[] result = new int[list.size()];
731         int i = -1;
732         while (++i < result.length) {
733             Object JavaDoc o = list.get(i);
734             if (!(o instanceof Integer JavaDoc))
735                 return new int[0];
736             result[i] = ((Integer JavaDoc)o).intValue();
737         }
738         return result;
739     }
740     
741     // if you use java.util.Arrays.asList(), we get an UnsupportedOperation later in the code
742
protected final ArrayList JavaDoc initializeNewList(Object JavaDoc[] values) {
743         ArrayList JavaDoc list = new ArrayList JavaDoc(values.length);
744         for (int i = 0; i < values.length; i++)
745             list.add(values[i]);
746         return list;
747     }
748
749     private boolean insideQuotes(String JavaDoc value) {
750         char[] chars = value.toCharArray();
751         int numOfQuotes = 0;
752         for (int i = 0; i < chars.length; i++)
753             if (chars[i] == '\"')
754                 ++numOfQuotes;
755         int j = numOfQuotes % 2;
756         return j == 1;
757     }
758
759     public void assistSessionEnded(ContentAssistEvent event) {
760         fHeaders = null;
761     }
762
763     public void assistSessionStarted(ContentAssistEvent event) {
764     }
765
766     public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) {
767     }
768
769     public Image getImage(int type) {
770         if (type >= 0 && type < F_TOTAL_TYPES)
771             if (fImages[type] == null) {
772                 switch(type) {
773                 case F_TYPE_HEADER:
774                     return fImages[type] = PDEPluginImages.DESC_BUILD_VAR_OBJ.createImage();
775                 case F_TYPE_PKG:
776                     return PDEPluginImages.get(PDEPluginImages.OBJ_DESC_PACKAGE);
777                 case F_TYPE_BUNDLE:
778                     return fImages[type] = PDEPluginImages.DESC_PLUGIN_OBJ.createImage();
779                 case F_TYPE_CLASS:
780                     return PDEPluginImages.get(PDEPluginImages.OBJ_DESC_GENERATE_CLASS);
781                 case F_TYPE_ATTRIBUTE:
782                     return fImages[type] = PDEPluginImages.DESC_ATT_URI_OBJ.createImage();
783                 case F_TYPE_DIRECTIVE:
784                     fImages[F_TYPE_ATTRIBUTE] = PDEPluginImages.DESC_ATT_URI_OBJ.createImage();
785                     ImageOverlayIcon icon = new ImageOverlayIcon(fImages[F_TYPE_ATTRIBUTE],
786                             new ImageDescriptor[][] {new ImageDescriptor[] {PDEPluginImages.DESC_DOC_CO}, null, null, null});
787                     return fImages[type] = icon.createImage();
788                 case F_TYPE_EXEC_ENV:
789                     return fImages[type] = PDEPluginImages.DESC_JAVA_LIB_OBJ.createImage();
790                 case F_TYPE_VALUE:
791                     return null;
792                 }
793             } else
794                 return fImages[type];
795         return null;
796     }
797     
798     public void dispose() {
799         for (int i = 0; i < fImages.length; i++)
800             if (fImages[i] != null && !fImages[i].isDisposed())
801                 fImages[i].dispose();
802     }
803     
804     private String JavaDoc getJavaDoc(String JavaDoc constant) {
805         if (fJP == null) {
806             IProject project = ((PDEFormEditor)fSourcePage.getEditor()).getCommonProject();
807             fJP = JavaCore.create(project);
808         }
809         return PDEJavaHelperUI.getOSGIConstantJavaDoc(constant, fJP);
810     }
811
812 }
Popular Tags