1 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.eclipse.core.runtime.CoreException; 32 import org.eclipse.core.runtime.IPath; 33 import org.eclipse.core.runtime.IProgressMonitor; 34 import org.eclipse.core.runtime.IStatus; 35 import org.eclipse.core.runtime.Path; 36 import org.eclipse.core.runtime.QualifiedName; 37 import org.eclipse.core.runtime.Status; 38 import org.eclipse.core.runtime.SubProgressMonitor; 39 import org.eclipse.core.runtime.jobs.Job; 40 41 import org.eclipse.core.resources.IWorkspaceRoot; 42 import org.eclipse.core.resources.IWorkspaceRunnable; 43 import org.eclipse.core.resources.ResourcesPlugin; 44 45 import org.eclipse.jface.preference.IPreferenceStore; 46 47 import org.eclipse.jdt.core.Flags; 48 import org.eclipse.jdt.core.IClassFile; 49 import org.eclipse.jdt.core.IClasspathAttribute; 50 import org.eclipse.jdt.core.IClasspathContainer; 51 import org.eclipse.jdt.core.IClasspathEntry; 52 import org.eclipse.jdt.core.ICompilationUnit; 53 import org.eclipse.jdt.core.IField; 54 import org.eclipse.jdt.core.IImportDeclaration; 55 import org.eclipse.jdt.core.IJavaElement; 56 import org.eclipse.jdt.core.IJavaProject; 57 import org.eclipse.jdt.core.IMember; 58 import org.eclipse.jdt.core.IMethod; 59 import org.eclipse.jdt.core.IPackageFragment; 60 import org.eclipse.jdt.core.IPackageFragmentRoot; 61 import org.eclipse.jdt.core.IType; 62 import org.eclipse.jdt.core.JavaCore; 63 import org.eclipse.jdt.core.JavaModelException; 64 import org.eclipse.jdt.core.Signature; 65 66 import org.eclipse.jdt.internal.corext.CorextMessages; 67 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 68 69 import org.eclipse.jdt.ui.JavaUI; 70 import org.eclipse.jdt.ui.PreferenceConstants; 71 72 import org.eclipse.jdt.internal.ui.JavaPlugin; 73 import org.eclipse.jdt.internal.ui.JavaUIException; 74 import org.eclipse.jdt.internal.ui.JavaUIStatus; 75 import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter; 76 import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathSupport; 77 import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement; 78 79 import org.w3c.dom.Element ; 80 import org.w3c.dom.Node ; 81 import org.w3c.dom.NodeList ; 82 import org.xml.sax.InputSource ; 83 import org.xml.sax.SAXException ; 84 85 public class JavaDocLocations { 86 87 public static final String ARCHIVE_PREFIX= "jar:"; private static final String PREF_JAVADOCLOCATIONS= "org.eclipse.jdt.ui.javadoclocations"; public static final String PREF_JAVADOCLOCATIONS_MIGRATED= "org.eclipse.jdt.ui.javadoclocations.migrated"; 91 92 private static final String NODE_ROOT= "javadoclocation"; private static final String NODE_ENTRY= "location_01"; private static final String NODE_PATH= "path"; private static final String NODE_URL= "url"; 97 private static final QualifiedName PROJECT_JAVADOC= new QualifiedName(JavaUI.ID_PLUGIN, "project_javadoc_location"); 99 public static void migrateToClasspathAttributes() { 100 final Map oldLocations= loadOldForCompatibility(); 101 if (oldLocations.isEmpty()) { 102 IPreferenceStore preferenceStore= PreferenceConstants.getPreferenceStore(); 103 preferenceStore.setValue(PREF_JAVADOCLOCATIONS, ""); preferenceStore.setValue(PREF_JAVADOCLOCATIONS_MIGRATED, true); 105 return; 106 } 107 108 Job job= new Job(CorextMessages.JavaDocLocations_migratejob_name) { 109 protected IStatus run(IProgressMonitor monitor) { 110 try { 111 IWorkspaceRunnable runnable= new IWorkspaceRunnable() { 112 public void run(IProgressMonitor pm) throws CoreException { 113 updateClasspathEntries(oldLocations, pm); 114 IPreferenceStore preferenceStore= PreferenceConstants.getPreferenceStore(); 115 preferenceStore.setValue(PREF_JAVADOCLOCATIONS, ""); preferenceStore.setValue(PREF_JAVADOCLOCATIONS_MIGRATED, true); 117 } 118 }; 119 new WorkbenchRunnableAdapter(runnable).run(monitor); 120 } catch (InvocationTargetException e) { 121 JavaPlugin.log(e); 122 } catch (InterruptedException e) { 123 } 125 return Status.OK_STATUS; 126 } 127 }; 128 job.schedule(); 129 } 130 131 final static void updateClasspathEntries(Map oldLocationMap, IProgressMonitor monitor) throws JavaModelException { 132 IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); 133 IJavaProject[] javaProjects= JavaCore.create(root).getJavaProjects(); 134 try { 135 monitor.beginTask(CorextMessages.JavaDocLocations_migrate_operation, javaProjects.length); 136 for (int i= 0; i < javaProjects.length; i++) { 137 IJavaProject project= javaProjects[i]; 138 String projectJavadoc= (String ) oldLocationMap.get(project.getPath()); 139 if (projectJavadoc != null) { 140 try { 141 setProjectJavadocLocation(project, projectJavadoc); 142 } catch (CoreException e) { 143 } 145 } 146 147 IClasspathEntry[] rawClasspath= project.getRawClasspath(); 148 boolean hasChange= false; 149 for (int k= 0; k < rawClasspath.length; k++) { 150 IClasspathEntry updated= getConvertedEntry(rawClasspath[k], project, oldLocationMap); 151 if (updated != null) { 152 rawClasspath[k]= updated; 153 hasChange= true; 154 } 155 } 156 if (hasChange) { 157 project.setRawClasspath(rawClasspath, new SubProgressMonitor(monitor, 1)); 158 } else { 159 monitor.worked(1); 160 } 161 } 162 } finally { 163 monitor.done(); 164 } 165 } 166 167 private static IClasspathEntry getConvertedEntry(IClasspathEntry entry, IJavaProject project, Map oldLocationMap) { 168 IPath path= null; 169 switch (entry.getEntryKind()) { 170 case IClasspathEntry.CPE_SOURCE: 171 case IClasspathEntry.CPE_PROJECT: 172 return null; 173 case IClasspathEntry.CPE_CONTAINER: 174 convertContainer(entry, project, oldLocationMap); 175 return null; 176 case IClasspathEntry.CPE_LIBRARY: 177 path= entry.getPath(); 178 break; 179 case IClasspathEntry.CPE_VARIABLE: 180 path= JavaCore.getResolvedVariablePath(entry.getPath()); 181 break; 182 default: 183 return null; 184 } 185 if (path == null) { 186 return null; 187 } 188 IClasspathAttribute[] extraAttributes= entry.getExtraAttributes(); 189 for (int i= 0; i < extraAttributes.length; i++) { 190 if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals(extraAttributes[i].getName())) { 191 return null; 192 } 193 } 194 String libraryJavadocLocation= (String ) oldLocationMap.get(path); 195 if (libraryJavadocLocation != null) { 196 CPListElement element= CPListElement.createFromExisting(entry, project); 197 element.setAttribute(CPListElement.JAVADOC, libraryJavadocLocation); 198 return element.getClasspathEntry(); 199 } 200 return null; 201 } 202 203 private static void convertContainer(IClasspathEntry entry, IJavaProject project, Map oldLocationMap) { 204 try { 205 IClasspathContainer container= JavaCore.getClasspathContainer(entry.getPath(), project); 206 if (container == null) { 207 return; 208 } 209 210 IClasspathEntry[] entries= container.getClasspathEntries(); 211 boolean hasChange= false; 212 for (int i= 0; i < entries.length; i++) { 213 IClasspathEntry curr= entries[i]; 214 IClasspathEntry updatedEntry= getConvertedEntry(curr, project, oldLocationMap); 215 if (updatedEntry != null) { 216 entries[i]= updatedEntry; 217 hasChange= true; 218 } 219 } 220 if (hasChange) { 221 BuildPathSupport.requestContainerUpdate(project, container, entries); 222 } 223 } catch (CoreException e) { 224 } 226 } 227 228 231 public static void setProjectJavadocLocation(IJavaProject project, URL url) { 232 try { 233 String location= url != null ? url.toExternalForm() : null; 234 setProjectJavadocLocation(project, location); 235 } catch (CoreException e) { 236 JavaPlugin.log(e); 237 } 238 } 239 240 private static void setProjectJavadocLocation(IJavaProject project, String url) throws CoreException { 241 project.getProject().setPersistentProperty(PROJECT_JAVADOC, url); 242 } 243 244 public static URL getProjectJavadocLocation(IJavaProject project) { 245 try { 246 String prop= project.getProject().getPersistentProperty(PROJECT_JAVADOC); 247 if (prop == null) { 248 return null; 249 } 250 return new URL (prop); 251 } catch (CoreException e) { 252 JavaPlugin.log(e); 253 } catch (MalformedURLException e) { 254 JavaPlugin.log(e); 255 } 256 return null; 257 } 258 259 260 public static URL getLibraryJavadocLocation(IClasspathEntry entry) { 261 if (entry == null) { 262 throw new IllegalArgumentException ("Entry must not be null"); } 264 265 int kind= entry.getEntryKind(); 266 if (kind != IClasspathEntry.CPE_LIBRARY && kind != IClasspathEntry.CPE_VARIABLE) { 267 throw new IllegalArgumentException ("Entry must be of kind CPE_LIBRARY or CPE_VARIABLE"); } 269 270 IClasspathAttribute[] extraAttributes= entry.getExtraAttributes(); 271 for (int i= 0; i < extraAttributes.length; i++) { 272 IClasspathAttribute attrib= extraAttributes[i]; 273 if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals(attrib.getName())) { 274 try { 275 return new URL (attrib.getValue()); 276 } catch (MalformedURLException e) { 277 return null; 278 } 279 } 280 } 281 return null; 282 } 283 284 public static URL getJavadocBaseLocation(IJavaElement element) throws JavaModelException { 285 if (element.getElementType() == IJavaElement.JAVA_PROJECT) { 286 return getProjectJavadocLocation((IJavaProject) element); 287 } 288 289 IPackageFragmentRoot root= JavaModelUtil.getPackageFragmentRoot(element); 290 if (root == null) { 291 return null; 292 } 293 294 if (root.getKind() == IPackageFragmentRoot.K_BINARY) { 295 IClasspathEntry entry= root.getRawClasspathEntry(); 296 if (entry == null) { 297 return null; 298 } 299 if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { 300 entry= getRealClasspathEntry(root.getJavaProject(), entry.getPath(), root.getPath()); 301 if (entry == null) { 302 return null; 303 } 304 } 305 return getLibraryJavadocLocation(entry); 306 } else { 307 return getProjectJavadocLocation(root.getJavaProject()); 308 } 309 } 310 311 private static IClasspathEntry getRealClasspathEntry(IJavaProject jproject, IPath containerPath, IPath libPath) throws JavaModelException { 312 IClasspathContainer container= JavaCore.getClasspathContainer(containerPath, jproject); 313 if (container != null) { 314 IClasspathEntry[] entries= container.getClasspathEntries(); 315 for (int i= 0; i < entries.length; i++) { 316 IClasspathEntry curr= entries[i]; 317 IClasspathEntry resolved= JavaCore.getResolvedClasspathEntry(curr); 318 if (resolved != null && libPath.equals(resolved.getPath())) { 319 return curr; } 321 } 322 } 323 return null; } 325 326 327 329 private static JavaUIException createException(Throwable t, String message) { 330 return new JavaUIException(JavaUIStatus.createError(IStatus.ERROR, message, t)); 331 } 332 333 private static Map loadOldForCompatibility() { 334 HashMap resultingOldLocations= new HashMap (); 335 336 String string= PreferenceConstants.getPreferenceStore().getString(PREF_JAVADOCLOCATIONS); 338 if (string != null && string.length() > 0) { 339 byte[] bytes; 340 try { 341 bytes= string.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { 343 bytes= string.getBytes(); 344 } 345 InputStream is= new ByteArrayInputStream (bytes); 346 try { 347 loadFromStream(new InputSource (is), resultingOldLocations); 348 PreferenceConstants.getPreferenceStore().setValue(PREF_JAVADOCLOCATIONS, ""); return resultingOldLocations; 350 } catch (CoreException e) { 351 JavaPlugin.log(e); } finally { 353 try { 354 is.close(); 355 } catch (IOException e) { 356 } 358 } 359 } 360 361 try { 364 final String STORE_FILE= "javadoclocations.xml"; File file= JavaPlugin.getDefault().getStateLocation().append(STORE_FILE).toFile(); 366 if (file.exists()) { 367 Reader reader= null; 368 try { 369 reader= new FileReader (file); 370 loadFromStream(new InputSource (reader), resultingOldLocations); 371 file.delete(); return resultingOldLocations; 373 } catch (IOException e) { 374 JavaPlugin.log(e); } finally { 376 try { 377 if (reader != null) { 378 reader.close(); 379 } 380 } catch (IOException e) {} 381 } 382 } 383 } catch (CoreException e) { 384 JavaPlugin.log(e); } 386 387 try { 390 final QualifiedName QUALIFIED_NAME= new QualifiedName(JavaUI.ID_PLUGIN, "jdoclocation"); 392 IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); 393 String xmlString= root.getPersistentProperty(QUALIFIED_NAME); 394 if (xmlString != null) { Reader reader= new StringReader (xmlString); 396 try { 397 loadFromStream(new InputSource (reader), resultingOldLocations); 398 root.setPersistentProperty(QUALIFIED_NAME, null); return resultingOldLocations; 400 } finally { 401 402 try { 403 reader.close(); 404 } catch (IOException e) { 405 } 407 } 408 } 409 } catch (CoreException e) { 410 JavaPlugin.log(e); } 412 return resultingOldLocations; 413 } 414 415 private static void loadFromStream(InputSource inputSource, Map oldLocations) throws CoreException { 416 Element cpElement; 417 try { 418 DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 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("/")) { 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 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"); } 543 544 private static void appendIndexPath(StringBuffer buf) { 545 buf.append("index.html"); } 547 548 private static void appendTypePath(IType type, StringBuffer buf) { 549 IPackageFragment pack= type.getPackageFragment(); 550 String packPath= pack.getElementName().replace('.', '/'); 551 String typePath= JavaModelUtil.getTypeQualifiedName(type); 552 buf.append(packPath); 553 buf.append('/'); 554 buf.append(typePath); 555 buf.append(".html"); } 557 558 private static void appendFieldReference(IField field, StringBuffer buf) { 559 buf.append('#'); 560 buf.append(field.getElementName()); 561 } 562 563 private static void appendMethodReference(IMethod meth, StringBuffer buf) throws JavaModelException { 564 buf.append('#'); 565 buf.append(meth.getElementName()); 566 567 buf.append('('); 568 String [] params= meth.getParameterTypes(); 569 IType declaringType= meth.getDeclaringType(); 570 boolean isVararg= Flags.isVarargs(meth.getFlags()); 571 int lastParam= params.length - 1; 572 for (int i= 0; i <= lastParam; i++) { 573 if (i != 0) { 574 buf.append(", "); } 576 String curr= Signature.getTypeErasure(params[i]); 577 String fullName= JavaModelUtil.getResolvedTypeName(curr, declaringType); 578 if (fullName != null) { 579 buf.append(fullName); 580 int dim= Signature.getArrayCount(curr); 581 if (i == lastParam && isVararg) { 582 dim--; 583 } 584 while (dim > 0) { 585 buf.append("[]"); dim--; 587 } 588 if (i == lastParam && isVararg) { 589 buf.append("..."); } 591 } 592 } 593 buf.append(')'); 594 } 595 596 597 } 598 | Popular Tags |