1 12 13 package org.eclipse.ant.internal.ui.editor.outline; 14 15 import java.io.File ; 16 import java.text.MessageFormat ; 17 import java.util.ArrayList ; 18 import java.util.Collection ; 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.List ; 22 import java.util.Map ; 23 import java.util.Set ; 24 import java.util.Stack ; 25 26 import org.apache.tools.ant.AntTypeDefinition; 27 import org.apache.tools.ant.BuildException; 28 import org.apache.tools.ant.ComponentHelper; 29 import org.apache.tools.ant.IntrospectionHelper; 30 import org.apache.tools.ant.Location; 31 import org.apache.tools.ant.Project; 32 import org.apache.tools.ant.Target; 33 import org.apache.tools.ant.Task; 34 import org.apache.tools.ant.TaskAdapter; 35 import org.apache.tools.ant.UnknownElement; 36 import org.eclipse.ant.core.AntCorePlugin; 37 import org.eclipse.ant.core.Type; 38 import org.eclipse.ant.internal.core.IAntCoreConstants; 39 import org.eclipse.ant.internal.ui.editor.model.AntDefiningTaskNode; 40 import org.eclipse.ant.internal.ui.editor.model.AntElementNode; 41 import org.eclipse.ant.internal.ui.editor.model.AntImportNode; 42 import org.eclipse.ant.internal.ui.editor.model.AntProjectNode; 43 import org.eclipse.ant.internal.ui.editor.model.AntPropertyNode; 44 import org.eclipse.ant.internal.ui.editor.model.AntTargetNode; 45 import org.eclipse.ant.internal.ui.editor.model.AntTaskNode; 46 import org.eclipse.ant.internal.ui.editor.model.IAntModelConstants; 47 import org.eclipse.ant.internal.ui.editor.utils.ProjectHelper; 48 import org.eclipse.ant.internal.ui.model.AntUIPlugin; 49 import org.eclipse.ant.internal.ui.preferences.AntEditorPreferenceConstants; 50 import org.eclipse.core.resources.IFile; 51 import org.eclipse.core.resources.ResourcesPlugin; 52 import org.eclipse.core.runtime.IPath; 53 import org.eclipse.core.runtime.Preferences; 54 import org.eclipse.jface.text.BadLocationException; 55 import org.eclipse.jface.text.DocumentEvent; 56 import org.eclipse.jface.text.IDocument; 57 import org.eclipse.jface.text.IDocumentListener; 58 import org.eclipse.jface.text.reconciler.DirtyRegion; 59 import org.xml.sax.Attributes ; 60 import org.xml.sax.SAXParseException ; 61 62 public class AntModel { 63 64 private static ClassLoader fgClassLoader; 65 private static int fgInstanceCount= 0; 66 67 private XMLCore fCore; 68 private IDocument fDocument; 69 private IProblemRequestor fProblemRequestor; 70 private LocationProvider fLocationProvider; 71 72 private AntProjectNode fProjectNode; 73 private AntTargetNode fCurrentTargetNode; 74 private AntElementNode fLastNode; 75 private AntElementNode fNodeBeingResolved; 76 77 private AntTargetNode fIncrementalTarget= null; 78 private boolean fReplaceHasOccurred= false; 79 private int fRemoveLengthOfReplace= 0; 80 private DirtyRegion fDirtyRegion= null; 81 82 87 private Stack fStillOpenElements = new Stack (); 88 89 private Map fTaskToNode= new HashMap (); 90 91 private List fTaskNodes= new ArrayList (); 92 93 private Map fEntityNameToPath; 94 95 private final Object fDirtyLock= new Object (); 96 private boolean fIsDirty= true; 97 private IDocumentListener fListener; 98 private File fEditedFile= null; 99 private AntEditorMarkerUpdater fMarkerUpdater= null; 100 private Set fNamesOfOldDefiningNodes; 101 102 private Preferences.IPropertyChangeListener fCorePropertyChangeListener= new Preferences.IPropertyChangeListener() { 103 public void propertyChange(Preferences.PropertyChangeEvent event) { 104 if (event.getProperty().equals(IAntCoreConstants.PREFERENCE_CLASSPATH_CHANGED)) { 105 if (((Boolean )event.getNewValue()) == Boolean.TRUE) { 106 reconcileForPropertyChange(true); 107 } 108 } 109 } 110 }; 111 112 private Preferences.IPropertyChangeListener fUIPropertyChangeListener= new Preferences.IPropertyChangeListener() { 113 public void propertyChange(Preferences.PropertyChangeEvent event) { 114 String property= event.getProperty(); 115 if (property.equals(AntEditorPreferenceConstants.PROBLEM)) { 116 AntUIPlugin.getDefault().getPluginPreferences().removePropertyChangeListener(fUIPropertyChangeListener); 117 reconcileForPropertyChange(false); 118 AntUIPlugin.getDefault().getPluginPreferences().setToDefault(AntEditorPreferenceConstants.PROBLEM); 119 AntUIPlugin.getDefault().getPluginPreferences().addPropertyChangeListener(fUIPropertyChangeListener); 120 } else if (property.equals(AntEditorPreferenceConstants.CODEASSIST_USER_DEFINED_TASKS)) { 121 if (((Boolean )event.getNewValue()).booleanValue()) { 122 reconcileForPropertyChange(false); 123 } 124 } 125 } 126 }; 127 128 public AntModel(XMLCore core, IDocument document, IProblemRequestor problemRequestor, LocationProvider locationProvider) { 129 fCore= core; 130 fDocument= document; 131 fProblemRequestor= problemRequestor; 132 fMarkerUpdater= new AntEditorMarkerUpdater(); 133 fMarkerUpdater.setModel(this); 134 fLocationProvider= locationProvider; 135 AntCorePlugin.getPlugin().getPluginPreferences().addPropertyChangeListener(fCorePropertyChangeListener); 136 AntUIPlugin.getDefault().getPluginPreferences().addPropertyChangeListener(fUIPropertyChangeListener); 137 AntDefiningTaskNode.setJavaClassPath(); 138 fgInstanceCount++; 139 } 140 141 private void reconcileForPropertyChange(boolean classpathChanged) { 142 if (classpathChanged) { 143 fgClassLoader= null; 144 AntDefiningTaskNode.setJavaClassPath(); 145 } 146 fIsDirty= true; 147 reconcile(null); 148 fCore.notifyDocumentModelListeners(new DocumentModelChangeEvent(this, true)); 149 fMarkerUpdater.updateMarkers(); 150 } 151 152 public void install() { 153 fListener= new IDocumentListener() { 154 public void documentAboutToBeChanged(DocumentEvent event) { 155 synchronized (fDirtyLock) { 156 fIsDirty= true; 157 } 158 } 159 public void documentChanged(DocumentEvent event) {} 160 }; 161 fDocument.addDocumentListener(fListener); 162 } 163 164 public void dispose() { 165 synchronized (this) { 166 if (fDocument != null) { 167 fDocument.removeDocumentListener(fListener); 168 } 169 fDocument= null; 170 fCore= null; 171 ProjectHelper.setAntModel(null); 172 } 173 174 AntCorePlugin.getPlugin().getPluginPreferences().removePropertyChangeListener(fCorePropertyChangeListener); 175 AntUIPlugin.getDefault().getPluginPreferences().removePropertyChangeListener(fUIPropertyChangeListener); 176 fgInstanceCount--; 177 if (fgInstanceCount == 0) { 178 fgClassLoader= null; 179 } 180 if (getProjectNode() != null) { 181 IntrospectionHelper.getHelper(getProjectNode().getProject(), AntModel.class); 183 getProjectNode().getProject().fireBuildFinished(null); 184 } 185 } 186 187 public void reconcile(DirtyRegion region) { 188 region= null; 190 fDirtyRegion= region; 191 synchronized (fDirtyLock) { 192 if (!fIsDirty) { 193 return; 194 } 195 if (fReplaceHasOccurred && region != null) { 196 fRemoveLengthOfReplace= region.getLength(); 199 fReplaceHasOccurred= false; 200 return; 201 } 202 fIsDirty= false; 203 } 204 205 synchronized (this) { 206 if (fCore == null) { 207 return; 209 } 210 211 if (fDocument == null) { 212 fProjectNode= null; 213 } else { 214 reset(region); 215 parseDocument(fDocument, region); 216 fRemoveLengthOfReplace= 0; 217 fDirtyRegion= null; 218 reconcileTaskAndTypes(); 219 } 220 221 fCore.notifyDocumentModelListeners(new DocumentModelChangeEvent(this)); 222 } 223 } 224 225 private void reset(DirtyRegion region) { 226 fCurrentTargetNode= null; 229 230 if (region == null ) { 231 fStillOpenElements= new Stack (); 232 fTaskToNode= new HashMap (); 233 fTaskNodes= new ArrayList (); 234 fNodeBeingResolved= null; 235 fLastNode= null; 236 } 237 } 238 239 public AntElementNode[] getRootElements() { 240 reconcile(null); 241 if (fProjectNode == null) { 242 return new AntElementNode[0]; 243 } 244 return new AntElementNode[] {fProjectNode}; 245 } 246 247 private void parseDocument(IDocument input, DirtyRegion region) { 248 boolean parsed= true; 249 if (input.getLength() == 0) { 250 fProjectNode= null; 251 parsed= false; 252 return; 253 } 254 ClassLoader parsingClassLoader= getClassLoader(); 255 ClassLoader originalClassLoader= Thread.currentThread().getContextClassLoader(); 256 Thread.currentThread().setContextClassLoader(parsingClassLoader); 257 boolean incremental= false; 258 Project project= null; 259 try { 260 String textToParse= null; 261 ProjectHelper projectHelper= null; 262 if (region == null || fProjectNode == null) { if (fProjectNode == null || !fProjectNode.hasChildren()) { 264 fProjectNode= null; 265 project = new AntModelProject(); 266 projectHelper= prepareForFullParse(project, parsingClassLoader); 267 textToParse= input.get(); } else { 269 project= fProjectNode.getProject(); 270 projectHelper= (ProjectHelper)project.getReference("ant.projectHelper"); textToParse= prepareForFullIncremental(input); 272 } 273 } else { project= fProjectNode.getProject(); 275 textToParse= prepareForIncrementalParse(project, region, input); 276 if (textToParse == null) { 277 parsed= false; 278 return; 279 } 280 incremental= true; 281 projectHelper= (ProjectHelper)project.getReference("ant.projectHelper"); } 283 beginReporting(); 284 Map references= project.getReferences(); 285 references.remove("ant.parsing.context"); ProjectHelper.setAntModel(this); 287 projectHelper.parse(project, textToParse); 288 289 } catch(BuildException e) { 290 handleBuildException(e, null); 291 } finally { 292 Thread.currentThread().setContextClassLoader(originalClassLoader); 293 if (parsed) { 294 if (incremental) { 295 updateAfterIncrementalChange(region, true); 296 } 297 resolveBuildfile(); 298 endReporting(); 299 project.fireBuildFinished(null); fIncrementalTarget= null; 301 } 302 } 303 } 304 305 private void updateAfterIncrementalChange(DirtyRegion region, boolean updateProjectLength) { 306 if (fProjectNode == null) { 307 return; 308 } 309 int editAdjustment= determineEditAdjustment(region); 310 if (editAdjustment == 0) { 311 return; 312 } 313 if (updateProjectLength) { fProjectNode.setLength(fProjectNode.getLength() + editAdjustment); 315 } else { 316 fProjectNode.setOffset(fProjectNode.getOffset() + editAdjustment); 317 } 318 if ((fIncrementalTarget != null || !updateProjectLength) && fProjectNode.hasChildren()) { 319 List children= fProjectNode.getChildNodes(); 320 int index= children.indexOf(fIncrementalTarget) + 1; 321 updateNodesForIncrementalParse(editAdjustment, children, index); 322 } 323 } 324 325 private void updateNodesForIncrementalParse(int editAdjustment, List children, int index) { 326 AntElementNode node; 327 for (int i = index; i < children.size(); i++) { 328 node= (AntElementNode)children.get(i); 329 node.setOffset(node.getOffset() + editAdjustment); 330 if (node.hasChildren()) { 331 updateNodesForIncrementalParse(editAdjustment, node.getChildNodes(), 0); 332 } 333 } 334 } 335 336 private ProjectHelper prepareForFullParse(Project project, ClassLoader parsingClassLoader) { 337 initializeProject(project, parsingClassLoader); 338 File file = getEditedFile(); 342 String filePath= ""; if (file != null) { 344 filePath= file.getAbsolutePath(); 345 } 346 project.setUserProperty("ant.file", filePath); 348 ProjectHelper projectHelper= new ProjectHelper(this); 349 projectHelper.setBuildFile(file); 350 project.addReference("ant.projectHelper", projectHelper); return projectHelper; 352 } 353 354 private String prepareForIncrementalParse(Project project, DirtyRegion region, IDocument input) { 355 String textToParse= null; 356 AntElementNode node= fProjectNode.getNode(region.getOffset()); 357 if (node == null) { 358 if (fProjectNode.getLength() > 0) { 359 if (region.getOffset() < fProjectNode.getOffset()) { 361 updateAfterIncrementalChange(region, false); 362 } 363 return null; 364 } 365 textToParse = prepareForFullIncremental(input); 367 return textToParse; 368 } 369 370 while (node != null && !(node instanceof AntTargetNode)) { 371 node= node.getParentNode(); 372 } 373 if (node == null) { if (region.getText() != null && region.getText().trim().length() == 0) { 375 return null; } 377 textToParse= prepareForFullIncremental(input); 378 } else { 379 fIncrementalTarget= (AntTargetNode)node; 380 if (fIncrementalTarget.hasChildren()) { 381 Collection nodes= fTaskToNode.values(); 382 nodes.removeAll(fIncrementalTarget.getDescendents()); 383 } 384 385 markHierarchy(node, XMLProblem.NO_PROBLEM); 386 387 StringBuffer temp = createIncrementalContents(project); 388 fIncrementalTarget.reset(); 389 try { 390 int editAdjustment = determineEditAdjustment(region) + 1; 391 String targetString= input.get(node.getOffset() - 1, node.getLength() + editAdjustment); 392 temp.append(targetString); 393 temp.append("\n</project>"); textToParse= temp.toString(); 395 } catch (BadLocationException e) { 396 textToParse= input.get(); 397 } 398 } 399 return textToParse; 400 } 401 402 private String prepareForFullIncremental(IDocument input) { 403 String textToParse= input.get(); 404 fProjectNode.reset(); 405 fTaskToNode= new HashMap (); 406 fTaskNodes= new ArrayList (); 407 return textToParse; 408 } 409 410 private StringBuffer createIncrementalContents(Project project) { 411 int offset= fIncrementalTarget.getOffset(); 412 int line= getLine(offset) - 1; 413 414 StringBuffer temp= new StringBuffer ("<project"); String defltTarget= project.getDefaultTarget(); 416 if (defltTarget != null) { 417 temp.append(" default=\""); temp.append(defltTarget); 419 temp.append("\""); } 421 temp.append(">"); while (line > 0) { 423 temp.append("\n"); line--; 425 } 426 return temp; 427 } 428 429 private int determineEditAdjustment(DirtyRegion region) { 430 int editAdjustment= 0; 431 if (region.getType().equals(DirtyRegion.INSERT)) { 432 editAdjustment+= region.getLength() - fRemoveLengthOfReplace; 433 } else { 434 editAdjustment-= region.getLength(); 435 } 436 return editAdjustment; 437 } 438 439 private void initializeProject(Project project, ClassLoader loader) { 440 project.init(); 441 setTasks(project, loader); 442 setTypes(project, loader); 443 } 444 445 private void setTasks(Project project, ClassLoader loader) { 446 List tasks = AntCorePlugin.getPlugin().getPreferences().getTasks(); 447 for (Iterator iterator = tasks.iterator(); iterator.hasNext();) { 448 org.eclipse.ant.core.Task task = (org.eclipse.ant.core.Task) iterator.next(); 449 AntTypeDefinition def= new AntTypeDefinition(); 450 def.setName(task.getTaskName()); 451 def.setClassName(task.getClassName()); 452 def.setClassLoader(loader); 453 def.setAdaptToClass(Task.class); 454 def.setAdapterClass(TaskAdapter.class); 455 ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def); 456 } 457 } 458 459 private void setTypes(Project project, ClassLoader loader) { 460 List types = AntCorePlugin.getPlugin().getPreferences().getTypes(); 461 for (Iterator iterator = types.iterator(); iterator.hasNext();) { 462 Type type = (Type) iterator.next(); 463 AntTypeDefinition def = new AntTypeDefinition(); 464 def.setName(type.getTypeName()); 465 def.setClassName(type.getClassName()); 466 def.setClassLoader(loader); 467 ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def); 468 } 469 } 470 471 private void resolveBuildfile() { 472 Collection nodeCopy= new ArrayList (fTaskNodes.size()); 473 nodeCopy.addAll(fTaskNodes); 474 Iterator iter= nodeCopy.iterator(); 475 while (iter.hasNext()) { 476 AntTaskNode node = (AntTaskNode) iter.next(); 477 fNodeBeingResolved= node; 478 if (node.configure(false)) { 479 resolveBuildfile(); 481 } 482 } 483 fNodeBeingResolved= null; 484 485 checkTargets(); 486 } 487 488 492 private void checkTargets() { 493 if (fProjectNode == null) { 494 return; 495 } 496 String defaultTargetName= fProjectNode.getProject().getDefaultTarget(); 497 if (defaultTargetName == null || fProjectNode.getProject().getTargets().get(defaultTargetName) == null) { 498 String message; 500 if (defaultTargetName == null) { 501 message= AntOutlineMessages.getString("AntModel.0"); } else { 503 message= MessageFormat.format(AntOutlineMessages.getString("AntModel.43"), new String []{defaultTargetName}); } 505 IProblem problem= createProblem(message, fProjectNode.getOffset(), fProjectNode.getSelectionLength(), XMLProblem.SEVERITY_ERROR); 506 acceptProblem(problem); 507 markHierarchy(fProjectNode, XMLProblem.SEVERITY_ERROR); 508 } 509 if (!fProjectNode.hasChildren()) { 510 return; 511 } 512 List children= fProjectNode.getChildNodes(); 513 Iterator iter= children.iterator(); 514 while (iter.hasNext()) { 515 AntElementNode node = (AntElementNode) iter.next(); 516 AntElementNode originalNode= node; 517 if (node instanceof AntTargetNode) { 518 String missing= ((AntTargetNode)node).checkDependencies(); 519 if (missing != null) { 520 String message= MessageFormat.format(AntOutlineMessages.getString("AntModel.44"), new String []{missing}); AntElementNode importNode= node.getImportNode(); 522 if (importNode != null) { 523 node= importNode; 524 } 525 IProblem problem= createProblem(message, node.getOffset(), node.getSelectionLength(), XMLProblem.SEVERITY_ERROR); 526 acceptProblem(problem); 527 markHierarchy(originalNode, XMLProblem.SEVERITY_ERROR); 528 } 529 } 530 } 531 532 } 533 534 public void handleBuildException(BuildException e, AntElementNode node, int severity) { 535 try { 536 if (node != null) { 537 markHierarchy(node, severity); 538 } 539 Location location= e.getLocation(); 540 int line= 0; 541 int originalOffset= 0; 542 int nonWhitespaceOffset= 0; 543 int length= 0; 544 if (location == Location.UNKNOWN_LOCATION && node != null) { 545 nonWhitespaceOffset= node.getOffset(); 546 length= node.getLength(); 547 } else { 548 line= location.getLineNumber(); 549 if (line == 0) { 550 if (getProjectNode() != null) { 551 length= getProjectNode().getSelectionLength(); 552 nonWhitespaceOffset= getProjectNode().getOffset(); 553 if (severity == XMLProblem.SEVERITY_ERROR) { 554 getProjectNode().setProblemSeverity(XMLProblem.NO_PROBLEM); 555 } 556 } else { 557 return; 558 } 559 } else { 560 if (node == null) { 561 originalOffset= getOffset(line, 1); 562 nonWhitespaceOffset= originalOffset; 563 try { 564 nonWhitespaceOffset= getNonWhitespaceOffset(line, 1); 565 } catch (BadLocationException be) { 566 } 567 length= getLastCharColumn(line) - (nonWhitespaceOffset - originalOffset); 568 } else { 569 nonWhitespaceOffset= node.getOffset(); 570 length= node.getLength(); 571 } 572 } 573 } 574 notifyProblemRequestor(e, nonWhitespaceOffset, length, severity); 575 } catch (BadLocationException e1) { 576 } 577 } 578 579 public void handleBuildException(BuildException e, AntElementNode node) { 580 handleBuildException(e, node, XMLProblem.SEVERITY_ERROR); 581 } 582 583 public File getEditedFile() { 584 if (fLocationProvider != null && fEditedFile == null) { 585 fEditedFile= fLocationProvider.getLocation().toFile(); 586 } 587 return fEditedFile; 588 } 589 590 private void markHierarchy(AntElementNode openElement, int severity) { 591 while (openElement != null) { 592 openElement.setProblemSeverity(severity); 593 openElement= openElement.getParentNode(); 594 } 595 } 596 597 public LocationProvider getLocationProvider() { 598 return fLocationProvider; 599 } 600 601 public void addTarget(Target newTarget, int line, int column) { 602 if (fIncrementalTarget != null) { 603 fCurrentTargetNode= fIncrementalTarget; 604 fCurrentTargetNode.setTarget(newTarget); 605 fStillOpenElements.push(fCurrentTargetNode); 606 } else { 607 AntTargetNode targetNode= new AntTargetNode(newTarget); 608 fProjectNode.addChildNode(targetNode); 609 fCurrentTargetNode= targetNode; 610 fStillOpenElements.push(targetNode); 611 computeOffset(targetNode, line, column); 612 if (fNodeBeingResolved instanceof AntImportNode) { 613 targetNode.setImportNode(fNodeBeingResolved); 614 } 615 } 616 } 617 618 public void addProject(Project project, int line, int column) { 619 if (fIncrementalTarget != null) { 620 return; 621 } 622 fProjectNode= new AntProjectNode((AntModelProject)project, this); 623 fStillOpenElements.push(fProjectNode); 624 computeOffset(fProjectNode, line, column); 625 } 626 627 public void addTask(Task newTask, Task parentTask, Attributes attributes, int line, int column) { 628 AntTaskNode taskNode= null; 629 if (parentTask == null) { 630 taskNode= newTaskNode(newTask, attributes); 631 if (fCurrentTargetNode == null) { 632 fProjectNode.addChildNode(taskNode); 633 } else { 634 fCurrentTargetNode.addChildNode(taskNode); 635 if (taskNode.isExternal()) { 636 fCurrentTargetNode.setExternal(true); 637 fCurrentTargetNode.setFilePath(taskNode.getFilePath()); 638 } 639 } 640 } else { 641 taskNode= newNotWellKnownTaskNode(newTask, attributes); 642 ((AntTaskNode)fTaskToNode.get(parentTask)).addChildNode(taskNode); 643 } 644 fTaskToNode.put(newTask, taskNode); 645 646 fStillOpenElements.push(taskNode); 647 computeOffset(taskNode, line, column); 648 if (fNodeBeingResolved instanceof AntImportNode) { 649 taskNode.setImportNode(fNodeBeingResolved); 650 int index= fTaskNodes.indexOf(fNodeBeingResolved) + 1; 652 fTaskNodes.add(index, taskNode); 653 } else { 654 fTaskNodes.add(taskNode); 655 } 656 } 657 658 public void addEntity(String entityName, String entityPath) { 659 if (fEntityNameToPath == null) { 660 fEntityNameToPath= new HashMap (); 661 } 662 fEntityNameToPath.put(entityName, entityPath); 663 } 664 665 private AntTaskNode newTaskNode(Task newTask, Attributes attributes) { 666 AntTaskNode newNode= null; 667 String taskName= newTask.getTaskName(); 668 if (isPropertySettingTask(taskName)) { newNode= new AntPropertyNode(newTask, attributes); 670 } else if (taskName.equalsIgnoreCase("import")) { newNode= new AntImportNode(newTask, attributes); 672 } else if (taskName.equalsIgnoreCase("macrodef") || taskName.equalsIgnoreCase("presetdef") || taskName.equalsIgnoreCase("typedef") || taskName.equalsIgnoreCase("taskdef")) { String name = attributes.getValue(IAntModelConstants.ATTR_NAME); 677 newNode= new AntDefiningTaskNode(newTask, name); 678 } else if(taskName.equalsIgnoreCase("antcall")) { newNode= new AntTaskNode(newTask, generateLabel(taskName, attributes, IAntModelConstants.ATTR_TARGET)); 680 } else if(taskName.equalsIgnoreCase("mkdir")) { newNode= new AntTaskNode(newTask, generateLabel(taskName, attributes, IAntModelConstants.ATTR_DIR)); 682 } else if(taskName.equalsIgnoreCase("copy")) { newNode= new AntTaskNode(newTask, generateLabel(taskName, attributes, IAntModelConstants.ATTR_DESTFILE)); 684 } else if(taskName.equalsIgnoreCase("tar") || taskName.equalsIgnoreCase("jar") || taskName.equalsIgnoreCase("war") || taskName.equalsIgnoreCase("zip")) { newNode= new AntTaskNode(newTask, generateLabel(newTask.getTaskName(), attributes, IAntModelConstants.ATTR_DESTFILE)); 689 } else if(taskName.equalsIgnoreCase("untar") || taskName.equalsIgnoreCase("unjar") || taskName.equalsIgnoreCase("unwar") || taskName.equalsIgnoreCase("gunzip") || taskName.equalsIgnoreCase("bunzip2") || taskName.equalsIgnoreCase("unzip")) { newNode= new AntTaskNode(newTask, generateLabel(newTask.getTaskName(), attributes, IAntModelConstants.ATTR_SRC)); 696 } else if(taskName.equalsIgnoreCase("gzip") || taskName.equalsIgnoreCase("bzip2")) { newNode= new AntTaskNode(newTask, generateLabel(newTask.getTaskName(), attributes, IAntModelConstants.ATTR_ZIPFILE)); 699 } else if(taskName.equalsIgnoreCase("exec")) { String label = "exec "; String command = attributes.getValue(IAntModelConstants.ATTR_COMMAND); 702 if(command != null) { 703 label += command; 704 } 705 command = attributes.getValue(IAntModelConstants.ATTR_EXECUTABLE); 706 if(command != null) { 707 label += command; 708 } 709 newNode= new AntTaskNode(newTask, label); 710 } else if(taskName.equalsIgnoreCase("delete")) { 712 String label = "delete "; String file = attributes.getValue(IAntModelConstants.ATTR_FILE); 714 if(file != null) { 715 label+= file; 716 } else { 717 file = attributes.getValue(IAntModelConstants.ATTR_DIR); 718 if(file != null) { 719 label+= file; 720 } 721 } 722 newNode= new AntTaskNode(newTask, label); 723 724 } else if(taskName.equalsIgnoreCase("import")) { newNode= new AntTaskNode(newTask, generateLabel(taskName, attributes, IAntModelConstants.ATTR_FILE)); } else { 727 newNode = newNotWellKnownTaskNode(newTask, attributes); 728 } 729 String taskFileName= newTask.getLocation().getFileName(); 730 boolean external= isTaskExternal(taskFileName); 731 newNode.setExternal(external); 732 if (external) { 733 newNode.setFilePath(taskFileName); 734 } 735 return newNode; 736 } 737 738 742 public static boolean isPropertySettingTask(String taskName) { 743 return taskName.equalsIgnoreCase("property") || taskName.equalsIgnoreCase("available") || taskName.equalsIgnoreCase("basename") || taskName.equalsIgnoreCase("condition") || taskName.equalsIgnoreCase("dirname") || taskName.equalsIgnoreCase("loadfile") || taskName.equalsIgnoreCase("pathconvert") || taskName.equalsIgnoreCase("uptodate") || taskName.equalsIgnoreCase("xmlproperty"); } 753 754 private boolean isTaskExternal(String taskFileName) { 755 File taskFile= new File (taskFileName); 756 return !taskFile.equals(getEditedFile()); 757 } 758 759 private AntTaskNode newNotWellKnownTaskNode(Task newTask, Attributes attributes) { 760 AntTaskNode newNode= new AntTaskNode(newTask); 761 String id= attributes.getValue("id"); if (id != null) { 763 newNode.setId(id); 764 } 765 return newNode; 766 } 767 768 private String generateLabel(String taskName, Attributes attributes, String attributeName) { 769 StringBuffer label = new StringBuffer (taskName); 770 String srcFile = attributes.getValue(attributeName); 771 if(srcFile != null) { 772 label.append(' '); 773 label.append(srcFile); 774 } 775 return label.toString(); 776 } 777 778 private void computeLength(AntElementNode element, int line, int column) { 779 if (element.isExternal()) { 780 element.setExternalInfo(line, column); 781 return; 782 } 783 try { 784 int length; 785 int offset; 786 if (column <= 0) { 787 column= getLastCharColumn(line); 788 String lineText= fDocument.get(fDocument.getLineOffset(line - 1), column); 789 StringBuffer searchString= new StringBuffer ("</"); searchString.append(element.getName()); 791 searchString.append('>'); 792 int index= lineText.indexOf(searchString.toString()); 793 if (index == -1) { 794 index= lineText.indexOf("/>"); if (index == -1 ) { 796 index= column; } else { 798 index= index + 3; 799 } 800 } else { 801 index= index + searchString.length() + 1; 802 } 803 offset= getOffset(line, index); 804 } else { 805 offset= getOffset(line, column); 806 } 807 808 length= offset - element.getOffset(); 809 element.setLength(length); 810 } catch (BadLocationException e) { 811 } 813 } 814 815 private void computeOffset(AntElementNode element, int line, int column) { 816 if (element.isExternal()) { 817 return; 818 } 819 try { 820 int offset; 821 String prefix= "<"; if (column <= 0) { 823 offset= getOffset(line, 0); 824 int lastCharColumn= getLastCharColumn(line); 825 offset= computeOffsetUsingPrefix(element, line, offset, prefix, lastCharColumn); 826 } else { 827 offset= getOffset(line, column); 828 offset= computeOffsetUsingPrefix(element, line, offset, prefix, column); 829 } 830 831 element.setOffset(offset + 1); 832 element.setSelectionLength(element.getName().length()); 833 } catch (BadLocationException e) { 834 } 836 } 837 838 private int computeOffsetUsingPrefix(AntElementNode element, int line, int offset, String prefix, int column) throws BadLocationException { 839 String lineText= fDocument.get(fDocument.getLineOffset(line - 1), column); 840 int lastIndex= lineText.indexOf(prefix + element.getName()); 841 if (lastIndex > -1) { 842 offset= getOffset(line, lastIndex + 1); 843 } else { 844 return computeOffsetUsingPrefix(element, line - 1, offset, prefix, getLastCharColumn(line - 1)); 845 } 846 return offset; 847 } 848 849 public int getOffset(int line, int column) throws BadLocationException { 850 return fDocument.getLineOffset(line - 1) + column - 1; 851 } 852 853 private int getNonWhitespaceOffset(int line, int column) throws BadLocationException { 854 int offset= fDocument.getLineOffset(line - 1) + column - 1; 855 while(Character.isWhitespace(fDocument.getChar(offset))) { 856 offset++; 857 } 858 return offset; 859 } 860 861 private int getLine(int offset) { 862 try { 863 return fDocument.getLineOfOffset(offset) + 1; 864 } catch (BadLocationException be) { 865 return -1; 866 } 867 } 868 869 private int getLastCharColumn(int line) throws BadLocationException { 870 String lineDelimiter= fDocument.getLineDelimiter(line - 1); 871 int lineDelimiterLength= lineDelimiter != null ? lineDelimiter.length() : 0; 872 return fDocument.getLineLength(line - 1) - lineDelimiterLength; 873 } 874 875 public void setCurrentElementLength(int lineNumber, int column) { 876 fLastNode= (AntElementNode)fStillOpenElements.pop(); 877 if (fLastNode == fCurrentTargetNode) { 878 fCurrentTargetNode= null; } 880 computeLength(fLastNode, lineNumber, column); 881 } 882 883 public void acceptProblem(IProblem problem) { 884 if (fProblemRequestor != null) { 885 fProblemRequestor.acceptProblem(problem); 886 fMarkerUpdater.acceptProblem(problem); 887 } 888 } 889 890 protected IFile getFile() { 891 IPath location= fLocationProvider.getLocation(); 892 if (location == null) { 893 return null; 894 } 895 IFile[] files= ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(location); 896 if (files.length > 0) { 897 return files[0]; 898 } 899 return null; 900 } 901 902 private void beginReporting() { 903 if (fProblemRequestor != null) { 904 fProblemRequestor.beginReporting(); 905 fMarkerUpdater.beginReporting(); 906 } 907 } 908 909 private void endReporting() { 910 if (fProblemRequestor != null) { 911 fProblemRequestor.endReporting(); 912 } 913 } 914 915 private IProblem createProblem(Exception exception, int offset, int length, int severity) { 916 return createProblem(exception.getMessage(), offset, length, severity); 917 } 918 919 private IProblem createProblem(String message, int offset, int length, int severity) { 920 return new XMLProblem(message, severity, offset, length, getLine(offset)); 921 } 922 923 protected void notifyProblemRequestor(Exception exception, AntElementNode element, int severity) { 924 AntElementNode importNode= element.getImportNode(); 925 if (importNode != null) { 926 element= importNode; 927 } 928 IProblem problem= createProblem(exception, element.getOffset(), element.getLength(), severity); 929 acceptProblem(problem); 930 element.associatedProblem(problem); 931 } 932 933 protected void notifyProblemRequestor(Exception exception, int offset, int length, int severity) { 934 if (fProblemRequestor != null) { 935 IProblem problem= createProblem(exception, offset, length, severity); 936 acceptProblem(problem); 937 } 938 } 939 940 public void warning(Exception exception) { 941 notifyProblemRequestor(exception, (AntElementNode)fStillOpenElements.pop(), XMLProblem.SEVERITY_WARNING); 942 } 943 944 public void error(Exception exception) { 945 handleError(exception, XMLProblem.SEVERITY_ERROR); 946 } 947 948 public void errorFromElementText(Exception exception, int start, int count) { 949 AntElementNode node= fLastNode; 950 if (node == null) { 951 if (!fStillOpenElements.empty()) { 952 node= (AntElementNode)fStillOpenElements.peek(); 953 } 954 } 955 if (node == null) { 956 return; 957 } 958 computeEndLocationForErrorNode(node, start, count); 959 notifyProblemRequestor(exception, start, count, XMLProblem.SEVERITY_ERROR); 960 markHierarchy(fLastNode, XMLProblem.SEVERITY_ERROR); 961 } 962 963 public void errorFromElement(Exception exception, AntElementNode node, int lineNumber, int column) { 964 if (node == null) { 965 if (!fStillOpenElements.empty()) { 966 node= (AntElementNode)fStillOpenElements.peek(); 967 } else { 968 node= fLastNode; 969 } 970 } 971 computeEndLocationForErrorNode(node, lineNumber, column); 972 notifyProblemRequestor(exception, node, XMLProblem.SEVERITY_ERROR); 973 markHierarchy(node, XMLProblem.SEVERITY_ERROR); 974 } 975 976 private AntElementNode createProblemElement(SAXParseException exception) { 977 int lineNumber= exception.getLineNumber(); 978 StringBuffer message= new StringBuffer (exception.getMessage()); 979 if (lineNumber != -1){ 980 message.append(AntOutlineMessages.getString("AntModel.1") + lineNumber); } 982 983 AntElementNode errorNode= new AntElementNode(message.toString()); 984 errorNode.setFilePath(exception.getSystemId()); 985 errorNode.setProblemSeverity(XMLProblem.SEVERITY_ERROR); 986 computeErrorLocation(errorNode, exception); 987 return errorNode; 988 } 989 990 private void computeErrorLocation(AntElementNode element, SAXParseException exception) { 991 if (element.isExternal()) { 992 return; 993 } 994 995 int line= exception.getLineNumber(); 996 int startColumn= exception.getColumnNumber(); 997 computeEndLocationForErrorNode(element, line, startColumn); 998 } 999 1000 private void computeEndLocationForErrorNode(AntElementNode element, int line, int startColumn) { 1001 try { 1002 if (line <= 0) { 1003 line= 1; 1004 } 1005 int endColumn; 1006 if (startColumn <= 0) { 1007 if (element.getOffset() > -1) { 1008 startColumn= element.getOffset() + 1; 1009 } else { 1010 startColumn= 1; 1011 } 1012 endColumn= getLastCharColumn(line) + 1; 1013 } else { 1014 if (startColumn > 1) { 1015 --startColumn; 1016 } 1017 1018 endColumn= startColumn; 1019 if (startColumn <= getLastCharColumn(line)) { 1020 ++endColumn; 1021 } 1022 } 1023 1024 int correction= 0; 1025 if (element.getOffset() == -1) { 1026 int originalOffset= getOffset(line, startColumn); 1027 int nonWhitespaceOffset= originalOffset; 1028 try { 1029 nonWhitespaceOffset= getNonWhitespaceOffset(line, startColumn); 1030 } catch (BadLocationException be) { 1031 } 1032 element.setOffset(nonWhitespaceOffset); 1033 correction= nonWhitespaceOffset - originalOffset; 1034 } 1035 if (endColumn - startColumn == 0) { 1036 int offset= getOffset(line, startColumn); 1037 element.setLength(offset - element.getOffset() - correction); 1038 } else { 1039 element.setLength(endColumn - startColumn - correction); 1040 } 1041 } catch (BadLocationException e) { 1042 } 1044 } 1045 1046 private void handleError(Exception exception, int severity) { 1047 AntElementNode node= null; 1048 if (fStillOpenElements.isEmpty()) { 1049 if (exception instanceof SAXParseException ) { 1050 node= createProblemElement((SAXParseException )exception); 1051 } 1052 } else { 1053 node= (AntElementNode)fStillOpenElements.peek(); 1054 } 1055 if (node == null) { 1056 return; 1057 } 1058 markHierarchy(node, severity); 1059 1060 if (exception instanceof SAXParseException ) { 1061 SAXParseException parseException= (SAXParseException )exception; 1062 if (node.getOffset() == -1) { 1063 computeEndLocationForErrorNode(node, parseException.getLineNumber() - 1, parseException.getColumnNumber()); 1064 } else { 1065 int lineNumber= parseException.getLineNumber(); 1066 int columnNumber= parseException.getColumnNumber(); 1067 if (columnNumber == -1) { 1068 columnNumber= 1; 1069 } 1070 try { 1071 AntElementNode childNode= node.getNode(getNonWhitespaceOffset(lineNumber, columnNumber) + 1); 1072 if (childNode != null && childNode != node) { 1073 node= childNode; 1074 node.setProblemSeverity(severity); 1075 } else { 1076 node= createProblemElement(parseException); 1077 } 1078 } catch (BadLocationException be) { 1079 node= createProblemElement(parseException); 1080 } 1081 } 1082 } 1083 1084 notifyProblemRequestor(exception, node, severity); 1085 1086 if (node != null) { 1087 while (node.getParentNode() != null) { 1088 AntElementNode parentNode= node.getParentNode(); 1089 if (parentNode.getLength() == -1) { 1090 parentNode.setLength(node.getOffset() - parentNode.getOffset() + node.getLength()); 1091 } 1092 node= parentNode; 1093 } 1094 } 1095 1096 if (fIncrementalTarget != null) { int editAdjustment= determineEditAdjustment(fDirtyRegion); 1098 fIncrementalTarget.setLength(fIncrementalTarget.getLength() + editAdjustment); 1099 AntElementNode startingNode= null; 1100 while(fStillOpenElements.peek() != fIncrementalTarget) { 1101 startingNode= (AntElementNode)fStillOpenElements.pop(); 1102 if (startingNode.getLength() > -1) { 1103 startingNode.setLength(startingNode.getLength() + editAdjustment); 1104 } 1105 } 1106 fStillOpenElements.pop(); if (startingNode != null && fIncrementalTarget.hasChildren()) { 1108 List children= fIncrementalTarget.getChildNodes(); 1109 int index= children.indexOf(startingNode); 1110 updateNodesForIncrementalParse(editAdjustment, children, index); 1111 } 1112 } 1113 } 1114 1115 public void fatalError(Exception exception) { 1116 handleError(exception, XMLProblem.SEVERITY_FATAL_ERROR); 1117 } 1118 1119 public AntElementNode getOpenElement() { 1120 if (fStillOpenElements.isEmpty()) { 1121 return null; 1122 } 1123 return (AntElementNode)fStillOpenElements.peek(); 1124 } 1125 1126 1127 public String getEntityPath(String entityName) { 1128 if (fEntityNameToPath != null) { 1129 return (String )fEntityNameToPath.get(entityName); 1130 } 1131 return null; 1132 } 1133 1134 public String getEntityName(String path) { 1135 if (fEntityNameToPath != null) { 1136 Iterator itr= fEntityNameToPath.keySet().iterator(); 1137 String entityPath; 1138 String name; 1139 while (itr.hasNext()) { 1140 name= (String ) itr.next(); 1141 entityPath= (String ) fEntityNameToPath.get(name); 1142 if (entityPath.equals(path)) { 1143 return name; 1144 } 1145 } 1146 } 1147 return null; 1148 } 1149 1150 public String getPropertyValue(String propertyName) { 1151 AntProjectNode projectNode= getProjectNode(); 1152 if (projectNode == null) { 1153 return null; 1154 } 1155 return projectNode.getProject().getProperty(propertyName); 1156 } 1157 1158 public Object getReferenceObject(String refId) { 1159 AntProjectNode projectNode= getProjectNode(); 1160 if (projectNode == null) { 1161 return null; 1162 } 1163 try { 1164 Project project= projectNode.getProject(); 1165 Object ref= project.getReference(refId); 1166 return ref; 1167 1168 } catch (BuildException be) { 1169 handleBuildException(be, null); 1170 } 1171 return null; 1172 } 1173 1174 public AntElementNode getReferenceNode(String text) { 1175 Object reference= getReferenceObject(text); 1176 if (reference == null) { 1177 return null; 1178 } 1179 1180 Collection nodes= fTaskToNode.keySet(); 1181 Iterator iter= nodes.iterator(); 1182 while (iter.hasNext()) { 1183 Object original = iter.next(); 1184 Object object= original; 1185 if (object instanceof UnknownElement) { 1186 UnknownElement element= (UnknownElement) object; 1187 object= element.getRealThing(); 1188 if (object == null) { 1189 continue; 1190 } 1191 } 1192 if (object == reference) { 1193 return (AntElementNode)fTaskToNode.get(original); 1194 } 1195 } 1196 return null; 1197 } 1198 1199 private ClassLoader getClassLoader() { 1200 if (fgClassLoader == null) { 1201 fgClassLoader= AntCorePlugin.getPlugin().getNewClassLoader(true); 1202 } 1203 return fgClassLoader; 1204 } 1205 1206 1207 public String getTargetDescription(String targetRename) { 1208 AntProjectNode projectNode= getProjectNode(); 1209 if (projectNode == null) { 1210 return null; 1211 } 1212 Project project= projectNode.getProject(); 1213 Map targets= project.getTargets(); 1214 Target target= (Target)targets.get(targetRename); 1215 if (target != null) { 1216 return target.getDescription(); 1217 } 1218 return null; 1219 } 1220 1221 public AntProjectNode getProjectNode(boolean doReconcile) { 1222 if (doReconcile) { 1223 reconcile(null); 1224 } 1225 return fProjectNode; 1226 } 1227 1228 public AntProjectNode getProjectNode() { 1229 return getProjectNode(true); 1230 } 1231 1232 public void setReplaceHasOccurred() { 1233 fReplaceHasOccurred= true; 1234 } 1235 1236 public void updateMarkers() { 1237 reconcile(null); 1238 fMarkerUpdater.updateMarkers(); 1239 } 1240 1241 public AntElementNode getNode(int offset, boolean waitForReconcile) { 1242 if (getProjectNode(waitForReconcile) != null) { 1243 return getProjectNode(waitForReconcile).getNode(offset); 1244 } 1245 return null; 1246 } 1247 1248 1253 public void updateForInitialReconcile() { 1254 fMarkerUpdater.updateMarkers(); 1255 } 1256 1257 1261 public void setNamesOfOldDefiningNodes(Set set) { 1262 fNamesOfOldDefiningNodes= set; 1263 } 1264 1265 1268 private void reconcileTaskAndTypes() { 1269 if (fNamesOfOldDefiningNodes == null) { 1270 return; 1271 } 1272 Iterator iter= fNamesOfOldDefiningNodes.iterator(); 1273 while (iter.hasNext()) { 1274 String nodeLabel = (String ) iter.next(); 1275 if (fProjectNode.getDefininingTaskNode(nodeLabel) == null) { 1276 ComponentHelper helper= ComponentHelper.getComponentHelper(fProjectNode.getProject()); 1277 helper.getAntTypeTable().remove(nodeLabel); 1278 iter.remove(); 1279 } 1280 } 1281 } 1282} | Popular Tags |