1 19 package org.netbeans.modules.javacore.jmiimpl.javamodel; 20 21 import java.beans.PropertyChangeListener ; 22 import java.beans.PropertyChangeSupport ; 23 import java.io.File ; 24 import java.io.IOException ; 25 import java.io.OutputStream ; 26 import java.io.Reader ; 27 import java.lang.reflect.Modifier ; 28 import java.util.*; 29 import java.util.regex.Pattern ; 30 import javax.jmi.reflect.*; 31 import javax.swing.text.Position ; 32 import javax.swing.text.StyledDocument ; 33 import org.netbeans.jmi.javamodel.*; 34 import org.netbeans.lib.java.parser.*; 35 import org.netbeans.api.mdr.MDRepository; 36 import org.netbeans.mdr.NBMDRepositoryImpl; 37 import org.netbeans.mdr.handlers.AttrListWrapper; 38 import org.netbeans.mdr.persistence.StorageException; 39 import org.netbeans.mdr.storagemodel.StorableObject; 40 import org.netbeans.modules.javacore.internalapi.JavaMetamodel; 41 import org.netbeans.modules.javacore.*; 42 import org.netbeans.modules.javacore.parser.*; 43 import org.netbeans.modules.javacore.parser.Util; 44 import org.openide.ErrorManager; 45 import org.openide.filesystems.FileLock; 46 import org.openide.filesystems.FileObject; 47 import org.openide.loaders.DataObject; 48 import org.openide.text.CloneableEditorSupport; 49 import org.openide.text.NbDocument; 50 import org.openide.text.PositionBounds; 51 import org.openide.text.PositionRef; 52 import org.netbeans.modules.javacore.scanning.ClassUpdater; 53 import org.netbeans.modules.javacore.scanning.JavaUpdater; 54 55 60 public abstract class ResourceImpl extends SemiPersistentElement implements Resource { 61 public static boolean READ_ONLY = false; 63 public static final int HAS_GENERICS = 1; 65 public static final int HAS_ENUMS = 2; 66 public static final int HAS_ANNOTATIONTYPES = 4; 67 public static final int HAS_ANNOTATION = 8; 68 public static final int HAS_SYNTAX_ERROR = 16; 69 public static final int IS_FROM_CLASSFILE = 0x80000000; 71 72 public static final String CLASSIFIERS_ATTR = "classifiers"; 74 private static final ElementInfo DEFAULT_INFO = new ResourceInfo(null, ResourceInfo.RESOURCE_TYPE, null, null, null); 75 76 private static final String lineSeparator = System.getProperty("line.separator"); private static final boolean lfOnly = "\n".equals(lineSeparator); private static final Pattern lineSepPattern = Pattern.compile("\r?\n"); 80 private LightAttrList classifiers = null; 81 private LightAttrList imports = null; 82 private FileObject fileToDeleteOnRollback = null; 83 84 private MultipartId packageIdentifier = null; 85 86 private boolean elementsInited = false; 87 88 private DiffList invertedDiffs = null; 89 90 private String lastSourceText; 92 private boolean isFromDoc; 93 private FileObject fobj; 95 96 private DiffList extDiffs; 97 98 private String rbText = null; 100 private List rbList = null; 101 102 private List errors = null; 103 104 105 public ResourceImpl(StorableObject s) { 106 super(s); 107 } 108 109 private static String lastPackageName = null; 110 private static JavaPackage lastPackage = null; 111 private static JavaPackageClass lastPackageProxy = null; 112 113 public void _setPackageName(String name) { 114 if (JMManager.INCONSISTENCY_DEBUG) System.err.println("ResourceImpl: Setting package name of resource " + getName() + " to " + name); 115 JavaPackage oldPackage = null; 116 try { 117 oldPackage = (JavaPackage) ((NBMDRepositoryImpl) repository()).getHandler(((StorableObject) _getDelegate()).getImmediateComposite()); 118 } catch (StorageException e) { 119 ErrorManager.getDefault().notify(e); 120 } 121 JavaPackageClassImpl pkgProxy = (JavaPackageClassImpl) ((JavaModelPackage) refImmediatePackage()).getJavaPackage(); 122 if (oldPackage != null) { 123 if (name.equals(oldPackage.getName())) return; 124 oldPackage.getResources().remove(this); 125 } 126 if (lastPackage == null || !name.equals(lastPackageName) || !pkgProxy.equals(lastPackageProxy)) { 127 lastPackage = pkgProxy.resolveRealPackage(name); 128 lastPackageName = name; 129 lastPackageProxy = pkgProxy; 130 } 131 lastPackage.getResources().add(this); 132 } 133 134 public void setPackageName(String name) { 135 String oldName = getPackageName(); 136 if (!name.equals(oldName)) { 137 MultipartIdClass proxy = ((JavaModelPackage) refImmediatePackage()).getMultipartId(); 138 setPackageIdentifier(proxy.createMultipartId(name, null, null)); 139 } 140 } 141 142 private void setPkgNameAndUpdateIdx(String name) { 143 if (isInitialized() && !isNew()) { 144 getElementInfo().hardRefAST(); 145 } 146 _setPackageName(name); 147 for (Iterator it = getClassifiers().iterator(); it.hasNext();) { 148 Object temp = it.next(); 149 if (temp instanceof JavaClassImpl) { 150 JavaClassImpl cls = (JavaClassImpl) temp; 151 String interName = name.length() == 0 ? "" : name + '.'; 152 cls.internalSetName(interName.concat(cls.getSimpleName())); 153 } 154 } 155 } 156 157 public Collection getReferences() { 158 return Collections.EMPTY_LIST; 159 } 160 161 public boolean classifiersInited() { 162 return classifiers != null; 163 } 164 165 public void reinitClassifiers() { 166 assert classifiers!=null; 167 classifiers.setInnerList(getPersistentClassifiers(), false); 168 } 169 170 public List getClassifiers() { 171 if (checkModCount() && !(isSafeTrans() && isPersisted())) checkUpToDate(false,false,true); 172 if (classifiers == null) { 173 classifiers = createChildrenList(CLASSIFIERS_ATTR, (AttrListWrapper) super_getClassifiers(), null, CHANGED_CLASSIFIERS); } 175 return classifiers; 176 } 177 178 public List getPersistentClassifiers() { 179 AttrListWrapper list = (AttrListWrapper) super_getClassifiers(); 180 list.setAttrName(CLASSIFIERS_ATTR); return list; 182 } 183 184 protected abstract List super_getClassifiers(); 185 186 public List getNakedClassifiers() { 187 try { 188 return (List) ((StorableObject) _getDelegate()).getAttribute(CLASSIFIERS_ATTR); } catch (StorageException e) { 190 throw (GeneralException) ErrorManager.getDefault().annotate(new GeneralException(e.getMessage()), e); 191 } 192 } 193 194 public String getPackageName() { 195 if (!isSafeTrans() && checkModCount()) checkUpToDate(false,false,true); 196 JavaPackage pkg = (JavaPackage) _realImmediateComposite(); 197 return pkg == null ? null : pkg.getName(); 198 } 199 200 202 207 protected void matchPersistent(ElementInfo info) { 208 super.matchPersistent(info); 209 if (!isPersisted()) { 210 setPersisted(true); 211 } 212 processMembers(getClassifiers(), ((ResourceInfo) info).classes); 213 } 214 215 public boolean isPersisted() { 216 return _getDelegate().getSlot1() != null; 217 } 218 219 public void setPersisted(boolean persisted) { 220 _getDelegate().setSlot1(persisted ? "" : null); 221 } 222 223 protected ElementInfo getDefaultInfo() { 224 return DEFAULT_INFO; 225 } 226 227 229 protected void matchElementInfo(ElementInfo newInfo) { 230 Iterator classIt; 231 ResourceInfo astInfo; 232 int i=0; 233 234 super.matchElementInfo(newInfo); 235 astInfo=(ResourceInfo)newInfo; 236 if (imports != null) { 237 processMembers(getImports(),astInfo.imports); 238 } 239 resetASTElements(); 240 } 241 242 protected void resetChildren() { 243 super.resetChildren(); 244 if (childrenInited) { 245 resetASTElements(); 246 initChildren(true); 247 } 248 } 249 250 protected List getInitedChildren() { 251 List list=new ArrayList(); 252 if (childrenInited) { 253 list.addAll(getImports()); 254 list.addAll(getClassifiers()); 255 } 256 if (elementsInited) { 257 addIfNotNull(list, packageIdentifier); 258 } 259 return list; 260 } 261 262 public List getChildren() { 263 List list = new ArrayList(); 264 addIfNotNull(list, getPackageIdentifier()); 265 list.addAll(getImports()); 266 list.addAll(getClassifiers()); 267 return list; 268 } 269 270 274 public List getImports() { 275 checkUpToDate(); 276 if (!childrenInited) { 277 initChildren(); 278 } 279 return imports; 280 } 281 282 public void setName(String name) { 283 assert !name.startsWith("/") : "Resource name cannot start with /"; super_setName(name); 287 } 288 289 public void setTimestamp(long timestamp) { 290 super_setTimestamp(timestamp); 291 } 292 293 300 public void setTimestamp(long timestamp, boolean isFromMemory) { 301 setTimestamp(timestamp); 302 setFromMemory(isFromMemory); 303 } 304 305 private void setFromMemory(boolean fromMemory) { 306 _getDelegate().setSlot2(fromMemory ? "" : null); 307 } 308 309 313 public boolean isFromMemory() { 314 return _getDelegate().getSlot2() != null; 315 } 316 317 protected abstract void super_setTimestamp(long timestamp); 318 319 protected abstract void super_setName(String name); 320 321 protected void initChildren() { 322 initChildren(false); 323 } 324 325 private void initChildren(boolean rebuild) { 326 childrenInited = false; 327 328 ClassInfo classes[] = ((ResourceInfo) getElementInfo()).classes; 329 if (getClassifiers().size() != classes.length) { 331 fixMembers(getPersistentClassifiers(), classes); 332 reinitClassifiers(); 333 } else { 334 Iterator it = getClassifiers().iterator(); 335 for (int i = 0; i < classes.length; i++) { 336 SemiPersistentElement element = (SemiPersistentElement) it.next(); 337 if (!element.infoIdenticalTo(classes[i])) { 338 element.setElementInfo(classes[i]); 339 } 340 } 341 } 342 343 imports = createChildrenList(imports, "imports", ((ResourceInfo) getElementInfo()).imports, CHANGED_IMPORTS, rebuild); 345 childrenInited = true; 346 347 if (elementsInited) { 348 initASTElements(); 349 } 350 351 fireImportsInited(); 352 } 353 354 protected void initASTElements() { 355 elementsInited = false; 356 357 if (!childrenInited) { 358 initChildren(); 359 } 360 ResourceInfo info = (ResourceInfo) getElementInfo(); 361 packageIdentifier = (MultipartId) initOrCreate(packageIdentifier, info.getTypeAST(this)); 362 elementsInited = true; 363 } 364 365 protected void resetASTElements() { 366 if (elementsInited) { 367 if (packageIdentifier != null) { 368 MultipartId temp = packageIdentifier; 369 packageIdentifier = null; 370 temp.refDelete(); 371 } 372 elementsInited = false; 373 } 374 } 375 376 public int getStatus() { 377 _lock(false); 378 try { 379 if (getName().endsWith(".class")) { return IS_FROM_CLASSFILE; 381 } else { 382 MDRParser parser = getParser(); 383 int res = parser.getJavaFeatures(); 384 if (parser.hasSyntaxError()) { 385 res |= HAS_SYNTAX_ERROR; 386 } 387 return res; 388 } 389 } finally { 390 _unlock(); 391 } 392 } 393 394 public List getErrors() { 395 _lock(false); 396 try { 397 if (errors == null) { 398 errors = new ErrorList(); 399 } 400 return errors; 401 } finally { 402 _unlock(); 403 } 404 } 405 406 public void resetErrors() { 407 if (errors != null) { 408 _lock(false); 409 try { 410 errors = null; 411 } finally { 412 _unlock(); 413 } 414 } 415 } 416 417 private ResourceInfo getResInfoFromClassFile() { 418 Iterator iter = getPersistentClassifiers().iterator(); 419 FileObject resFile = JavaMetamodel.getManager().getFileObject(this); 420 FileObject folder = resFile.getParent(); 421 ArrayList clsInfo = new ArrayList(); 422 ClassFileInfoUtil cfiu = new ClassFileInfoUtil(); 423 while (iter.hasNext()) { 424 Object elem = iter.next(); 425 if (elem instanceof JavaClassImpl) { 426 JavaClassImpl jc = (JavaClassImpl) elem; 427 ClassInfo inf = cfiu.createClassInfo (folder, jc.getSimpleName(), -1); 428 if (inf != null) 429 clsInfo.add(inf); 430 } } return new ResourceInfo(null, ResourceInfo.RESOURCE_TYPE, this, (ClassInfo[]) clsInfo.toArray(new ClassInfo[clsInfo.size()]), null); 433 } 434 435 void initResource() { 436 checkUpToDate(false, true, false); 437 } 438 439 protected void objectChanged(int mask) { 440 if (disableChanges) return; 441 if (!isChanged()) { 442 ElementInfo info = getElementInfo(); 443 if (info.getASTree() == null && info != getDefaultInfo()) { 444 throw new UnsupportedOperationException ("This object is immutable."); } 446 ((ExclusiveMutex) _getMdrStorage().getRepositoryMutex()).registerChange(this); 447 } 448 super.objectChanged(mask); 449 } 450 451 public void updateFromFileObject(FileObject fo, boolean force) { 452 boolean fail = true; 453 _lock(true); 454 try { 455 checkUpToDate(fo, force, false, false, false); 456 fail = false; 457 } finally { 458 _unlock(fail); 459 } 460 } 461 462 PositionBounds getFeaturePosition(FeatureImpl feature) { 463 if (!isValid()) 464 return null; 465 466 MDRParser parser = getParser(); 467 if (parser == null) 468 return null; 469 if (parser.mofidToBounds == null) { 470 MDRepository repository = repository(); 472 repository.beginTrans(false); 473 try { 474 parser.mofidToBounds = new HashMap(); 475 if (((JMManager) JavaMetamodel.getManager()).getTransactionMutex().getClassPath() == null) { 476 JavaMetamodel.getManager().setClassPath(this); 477 } 478 for (Iterator iter = getClassifiers().iterator(); iter.hasNext(); ) { 479 cachePositions(parser, (MetadataElement)iter.next()); 480 } 481 } catch (InvalidObjectException e) { 482 } finally { 484 repository.endTrans(false); 485 } 486 } 487 return parser.mofidToBounds == null ? null : (PositionBounds) parser.mofidToBounds.get(feature._getMofId()); 488 } 489 490 private void cachePositions(MDRParser parser, MetadataElement f) { 491 ASTree tree = f.getASTree(); 492 if (tree != null) 493 parser.mofidToBounds.put(f._getMofId(), parser.createBounds(tree, tree, false)); 494 if (f instanceof JavaClassImpl) { 495 Object [] features=((JavaClassImpl)f).getFeatures().toArray(); 496 for (int i=0;i<features.length;i++) { 497 cachePositions(parser, (MetadataElement)features[i]); 498 } 499 } 500 } 501 502 public RuntimeException alreadyCheckingStackTrace; 503 504 private void resetAST(MDRParser parser) { 505 try { 506 alreadyChecking = true; 507 alreadyCheckingStackTrace = new RuntimeException (); 508 ClassIndex classIndex=ClassIndex.getIndex((JavaModelPackage)refOutermostPackage()); 509 Set ids=new HashSet(60); 510 TokenIterator tokens; 511 int idIndexes[]; 512 int token; 513 int i=0; 514 Iterator idIt; 515 516 parser.getASTree(); 517 tokens=new TokenIterator(parser); 518 while((token=tokens.getNextTokenType())!=0) { 519 if (token==ParserTokens.IDENTIFIER) { 520 ids.add(tokens.getIdentifierText()); 521 } 522 } 523 idIndexes=new int[ids.size()]; 524 idIt=ids.iterator(); 525 while(idIt.hasNext()) { 526 idIndexes[i++]=idIt.next().hashCode(); 527 } 528 classIndex.setIdentifiers(this,idIndexes); 529 updateMetadata(parser.enterMembers()); 530 } catch (IOException ex) { 531 ErrorManager.getDefault().notify(ex); 532 } finally { 533 alreadyChecking = false; 534 } 535 } 536 537 public FileObject getFileObject() { 538 FileObject fo = JMManager.getManager().getFileObject(this); 539 if (fo != null) { 540 if (fo.isVirtual()) { 541 this.fobj = null; 542 return null; 543 } 544 } 545 if (fo == null) { 546 fo = this.fobj; 547 } else if (JMManager.PERF_DEBUG && !fo.equals(this.fobj) && this.fobj != null) { 548 System.err.println("FileObject for resource " + getName() + " changed from " + this.fobj.toString() + " to " + fo.toString()); } 550 if (fo != null && !fo.isValid()) fo = null; 551 this.fobj = fo; 552 return fo; 553 } 554 555 public MDRParser createMDRParser(FileObject fobj, boolean resetSourceText) { 556 if (fobj == null) { 557 fobj = getFileObject(); 558 if (fobj == null) { 559 JMManager.getLog().log(ErrorManager.WARNING, "FileObject not found for resource: " + getName()); 560 return null; 561 } 562 } 563 if (resetSourceText || lastSourceText == null) { 564 if (!resetSourceText && isInitialized()) { 565 System.err.println("Resource is initialized, but lastSourceText == null."); 566 Thread.dumpStack(); 567 } 568 MDRParser result = new MDRParser(this, fobj, null, false); 569 lastSourceText = result.getSourceText(); 570 isFromDoc = result.isFromDocument(); 571 return result; 572 } else { 573 return new MDRParser(this, fobj, lastSourceText, isFromDoc); 574 } 575 } 576 577 586 boolean checkUpToDate(boolean initIfOutOfDate, boolean initialize, boolean canUpdate) { 587 FileObject fobj = JavaMetamodel.getManager().getFileObject(this); 588 589 if (fobj==null) { 590 JMManager.getLog().log(ErrorManager.WARNING, "FileObject not found for resource: " + getName()); 591 return true; 592 } 593 return checkUpToDate(fobj, false, initialize, initIfOutOfDate, canUpdate); 594 } 595 596 public boolean alreadyChecking = false; 597 598 610 private boolean checkUpToDate(FileObject fobj, boolean force, boolean initialize, boolean initIfOutOfDate, boolean canUpdate) { 611 if (!alreadyChecking && !isChanged()) { 613 canUpdate |= checkAndUpdateModCount(); 614 try { 615 alreadyChecking = true; 616 alreadyCheckingStackTrace = new RuntimeException (); 617 long timestamp; 618 if (canUpdate) { 619 timestamp = fobj.lastModified().getTime(); 620 621 if (!force && timestamp == getTimestamp()) { 626 force = isFromMemory() && !Util.isModified(fobj); 627 } 628 630 } else { 636 timestamp = getTimestamp(); 637 if (force) { 638 JMManager.getTransactionMutex().addModified(fobj); 642 } 643 } 644 645 boolean isOutOfDate = force || getTimestamp() != timestamp; 646 boolean shouldUpdate = canUpdate && isOutOfDate; 647 boolean shouldParse = initialize || (initIfOutOfDate && !isPersisted()) || (shouldUpdate && (initIfOutOfDate || isInitialized())); 648 if (shouldUpdate || shouldParse) { 649 if (getName().endsWith(".java")) { directUpdate(fobj, shouldUpdate, shouldParse, timestamp); 651 } else { 652 directClassFileUpdate(fobj, isOutOfDate, shouldParse); 655 } 656 return false; 657 } else { 658 if (lastSourceText == null && getName().endsWith(".java")) { createMDRParser(fobj, true); 660 } 661 } 662 } finally { 663 alreadyChecking = false; 664 } 665 } 666 return true; 667 } 668 669 private void directClassFileUpdate(FileObject fobj, boolean isOutOfDate, boolean shouldParse) { 670 if (isOutOfDate) { 671 boolean changes = disableChanges; 672 disableChanges = true; 673 try { 674 ClassUpdater.updateIndex(this,fobj); 675 } finally { 676 disableChanges = changes; 677 } 678 } 679 if (shouldParse) { 680 ResourceInfo resInfo=getResInfoFromClassFile(); 681 updateMetadata(resInfo); 682 } else { 683 setPersisted(false); 684 } 685 } 686 687 private void directUpdate(FileObject fobj, boolean isOutOfDate, boolean shouldParse, long timestamp) { 688 if (JMManager.INCONSISTENCY_DEBUG) { 689 System.err.println("Direct update of: " + getName()); 690 System.err.println("isOutOfDate: " + isOutOfDate + " shouldParse: " + shouldParse); 691 Thread.dumpStack(); 692 } 693 694 MDRParser parser = createMDRParser(fobj, isOutOfDate); 695 696 TokenIterator tokenIterator = null; 697 Reader reader = null; 698 699 boolean changes = disableChanges; 700 disableChanges = true; 701 try { 702 if (shouldParse) { 703 parser.getASTree(); 704 tokenIterator = new TokenIterator(parser); 705 } else if (isOutOfDate) { 706 reader = parser.getReader(); 707 tokenIterator = new TokenIterator(reader, parser.getSourceLevel()); 708 } 709 710 if (isOutOfDate) { 711 errors = null; 712 int ids[]; 713 JavaModelPackage pck=(JavaModelPackage)refOutermostPackage(); 714 ClassIndex classIndex=ClassIndex.getIndex(pck); 715 716 boolean isModified = Util.isModified(fobj); 717 718 setTimestamp(timestamp, isModified); 719 ids=new JavaUpdater(pck, null, null).computeIndex(this, tokenIterator); 720 classIndex.setIdentifiers(this,ids); 721 if (!shouldParse) { 722 setPersisted(false); 723 } 724 } 725 } catch (IOException e) { 726 ErrorManager.getDefault().notify(e); 727 } finally { 728 disableChanges = changes; 729 try { 730 if (reader != null) { 731 reader.close(); 732 } 733 } catch (IOException e) { 734 ErrorManager.getDefault().notify(e); 735 } 736 } 737 if (shouldParse) { 738 errors = null; 739 ResourceInfo resInfo=parser.enterMembers(); 740 741 if (resInfo==null) { if (isInitialized()) { 743 JMManager.fireResourceParsed(_getMofId()); 744 return; 745 } 746 Collection javaClasses=getPersistentClassifiers(); 747 ClassInfo classes[]=new ClassInfo[javaClasses.size()]; 748 int i=0; 749 for (Iterator it = javaClasses.iterator(); it.hasNext();) { 752 JavaClassImpl jcls=(JavaClassImpl)it.next(); 753 int infoType=jcls.isInterface()?ClassInfo.INTERFACE_TYPE:ClassInfo.CLASS_TYPE; 754 ClassInfo clsInfo=new ClassInfo(null, infoType, jcls.getName(), jcls.getModifiers(), null, null, null, null, null); 755 756 classes[i++]=clsInfo; 757 } 758 resInfo=new ResourceInfo(null, ResourceInfo.RESOURCE_TYPE, this, classes, null); 759 } 760 updateMetadata(resInfo); 761 JMManager.fireResourceParsed(_getMofId()); 762 } 763 } 764 765 private void updateMetadata(ResourceInfo info) { 766 if (infoIdenticalTo(info)) return; 767 updatePersistent(info); 768 setElementInfo(info); 769 } 770 771 void setFileToDeleteOnRollback(FileObject file){ 772 this.fileToDeleteOnRollback = file; 773 } 774 775 public void rollbackChanges() { 776 if (fileToDeleteOnRollback != null) { 777 try { 778 fileToDeleteOnRollback.delete(); 779 } catch (IOException ioe) { 780 ErrorManager.getDefault().notify(ioe); 781 } 782 } 783 784 rollback(); 785 786 if (invertedDiffs != null) { 787 rollbackDiff(); 788 invertedDiffs = null; 789 MDRParser parser = createMDRParser(null, true); 790 try { 791 alreadyChecking = true; 792 alreadyCheckingStackTrace = new RuntimeException (); 793 ResourceInfo resInfo=parser.enterMembers(); 794 uninitialize(); 795 updateMetadata(resInfo); 796 } finally { 797 alreadyChecking = false; 798 } 799 } 800 801 } 802 803 protected void uninitialize() { 804 super.uninitialize(); 805 } 806 807 public void commitChanges() { 808 errors = null; 809 fileToDeleteOnRollback = null; 810 if (!READ_ONLY) { 811 String newSourceText = null; 812 DiffList tmpdiff = new DiffList(getParser().isFromDocument()); 813 if (isNew()) { 814 newSourceText = getSourceText(); 815 } else { 816 getDiff(tmpdiff); 817 if (isChanged(CHANGED_EXTERNAL)) { 818 DiffList dl = new DiffList(getParser().isFromDocument()); 819 Iterator external = extDiffs.iterator(); 820 DiffElement extDiff = (DiffElement) external.next(); 821 for (Iterator it = tmpdiff.iterator(); it.hasNext();) { 822 DiffElement de = (DiffElement) it.next(); 823 while (extDiff != null && extDiff.getStartOffset() < de.getStartOffset()) { 824 dl.add(extDiff); 825 extDiff = external.hasNext() ? (DiffElement) external.next() : null; 826 } 827 dl.add(de); 828 } 829 830 while (extDiff != null) { 831 dl.add(extDiff); 832 extDiff = external.hasNext() ? (DiffElement) external.next() : null; 833 } 834 835 tmpdiff = dl; 836 } 837 } 838 extDiffs = null; 839 DataObject dobj = JavaMetamodel.getManager().getDataObject(this); 840 final CloneableEditorSupport editor = Util.findCloneableEditorSupport(dobj); 841 StyledDocument doc = null; 842 if (editor != null) { 843 doc = editor.getDocument(); 844 if (doc == null && getParser().isFromDocument()) { 845 try { 846 doc = editor.openDocument(); 847 } catch (IOException ex) { 848 throw (RuntimeException ) ErrorManager.getDefault().annotate(new RuntimeException (), ex); 849 } 850 } 851 } 852 if (doc != null) { 853 if (newSourceText == null) { 854 final DiffList diff = tmpdiff; 855 NbDocument.runAtomic(doc, new Runnable () { 856 public void run() { 857 applyDiff(diff, editor); } 859 }); 860 } else { 861 try { 862 PositionRef start = editor.createPositionRef(0, Position.Bias.Forward); 863 PositionRef end = editor.createPositionRef(doc.getLength(), Position.Bias.Backward); 864 new PositionBounds(start, end).setText(newSourceText); 865 setTimestamp(getTimestamp(), true); 866 } catch (Exception e) { 867 throw (RuntimeException ) ErrorManager.getDefault().annotate(new RuntimeException (), e); 868 } 869 } 870 } else { 871 if (newSourceText == null) { 872 applyDiff(tmpdiff, dobj); } else { 874 FileObject primaryFile = dobj.getPrimaryFile(); 875 OutputStream stream = null; 876 FileLock lock = null; 877 try { 878 lock = primaryFile.lock(); 879 stream = primaryFile.getOutputStream(lock); 880 stream.write(newSourceText.getBytes()); 881 stream.close(); 882 setTimestamp(primaryFile.lastModified().getTime(), false); 883 } 884 catch (IOException ex) { 885 throw (RuntimeException ) ErrorManager.getDefault().annotate(new RuntimeException (ex.toString()), ex); 886 } 887 finally { 888 if (lock != null) 889 lock.releaseLock(); 890 } 891 } 892 } 893 } 894 } 895 896 898 public void parseResource() { 899 if (!READ_ONLY) { 900 FileObject fobj = getFileObject(); 901 MDRParser parser = createMDRParser(fobj, true); 902 if (parser.getASTree() == null) { 903 throw new ConstraintViolationException(null, this, "Cannot parse resource " + getName()); } 905 commit(); 906 try { 907 resetAST(parser); 908 } catch (Exception e) { 909 ErrorManager.getDefault().notify(e); 910 } 911 } 912 } 913 914 public void commitConfirmed() { 915 JavaMetamodel.getUndoManager().addItem(this, invertedDiffs); 916 invertedDiffs = null; 917 rbText = null; 918 rbList = null; 919 JMManager.fireResourceParsed(_getMofId()); 920 } 921 922 public void applyDiff(DiffList diff) { 923 DataObject dobj = JavaMetamodel.getManager().getDataObject(this); 924 final CloneableEditorSupport editor = Util.findCloneableEditorSupport(dobj); 925 if (diff.isFromDocument()) { 926 if (editor!=null) { 927 StyledDocument doc = null; 928 try { 929 doc = editor.openDocument(); 930 } catch (IOException ex) { 931 ErrorManager.getDefault().notify(ex); 932 } 933 assert doc !=null : this.getName(); 934 final DiffList diffList = diff; 935 NbDocument.runAtomic(doc, new Runnable () { 936 public void run() { 937 applyDiff(diffList, editor); 938 } 939 }); 940 } 941 } else { 942 if (editor!=null) { 943 StyledDocument doc = editor.getDocument(); 944 if (doc!=null) { 945 final DiffList diffList = diff; 946 NbDocument.runAtomic(doc, new Runnable () { 947 public void run() { 948 applyDiff(diffList, editor); 949 } 950 }); 951 } else { 952 applyDiff(diff, dobj); 953 } 954 } 955 } 956 JavaMetamodel.getUndoManager().addItem(this, invertedDiffs); 957 } 958 959 private void applyDiff(DiffList diffList, CloneableEditorSupport doc) { 960 List diff = new ArrayList(diffList); 961 DiffList tempDiffs = null; 962 List list = new ArrayList(diff.size()); 963 try { 964 HashMap positions = new HashMap(diff.size()); 965 int[] offsets = new int[diff.size() * 2]; 966 int i = 0; 967 MDRParser parser = getParser(); 968 969 for (ListIterator it = diff.listIterator(); it.hasNext();) { 970 DiffElement de = (DiffElement) it.next(); 971 if (de.getText().startsWith("\n")) { 972 int increment = 0; 973 String sourceText = parser.getSourceText(); 974 int startOffset = de.getStartOffset(); 975 if (sourceText.length() > startOffset) { 976 char ch = sourceText.charAt(startOffset); 977 if (ch == '\n') { 978 increment = 1; 979 } else if (ch == '\r') { 980 if (sourceText.substring(startOffset).startsWith("\r\n")) { 981 increment = 2; 982 } 983 } 984 985 if (increment > 0) { 986 int so = startOffset + increment, eo = de.getEndOffset(); 987 String text = de.getText().substring(1); 988 if (so > eo) { 989 eo = so; 990 text += '\n'; 991 } 992 de = new DiffElement(so, eo, text); 993 it.set(de); 994 } 995 } 996 } 997 offsets[i++] = de.getStartOffset(); 998 offsets[i++] = de.getEndOffset(); 999 } 1000 1001 if (parser != null && offsets.length > 0 && !diffList.isFromDocument()) { 1002 offsets = parser.convertToDocumentOffsets(offsets); 1003 } 1004 1005 for (i = 0; i < diff.size(); i++) { 1006 PositionRef start = doc.createPositionRef(offsets[i * 2], Position.Bias.Forward); 1007 PositionRef end = doc.createPositionRef(offsets[i * 2 + 1], Position.Bias.Backward); 1008 positions.put(diff.get(i), new PositionBounds(start, end)); 1009 } 1010 1011 tempDiffs = new DiffList(true); 1012 for (Iterator it = diff.iterator(); it.hasNext();) { 1013 DiffElement de = (DiffElement) it.next(); 1014 PositionBounds pos = (PositionBounds) positions.get(de); 1015 int startOffset = pos.getBegin().getOffset(); 1016 DiffElement diffElement = new DiffElement(startOffset, startOffset+de.getText().length(), pos.getText()); 1017 String text = pos.getText(); 1018 pos.setText(de.getText()); 1019 list.add (new PosInfo(text, pos)); 1020 tempDiffs.add(diffElement); 1021 } 1022 } catch (Exception e) { 1023 throw (ConstraintViolationException) ErrorManager.getDefault().annotate( 1024 new ConstraintViolationException(null, this, "Exception thrown when applying diff: " + e.getMessage()), e ); 1026 } 1027 invertedDiffs = tempDiffs; 1028 rbList = list; 1029 setTimestamp(getTimestamp(), true); 1031 } 1032 1033 private void applyDiff(DiffList diff, DataObject dobj) { 1034 MDRParser parser = getParser(); 1035 String orig = parser.getSourceText(); 1036 int lastPrinted = 0; 1037 StringBuffer buf = new StringBuffer (); 1038 1039 invertedDiffs = null; 1040 DiffList tempDiffs = new DiffList(false); 1041 int shift = 0; 1042 int shiftedOffset = 0; 1043 1044 for (Iterator it = diff.iterator(); it.hasNext();) { 1045 DiffElement de = (DiffElement) it.next(); 1046 int startOffset = de.getStartOffset(); 1047 int endOffset = de.getEndOffset(); 1048 buf.append(orig.substring(lastPrinted, startOffset)); 1049 String d = lineSepPattern.matcher(de.getText()).replaceAll(lineSeparator); 1050 buf.append(d); 1051 lastPrinted = endOffset; 1052 shiftedOffset = startOffset + shift; 1053 tempDiffs.add(new DiffElement(shiftedOffset, shiftedOffset + d.length(), orig.substring(startOffset, endOffset))); 1054 shift += startOffset + d.length() - endOffset; 1055 } 1056 1057 buf.append(orig.substring(lastPrinted)); 1058 FileObject primaryFile = dobj.getPrimaryFile(); 1059 OutputStream stream = null; 1060 FileLock lock = null; 1061 try { 1062 lock = primaryFile.lock(); 1063 stream = primaryFile.getOutputStream(lock); 1064 String encoding = Util.getFileEncoding(primaryFile); 1065 if (encoding == null) { 1066 stream.write(buf.toString().getBytes()); 1067 } else { 1068 stream.write(buf.toString().getBytes(encoding)); 1069 } 1070 stream.close(); 1071 1072 invertedDiffs = tempDiffs; 1073 rbText = orig; 1074 setTimestamp(primaryFile.lastModified().getTime(), false); 1075 } 1076 catch (IOException ex) { 1077 ex.printStackTrace(); 1078 throw (ConstraintViolationException) ErrorManager.getDefault().annotate( 1079 new ConstraintViolationException(null, this, "Exception thrown when applying diff: " + ex.getMessage()), ex ); 1081 } 1082 finally { 1083 if (lock != null) 1084 lock.releaseLock(); 1085 } 1086 } 1087 1088 private void rollbackDiff() { 1089 DataObject dobj = JavaMetamodel.getManager().getDataObject(this); 1090 if (rbList != null) { 1091 final CloneableEditorSupport editor = Util.findCloneableEditorSupport(dobj); 1092 StyledDocument doc = editor.getDocument(); 1093 final List list = rbList; 1094 rbList = null; 1095 NbDocument.runAtomic(doc, new Runnable () { 1096 public void run() { 1097 for (Iterator iter = list.iterator(); iter.hasNext();) { 1098 PosInfo info = (PosInfo) iter.next(); 1099 try { 1100 info.pos.setText(info.text); 1101 } catch (Exception ex) { 1102 ErrorManager.getDefault().notify(ex); 1103 } 1104 } 1105 } 1106 }); 1107 setTimestamp(getTimestamp(), true); 1108 } else { 1109 FileObject primaryFile = dobj.getPrimaryFile(); 1110 OutputStream stream = null; 1111 FileLock lock = null; 1112 try { 1113 lock = primaryFile.lock(); 1114 stream = primaryFile.getOutputStream(lock); 1115 stream.write(rbText.getBytes()); 1116 stream.close(); 1117 setTimestamp(primaryFile.lastModified().getTime(), false); 1118 } 1119 catch (IOException ex) { 1120 ErrorManager.getDefault().notify(ex); 1121 } 1122 finally { 1123 if (lock != null) 1124 lock.releaseLock(); 1125 rbText = null; 1126 } 1127 } 1128 } 1129 1130 public void getDiff(List diff) { 1131 ResourceInfo astInfo = (ResourceInfo) getElementInfo(); 1132 ASTProvider parser = getParser(); 1133 1134 ASTree tree = getASTree(); 1136 String packageName = getPackageName(); 1137 int endOffsetAfterRemovePackage = -1; 1138 if (isChanged(CHANGED_PACKAGE_NAME) && tree.getSubTrees()[0] == null) { 1139 if (packageName != null && packageName.length() > 0) { 1140 diff.add(new DiffElement(0, 0, "package " + getPackageName() + ";\n")); } 1142 } else if (isChanged(CHANGED_PACKAGE_NAME) && (packageName == null || packageName.length() == 0)) { 1143 int startPads = getStartOffset(parser, tree.getSubTrees()[0], false); 1146 int endOff = getEndOffset(parser, tree.getSubTrees()[0]); 1149 ASTree[] rscChildren = tree.getSubTrees(); 1150 Token newLine = null; 1151 if (rscChildren[1] != null) { 1153 newLine = getFirstEOL(parser, rscChildren[1].getFirstToken()); 1155 } else if (rscChildren[2] != null) { 1156 newLine = getFirstEOL(parser, rscChildren[2].getFirstToken()); 1158 } 1159 if (newLine != null) { 1160 endOff = newLine.getEndOffset(); 1163 } 1164 diff.add(new DiffElement(startPads, endOff, "")); 1165 endOffsetAfterRemovePackage = endOff; 1166 } else if (tree.getSubTrees()[0] != null) { 1167 getChildDiff(diff, parser, tree.getSubTrees()[0].getSubTrees()[1], (MetadataElement) getPackageIdentifier(), CHANGED_PACKAGE_NAME); 1168 } 1169 1170 int endOffset; 1172 int endOffset2 = -1; 1173 ASTree typeDecls = tree.getSubTrees()[2]; 1174 if (typeDecls == null) { 1175 endOffset = parser.getSourceText().length(); 1176 } else { 1177 if (isChanged(CHANGED_IMPORTS)) { 1178 if (tree.getSubTrees()[0] == null && tree.getSubTrees()[1] == null) { 1180 endOffset = 0; 1184 } else if (tree.getSubTrees()[1] == null) { 1185 if (packageName==null || "".equals(packageName)) { 1186 endOffset = endOffsetAfterRemovePackage; 1187 } else { 1188 int firstAfterPckg = tree.getSubTrees()[0].getLastToken()+1; 1190 Token t1 = parser.getToken(firstAfterPckg); 1191 Token[] pads = t1.getPadding(); 1192 endOffset = getStartOffset(parser, typeDecls, true); 1193 for (int i = 0; i < pads.length; i++) { 1195 if (pads[i].getType() == ParserTokens.EOL) { 1196 endOffset = pads[i].getStartOffset(); 1197 break; 1198 } 1199 } 1200 diff.add(new DiffElement(endOffset, endOffset, "\n\n")); } 1202 } else { 1203 int lastImp = tree.getSubTrees()[1].getLastToken(); 1205 Token t1 = parser.getToken(lastImp+1); 1206 Token[] pads = t1.getPadding(); 1207 endOffset = parser.getToken(lastImp).getEndOffset(); 1208 for (int i = 0; i < pads.length; i++) { 1210 if (pads[i].getType() == ParserTokens.EOL) { 1211 endOffset = pads[i].getStartOffset(); 1212 if (getImports().isEmpty()) { 1213 endOffset2 = pads[i].getEndOffset(); 1214 } else { 1215 int inPos = parser.getText(pads[i]).lastIndexOf('\n'); 1216 endOffset2 = inPos != -1 ? endOffset + inPos : endOffset; 1217 } 1218 break; 1219 } 1220 } 1221 } 1222 } else { 1223 endOffset = getStartOffset(parser, typeDecls, true); 1224 } 1225 } 1226 int diff_size = diff.size(); 1227 1228 getImportsDiff(diff, parser, astInfo.imports, getImports(), endOffset, endOffset2, "\n", false, CHANGED_IMPORTS); 1230 if (isChanged(CHANGED_IMPORTS) && tree.getSubTrees()[0] == null && tree.getSubTrees()[1] == null || endOffset == endOffsetAfterRemovePackage) { 1233 diff.add(new DiffElement(endOffset, endOffset, "\n")); } 1235 1236 endOffset = parser.getSourceText().length(); 1238 getCollectionDiff(diff, parser, CHANGED_CLASSIFIERS, astInfo.classes, getClassifiers(), endOffset, "\n\n"); } 1240 1241 public String getSourceText() { 1242 String origElem; 1243 if ((origElem = checkChange()) != null) { 1244 return origElem; 1245 } 1246 StringBuffer buf = new StringBuffer (); 1247 1248 String packageName = getPackageName(); 1249 1250 if (packageName != null && packageName.length() > 0) { 1251 buf.append("package "); buf.append(getPackageName()); 1253 buf.append(";\n\n"); } 1255 1256 for (Iterator importsIt = getImports().iterator(); importsIt.hasNext(); ) { 1257 ImportImpl imp = (ImportImpl) importsIt.next(); 1258 buf.append(imp.getSourceText() + "\n"); } 1260 for (Iterator clazzIt = getClassifiers().iterator(); clazzIt.hasNext(); ) { 1261 JavaClassImpl javaClass = (JavaClassImpl) clazzIt.next(); 1262 buf.append('\n' + javaClass.getSourceText() + '\n'); 1263 } 1264 return buf.toString(); 1265 } 1266 1267 1287 protected String getIndentation() { 1288 return ""; 1289 } 1290 1291 1293 protected void _delete() { 1294 JavaPackage parent = (JavaPackage) _realImmediateComposite(); 1296 if (parent != null) { 1297 parent.getResources().remove(this); 1298 } 1299 for (Iterator it = getPersistentClassifiers().iterator(); it.hasNext();) { 1302 RefObject classifier = (RefObject) it.next(); 1303 it.remove(); 1304 classifier.refDelete(); 1305 } 1306 if (childrenInited) { 1307 deleteChildren(imports); 1308 if (elementsInited) 1309 deleteChild(packageIdentifier); 1310 } 1311 ClassIndex.getIndex((JavaModelPackage) refOutermostPackage()).removeResource(this); 1313 ((ExclusiveMutex) _getMdrStorage().getRepositoryMutex()).unregisterChange(this); 1314 1315 super._delete(); 1316 } 1317 1318 public void replaceChild(Element oldElement, Element newElement) { 1319 if (replaceObject(classifiersInited() ? getClassifiers() : getPersistentClassifiers(), oldElement, newElement)) return; 1320 1321 if (childrenInited) { 1322 if (replaceObject(getImports(), oldElement, newElement)) return; 1323 } 1324 if (elementsInited && oldElement.equals(packageIdentifier)) { 1325 if (newElement != null) { setPackageIdentifier((MultipartId) newElement); 1327 } return; 1329 } 1330 super.replaceChild(oldElement, newElement); 1331 } 1332 1333 1337 1339 private PropertyChangeSupport importsSupp; 1340 1341 public boolean importsInited () { 1342 return childrenInited; 1343 } 1344 1345 public void addImportsListener (PropertyChangeListener listener) { 1346 if (childrenInited) { 1347 listener.propertyChange (null); 1348 } else { 1349 synchronized (this) { 1350 if (importsSupp == null) { 1351 importsSupp = new PropertyChangeSupport (this); 1352 } 1353 } 1354 importsSupp.addPropertyChangeListener(listener); 1355 } 1356 } 1357 1358 private void fireImportsInited () { 1359 if (importsSupp != null) 1360 importsSupp.firePropertyChange (null, null, null); 1361 importsSupp = null; 1362 } 1363 1364 1366 protected ASTree getPartTree(ElementPartKind part) { 1367 if (ElementPartKindEnum.HEADER.equals(part)) 1368 return getASTree().getSubTrees()[0]; 1369 throw new IllegalArgumentException ("Invalid part for this element: " + part); } 1371 1372 public MultipartId getPackageIdentifier() { 1373 checkUpToDate(); 1374 if (!elementsInited) { 1375 initASTElements(); 1376 } 1377 return packageIdentifier; 1378 } 1379 1380 public void setPackageIdentifier(MultipartId packageIdentifier) { 1381 objectChanged(CHANGED_PACKAGE_NAME); 1382 changeChild(getPackageIdentifier(), packageIdentifier); 1383 this.packageIdentifier = packageIdentifier; 1384 setPkgNameAndUpdateIdx(packageIdentifier != null ? 1386 ((MetadataElement) packageIdentifier).getSourceText() : ""); 1387 } 1388 1389 1395 void childChanged(MetadataElement element) { 1396 if (element == getPackageIdentifier()) { 1397 setPkgNameAndUpdateIdx(((MetadataElement) packageIdentifier).getSourceText()); 1398 } 1399 } 1400 1401 public boolean containsIdentifier(String identifier) { 1402 return ClassIndex.containsIdentifier(this, identifier.hashCode()); 1403 } 1404 1405 1415 private static Token getFirstEOL(ASTProvider parser, int token) { 1416 Token[] pads = parser.getToken(token).getPadding(); 1417 for (int i = 0; i < pads.length; i++) { 1418 if (pads[i].getType() == ParserTokens.EOL) { 1419 return pads[i]; 1420 } 1421 } 1422 return null; 1423 } 1424 1425 1427 private static class PosInfo { 1428 String text; 1429 PositionBounds pos; 1430 1431 PosInfo(String text, PositionBounds pos) { 1432 this.text = text; 1433 this.pos = pos; 1434 } 1435 } 1436 1437 private class ErrorList extends AbstractList implements ErrConsumer { 1438 private List errors = null; 1439 private String name; 1440 1441 public ErrorList() { 1442 name = getName().replace('/', File.separatorChar); 1443 } 1444 1445 public Object get(int index) { 1446 initCheck(); 1447 return errors.get(index); 1448 } 1449 1450 private void initCheck() { 1451 synchronized (this) { 1452 if (errors != null) { 1453 return; 1454 } 1455 } 1456 MDRParser provider; 1457 _getRepository().beginTrans(false); 1458 try { 1459 provider = getParser(); 1460 } finally { 1461 _getRepository().endTrans(); 1462 } 1463 synchronized (this) { 1464 if (errors == null && provider != null) { 1465 try { 1466 ECRequestDesc desc = new ECRequestDescImpl(name, provider, this); 1467 Factory.getDefault().getErrorChecker(desc).parse(); 1468 } catch (CompilerException ex) { 1469 ErrorManager.getDefault().log(ErrorManager.WARNING, "ErrorChecker: " + ex.getMessage()); } 1471 } 1472 if (errors == null) { 1473 errors = Collections.EMPTY_LIST; 1474 } 1475 } 1476 } 1477 1478 public int size() { 1479 initCheck(); 1480 return errors.size(); 1481 } 1482 1483 public void pushError(Object severity, String errorFileName, int line, int column, String message, String key, String [] args) { 1484 if (errorFileName.equals(name)) { 1485 if (errors == null) { 1486 errors = new ArrayList(); 1487 } 1488 errors.add(new ErrorInfoImpl(severity, line, column, message, key, args)); 1489 } 1490 } 1491 } 1492 1493 private static class ErrorInfoImpl implements ErrorInfo { 1494 private final String description; 1495 private final int line, column; 1496 private final ErrorType severity; 1497 private final String errorId; 1498 private final String [] args; 1499 1500 private static List fieldNames = Arrays.asList((Object []) new String [] {"description", "lineNumber", "column", "severity"}); private static List typeName = Arrays.asList((Object []) new String [] {"JavaModel", "ErrorInfo"}); 1503 ErrorInfoImpl(Object severity, int line, int column, String message, String key, String [] args) { 1504 this.description = message; 1505 this.line = line; 1506 this.column = column; 1507 this.errorId = key; 1508 this.args = args; 1509 this.severity = severity == ErrConsumer.WARNING ? ErrorTypeEnum.WARNING : ErrorTypeEnum.ERROR; 1510 } 1511 1512 public String getDescription() { 1513 return description; 1514 } 1515 1516 public int getLineNumber() { 1517 return line; 1518 } 1519 1520 public int getColumn() { 1521 return column; 1522 } 1523 1524 public ErrorType getSeverity() { 1525 return severity; 1526 } 1527 1528 public List refFieldNames() { 1529 return fieldNames; 1530 } 1531 1532 public String getErrorId() { 1533 return errorId; 1534 } 1535 1536 public List getArguments() { 1537 return Arrays.asList(args); 1538 } 1539 1540 public Object refGetValue(String s) { 1541 if ("description".equals(s)) { return getDescription(); 1543 } else if ("lineNumber".equals(s)) { return new Integer (getLineNumber()); 1545 } else if ("column".equals(s)) { return new Integer (getColumn()); 1547 } else if ("severity".equals(s)) { return getSeverity(); 1549 } else if ("errorId".equals(s)) { return getErrorId(); 1551 } else if ("arguments".equals(s)) { return getArguments(); 1553 } else { 1554 throw new InvalidNameException(s); 1555 } 1556 } 1557 1558 public List refTypeName() { 1559 return typeName; 1560 } 1561 } 1562 1563 public static class DiffList extends AbstractList { 1564 private final ArrayList delegate = new ArrayList(); 1565 private boolean fromDocument; 1566 1567 public DiffList(boolean isFromDocument) { 1568 fromDocument = isFromDocument; 1569 1570 } 1571 1572 public int size() { 1573 return delegate.size(); 1574 } 1575 1576 public boolean isFromDocument() { 1577 return fromDocument; 1578 } 1579 1580 public Object get(int index) { 1581 return delegate.get(index); 1582 } 1583 1584 public void add(int index, Object object) { 1585 DiffElement element = (DiffElement) object; 1586 if (index == delegate.size()) { 1587 add(object); 1588 return; 1589 } 1590 DiffElement diff = (DiffElement) delegate.get(index); 1591 if (element.getEndOffset() > diff.getStartOffset()) { 1592 throw new IllegalArgumentException ("Start offset of the diff element is lower than end offset of the previous diff element. (previous: " + diff + ", this: " + element + ")"); } else if (element.getEndOffset() == diff.getStartOffset()) { 1594 delegate.remove(index); 1595 element = new DiffElement(element.getStartOffset(), diff.getEndOffset(), element.getText() + diff.getText()); 1596 } 1597 if (index > 0) { 1598 diff = (DiffElement) delegate.get(index - 1); 1599 if (diff.getEndOffset() > element.getStartOffset()) { 1600 throw new IllegalArgumentException ("Start offset of the diff element is lower than end offset of the previous diff element. (previous: " + diff + ", this: " + element + ")"); } else if (diff.getEndOffset() == element.getStartOffset()) { 1602 delegate.set(index - 1, new DiffElement(diff.getStartOffset(), element.getEndOffset(), diff.getText() + element.getText())); 1603 return; 1604 } 1605 } 1606 delegate.add(index, element); 1607 } 1608 1609 public Object remove(int index) { 1610 return delegate.remove(index); 1611 } 1612 1613 public Object set(int index, Object object) { 1614 Object result = remove(index); 1615 add(index, object); 1616 return result; 1617 } 1618 1619 public boolean add(Object object) { 1620 DiffElement element = (DiffElement) object; 1621 if (!delegate.isEmpty()) { 1622 int lastIndex = delegate.size() - 1; 1623 DiffElement diff = (DiffElement) delegate.get(lastIndex); 1624 if (diff.getEndOffset() > element.getStartOffset()) { 1625 throw new IllegalArgumentException ("Start offset of the diff element is lower than end offset of the previous diff element. (previous: " + diff + ", this: " + element); } else if (diff.getEndOffset() == element.getStartOffset()) { 1627 delegate.set(lastIndex, new DiffElement(diff.getStartOffset(), element.getEndOffset(), diff.getText() + element.getText())); 1628 return true; 1629 } 1630 } 1631 return delegate.add(element); 1632 } 1633 } 1634 1635 protected void hardRefParent(boolean enabled) { 1636 } 1637 1638 protected void parentChanged() { 1639 } 1640 1641 public Element duplicate(JavaModelPackage targetExtent) { 1642 throw new UnsupportedOperationException ("The operation is intentionally unsupported at this element."); } 1644 1645 1647 public boolean isComment(int offset) { 1648 MDRParser parser = getParser(); 1649 Token token = parser.getTokenByOffset(offset); 1650 if (token == null) return false; 1651 return token.getType() == ParserTokens.COMMENT || token.getType() == ParserTokens.EOL_COMMENT; 1652 } 1653 1654 public void addExtDiff(DiffElement diff) { 1655 objectChanged(CHANGED_EXTERNAL); 1656 if (extDiffs == null) { 1657 extDiffs = new DiffList(getParser().isFromDocument()); 1658 } 1659 extDiffs.add(diff); 1660 } 1661 1662 public Element getElementByOffset(int offset) { 1663 _lock(false); 1664 try { 1665 ElementFinder finder = new ElementFinder(this); 1666 1667 return finder.getElementByOffset(offset); 1668 } finally { 1669 _unlock(); 1670 } 1671 } 1672 1673 public boolean addImport(Import newImport) { 1674 boolean fail = true; 1675 _lock(true); 1676 try { 1677 String name=newImport.getName(); 1678 ListIterator it = getImports().listIterator(); 1679 1680 while (it.hasNext()) { 1681 Import imp =(Import)it.next(); 1682 String impName=imp.getName(); 1683 1684 if (impName!=null && name.compareTo(impName)<0) { 1685 it.previous(); 1686 break; 1687 } 1688 } 1689 it.add(newImport); 1690 fail = false; 1691 return true; 1692 } finally { 1693 _unlock(fail); 1694 } 1695 } 1696 1697 public List getMain() { 1698 _lock(false); 1699 try { 1700 if (getName().endsWith(".class") || containsIdentifier("main")) { List mainClasses=new ArrayList(1); 1702 for (Iterator i = getClassifiers().iterator(); i.hasNext();) { 1703 findMainIn((JavaClass) i.next(), mainClasses); 1704 } 1705 return mainClasses; 1706 } 1707 return Collections.EMPTY_LIST; 1708 } finally { 1709 _unlock(); 1710 } 1711 } 1712 1713 private void findMainIn(final JavaClass clazz, final Collection mainClasses) { 1714 if (clazz.isInterface()) 1715 return; 1716 final int correctMods = (Modifier.PUBLIC | Modifier.STATIC); 1717 Object [] features = clazz.getContents().toArray(); 1718 boolean mainFound = false; 1719 1720 for (int j = 0; j<features.length;j++) { 1721 ClassMember feature = (ClassMember)features[j]; 1722 1723 if (feature instanceof JavaClass) 1724 findMainIn((JavaClass)feature, mainClasses); 1725 if (mainFound) 1726 continue; 1727 if (!(feature instanceof Method)) 1729 continue; 1730 1731 Method m = (Method) feature; 1732 if (!"main".equals(m.getName()) || ((m.getModifiers() & correctMods) != correctMods) || 1737 (!"void".equals(m.getType().getName()))) continue; 1739 1740 Iterator parIt=m.getParameters().iterator(); 1743 if (parIt.hasNext()) { 1744 Parameter par = (Parameter) parIt.next(); 1745 if (parIt.hasNext()) continue; 1747 String typeName = par.getType().getName(); 1748 if (par.isVarArg() && ("java.lang.String".equals(typeName) || "String".equals(typeName))) { mainClasses.add(clazz); 1753 mainFound = true; 1754 } else if ("java.lang.String[]".equals(typeName) || "String[]".equals(typeName)) { mainClasses.add(clazz); 1759 mainFound = true; 1760 } 1761 } } } 1764 1765 void setData() { 1766 imports = createChildrenList("imports",Collections.EMPTY_LIST, CHANGED_IMPORTS); } 1768} 1769 | Popular Tags |