1 19 20 package org.netbeans.modules.javacore; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.io.BufferedInputStream ; 25 import java.io.File ; 26 import java.io.FileInputStream ; 27 import java.io.FileOutputStream ; 28 import java.io.IOException ; 29 import java.io.InputStream ; 30 import java.lang.ref.WeakReference ; 31 import java.net.MalformedURLException ; 32 import java.net.URL ; 33 import java.security.MessageDigest ; 34 import java.security.NoSuchAlgorithmException ; 35 import java.util.AbstractList ; 36 import java.util.ArrayList ; 37 import java.util.Arrays ; 38 import java.util.Collection ; 39 import java.util.Collections ; 40 import java.util.HashMap ; 41 import java.util.HashSet ; 42 import java.util.Iterator ; 43 import java.util.List ; 44 import java.util.Map ; 45 import java.util.Set ; 46 import java.util.logging.Level ; 47 import java.util.logging.Logger ; 48 import javax.jmi.reflect.InvalidObjectException; 49 import javax.jmi.reflect.RefBaseObject; 50 import org.netbeans.api.java.classpath.ClassPath; 51 import org.netbeans.api.java.queries.SourceForBinaryQuery; 52 import org.netbeans.api.java.queries.SourceLevelQuery; 53 import org.netbeans.api.mdr.MDRepository; 54 import org.netbeans.api.project.FileOwnerQuery; 55 import org.netbeans.jmi.javamodel.Array; 56 import org.netbeans.jmi.javamodel.CallableFeature; 57 import org.netbeans.jmi.javamodel.ClassDefinition; 58 import org.netbeans.jmi.javamodel.Codebase; 59 import org.netbeans.jmi.javamodel.CodebaseClass; 60 import org.netbeans.jmi.javamodel.Element; 61 import org.netbeans.jmi.javamodel.ElementPartKind; 62 import org.netbeans.jmi.javamodel.GenericElement; 63 import org.netbeans.jmi.javamodel.JavaClass; 64 import org.netbeans.jmi.javamodel.JavaModelPackage; 65 import org.netbeans.jmi.javamodel.JavaPackage; 66 import org.netbeans.jmi.javamodel.Parameter; 67 import org.netbeans.jmi.javamodel.ParameterizedType; 68 import org.netbeans.jmi.javamodel.Resource; 69 import org.netbeans.jmi.javamodel.TypeParameter; 70 import org.netbeans.jmi.javamodel.TypedElement; 71 import org.netbeans.jmi.javamodel.UnresolvedClass; 72 import org.netbeans.mdr.NBMDRepositoryImpl; 73 import org.netbeans.mdr.persistence.MOFID; 74 import org.netbeans.mdr.persistence.btreeimpl.btreestorage.BtreeFactory; 75 import org.netbeans.mdr.storagemodel.MdrStorage; 76 import org.netbeans.modules.javacore.classpath.FilterClassPathImplementation; 77 import org.netbeans.modules.javacore.classpath.MergedClassPathImplementation; 78 import org.netbeans.modules.javacore.internalapi.ExternalChange; 79 import org.netbeans.modules.javacore.internalapi.GuardedQuery; 80 import org.netbeans.modules.javacore.internalapi.JavaMetamodel; 81 import org.netbeans.modules.javacore.internalapi.ParsingListener; 82 import org.netbeans.modules.javacore.internalapi.ProgressSupport; 83 import org.netbeans.modules.javacore.jmiimpl.javamodel.JavaPackageClassImpl; 84 import org.netbeans.modules.javacore.jmiimpl.javamodel.MetadataElement; 85 import org.netbeans.modules.javacore.jmiimpl.javamodel.ParameterizedTypeImpl; 86 import org.netbeans.modules.javacore.jmiimpl.javamodel.ResourceClassImpl; 87 import org.netbeans.modules.javacore.jmiimpl.javamodel.ResourceImpl; 88 import org.netbeans.modules.javacore.parser.ArrayRef; 89 import org.netbeans.modules.javacore.parser.NameRef; 90 import org.netbeans.modules.javacore.parser.PrimitiveTypeRef; 91 import org.netbeans.modules.javacore.parser.TypeParamRef; 92 import org.netbeans.modules.javacore.parser.WildCardRef; 93 import org.netbeans.modules.javacore.scanning.FileScanner; 94 import org.netbeans.spi.java.classpath.ClassPathFactory; 95 import org.netbeans.spi.java.classpath.PathResourceImplementation; 96 import org.netbeans.spi.java.classpath.support.ClassPathSupport; 97 import org.openide.ErrorManager; 98 import org.openide.filesystems.FileObject; 99 import org.openide.filesystems.FileStateInvalidException; 100 import org.openide.filesystems.FileUtil; 101 import org.openide.filesystems.URLMapper; 102 import org.openide.loaders.DataObject; 103 import org.openide.loaders.DataObjectNotFoundException; 104 import org.openide.modules.InstalledFileLocator; 105 import org.openide.text.PositionBounds; 106 import org.openide.util.RequestProcessor; 107 108 112 public class JMManager extends JavaMetamodel implements PropertyChangeListener { 113 private static final String NAME_MAIN_EXTENT = "JavaCoreMain"; private static final String NAME_MAIN_STORAGE = "Main"; 116 private static final String PREFIX_EXTENT_CODEBASE = "codebase:"; private static final String PACKAGE_CODEBASE = "JavaModel"; private static final int THREAD_PRIORITY = Thread.MIN_PRIORITY; 119 120 private static final RequestProcessor EVENT_RP = new RequestProcessor("Parsing Event Queue"); private static final RequestProcessor SCANNING_RP = new RequestProcessor("Scanning Queue"); private static final RequestPoster RESOLVE_POSTER = new RequestPoster(SCANNING_RP); 123 private static final RequestPoster CLEANUP_POSTER = new RequestPoster(SCANNING_RP); 124 125 public static final boolean PERF_DEBUG = Boolean.getBoolean("perf.refactoring"); 127 public static final boolean PERF_TEST = Boolean.getBoolean("perf.refactoring.test"); 128 public static final boolean INCONSISTENCY_DEBUG = Boolean.getBoolean("javacore.debug.inconsistency"); 129 public static final boolean SCAN_DEBUG = Boolean.getBoolean("javacore.debug.scanning"); 130 public static final boolean TRANS_DEBUG = Boolean.getBoolean("javacore.debug.transactions"); 131 private static final boolean NO_SCAN = Boolean.getBoolean("netbeans.javacore.noscan"); 132 private static final int MDR_CACHE_SIZE = Integer.getInteger("org.netbeans.javacore.MDRCache.size", 256).intValue(); 134 private static final boolean DEBUG = false; 135 private static final String [] CP_TYPES = {ClassPath.BOOT, ClassPath.SOURCE, ClassPath.COMPILE}; 136 private static PropertyChangeListener indentListener; 137 138 142 public static final int BYTES4MD5 = 8192; 143 144 147 private static final String PREPARSED_LOCATION; 148 private static final HashSet PREPARSED_CACHE; 149 150 static { 151 String s = System.getProperty("prebuilt.storage.dir"); if (s == null) { 153 File f = InstalledFileLocator.getDefault().locate("./mdrstorage", "org.netbeans.modules.javacore", false); if (f != null) { 155 PREPARSED_LOCATION = f.getAbsolutePath() + "/"; } else { 157 PREPARSED_LOCATION = "./"; } 159 } else { 160 if (s.endsWith("/")) { PREPARSED_LOCATION = s; 162 } else { 163 PREPARSED_LOCATION = s + '/'; 164 } 165 } 166 PREPARSED_CACHE = new HashSet (); 167 File f = new File (PREPARSED_LOCATION); 168 File [] files = f.listFiles(); 169 if (files != null) { 170 for (int i = 0; i < files.length; i++) { 171 String name = files[i].getName(); 172 if (name.endsWith(".btd")) { 173 int pos = name.lastIndexOf("-"); 174 if (pos >= 0) { 175 PREPARSED_CACHE.add(name.substring(0, pos)); 176 } 177 } 178 } 179 } 180 } 181 182 private static final Map MDR_CACHE = new CacheClass(); 183 184 private static class CacheClass implements Map { 185 private final Object inner[] = new Object [MDR_CACHE_SIZE]; 186 private int size, cursor; 187 188 public CacheClass () {} 189 190 public Set keySet() { 191 throw new UnsupportedOperationException (); 192 } 193 194 public Set entrySet() { 195 throw new UnsupportedOperationException (); 196 } 197 198 public void putAll(Map t) { 199 throw new UnsupportedOperationException (); 200 } 201 202 public boolean isEmpty() { 203 return size == 0; 204 } 205 206 public boolean containsKey(Object key) { 207 throw new UnsupportedOperationException (); 208 } 209 210 public boolean containsValue(Object value) { 211 throw new UnsupportedOperationException (); 212 } 213 214 public Collection values() { 215 throw new UnsupportedOperationException (); 216 } 217 218 public Object put(Object key, Object value) { 219 if (inner[cursor] != value) { 220 cursor++; 221 if (size < MDR_CACHE_SIZE) { 222 size++; 223 } 224 if (cursor >= MDR_CACHE_SIZE) { 225 cursor = 0; 226 } 227 inner[cursor] = value; 228 } 229 return null; 230 } 231 232 public void clear() { 233 Arrays.fill(inner, null); 234 size = cursor = 0; 235 } 236 237 public int size() { 238 return size; 239 } 240 241 public Object get(Object key) { 242 throw new UnsupportedOperationException (); 243 } 244 245 public Object remove(Object key) { 246 throw new UnsupportedOperationException (); 247 } 248 } 249 250 251 private JavaModelPackage mainExtent; 252 private final HashMap sids = new HashMap (); 257 private final HashMap filesystems = new HashMap (); 259 private final HashMap extents = new HashMap (); 260 261 private final MergedClassPathImplementation cpImpl; 262 private final ClassPath classPath; 263 264 private static ProgressSupport progressSupport = null; 265 266 private Cache cpForFileObjectCache = new Cache(5); 267 private HashMap cpForFileObjectMap = new HashMap (10); 268 269 private static ErrorManager javamodelErr = ErrorManager.getDefault().getInstance("org.netbeans.javacore"); 271 private Set extentsToScan = new HashSet (); 272 273 private boolean cancelScan = false; 274 275 279 private static final MessageDigest md5digest; 280 private static final MessageDigest digest; 281 282 private static ThreadLocal documentLocks; 283 private static IndentationSettingsProvider settingsProvider; 284 285 private static ModifiedDOProvider modifiedDOProvider; 286 287 public static synchronized void setDocumentLocksCounter(ThreadLocal documentLocks) { 288 JMManager.documentLocks = documentLocks; 289 } 290 291 static synchronized ThreadLocal getDocumentLocksCounter() { 292 return documentLocks; 293 } 294 295 static { 296 try { 297 digest = MessageDigest.getInstance("SHA"); md5digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { 300 throw new RuntimeException ("Fatal error: " + e); } 302 } 303 304 public JMManager(MDRepository repository) { 305 super(repository, Codebase.class); 306 cpImpl = MergedClassPathImplementation.getDefault(); 307 cpImpl.addPropertyChangeListener(this); 308 classPath = ClassPathFactory.createClassPath (cpImpl); 309 classPath.addPropertyChangeListener (this); 310 } 311 312 private void init() { 313 if (mainExtent == null) { 314 repository.beginTrans(true); 315 boolean fail = true; 316 try { 317 int retry = 0; 318 String mainExtentSid = null; 319 String storageFileName = getFileName(NAME_MAIN_STORAGE); 320 while (mainExtent == null && retry < 2) { 321 try { 322 if (DEBUG) System.err.println("Initializing repository."); if (retry == 0) { 324 mainExtentSid = mountStorage(NAME_MAIN_STORAGE, storageFileName); } else { 326 mainExtentSid = rebootStorage(NAME_MAIN_STORAGE, storageFileName, mainExtentSid); } 328 JavaModelPackage main = (JavaModelPackage) repository.getExtent(NAME_MAIN_EXTENT); 329 if (main == null) { 330 NBMDRepositoryImpl nbRep = (NBMDRepositoryImpl) repository; 331 main = (JavaModelPackage) nbRep.createExtent(NAME_MAIN_EXTENT, findRootPackage(PACKAGE_CODEBASE), null, mainExtentSid); 332 } 333 mainExtent = main; 334 } catch (Exception e) { 335 retry++; 336 if (retry >= 2) { 337 JMManager.getLog().notify(e); 338 } else { 340 JMManager.getLog().log(ErrorManager.WARNING, "Rebooting Main storage because of a fatal error during storage mount."); JMManager.getLog().notify(ErrorManager.INFORMATIONAL, e); 342 } 343 } 344 } 345 fail = false; 346 } finally { 347 repository.endTrans(fail); 348 } 349 RepositoryUpdater.getDefault(); 350 } 351 } 352 353 359 public static ErrorManager getLog() { 360 return javamodelErr; 361 } 362 363 private String getDirName() { 364 NBMDRepositoryImpl nbRep = (NBMDRepositoryImpl) repository; 365 String fileName = nbRep.getParameter(BtreeFactory.STORAGE_FILE_NAME); 366 int li = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\')); 367 String folderName = getVersion(); 368 if (li > 0) { 369 folderName = fileName.substring(0, li + 1) + folderName; 370 } 371 return folderName; 372 } 373 374 public String getFileName(String name) { 375 String folderName = getDirName(); 376 new File (folderName).mkdirs(); 377 return folderName.concat("/").concat(name); } 379 380 private String mountStorage(String name, String fileName) { 381 HashMap properties = new HashMap (); 382 NBMDRepositoryImpl nbRep = (NBMDRepositoryImpl) repository; 383 properties.put(BtreeFactory.STORAGE_FILE_NAME, fileName); 384 properties.put(BtreeFactory.CACHE_INSTANCE, MDR_CACHE); String sid; 386 try { 387 if (DEBUG) System.out.println("mounting: " + fileName); sid = nbRep.mountStorage(nbRep.getParameter("storage"), properties); MdrStorage.ValuesObject values = nbRep.getMdrStorage().storageValues(sid); 390 values.store(NameRef.class.getName()); 391 values.store(TypeParamRef.class.getName()); 392 values.store(PrimitiveTypeRef.class.getName()); 393 values.store(WildCardRef.class.getName()); 394 values.store(ArrayRef.class.getName()); 395 396 return sid; 397 } catch (Exception e) { 398 throw (RuntimeException ) ErrorManager.getDefault().annotate(new RuntimeException (), e); 399 } 400 } 401 402 private String rebootStorage(String name, String fileName, String sid) { 403 NBMDRepositoryImpl nbRep = (NBMDRepositoryImpl) repository; 404 nbRep.disableEvents(); 405 nbRep.unmountStorage(sid); 406 nbRep.enableEvents(); 407 new File (fileName + ".btx").delete(); new File (fileName + ".btd").delete(); new File (fileName + ".btb").delete(); return mountStorage(name, fileName); 411 } 412 413 public ClassPath getClassPath() { 414 ClassPath result = ((ExclusiveMutex) ((NBMDRepositoryImpl) repository).getTransactionMutex()).getClassPath(); 415 416 if (result == null) { 418 result = FilterClassPathImplementation.createClassPath(Collections.singletonList(getMergedClassPath()), false); 419 } 420 421 return result; 422 } 423 424 public ClassPath getMergedClassPath() { 425 return classPath; 426 } 427 428 MergedClassPathImplementation getMergedClassPathImpl() { 429 return cpImpl; 430 } 431 432 public boolean mergedCPContains(FileObject fo) { 433 return cpImpl.contains(fo); 434 } 435 436 public boolean mergedCPContainsRoot(FileObject fo) { 437 return cpImpl.getRoots().contains(fo); 438 } 439 440 444 public void setClassPath(List cps) { 445 setClassPath(cps, false); 446 } 447 448 public void setClassPath(List cps, boolean preferSource) { 449 if (cps == null || cps.isEmpty()) return; 450 ((ExclusiveMutex) ((NBMDRepositoryImpl) repository).getTransactionMutex()).setClassPath(cps, preferSource); 451 } 452 453 public void setClassPath(ClassPath cp) { 454 setClassPath(Collections.singletonList(cp)); 455 } 456 457 public void setClassPath(Resource rsc) { 458 setClassPath(getFileObject(rsc)); 459 } 460 461 public void setClassPath(Resource rsc, boolean preferSource) { 462 setClassPath(getFileObject(rsc), preferSource); 463 } 464 465 private class CPList extends AbstractList implements Cache.CachedElement { 466 private final FileObject fo; 467 private final WeakReference inner[] = new WeakReference [CP_TYPES.length]; 468 469 public CPList(FileObject fo) { 470 this.fo = fo; 471 for (int i = 0; i < CP_TYPES.length; i++) { 472 ClassPath cp = ClassPath.getClassPath(fo, CP_TYPES[i]); 473 inner[i] = cp == null ? null : new WeakReference (cp); 474 } 475 cpForFileObjectMap.put(fo, this); 476 } 477 478 public Object get(int index) { 479 return inner[index] == null ? null : ((WeakReference ) inner[index]).get(); 480 } 481 482 public int size() { 483 return 3; 484 } 485 486 public boolean isValid() { 487 return true; 488 } 489 490 public void release() { 491 cpForFileObjectMap.remove(fo); 492 } 493 } 494 495 public void setClassPath(FileObject fo) { 496 setClassPath(fo, false); 497 } 498 499 public void setClassPath(FileObject fo, boolean preferSource) { 501 if (fo == null) return; 502 List cps = (List ) cpForFileObjectMap.get(fo); 503 if (cps == null) { 504 cps = new CPList(fo); 505 } 506 cpForFileObjectCache.put(cps); 507 setClassPath(cps, preferSource); 508 } 509 510 public JavaModelPackage getDefaultExtent() { 511 init(); 512 return mainExtent; 513 } 514 515 public void setSafeTrans(boolean isSafeTrans) { 516 getTransactionMutex().setSafeTrans(isSafeTrans); 517 } 518 519 public static ExclusiveMutex getTransactionMutex() { 520 return (ExclusiveMutex) ((NBMDRepositoryImpl) getDefaultRepository()).getTransactionMutex(); 521 } 522 523 public JavaModelPackage resolveJavaExtent(FileObject cpRoot) { 524 repository.beginTrans(false); 525 try { 526 synchronized (this) { 527 JavaModelPackage extent = getJavaExtent(cpRoot); 528 if (extent == null) { 529 ClassPath cp = ClassPath.getClassPath(cpRoot, ClassPath.SOURCE); 530 if (cp!=null) { 531 resolveCPRoot(cpRoot, false); 532 extent = (JavaModelPackage) extents.get(cpRoot); 533 if (FileOwnerQuery.getOwner(cpRoot) != null) { 534 try { 535 URL cpRootUrl = cpRoot.getURL(); 536 cpImpl.addClassPaths(new ClassPath[] {cp, ClassPath.getClassPath(cpRoot, ClassPath.COMPILE), ClassPath.getClassPath(cpRoot, ClassPath.BOOT)}); 537 } catch (FileStateInvalidException e) { 538 } 540 } 541 } 542 } 543 return extent; 544 } 545 } finally { 546 repository.endTrans(); 547 } 548 } 549 550 public synchronized JavaModelPackage getJavaExtent(FileObject cpRoot) { 551 if (cpImpl.getRoots().contains(cpRoot)) { 552 return (JavaModelPackage) extents.get(cpRoot); 553 } else { 554 return null; 555 } 556 } 557 558 public Resource getResource(FileObject fo) { 559 return getResource(fo, true); 560 } 561 562 public Resource getResource(FileObject fo, boolean force) { 563 if (fo.isVirtual() || !fo.isValid()) { 564 return null; 566 } 567 repository.beginTrans(false); 568 try { 569 FileObject cpRoot = this.cpImpl.findOwnerRoot(fo); 570 if (cpRoot==null && force) { 571 String ext=fo.getExt(); 572 ClassPath cp=null; 573 if ("java".equals(ext)) cp = ClassPath.getClassPath(fo, ClassPath.SOURCE); 575 else if ("class".equals(ext)) cp = ClassPath.getClassPath(fo, ClassPath.EXECUTE); 577 if (cp != null) { 578 cpRoot = cp.findOwnerRoot(fo); 579 } 580 } 581 Resource result = null; 582 if (cpRoot != null) { 583 String resourceName = getResourceName (cpRoot, fo); 584 result = getResource(cpRoot, resourceName); 585 } 586 return result; 587 } catch (Exception ex) { 588 ErrorManager.getDefault().notify(ex); 589 } finally { 590 repository.endTrans(); 591 } 592 return null; 593 } 594 595 public JavaPackage getPackage(FileObject fo) { 596 repository.beginTrans(false); 597 try { 598 FileObject cpRoot = this.cpImpl.findOwnerRoot (fo); 599 if (cpRoot == null) return null; 600 601 JavaModelPackage extent = getJavaExtent(cpRoot); 602 if (extent == null) return null; 603 604 String packageName = getResourceName (cpRoot, fo); 605 packageName = packageName.replace('/', '.'); 606 607 return ((JavaPackageClassImpl) extent.getJavaPackage()).findRealPackage(packageName); 608 } catch (Exception ex) { 609 ErrorManager.getDefault().notify(ex); 610 } finally { 611 repository.endTrans(); 612 } 613 return null; 614 } 615 616 public void registerExtChange(ExternalChange ch) { 617 getTransactionMutex().registerExtChange(ch); 618 } 619 620 public void registerUndoElement(ExternalChange ch) { 621 getTransactionMutex().registerUndoElement(ch); 622 } 623 624 public Resource getResource(FileObject cpRoot, String name) { 625 repository.beginTrans(false); 626 try { 627 if (cpRoot != null && cpRoot.isValid()) { 628 JavaModelPackage pck=resolveJavaExtent(cpRoot); 629 if (pck == null) { 630 return null; 631 } 632 ResourceClassImpl resClass=(ResourceClassImpl)pck.getResource(); 633 ResourceImpl result = (ResourceImpl) resClass.resolveResource(name, false); 634 635 if (result == null && name.endsWith(".class")) { String srcName = name.substring(0, name.length() - ".class".length()) + ".java"; if (cpRoot.getFileObject(srcName) != null) { 640 name = srcName; 641 result = (ResourceImpl) resClass.resolveResource(name, false); 642 } 643 } 644 646 if (result == null) { 647 result = (ResourceImpl) resClass.resolveResource(name, true, false); 648 if (result != null) { 649 if (!result.isValid()) return null; 650 FileObject fobj = getFileObject(result); 651 if (fobj != null) { 652 result.updateFromFileObject(fobj, false); 653 } else { 654 result.refDelete(); 655 return null; 656 } 657 } 658 } 659 return result; 660 } else { 661 return null; 662 } 663 } catch (Exception ex) { 664 ErrorManager.getDefault().notify(ex); 665 } finally { 666 repository.endTrans(); 667 } 668 669 return null; 670 } 671 672 public FileObject getFileObject(Resource res) { 673 if (res == null) return null; 674 repository.beginTrans(false); 675 try { 676 if (!res.isValid()) { 677 return null; 678 } 679 FileObject cpRoot = getCPRoot((JavaModelPackage) res.refImmediatePackage()); 680 if (cpRoot != null) { 681 FileObject result = cpRoot.getFileObject(res.getName()); 682 return result; 683 } 684 return null; 685 } catch (InvalidObjectException e) { 686 return null; 687 } finally { 688 repository.endTrans(); 689 } 690 } 691 692 public synchronized FileObject getCPRoot(JavaModelPackage javaModelPackage) { 693 return (FileObject) filesystems.get(javaModelPackage); 694 } 695 696 public DataObject getDataObject(Resource res) { 697 FileObject fo = getFileObject(res); 698 DataObject result = null; 699 if (fo != null) { 700 if (fo.isVirtual()) { 701 return null; 702 } 703 try { 704 result = DataObject.find(fo); 705 } catch (DataObjectNotFoundException e) { 706 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 707 result = null; 708 } 709 } 710 if (result != null && !result.isValid()) result = null; 711 return result; 712 } 713 714 public boolean waitScanFinished() { 715 if (NO_SCAN) return false; 716 boolean wait=false; 717 while (cpImpl.getUnresolvedRoots().length > 0) { 718 wait=true; 719 try { 720 boolean isStartupInProgress = JavaCoreModule.isStartupInProgress(); 721 ProgressDisplayer disp = ProgressDisplayer.getVisibleProgressDisplayer(); 722 if (SCAN_DEBUG) { 723 System.err.println("JMManager.waitScanFinished(), isStartupInProgress = " + isStartupInProgress); 724 System.err.println("JMManager.waitScanFinished(), getVisibleProgressDisplayer() = " + disp); 725 } 726 if (!isStartupInProgress && (disp == null)) { 727 SCANNING_RP.post(new Runnable () { 728 public void run() { 729 refreshCodebases(); 730 } 731 }, 0, THREAD_PRIORITY); 732 } 733 Thread.sleep(100); 734 } catch (InterruptedException e) { 735 } 736 } 737 return wait; 738 } 739 740 public boolean isScanInProgress() { 741 return ProgressDisplayer.getVisibleProgressDisplayer()!=null; 742 } 743 744 746 public boolean isElementGuarded(Element element) { 747 PositionBounds pos = getElementPosition(element); 748 if (pos == null) { 749 return false; 750 } 751 RefBaseObject refObj = element; 752 while ((refObj instanceof Element) && !(refObj instanceof Resource)) { 753 refObj = ((Element)refObj).refImmediateComposite(); 754 } 755 if (!(refObj instanceof Resource)) { 756 return false; 757 } 758 ResourceImpl resource = (ResourceImpl)refObj; 759 return GuardedQuery.isSectionGuarded(resource, pos); 760 } 761 762 764 public PositionBounds getElementPosition(Element element) { 765 return getElementPosition(element, false); 766 } 767 768 773 public PositionBounds getElementPosition(Element element, boolean inclDoc) { 774 if (element instanceof ParameterizedType) 775 element=((ParameterizedType)element).getDefinition(); 776 else if (element instanceof ParameterizedTypeImpl.Wrapper) 777 element=(Element)((ParameterizedTypeImpl.Wrapper)element).getWrappedObject(); 778 if (element instanceof MetadataElement) { 779 return ((MetadataElement) element).getPosition(inclDoc); 780 } else { 781 return null; 782 } 783 } 784 785 public PositionBounds getElementPartPosition(Element element, ElementPartKind part, int position) { 786 if (element instanceof ParameterizedType) 787 element=((ParameterizedType)element).getDefinition(); 788 else if (element instanceof ParameterizedTypeImpl.Wrapper) 789 element=(Element)((ParameterizedTypeImpl.Wrapper)element).getWrappedObject(); 790 if (element instanceof MetadataElement) { 791 return ((MetadataElement) element).getPartPosition(part, position); 792 } else { 793 return null; 794 } 795 } 796 797 public Element getElementByOffset(FileObject file,int offset) { 798 repository.beginTrans(false); 799 try { 800 Resource cr = getResource(file); 801 if (cr == null) { 802 return null; 803 } 804 return cr.getElementByOffset(offset); 805 } finally { 806 repository.endTrans(); 807 } 808 } 809 810 813 private static String getCBExtentName(String uri) { 814 return PREFIX_EXTENT_CODEBASE + uri; 815 } 816 817 void startResolution() { 818 if (SCAN_DEBUG) System.err.println("JMManager: startResolution1"); 819 RESOLVE_POSTER.post(new Runnable () { 820 public void run() { 821 if (SCAN_DEBUG) System.err.println("JMManager: startResolution2 - runnable"); 822 try { 823 resolveCodebases(); 824 } catch (Throwable e) { 825 ErrorManager.getDefault().notify(e); 826 } 827 if (SCAN_DEBUG) System.err.println("JMManager: startResolution3 - runnable"); 828 } 829 }); 830 if (SCAN_DEBUG) System.err.println("JMManager: startResolution4"); 831 } 832 833 836 protected void resolveCodebases() { 837 boolean fail = true; 838 try { 840 repository.beginTrans(true); 841 repository.endTrans(); 842 } catch (Throwable t) { 843 ErrorManager.getDefault().notify(t); 844 } 845 repository.beginTrans(true); 847 try { 848 ArrayList resources = new ArrayList (Arrays.asList((Object []) cpImpl.getUnresolvedRoots())); 849 this.getProgressSupport().fireProgressListenerStart(0,resources.size()); 851 for (Iterator it = resources.iterator(); it.hasNext() && !cancelScan;) { 852 try { 853 this.getProgressSupport().fireProgressListenerStep(); 854 } catch (Throwable t) { 855 JMManager.getLog().notify(t); 856 } 857 PathResourceImplementation resource = (PathResourceImplementation) it.next(); 858 URL url = resource.getRoots()[0]; 859 FileObject root = URLMapper.findFileObject(url); 860 if (root != null) { 861 URL rootURL; 862 try { 863 rootURL = root.getURL(); 864 } catch (FileStateInvalidException e) { 865 JMManager.getLog().notify(e); 866 rootURL = null; 867 } 868 if (!url.equals(rootURL)) { 869 JMManager.getLog().notify(new RuntimeException ("ClassPath returned the invalid (non-normalized) URL from getRoots(): " + url + ". This classpath element will not be scanned.")); cpImpl.removeRoot(resource); 871 continue; 872 } 873 resolveCPRoot(root, true); 874 } else { 875 cpImpl.removeRoot(resource); 878 } 879 } 880 fail = false; 881 } catch (RuntimeException e) { 882 ErrorManager.getDefault().notify(e); 883 } catch (AssertionError e) { 884 ErrorManager.getDefault().notify(e); 885 } finally { 886 repository.endTrans(fail); 887 this.getProgressSupport().fireProgressListenerStop(); 888 } 889 } 890 891 private void cleanUpCodebases () { 892 List rootsToReresolve = new ArrayList (); 893 getDefaultRepository().beginTrans(true); 894 boolean fail = true; 895 try { 896 synchronized (this) { 897 Set backup = new HashSet (sids.keySet()); 898 Set existingUnresolved = new HashSet (); 899 FileObject[] roots = this.classPath.getRoots(); 900 for (int i = 0; i < roots.length; i++) { 901 try { 902 String uriBase = roots[i].getURL().toString(); 903 if (!removeURI(backup, uriBase)) { 904 existingUnresolved.add(uriBase); 905 } 906 } catch (FileStateInvalidException e) { 907 JMManager.getLog().notify(ErrorManager.INFORMATIONAL, e); 908 } 909 } 910 PathResourceImplementation unresolved[] = this.cpImpl.getUnresolvedRoots(); 911 for (int i = 0; i < unresolved.length; i++) { 912 PathResourceImplementation resource = unresolved[i]; 913 URL url = resource.getRoots()[0]; 914 FileObject root = URLMapper.findFileObject(url); 915 if (root != null) { 916 try { 917 String uriBase = root.getURL().toString(); 918 if (!removeURI(backup, uriBase)) { 919 existingUnresolved.add(url.toString()); 920 } 921 } catch (FileStateInvalidException e) { 922 JMManager.getLog().notify(ErrorManager.INFORMATIONAL, e); 923 } 924 } 925 } 926 927 for (Iterator it = backup.iterator(); it.hasNext();) { 928 String uri = (String ) it.next (); 929 disposeCodebase(uri); 930 int index = uri.lastIndexOf('/'); if (index < uri.length()-1) { 934 String url = uri.substring(0,index+1); 935 if (existingUnresolved.remove(url)) { 936 try { 937 rootsToReresolve.add (ClassPathSupport.createResource(new URL (url))); 938 } catch (MalformedURLException mfe) { 939 ErrorManager.getDefault().notify(mfe); 940 } 941 } 942 } 943 } 944 } 945 fail = false; 946 } finally { 947 getDefaultRepository().endTrans(fail); 948 } 949 if (rootsToReresolve.size() > 0) { 950 cpImpl.addUnresolvedRoots (rootsToReresolve); 951 } 952 } 953 private boolean removeURI(Set uris, String uriBase) { 954 boolean removed = false; if (uris.remove(uriBase)) { 958 removed = true; 959 } 960 if (uris.remove(uriBase + "1.4")) { removed = true; 962 } 963 if (uris.remove(uriBase + "1.5")) { removed = true; 965 } 966 if (removed) { 967 return true; 968 } 969 String prefix = uriBase + "1."; Iterator it = uris.iterator(); 972 while (it.hasNext()) { 973 String uri = (String ) it.next(); 974 if (uri.startsWith(prefix)) { 975 it.remove(); 977 return true; 978 } 979 } 980 return false; 981 } 982 983 private void resolveCPRoot(FileObject root, boolean scanIfNeeded) { 984 if (root == null) return; 985 boolean fail = true; 986 if (!scanIfNeeded) getDefaultRepository().beginTrans(true); 987 try { 988 JavaModelPackage extent; 989 int state = 0; 990 synchronized (this) { 991 String uri = getRootURI(root); 992 String extentName = getCBExtentName(uri); 993 extent = (JavaModelPackage) repository.getExtent(extentName); 994 if (extent == null) { 995 state++; 996 init(); 997 int retry = 0; 998 String sid = null; 999 String storageName = getValidName(uri); 1000 String storageFileName = getFileName(storageName); 1001 String simpleName = getCodebaseSimpleName(root); 1002 while (extent == null && retry < 2) { 1003 try { 1004 boolean preparsedUsed = false; 1005 if (retry == 0) { 1006 if (simpleName != null) { 1007 preparsedUsed = usePreparsed(simpleName, root, getFileName(storageName)); 1008 if (preparsedUsed) { 1009 System.err.println("Using '" + uri + "' pre-parsed database!"); 1010 } 1011 } 1012 sid = mountStorage(storageName, storageFileName); 1013 } else { 1014 sid = rebootStorage(storageName, storageFileName, sid); 1015 } 1016 sids.put(uri, sid); 1017 if (!preparsedUsed) { 1018 extent = (JavaModelPackage) repository.getExtent(extentName); 1019 } 1020 if (extent == null && simpleName != null) { 1021 extent = (JavaModelPackage) repository.getExtent(getCBExtentName(simpleName)); if (extent != null) { 1023 preparsedUsed = true; 1024 } 1025 } 1026 NBMDRepositoryImpl nbRep = (NBMDRepositoryImpl) repository; 1027 if (extent == null) { 1028 state += 2; 1029 extent = (JavaModelPackage) nbRep.createExtent(extentName, findRootPackage(PACKAGE_CODEBASE), null, sid); 1030 ClassIndex.addIndex(extent, storageFileName); 1031 } else { 1032 Collection c = extent.getCodebase().refAllOfClass(); 1034 1035 if (preparsedUsed) { 1036 if (c.size() != 1) { 1042 throw new RuntimeException ("Not exactly one codebase in extent!"); } 1045 Codebase cb = (Codebase) c.iterator().next(); 1046 cb.setName(uri); 1047 cb.setTimestamp(FileUtil.getArchiveFile(root).lastModified().getTime()); 1048 nbRep.renameExtent(extent, extentName); 1049 } else { 1050 c.isEmpty(); 1053 } 1054 ((JavaPackageClassImpl) extent.getJavaPackage()).addAllRealPackages(); 1056 if (!ClassIndex.loadIndex(storageFileName, extent)) { 1057 state++; 1058 } 1059 if (preparsedUsed) { 1060 ClassIndex.getIndex(extent).setTimestamp(); 1061 } 1062 } 1063 } catch (Exception e) { 1064 sids.remove(uri); 1065 retry++; 1066 if (retry >= 2) { 1067 JMManager.getLog().notify(e); 1068 } else { 1069 JMManager.getLog().log(ErrorManager.WARNING, "Rebooting storage for " + root.getURL() + " because of a fatal error during storage mount."); JMManager.getLog().notify(ErrorManager.INFORMATIONAL, e); 1071 } 1072 } 1073 } 1074 extents.put(root, extent); 1075 filesystems.put(extent, root); 1076 } else { 1077 CodebaseClass cbClass = extent.getCodebase(); 1078 if (cbClass.refAllOfClass().isEmpty()) { 1079 state++; 1080 } else { 1081 Codebase cb = (Codebase) cbClass.refAllOfClass().iterator().next(); 1082 long timeStamp = cb.getTimestamp(); 1083 long fileTimeStamp; 1084 FileObject f = FileUtil.getArchiveFile(root); 1085 if (f != null) { 1086 fileTimeStamp = f.lastModified().getTime(); 1087 } else { 1088 fileTimeStamp = root.lastModified().getTime(); 1089 } 1090 if (timeStamp != 0 && fileTimeStamp != timeStamp) { 1091 state++; 1092 } 1093 } 1094 } 1095 } 1096 if (scanIfNeeded) { 1097 Resource[] resourcesToParse; 1098 if (state != 0 || extentsToScan.remove(extent)) { resourcesToParse = scanFiles(root, extent, state > 1); 1100 } else { 1102 resourcesToParse = new Resource[0]; 1103 } 1104 if (resourcesToParse != null) { 1106 this.cpImpl.classPathRootResolved(root.getURL()); 1107 if (resourcesToParse.length > 0) { 1108 for (int i = 0; i < resourcesToParse.length; i++) { 1109 setClassPath(resourcesToParse[i]); 1110 traverseResource(resourcesToParse[i]); 1111 setClassPath(resourcesToParse[i], true); 1112 traverseResource(resourcesToParse[i]); 1113 } 1114 } 1115 } 1116 } else { 1117 extentsToScan.add(extent); 1118 } 1119 fail = false; 1120 } catch (FileStateInvalidException e) { 1121 ErrorManager.getDefault().notify(e); 1122 } finally { 1123 if (!scanIfNeeded) getDefaultRepository().endTrans(fail); 1124 } 1125 } 1126 1127 private void traverseResource(Resource resource) { 1128 for (Iterator it = resource.getClassifiers().iterator(); it.hasNext();) { 1129 traverseClass((JavaClass) it.next()); 1130 } 1131 } 1132 1133 private void traverseGenericElement(GenericElement element) { 1134 for (Iterator it = element.getTypeParameters().iterator(); it.hasNext();) { 1135 ((TypeParameter) it.next()).getSuperClass(); 1136 } 1137 } 1138 1139 private void traverseCallableFeature(CallableFeature element) { 1140 for (Iterator it = element.getParameters().iterator(); it.hasNext();) { 1141 ((Parameter) it.next()).getType(); 1142 } 1143 } 1144 1145 private void traverseClass(JavaClass cls) { 1146 traverseGenericElement(cls); 1147 JavaClass superClass = cls.getSuperClass(); 1148 if (superClass != null) traverseClass(superClass); 1149 for (Iterator it = cls.getInterfaces().iterator(); it.hasNext();) { 1150 traverseClass((JavaClass) it.next()); 1151 } 1152 Object [] features=cls.getContents().toArray(); 1153 for (int i=0;i<features.length;i++) { 1154 Object temp = features[i]; 1155 if (temp instanceof JavaClass) { 1156 traverseClass((JavaClass) temp); 1157 } else if (temp instanceof GenericElement) { 1158 traverseGenericElement((GenericElement) temp); 1159 if (temp instanceof CallableFeature) { 1160 traverseCallableFeature((CallableFeature) temp); 1161 } 1162 } else if (temp instanceof TypedElement) { 1163 ((TypedElement) temp).getType(); 1164 } 1165 } 1166 } 1167 1168 Resource[] scanFiles(FileObject root, JavaModelPackage extent, boolean isInitial) { 1170 CodebaseClass cbClass = extent.getCodebase(); 1171 if (cbClass.refAllOfClass().isEmpty()) { 1172 cbClass.createCodebase(getRootURI(root), 0, false, null); 1173 } 1174 Codebase cb = (Codebase) cbClass.refAllOfClass().iterator().next(); 1175 try { 1176 URL url = root.getURL(); 1177 String uri = null; 1178 long startT = 0, endT; 1179 if (PERF_DEBUG || PERF_TEST) { 1180 startT = 0; 1181 startT = System.currentTimeMillis(); 1182 uri = url.toString(); 1183 } 1184 String sourceLevel = SourceLevelQuery.getSourceLevel(root); 1185 Resource[] resources = new FileScanner(url,sourceLevel,cb).scan(); 1186 if (PERF_DEBUG || PERF_TEST) { 1187 endT = System.currentTimeMillis(); 1188 System.out.println("PERF: '" + uri + "' scanning takes " + (endT - startT) + " ms."); 1190 if (PERF_TEST) { 1191 try { 1192 Class c = Class.forName("org.netbeans.performance.test.utilities.LoggingScanClasspath",true,Thread.currentThread().getContextClassLoader()); java.lang.reflect.Method m = c.getMethod("reportScanOfFile", new Class [] {String .class, Long .class}); Object o = m.invoke(c.newInstance(), new Object [] {new String (uri), new Long (endT - startT)}); 1195 } catch (Exception e) { 1196 e.printStackTrace(System.err); 1197 } 1198 } 1199 } 1200 return resources; 1201 } catch (Exception ex) { 1202 ErrorManager.getDefault().notify(ex); 1203 } 1204 return null; 1205 } 1206 1207 private String getSourceLevel(FileObject root) { 1208 String result = SourceLevelQuery.getSourceLevel(root); 1209 return result == null ? "" : result; 1210 } 1211 1212 public String getRootURI(FileObject root) { 1213 try { 1214 return root.getURL().toString() + getSourceLevel(root); 1215 } catch (FileStateInvalidException e) { 1216 throw (RuntimeException ) ErrorManager.getDefault().annotate(new RuntimeException (), e); 1217 } 1218 } 1219 1220 1221 private synchronized void disposeCodebase(String uri) { 1222 JavaModelPackage extent = (JavaModelPackage) repository.getExtent(getCBExtentName(uri)); 1223 if (extent != null) { 1224 ((JavaPackageClassImpl) extent.getJavaPackage()).removeAllRealPackages(); 1225 FileObject root = (FileObject) filesystems.remove(extent); 1226 ((NBMDRepositoryImpl) repository).unmountStorage((String ) sids.remove(uri)); 1227 JavaModelPackage oldExtent = (JavaModelPackage) extents.remove(root); 1228 if (!extent.equals(oldExtent)) { 1229 extents.put(root, oldExtent); 1230 } 1231 ClassIndex.removeIndex(extent); 1232 } 1233 } 1235 1236 private static String computeHash(String val) { 1237 int len = val.length(); 1238 byte[] data=new byte[len*2]; 1239 int offset=0; 1240 for (int i = 0; i < len; i++) { 1241 char ch = val.charAt(i); 1242 data[offset++]=(byte)(ch>>8); 1243 data[offset++]=(byte)ch; 1244 } 1245 byte[] hashCode = digest.digest(data); 1246 int len2 = hashCode.length; 1247 StringBuffer sb = new StringBuffer (len2 * 3); 1248 for (int i = 0; i < len2; i++) { 1249 String number = Integer.toHexString((int) hashCode[i] - Byte.MIN_VALUE); 1250 if (number.length() == 1) { 1251 sb.append('0'); 1252 } 1253 sb.append(number); 1254 } 1255 return sb.toString(); 1256 } 1257 1258 public void resetExtents() { 1259 cleanUpCodebases(); 1260 init(); 1261 1262 getDefaultRepository().beginTrans(true); 1263 boolean fail = true; 1264 try { 1265 synchronized (this) { 1266 Set sidSet = new HashSet (sids.keySet()); 1267 for (Iterator it = sidSet.iterator(); it.hasNext();) { 1268 String uri = (String ) it.next(); 1269 disposeCodebase(uri); 1270 } 1271 Iterator itr = cpImpl.getRoots().iterator(); 1272 while (itr.hasNext()) { 1273 Object obj = itr.next(); 1274 FileObject resource = (FileObject)obj; 1275 try { 1276 cpImpl.updateRoot(resource.getURL()); 1277 } catch (FileStateInvalidException e) { 1278 1279 } 1280 } 1281 resolveCodebases(); 1282 fail = false; 1283 } 1284 } finally { 1285 getDefaultRepository().endTrans(fail); 1286 Logger.getLogger("global").log(Level.INFO, "rescanning " + fail); 1287 if (!fail) 1288 startRescan(); 1289 } 1290 } 1291 1292 1293 public static String getValidName(String uri) { 1294 String hashCode = computeHash(uri); 1295 StringBuffer result = new StringBuffer (uri.length()); 1296 for (int i = 0; i < uri.length(); i++) { 1297 char z = uri.charAt(i); 1298 if ((z >= 'A' && z <= 'Z') || (z >= 'a' && z <= 'z') || (z >= '0' && z <= '9')) { 1299 result.append(z); 1300 } 1301 } 1302 int len = result.length(); 1303 return 'f' + hashCode + (len > 18 ? result.substring(len - 18) : result.toString()); 1304 } 1305 1306 1307 private synchronized boolean shouldOpenProgress() { 1308 return ProgressDisplayer.getVisibleProgressDisplayer()==null; 1309 } 1310 1311 public void propertyChange(PropertyChangeEvent evt) { 1312 String propName = evt.getPropertyName(); 1313 if (MergedClassPathImplementation.PROP_UNRESOLVED_ROOTS.equals(propName)) { 1314 if (JavaCoreModule.isStartupInProgress()) { 1315 return; 1316 } 1317 if (SCAN_DEBUG) System.err.println("JMManager: globalpath changed"); 1318 SCANNING_RP.post(new Runnable () { 1321 public void run() { 1322 refreshCodebases(); 1323 } 1324 }, 0, THREAD_PRIORITY); 1325 } 1326 else if (ClassPath.PROP_ROOTS.equals(propName)) { 1327 if (JavaCoreModule.isStartupInProgress()) { 1328 return; 1329 } 1330 if (SCAN_DEBUG) System.err.println("JMManager: posting cleanup"); 1331 CLEANUP_POSTER.post(new Runnable () { 1332 public void run() { 1333 try { 1334 if (SCAN_DEBUG) System.err.println("JMManager: cleanup running"); 1335 cleanUpCodebases(); 1336 } catch (Throwable e) { 1337 ErrorManager.getDefault().notify(e); 1338 } 1339 } 1340 }); 1341 } 1342 } 1343 1344 private void refreshCodebases() { 1345 if (NO_SCAN) return; 1346 if (shouldOpenProgress()) { 1347 if (SCAN_DEBUG) System.err.println("JMManager: refreshCodebases1"); 1348 if (cpImpl.getUnresolvedRoots().length > 0) { 1349 ProgressDisplayer.showProgress(JMManager.this); 1350 } 1351 } 1352 if (SCAN_DEBUG) System.err.println("JMManager: refreshCodebases2"); 1353 } 1354 1355 1361 public static String getResourceName (FileObject cpRoot, FileObject file) { 1362 assert cpRoot != null && file!= null; 1363 return FileUtil.getRelativePath(cpRoot, file); 1364 } 1365 1366 1367 1372 public String getResourceName (FileObject fo) { 1373 repository.beginTrans(false); 1374 try { 1375 FileObject cpRoot = this.cpImpl.findOwnerRoot (fo); 1376 if (cpRoot == null) { 1377 ClassPath cp = ClassPath.getClassPath(fo, ClassPath.SOURCE); 1378 if (cp!=null) { 1379 cpRoot = cp.findOwnerRoot(fo); 1380 } 1381 } 1382 String result = null; 1383 if (cpRoot != null) { 1384 result = getResourceName(cpRoot,fo); 1385 } 1386 return cpRoot == null ? null : getResourceName(cpRoot, fo); 1387 } catch (Exception ex) { 1388 ErrorManager.getDefault().notify(ex); 1389 } finally { 1390 repository.endTrans(); 1391 } 1392 return null; 1393 } 1394 1395 void removeListener() { 1396 classPath.removePropertyChangeListener(this); 1397 } 1398 1399 public ProgressSupport getProgressSupport() { 1400 if (progressSupport == null) { 1401 progressSupport = new ProgressSupport(); 1402 } 1403 return progressSupport; 1404 } 1405 1406 public void addModified(FileObject fo) { 1407 getTransactionMutex().addModified(fo); 1408 } 1409 1410 public boolean isModified(FileObject fo) { 1411 return getTransactionMutex().isModified(fo); 1412 } 1413 1414 public static void fireResourceParsed(final MOFID mofId) { 1415 1416 EVENT_RP.post(new Runnable () { 1417 public void run() { 1418 ArrayList listenersCopy; 1419 synchronized (listeners) { 1420 if (listeners.isEmpty()) return; 1421 listenersCopy = (ArrayList ) listeners.clone(); 1422 } 1423 Resource rsc = (Resource) ((NBMDRepositoryImpl) JavaMetamodel.getDefaultRepository()).getByMofId(mofId); 1424 if (rsc == null) return; 1425 for (Iterator it = listenersCopy.iterator(); it.hasNext();) { 1426 ParsingListener listener = (ParsingListener) it.next(); 1427 listener.resourceParsed(rsc); 1428 } 1429 } 1430 }); 1431 } 1432 1433 public void startupFinished() { 1434 if (cpImpl.getUnresolvedRoots().length > 0) { 1435 SCANNING_RP.post(new Runnable () { 1436 public void run() { 1437 refreshCodebases(); 1438 } 1439 }); 1440 } else { 1441 RequestProcessor.getDefault().post(new Runnable () { 1442 public void run() { 1443 init(); 1444 } 1445 }, 1500); 1446 } 1447 } 1448 1449 public ClassDefinition getSourceElementIfExists(ClassDefinition cls) { 1450 if (cls == null) return null; 1451 1452 repository.beginTrans(false); 1453 try { 1454 Resource rsc=cls.getResource(); 1455 1456 if (rsc!=null) { 1457 if (rsc.getName().endsWith(".java")) { 1458 return cls; 1459 } 1460 } else { 1461 return cls; 1462 } 1463 try { 1464 ClassDefinition realJcls=cls instanceof ParameterizedType ? ((ParameterizedType)cls).getDefinition(): cls; 1465 1466 if (!(realJcls instanceof UnresolvedClass) && !(realJcls instanceof Array)) { 1467 FileObject fo = getCPRoot((JavaModelPackage)realJcls.refImmediatePackage()); 1468 FileObject[] fos = SourceForBinaryQuery.findSourceRoots(fo.getURL()).getRoots(); 1469 String name=realJcls.getName(); 1470 1471 for (int i = 0; i < fos.length; i++) { 1472 FileObject fileObject = fos[i]; 1473 JavaModelPackage javaExtent = getJavaExtent(fileObject); 1474 ClassIndex ci = ClassIndex.getIndex(javaExtent); 1475 1476 if (ci != null) { 1477 JavaClass jc = ci.getClassByFqn(name); 1478 1479 if (jc != null && cls instanceof ParameterizedType) { 1480 ParameterizedType parType = (ParameterizedType)cls; 1481 ClassDefinition outerCls = parType.getDeclaringClass(); 1482 List pars = parType.getParameters(); 1483 1484 jc = javaExtent.getParameterizedType().resolveParameterizedType(jc, pars, outerCls instanceof ParameterizedType ? (ParameterizedType)outerCls : null); 1485 if (parType instanceof ParameterizedTypeImpl) { 1486 ParameterizedTypeImpl parTypeImpl = (ParameterizedTypeImpl)parType; 1487 ParameterizedTypeImpl newTypeImpl = (ParameterizedTypeImpl)jc; 1488 int size = pars.size(); 1489 1490 for (int j=0;j<size;j++) { 1491 newTypeImpl.setWildCardStatus(j,parTypeImpl.getWildCardStatus(j)); 1492 } 1493 } 1494 } 1495 if (jc != null) { 1496 return jc; 1497 } 1498 } 1499 } 1500 } 1501 } catch (Exception e) { 1502 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 1503 } 1504 return cls; 1505 } finally { 1506 repository.endTrans(); 1507 } 1508 } 1509 1510 1515 public static void initIndentation() { 1516 if (MetadataElement.getIndentSpace() != -1) { 1517 return; 1518 } 1519 IndentationSettingsProvider settingsProvider = getIndentationSettingsProvider(); 1520 if (settingsProvider == null) { 1521 setIndentSpace(4, true); 1522 formatCurlies(false); 1523 formatParenthesis(false); 1524 return; 1525 } 1526 Boolean tabs = (Boolean ) settingsProvider.getPropertyValue("expandTabs"); Integer spaces = (Integer ) settingsProvider.getPropertyValue("spacesPerTab"); if (spaces == null || tabs == null) { 1529 setIndentSpace(4, true); 1530 } else { 1531 setIndentSpace(spaces.intValue(), tabs.booleanValue()); 1532 } 1533 Boolean newlineBrace = (Boolean ) settingsProvider.getPropertyValue("javaFormatNewlineBeforeBrace"); if (newlineBrace == null) { 1535 formatCurlies(false); 1536 } else { 1537 formatCurlies(newlineBrace.booleanValue()); 1538 } 1539 Boolean parenthesisSpace = (Boolean ) settingsProvider.getPropertyValue("javaFormatSpaceBeforeParenthesis"); if (parenthesisSpace == null) { 1541 formatParenthesis(false); 1542 } else { 1543 formatParenthesis(parenthesisSpace.booleanValue()); 1544 } 1545 } 1546 1547 1554 private static void formatCurlies(boolean breakBefore) { 1555 int[] curlies = { 1556 MetadataElement.CLASS_OPEN_CURLY, 1557 MetadataElement.BODY_OPEN_CURLY, 1558 MetadataElement.ARRAY_OPEN_CURLY, 1559 MetadataElement.BLOCK_OPEN_CURLY 1560 }; 1561 String before = breakBefore ? "ni" : "s"; for (int i = 0; i < curlies.length; i++) { 1563 MetadataElement.setFormattingFor(curlies[i], before, MetadataElement.getFormattingFor(curlies[i])[2]); 1564 } 1565 } 1566 1567 1574 private static void formatParenthesis(boolean parenthesisSpace) { 1575 int[] parenthesis = { 1576 MetadataElement.PAR_OPEN_BRACKET, 1577 }; 1578 String before = parenthesisSpace ? "s" : ""; for (int i = 0; i < parenthesis.length; i++) { 1580 MetadataElement.setFormattingFor(parenthesis[i], before, MetadataElement.getFormattingFor(parenthesis[i])[2]); 1581 } 1582 } 1583 1584 1591 public static void setIndentSpace(int spaces, boolean expandTabs) { 1592 MetadataElement.setIndentSpace(spaces, expandTabs); 1593 } 1594 1595 1608 public static boolean copyStorage(String in, String out, boolean force) { 1609 long startTime = 0; 1610 if (PERF_DEBUG) startTime = System.currentTimeMillis(); 1611 1612 String [] ext = new String [] { "btd", "btx", "cdx" }; 1614 for (int i = 0; i < ext.length; i++) { 1616 File f = new File (in + '.' + ext[i]); 1617 if (!f.exists()) { 1618 return false; 1620 } 1621 } 1622 1623 if (!force) { 1624 boolean doCopy = false; 1625 for (int i = 0; i < ext.length; i++) { 1626 File f = new File (out + '.' + ext[i]); 1627 if (!f.exists()) { 1628 doCopy = true; 1629 break; 1630 } 1631 } 1632 if (!doCopy) return false; 1633 } 1634 for (int i = 0; i < ext.length; i++) { 1635 FileInputStream fis = null; 1636 FileOutputStream fos = null; 1637 try { 1638 fis = new FileInputStream (new File (in + '.' + ext[i])); 1639 fos = new FileOutputStream (new File (out + '.' + ext[i])); 1640 byte[] buf = new byte[65535]; 1641 int j = 0; 1642 while ((j = fis.read(buf)) != -1) { 1643 fos.write(buf, 0, j); 1644 } 1645 } catch (Exception e) { 1646 System.out.println("copyStorage failed: " + e.getMessage()); e.printStackTrace(); 1648 return false; 1649 } finally { 1650 try { 1651 if (fis != null) 1652 fis.close(); 1653 if (fos != null) 1654 fos.close(); 1655 } catch (IOException e) { 1656 System.out.println("copyStorage failed: " + e.getMessage()); e.printStackTrace(); 1658 return false; 1659 } 1660 } 1661 } 1662 if (PERF_DEBUG) System.err.println("PERF: Copy of " + in + " took " + (System.currentTimeMillis() - startTime) + " ms."); return true; 1665 } 1666 1667 1679 private static boolean usePreparsed(String simpleName, FileObject root, String storageName) { 1680 try { 1681 if (simpleName != null) { 1682 FileObject archiveRoot = FileUtil.getArchiveFile(root); 1683 String toCopy = PREPARSED_LOCATION + simpleName + "-" + computePreparsedHash(FileUtil.toFile(archiveRoot), BYTES4MD5); return copyStorage(toCopy, storageName, false); 1685 } 1686 } catch (IOException e) { 1687 ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, e.getMessage()); 1688 } 1689 return false; 1690 } 1691 1692 private static String getCodebaseSimpleName(FileObject root) { 1693 try { 1694 String uri = root.getURL().toString(); 1695 if (uri.endsWith("!/")) { String simpleName = uri.substring(0, uri.length() - 2); 1697 int pos = simpleName.lastIndexOf('/'); 1698 if (pos >= 0) simpleName = simpleName.substring(pos + 1); 1699 pos = simpleName.lastIndexOf('.'); 1700 if (pos >= 0) simpleName = simpleName.substring(0, pos); 1701 if (PREPARSED_CACHE.contains(simpleName)) { 1702 return simpleName; 1703 } 1704 } 1705 } catch (FileStateInvalidException e) { 1706 ErrorManager.getDefault().notify(e); 1707 } 1708 return null; 1709 } 1710 1711 1721 public static String computePreparsedHash(File file, int len) throws IOException { 1722 StringBuffer sb = new StringBuffer (32); 1723 InputStream stream = new BufferedInputStream (new FileInputStream (file)); 1724 try { 1725 byte[] input = new byte[len]; 1726 stream.read(input); 1727 byte[] hash = md5digest.digest(input); 1728 for (int i = 0; i < hash.length; i++) { 1729 String s = Integer.toHexString(hash[i] - Byte.MIN_VALUE); 1730 if (s.length() == 1) sb.append('0'); 1731 sb.append(s); 1732 } 1733 } finally { 1734 stream.close(); 1735 } 1736 return sb.toString(); 1737 } 1738 1739 public static synchronized void setIndentationSettingsProvider(IndentationSettingsProvider p) { 1740 if (p == null) { 1741 settingsProvider.removePropertyChangeListener(indentListener); 1742 indentListener = null; 1743 } else if (settingsProvider != null && indentListener != null) { 1744 settingsProvider.removePropertyChangeListener(indentListener); 1746 p.addPropertyChangeListener(indentListener); 1747 } 1748 settingsProvider = p; 1749 } 1750 1751 private static synchronized IndentationSettingsProvider getIndentationSettingsProvider() { 1752 if (settingsProvider != null && indentListener == null) { indentListener = new PropertyChangeListener () { 1754 public void propertyChange(PropertyChangeEvent evt) { 1757 if ("spacesPerTab".equals(evt.getPropertyName())) { setIndentSpace(((Integer ) evt.getNewValue()).intValue(), MetadataElement.isExpandTab()); 1759 } else if ("expandTabs".equals(evt.getPropertyName())) { setIndentSpace(MetadataElement.getIndentSpace(), ((Boolean ) evt.getNewValue()).booleanValue()); 1761 } else if ("javaFormatNewlineBeforeBrace".equals(evt.getPropertyName())) { formatCurlies(((Boolean ) evt.getNewValue()).booleanValue()); 1763 } else if ("javaFormatSpaceBeforeParenthesis".equals(evt.getPropertyName())) { formatParenthesis(((Boolean ) evt.getNewValue()).booleanValue()); 1765 } 1766 } 1767 }; 1768 settingsProvider.addPropertyChangeListener(indentListener); 1769 } 1770 return settingsProvider; 1771 } 1772 1773 private static String defaultEncoding; 1774 1775 public static String getDefaultEncoding() { 1776 return defaultEncoding; 1777 } 1778 1779 public static void setDefaultEncoding(String enc) { 1780 defaultEncoding = enc; 1781 } 1782 1783 public void startRescan() { 1784 ((RescanAction) RescanAction.get(RescanAction.class)).performAction(); 1785 } 1786 1787 void cancelScanning() { 1788 cancelScan = true; 1789 } 1790 1791 public static abstract class ModifiedDOProvider { 1792 private ModifiedDOProvider delegate; 1793 private boolean assigned; 1794 1795 public final DataObject getModifiedDataObject(FileObject fo) { 1796 DataObject result = getModifiedDOImpl(fo); 1797 if (result == null && delegate != null) { 1798 result = delegate.getModifiedDataObject(fo); 1799 } 1800 return result; 1801 } 1802 1803 protected abstract DataObject getModifiedDOImpl(FileObject fo); 1804 1805 public static synchronized void setModifiedDOProvider(ModifiedDOProvider provider) { 1806 assert !provider.assigned : "Cannot set the same ModifiedDOProvider twice."; provider.delegate = modifiedDOProvider; 1808 modifiedDOProvider = provider; 1809 provider.assigned = true; 1810 } 1811 1812 public static synchronized ModifiedDOProvider getModifiedDOProvider() { 1813 return modifiedDOProvider; 1814 } 1815 } 1816} 1817 | Popular Tags |