]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/core extension/org/eclipse/jdt/internal/corext/javadoc/JavaDocLocations.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core extension / org / eclipse / jdt / internal / corext / javadoc / JavaDocLocations.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 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.jdt.internal.corext.javadoc;
12
13 import java.io.ByteArrayInputStream;
14 import java.io.File;
15 import java.io.FileReader;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.Reader;
19 import java.io.StringReader;
20 import java.io.UnsupportedEncodingException;
21 import java.lang.reflect.InvocationTargetException;
22 import java.net.MalformedURLException;
23 import java.net.URL;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import javax.xml.parsers.DocumentBuilder;
28 import javax.xml.parsers.DocumentBuilderFactory;
29 import javax.xml.parsers.ParserConfigurationException;
30
31 import org.xml.sax.InputSource;
32 import org.xml.sax.SAXException;
33 import org.xml.sax.helpers.DefaultHandler;
34
35 import org.w3c.dom.Element;
36 import org.w3c.dom.Node;
37 import org.w3c.dom.NodeList;
38
39 import org.eclipse.core.runtime.CoreException;
40 import org.eclipse.core.runtime.IPath;
41 import org.eclipse.core.runtime.IProgressMonitor;
42 import org.eclipse.core.runtime.IStatus;
43 import org.eclipse.core.runtime.Path;
44 import org.eclipse.core.runtime.QualifiedName;
45 import org.eclipse.core.runtime.Status;
46 import org.eclipse.core.runtime.SubProgressMonitor;
47 import org.eclipse.core.runtime.jobs.Job;
48
49 import org.eclipse.core.resources.IResource;
50 import org.eclipse.core.resources.IWorkspaceRoot;
51 import org.eclipse.core.resources.IWorkspaceRunnable;
52 import org.eclipse.core.resources.ResourcesPlugin;
53
54 import org.eclipse.jface.preference.IPreferenceStore;
55
56 import org.eclipse.ui.PlatformUI;
57
58 import org.eclipse.jdt.core.Flags;
59 import org.eclipse.jdt.core.IClassFile;
60 import org.eclipse.jdt.core.IClasspathAttribute;
61 import org.eclipse.jdt.core.IClasspathContainer;
62 import org.eclipse.jdt.core.IClasspathEntry;
63 import org.eclipse.jdt.core.ICompilationUnit;
64 import org.eclipse.jdt.core.IField;
65 import org.eclipse.jdt.core.IImportDeclaration;
66 import org.eclipse.jdt.core.IJavaElement;
67 import org.eclipse.jdt.core.IJavaProject;
68 import org.eclipse.jdt.core.IMember;
69 import org.eclipse.jdt.core.IMethod;
70 import org.eclipse.jdt.core.IPackageFragment;
71 import org.eclipse.jdt.core.IPackageFragmentRoot;
72 import org.eclipse.jdt.core.IType;
73 import org.eclipse.jdt.core.JavaCore;
74 import org.eclipse.jdt.core.JavaModelException;
75 import org.eclipse.jdt.core.Signature;
76
77 import org.eclipse.jdt.internal.corext.CorextMessages;
78 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
79
80 import org.eclipse.jdt.ui.JavaUI;
81 import org.eclipse.jdt.ui.PreferenceConstants;
82
83 import org.eclipse.jdt.internal.ui.JavaPlugin;
84 import org.eclipse.jdt.internal.ui.JavaUIException;
85 import org.eclipse.jdt.internal.ui.JavaUIStatus;
86 import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter;
87 import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathSupport;
88 import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
89
90
91 public class JavaDocLocations {
92
93         private static final String JAR_PROTOCOL= "jar"; //$NON-NLS-1$
94         public static final String ARCHIVE_PREFIX= "jar:"; //$NON-NLS-1$
95         private static final String PREF_JAVADOCLOCATIONS= "org.eclipse.jdt.ui.javadoclocations"; //$NON-NLS-1$
96         public static final String PREF_JAVADOCLOCATIONS_MIGRATED= "org.eclipse.jdt.ui.javadoclocations.migrated"; //$NON-NLS-1$
97
98
99         private static final String NODE_ROOT= "javadoclocation"; //$NON-NLS-1$
100         private static final String NODE_ENTRY= "location_01"; //$NON-NLS-1$
101         private static final String NODE_PATH= "path"; //$NON-NLS-1$
102         private static final String NODE_URL= "url"; //$NON-NLS-1$
103
104         private static final QualifiedName PROJECT_JAVADOC= new QualifiedName(JavaUI.ID_PLUGIN, "project_javadoc_location"); //$NON-NLS-1$
105
106         public static void migrateToClasspathAttributes() {
107                 final Map<IPath, String> oldLocations= loadOldForCompatibility();
108                 if (oldLocations.isEmpty()) {
109                         IPreferenceStore preferenceStore= PreferenceConstants.getPreferenceStore();
110                         preferenceStore.setValue(PREF_JAVADOCLOCATIONS, ""); //$NON-NLS-1$
111                         preferenceStore.setValue(PREF_JAVADOCLOCATIONS_MIGRATED, true);
112                         return;
113                 }
114
115                 Job job= new Job(CorextMessages.JavaDocLocations_migratejob_name) {
116                         @Override
117                         protected IStatus run(IProgressMonitor monitor) {
118                                 try {
119                                         IWorkspaceRunnable runnable= new IWorkspaceRunnable() {
120                                                 public void run(IProgressMonitor pm) throws CoreException {
121                                                         updateClasspathEntries(oldLocations, pm);
122                                                         IPreferenceStore preferenceStore= PreferenceConstants.getPreferenceStore();
123                                                         preferenceStore.setValue(PREF_JAVADOCLOCATIONS, ""); //$NON-NLS-1$
124                                                         preferenceStore.setValue(PREF_JAVADOCLOCATIONS_MIGRATED, true);
125                                                 }
126                                         };
127                                         new WorkbenchRunnableAdapter(runnable).run(monitor);
128                                 } catch (InvocationTargetException e) {
129                                         JavaPlugin.log(e);
130                                 } catch (InterruptedException e) {
131                                         // should not happen, cannot cancel
132                                 }
133                                 return Status.OK_STATUS;
134                         }
135                 };
136                 job.schedule();
137         }
138
139         final static void updateClasspathEntries(Map<IPath, String> oldLocationMap, IProgressMonitor monitor) throws JavaModelException {
140                 IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
141                 IJavaProject[] javaProjects= JavaCore.create(root).getJavaProjects();
142                 try {
143                         monitor.beginTask(CorextMessages.JavaDocLocations_migrate_operation, javaProjects.length);
144                         for (int i= 0; i < javaProjects.length; i++) {
145                                 IJavaProject project= javaProjects[i];
146                                 String projectJavadoc= oldLocationMap.get(project.getPath());
147                                 if (projectJavadoc != null) {
148                                         try {
149                                                 setProjectJavadocLocation(project, projectJavadoc);
150                                         } catch (CoreException e) {
151                                                 // ignore
152                                         }
153                                 }
154
155                                 IClasspathEntry[] rawClasspath= project.getRawClasspath();
156                                 boolean hasChange= false;
157                                 for (int k= 0; k < rawClasspath.length; k++) {
158                                         IClasspathEntry updated= getConvertedEntry(rawClasspath[k], project, oldLocationMap);
159                                         if (updated != null) {
160                                                 rawClasspath[k]= updated;
161                                                 hasChange= true;
162                                         }
163                                 }
164                                 if (hasChange) {
165                                         project.setRawClasspath(rawClasspath, new SubProgressMonitor(monitor, 1));
166                                 } else {
167                                         monitor.worked(1);
168                                 }
169                         }
170                 } finally {
171                         monitor.done();
172                 }
173         }
174
175         private static IClasspathEntry getConvertedEntry(IClasspathEntry entry, IJavaProject project, Map<IPath, String> oldLocationMap) {
176                 IPath path= null;
177                 switch (entry.getEntryKind()) {
178                         case IClasspathEntry.CPE_SOURCE:
179                         case IClasspathEntry.CPE_PROJECT:
180                                 return null;
181                         case IClasspathEntry.CPE_CONTAINER:
182                                 convertContainer(entry, project, oldLocationMap);
183                                 return null;
184                         case IClasspathEntry.CPE_LIBRARY:
185                                 path= entry.getPath();
186                                 break;
187                         case IClasspathEntry.CPE_VARIABLE:
188                                 path= JavaCore.getResolvedVariablePath(entry.getPath());
189                                 break;
190                         default:
191                                 return null;
192                 }
193                 if (path == null) {
194                         return null;
195                 }
196                 IClasspathAttribute[] extraAttributes= entry.getExtraAttributes();
197                 for (int i= 0; i < extraAttributes.length; i++) {
198                         if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals(extraAttributes[i].getName())) {
199                                 return null;
200                         }
201                 }
202                 String libraryJavadocLocation= oldLocationMap.get(path);
203                 if (libraryJavadocLocation != null) {
204                         CPListElement element= CPListElement.createFromExisting(entry, project);
205                         element.setAttribute(CPListElement.JAVADOC, libraryJavadocLocation);
206                         return element.getClasspathEntry();
207                 }
208                 return null;
209         }
210
211         private static void convertContainer(IClasspathEntry entry, IJavaProject project, Map<IPath, String> oldLocationMap) {
212                 try {
213                         IClasspathContainer container= JavaCore.getClasspathContainer(entry.getPath(), project);
214                         if (container == null) {
215                                 return;
216                         }
217
218                         IClasspathEntry[] entries= container.getClasspathEntries();
219                         boolean hasChange= false;
220                         for (int i= 0; i < entries.length; i++) {
221                                 IClasspathEntry curr= entries[i];
222                                 IClasspathEntry updatedEntry= getConvertedEntry(curr, project, oldLocationMap);
223                                 if (updatedEntry != null) {
224                                         entries[i]= updatedEntry;
225                                         hasChange= true;
226                                 }
227                         }
228                         if (hasChange) {
229                                 BuildPathSupport.requestContainerUpdate(project, container, entries);
230                         }
231                 } catch (CoreException e) {
232                         // ignore
233                 }
234         }
235
236         /**
237          * Sets the Javadoc location for an archive with the given path.
238          * @param project the Java project
239          * @param url the Javadoc location
240          */
241         public static void setProjectJavadocLocation(IJavaProject project, URL url) {
242                 try {
243                         String location= url != null ? url.toExternalForm() : null;
244                         setProjectJavadocLocation(project, location);
245                 } catch (CoreException e) {
246                         JavaPlugin.log(e);
247                 }
248         }
249
250         private static void setProjectJavadocLocation(IJavaProject project, String url) throws CoreException {
251                 project.getProject().setPersistentProperty(PROJECT_JAVADOC, url);
252         }
253
254         public static URL getProjectJavadocLocation(IJavaProject project) {
255                 if (!project.getProject().isAccessible()) {
256                         return null;
257                 }
258                 try {
259                         String prop= project.getProject().getPersistentProperty(PROJECT_JAVADOC);
260                         if (prop == null) {
261                                 return null;
262                         }
263                         return new URL(prop);
264                 } catch (CoreException e) {
265                         JavaPlugin.log(e);
266                 } catch (MalformedURLException e) {
267                         JavaPlugin.log(e);
268                 }
269                 return null;
270         }
271
272
273         public static URL getLibraryJavadocLocation(IClasspathEntry entry) {
274                 if (entry == null) {
275                         throw new IllegalArgumentException("Entry must not be null"); //$NON-NLS-1$
276                 }
277
278                 int kind= entry.getEntryKind();
279                 if (kind != IClasspathEntry.CPE_LIBRARY && kind != IClasspathEntry.CPE_VARIABLE) {
280                         throw new IllegalArgumentException("Entry must be of kind CPE_LIBRARY or CPE_VARIABLE"); //$NON-NLS-1$
281                 }
282
283                 IClasspathAttribute[] extraAttributes= entry.getExtraAttributes();
284                 for (int i= 0; i < extraAttributes.length; i++) {
285                         IClasspathAttribute attrib= extraAttributes[i];
286                         if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals(attrib.getName())) {
287                                 try {
288                                         return new URL(attrib.getValue());
289                                 } catch (MalformedURLException e) {
290                                         return null;
291                                 }
292                         }
293                 }
294                 return null;
295         }
296
297         public static URL getJavadocBaseLocation(IJavaElement element) throws JavaModelException {
298                 if (element.getElementType() == IJavaElement.JAVA_PROJECT) {
299                         return getProjectJavadocLocation((IJavaProject) element);
300                 }
301
302                 IPackageFragmentRoot root= JavaModelUtil.getPackageFragmentRoot(element);
303                 if (root == null) {
304                         return null;
305                 }
306
307                 if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
308                         IClasspathEntry entry= root.getResolvedClasspathEntry();
309                         URL javadocLocation= getLibraryJavadocLocation(entry);
310                         if (javadocLocation != null) {
311                                 return getLibraryJavadocLocation(entry);
312                         }
313                         entry= root.getRawClasspathEntry();
314                         switch (entry.getEntryKind()) {
315                                 case IClasspathEntry.CPE_LIBRARY:
316                                 case IClasspathEntry.CPE_VARIABLE:
317                                         return getLibraryJavadocLocation(entry);
318                                 default:
319                                         return null;
320                         }
321                 } else {
322                         return getProjectJavadocLocation(root.getJavaProject());
323                 }
324         }
325
326         // loading for compatibility
327
328         private static JavaUIException createException(Throwable t, String message) {
329                 return new JavaUIException(JavaUIStatus.createError(IStatus.ERROR, message, t));
330         }
331
332         private static Map<IPath, String> loadOldForCompatibility() {
333                 HashMap<IPath, String> resultingOldLocations= new HashMap<IPath, String>();
334
335                 // in 3.0, the javadoc locations were stored as one big string in the preferences
336                 String string= PreferenceConstants.getPreferenceStore().getString(PREF_JAVADOCLOCATIONS);
337                 if (string != null && string.length() > 0) {
338                         byte[] bytes;
339                         try {
340                                 bytes= string.getBytes("UTF-8"); //$NON-NLS-1$
341                         } catch (UnsupportedEncodingException e) {
342                                 bytes= string.getBytes();
343                         }
344                         InputStream is= new ByteArrayInputStream(bytes);
345                         try {
346                                 loadFromStream(new InputSource(is), resultingOldLocations);
347                                 PreferenceConstants.getPreferenceStore().setValue(PREF_JAVADOCLOCATIONS, ""); //$NON-NLS-1$
348                                 return resultingOldLocations;
349                         } catch (CoreException e) {
350                                 JavaPlugin.log(e); // log but ignore
351                         } finally {
352                                 try {
353                                         is.close();
354                                 } catch (IOException e) {
355                                         // ignore
356                                 }
357                         }
358                 }
359
360                 // in 2.1, the Javadoc locations were stored in a file in the meta data
361                 // note that it is wrong to use a stream reader with XML declaring to be UTF-8
362                 try {
363                         final String STORE_FILE= "javadoclocations.xml"; //$NON-NLS-1$
364                         File file= JavaPlugin.getDefault().getStateLocation().append(STORE_FILE).toFile();
365                         if (file.exists()) {
366                                 Reader reader= null;
367                                 try {
368                                         reader= new FileReader(file);
369                                         loadFromStream(new InputSource(reader), resultingOldLocations);
370                                         file.delete(); // remove file after successful store
371                                         return resultingOldLocations;
372                                 } catch (IOException e) {
373                                         JavaPlugin.log(e); // log but ignore
374                                 } finally {
375                                         try {
376                                                 if (reader != null) {
377                                                         reader.close();
378                                                 }
379                                         } catch (IOException e) {}
380                                 }
381                         }
382                 } catch (CoreException e) {
383                         JavaPlugin.log(e); // log but ignore
384                 }
385
386                 // in 2.0, the Javadoc locations were stored as one big string in the persistent properties
387                 // note that it is wrong to use a stream reader with XML declaring to be UTF-8
388                 try {
389                         final QualifiedName QUALIFIED_NAME= new QualifiedName(JavaUI.ID_PLUGIN, "jdoclocation"); //$NON-NLS-1$
390
391                         IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
392                         String xmlString= root.getPersistentProperty(QUALIFIED_NAME);
393                         if (xmlString != null) { // only set when workspace is old
394                                 Reader reader= new StringReader(xmlString);
395                                 try {
396                                         loadFromStream(new InputSource(reader), resultingOldLocations);
397                                         root.setPersistentProperty(QUALIFIED_NAME, null); // clear property
398                                         return resultingOldLocations;
399                                 } finally {
400
401                                         try {
402                                                 reader.close();
403                                         } catch (IOException e) {
404                                                 // error closing reader: ignore
405                                         }
406                                 }
407                         }
408                 } catch (CoreException e) {
409                         JavaPlugin.log(e); // log but ignore
410                 }
411                 return resultingOldLocations;
412         }
413
414         private static void loadFromStream(InputSource inputSource, Map<IPath, String> oldLocations) throws CoreException {
415                 Element cpElement;
416                 try {
417                         DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
418                         parser.setErrorHandler(new DefaultHandler());
419                         cpElement = parser.parse(inputSource).getDocumentElement();
420                 } catch (SAXException e) {
421                         throw createException(e, CorextMessages.JavaDocLocations_error_readXML);
422                 } catch (ParserConfigurationException e) {
423                         throw createException(e, CorextMessages.JavaDocLocations_error_readXML);
424                 } catch (IOException e) {
425                         throw createException(e, CorextMessages.JavaDocLocations_error_readXML);
426                 }
427
428                 if (cpElement == null) return;
429                 if (!cpElement.getNodeName().equalsIgnoreCase(NODE_ROOT)) {
430                         return;
431                 }
432                 NodeList list= cpElement.getChildNodes();
433                 int length= list.getLength();
434                 for (int i= 0; i < length; ++i) {
435                         Node node= list.item(i);
436                         short type= node.getNodeType();
437                         if (type == Node.ELEMENT_NODE) {
438                                 Element element= (Element) node;
439                                 if (element.getNodeName().equalsIgnoreCase(NODE_ENTRY)) {
440                                         String varPath = element.getAttribute(NODE_PATH);
441                                         String varURL = element.getAttribute(NODE_URL);
442
443                                         oldLocations.put(Path.fromPortableString(varPath), varURL);
444                                 }
445                         }
446                 }
447         }
448
449         public static URL getJavadocLocation(IJavaElement element, boolean includeMemberReference) throws JavaModelException {
450                 URL baseLocation= getJavadocBaseLocation(element);
451                 if (baseLocation == null) {
452                         return null;
453                 }
454
455                 String urlString= baseLocation.toExternalForm();
456
457                 StringBuffer pathBuffer= new StringBuffer(urlString);
458                 if (!urlString.endsWith("/")) { //$NON-NLS-1$
459                         pathBuffer.append('/');
460                 }
461
462                 switch (element.getElementType()) {
463                         case IJavaElement.PACKAGE_FRAGMENT:
464                                 appendPackageSummaryPath((IPackageFragment) element, pathBuffer);
465                                 break;
466                         case IJavaElement.JAVA_PROJECT:
467                         case IJavaElement.PACKAGE_FRAGMENT_ROOT :
468                                 appendIndexPath(pathBuffer);
469                                 break;
470                         case IJavaElement.IMPORT_CONTAINER :
471                                 element= element.getParent();
472                                 //$FALL-THROUGH$
473                         case IJavaElement.COMPILATION_UNIT :
474                                 IType mainType= ((ICompilationUnit) element).findPrimaryType();
475                                 if (mainType == null) {
476                                         return null;
477                                 }
478                                 appendTypePath(mainType, pathBuffer);
479                                 break;
480                         case IJavaElement.CLASS_FILE :
481                                 appendTypePath(((IClassFile) element).getType(), pathBuffer);
482                                 break;
483                         case IJavaElement.TYPE :
484                                 appendTypePath((IType) element, pathBuffer);
485                                 break;
486                         case IJavaElement.FIELD :
487                                 IField field= (IField) element;
488                                 appendTypePath(field.getDeclaringType(), pathBuffer);
489                                 if (includeMemberReference) {
490                                         appendFieldReference(field, pathBuffer);
491                                 }
492                                 break;
493                         case IJavaElement.METHOD :
494                                 IMethod method= (IMethod) element;
495                                 appendTypePath(method.getDeclaringType(), pathBuffer);
496                                 if (includeMemberReference) {
497                                         appendMethodReference(method, pathBuffer);
498                                 }
499                                 break;
500                         case IJavaElement.INITIALIZER :
501                                 appendTypePath(((IMember) element).getDeclaringType(), pathBuffer);
502                                 break;
503                         case IJavaElement.IMPORT_DECLARATION :
504                                 IImportDeclaration decl= (IImportDeclaration) element;
505
506                                 if (decl.isOnDemand()) {
507                                         IJavaElement cont= JavaModelUtil.findTypeContainer(element.getJavaProject(), Signature.getQualifier(decl.getElementName()));
508                                         if (cont instanceof IType) {
509                                                 appendTypePath((IType) cont, pathBuffer);
510                                         } else if (cont instanceof IPackageFragment) {
511                                                 appendPackageSummaryPath((IPackageFragment) cont, pathBuffer);
512                                         }
513                                 } else {
514                                         IType imp= element.getJavaProject().findType(decl.getElementName());
515                                         appendTypePath(imp, pathBuffer);
516                                 }
517                                 break;
518                         case IJavaElement.PACKAGE_DECLARATION :
519                                 IJavaElement pack= element.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
520                                 if (pack != null) {
521                                         appendPackageSummaryPath((IPackageFragment) pack, pathBuffer);
522                                 } else {
523                                         return null;
524                                 }
525                                 break;
526                         default :
527                                 return null;
528                 }
529
530                 try {
531                         return new URL(pathBuffer.toString());
532                 } catch (MalformedURLException e) {
533                         JavaPlugin.log(e);
534                 }
535                 return null;
536         }
537
538         private static void appendPackageSummaryPath(IPackageFragment pack, StringBuffer buf) {
539                 String packPath= pack.getElementName().replace('.', '/');
540                 buf.append(packPath);
541                 buf.append("/package-summary.html"); //$NON-NLS-1$
542         }
543
544         private static void appendIndexPath(StringBuffer buf) {
545                 buf.append("index.html"); //$NON-NLS-1$
546         }
547
548         private static void appendTypePath(IType type, StringBuffer buf) {
549                 IPackageFragment pack= type.getPackageFragment();
550                 String packPath= pack.getElementName().replace('.', '/');
551                 String typePath= type.getTypeQualifiedName('.');
552                 if (packPath.length() > 0) {
553                         buf.append(packPath);
554                         buf.append('/');
555                 }
556                 buf.append(typePath);
557                 buf.append(".html"); //$NON-NLS-1$
558         }
559
560         private static void appendFieldReference(IField field, StringBuffer buf) {
561                 buf.append('#');
562                 buf.append(field.getElementName());
563         }
564
565         private static void appendMethodReference(IMethod meth, StringBuffer buf) throws JavaModelException {
566                 buf.append('#');
567                 buf.append(meth.getElementName());
568
569                 buf.append('(');
570                 String[] params= meth.getParameterTypes();
571                 IType declaringType= meth.getDeclaringType();
572                 boolean isVararg= Flags.isVarargs(meth.getFlags());
573                 int lastParam= params.length - 1;
574                 for (int i= 0; i <= lastParam; i++) {
575                         if (i != 0) {
576                                 buf.append(", "); //$NON-NLS-1$
577                         }
578                         String curr= Signature.getTypeErasure(params[i]);
579                         String fullName= JavaModelUtil.getResolvedTypeName(curr, declaringType);
580                         if (fullName != null) {
581                                 buf.append(fullName);
582                                 int dim= Signature.getArrayCount(curr);
583                                 if (i == lastParam && isVararg) {
584                                         dim--;
585                                 }
586                                 while (dim > 0) {
587                                         buf.append("[]"); //$NON-NLS-1$
588                                         dim--;
589                                 }
590                                 if (i == lastParam && isVararg) {
591                                         buf.append("..."); //$NON-NLS-1$
592                                 }
593                         }
594                 }
595                 buf.append(')');
596         }
597
598         public static String getBaseURL(IMember member) throws JavaModelException {
599                 if (member.isBinary()) {
600                         // Source attachment usually does not include Javadoc resources
601                         // => Always use the Javadoc location as base:
602                         URL baseURL= JavaUI.getJavadocLocation(member, false);
603                         if (baseURL != null) {
604                                 if (baseURL.getProtocol().equals(JAR_PROTOCOL)) {
605                                         // It's a JarURLConnection, which is not known to the browser widget.
606                                         // Let's start the help web server:
607                                         URL baseURL2= PlatformUI.getWorkbench().getHelpSystem().resolve(baseURL.toExternalForm(), true);
608                                         if (baseURL2 != null) { // can be null if org.eclipse.help.ui is not available
609                                                 baseURL= baseURL2;
610                                         }
611                                 }
612                                 return baseURL.toExternalForm();
613                         }
614                 } else {
615                         IResource resource= member.getResource();
616                         if (resource != null) {
617                                 /*
618                                  * Too bad: Browser widget knows nothing about EFS and custom URL handlers,
619                                  * so IResource#getLocationURI() does not work in all cases.
620                                  * We only support the local file system for now.
621                                  * A solution could be https://bugs.eclipse.org/bugs/show_bug.cgi?id=149022 .
622                                  */
623                                 IPath location= resource.getLocation();
624                                 if (location != null)
625                                         return location.toFile().toURI().toASCIIString();
626                         }
627                 }
628                 return null;
629         }
630
631
632 }