/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Nico Seessle - bug 51332 *******************************************************************************/ package org.ganoro.phing.ui.internal.model; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.Stack; import java.util.regex.Pattern; import org.apache.tools.ant.AntTypeDefinition; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.ComponentHelper; import org.apache.tools.ant.IntrospectionHelper; import org.apache.tools.ant.Location; import org.apache.tools.ant.Main; import org.apache.tools.ant.Project; import org.apache.tools.ant.ProjectHelperRepository; import org.apache.tools.ant.RuntimeConfigurable; import org.apache.tools.ant.Target; import org.apache.tools.ant.Task; import org.apache.tools.ant.TaskAdapter; import org.apache.tools.ant.UnknownElement; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.content.IContentDescription; import org.eclipse.core.variables.IStringVariableManager; import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.ISynchronizable; import org.ganoro.phing.core.AntCorePreferences; import org.ganoro.phing.core.AntCoreUtil; import org.ganoro.phing.core.AntSecurityException; import org.ganoro.phing.core.IPhingCoreConstants; import org.ganoro.phing.core.PhingCore; import org.ganoro.phing.core.Property; import org.ganoro.phing.core.Type; import org.ganoro.phing.ui.AntUtil; import org.ganoro.phing.ui.PhingUi; import org.ganoro.phing.ui.editors.DecayCodeCompletionDataStructuresThread; import org.ganoro.phing.ui.editors.outline.AntEditorMarkerUpdater; import org.ganoro.phing.ui.editors.utils.ProjectHelper; import org.ganoro.phing.ui.internal.preferences.AntEditorPreferenceConstants; import org.xml.sax.Attributes; import org.xml.sax.SAXParseException; import com.ibm.icu.text.MessageFormat; public class AntModel implements IAntModel { private static ClassLoader fgClassLoader; private static int fgInstanceCount= 0; private static Object loaderLock = new Object(); private IDocument fDocument; private IProblemRequestor fProblemRequestor; private LocationProvider fLocationProvider; private AntProjectNode fProjectNode; private AntTargetNode fCurrentTargetNode; private AntElementNode fLastNode; private AntElementNode fNodeBeingResolved; private int fNodeBeingResolvedIndex= -1; private String fEncoding = null; private Map fEntityNameToPath; /** * Stack of still open elements. * <P> * On top of the stack is the innermost element. */ private Stack fStillOpenElements = new Stack(); private Map fTaskToNode= new HashMap(); private List fTaskNodes= new ArrayList(); private final Object fDirtyLock= new Object(); private boolean fIsDirty= true; private File fEditedFile= null; private ClassLoader fLocalClassLoader= null; private boolean fHasLexicalInfo= true; private boolean fHasPositionInfo= true; private boolean fHasTaskInfo= true; private IDocumentListener fListener; private AntEditorMarkerUpdater fMarkerUpdater= null; private List fNonStructuralNodes= new ArrayList(1); private Preferences.IPropertyChangeListener fCorePropertyChangeListener; private Preferences.IPropertyChangeListener fUIPropertyChangeListener; private Map fProperties= null; private List fPropertyFiles= null; private Map fDefinersToText; private Map fPreviousDefinersToText; private Map fDefinerNodeIdentifierToDefinedTasks; private Map fTaskNameToDefiningNode; private Map fCurrentNodeIdentifiers; private boolean fReportingProblemsCurrent= false; private boolean fDoNotReportProblems= false; private boolean fShouldReconcile= true; private HashMap fNamespacePrefixMappings; public AntModel(IDocument document, IProblemRequestor problemRequestor, LocationProvider locationProvider) { init(document, problemRequestor, locationProvider); fMarkerUpdater= new AntEditorMarkerUpdater(); fMarkerUpdater.setModel(this); fCorePropertyChangeListener= new Preferences.IPropertyChangeListener() { /* (non-Javadoc) * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent) */ public void propertyChange(Preferences.PropertyChangeEvent event) { if (event.getProperty().equals(org.ganoro.phing.core.IPhingCoreConstants.PREFERENCE_CLASSPATH_CHANGED)) { if (((Boolean)event.getNewValue()) == Boolean.TRUE) { reconcileForPropertyChange(true); } } } }; PhingCore.getPlugin().getPluginPreferences().addPropertyChangeListener(fCorePropertyChangeListener); fUIPropertyChangeListener= new Preferences.IPropertyChangeListener() { /* (non-Javadoc) * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent) */ public void propertyChange(Preferences.PropertyChangeEvent event) { String property= event.getProperty(); if (property.equals(AntEditorPreferenceConstants.PROBLEM)) { PhingUi.getDefault().getPluginPreferences().removePropertyChangeListener(fUIPropertyChangeListener); reconcileForPropertyChange(false); PhingUi.getDefault().getPluginPreferences().setToDefault(AntEditorPreferenceConstants.PROBLEM); PhingUi.getDefault().getPluginPreferences().addPropertyChangeListener(fUIPropertyChangeListener); } else if (property.equals(AntEditorPreferenceConstants.CODEASSIST_USER_DEFINED_TASKS)) { reconcileForPropertyChange(false); } else if (property.equals(AntEditorPreferenceConstants.BUILDFILE_NAMES_TO_IGNORE) || property.equals(AntEditorPreferenceConstants.BUILDFILE_IGNORE_ALL)) { fReportingProblemsCurrent= false; reconcileForPropertyChange(false); } } }; PhingUi.getDefault().getPluginPreferences().addPropertyChangeListener(fUIPropertyChangeListener); } public AntModel(IDocument document, IProblemRequestor problemRequestor, LocationProvider locationProvider, boolean resolveLexicalInfo, boolean resolvePositionInfo, boolean resolveTaskInfo) { init(document, problemRequestor, locationProvider); fHasLexicalInfo= resolveLexicalInfo; fHasPositionInfo= resolvePositionInfo; fHasTaskInfo= resolveTaskInfo; } private void init(IDocument document, IProblemRequestor problemRequestor, LocationProvider locationProvider) { fDocument= document; fProblemRequestor= problemRequestor; fLocationProvider= locationProvider; if (fgInstanceCount == 0) { //no other models are open to ensure that the classpath is up to date wrt the //Ant preferences and start listening for breakpoint changes AntDefiningTaskNode.setJavaClassPath(); AntModelCore.getDefault().startBreakpointListening(); } fgInstanceCount++; DecayCodeCompletionDataStructuresThread.cancel(); ProjectHelper helper = getProjectHelper(); if(helper == null) { ProjectHelperRepository.getInstance().registerProjectHelper(ProjectHelper.class); } computeEncoding(); } /** * Searches the collection of registered {@link org.apache.tools.ant.ProjectHelper}s to see if we have one * registered already. * * @return the {@link ProjectHelper} from our implementation of <code>null</code> if we have not registered one yet * @since 3.7 * @see ProjectHelperRepository */ ProjectHelper getProjectHelper() { Iterator helpers = ProjectHelperRepository.getInstance().getHelpers(); while(helpers.hasNext()) { org.apache.tools.ant.ProjectHelper helper = (org.apache.tools.ant.ProjectHelper) helpers.next(); if(helper instanceof ProjectHelper) { return (ProjectHelper) helper; } } return null; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#dispose() */ public void dispose() { synchronized (getLockObject()) { if (fDocument != null && fListener != null) { fDocument.removeDocumentListener(fListener); } fDocument= null; fLocationProvider= null; ProjectHelper.setAntModel(null); } if (fCorePropertyChangeListener != null) { PhingCore.getPlugin().getPluginPreferences().removePropertyChangeListener(fCorePropertyChangeListener); } if (fUIPropertyChangeListener != null) { PhingUi.getDefault().getPluginPreferences().removePropertyChangeListener(fUIPropertyChangeListener); } fgInstanceCount--; if (fgInstanceCount == 0) { fgClassLoader= null; DecayCodeCompletionDataStructuresThread.getDefault().start(); AntModelCore.getDefault().stopBreakpointListening(); cleanup(); } } private Object getLockObject() { if (fDocument instanceof ISynchronizable) { Object lock= ((ISynchronizable)fDocument).getLockObject(); if (lock != null) { return lock; } } return this; } private void cleanup() { AntProjectNode projectNode= getProjectNode(); if (projectNode != null) { //cleanup the introspection helpers that may have been generated IntrospectionHelper.getHelper(projectNode.getProject(), Small.class); projectNode.getProject().fireBuildFinished(null); } fEncoding = null; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#reconcile() */ public void reconcile() { synchronized (fDirtyLock) { if (!fShouldReconcile || !fIsDirty) { return; } fIsDirty= false; } synchronized (getLockObject()) { if (fLocationProvider == null) { // disposed return; } if (fDocument == null) { fProjectNode= null; } else { reset(); parseDocument(fDocument); reconcileTaskAndTypes(); } AntModelCore.getDefault().notifyAntModelListeners(new AntModelChangeEvent(this)); } } private void reset() { fCurrentTargetNode= null; fStillOpenElements= new Stack(); fTaskToNode= new HashMap(); fTaskNodes= new ArrayList(); fNodeBeingResolved= null; fNodeBeingResolvedIndex= -1; fLastNode= null; fCurrentNodeIdentifiers= null; fNamespacePrefixMappings= null; fNonStructuralNodes= new ArrayList(1); if (fDefinersToText != null) { fPreviousDefinersToText= new HashMap(fDefinersToText); fDefinersToText= null; } } private void parseDocument(IDocument input) { boolean parsed= true; if (input.getLength() == 0) { fProjectNode= null; parsed= false; return; } ClassLoader originalClassLoader= Thread.currentThread().getContextClassLoader(); ClassLoader parsingClassLoader= originalClassLoader; Thread.currentThread().setContextClassLoader(parsingClassLoader); Project project= null; try { ProjectHelper projectHelper= null; String textToParse= input.get(); if (fProjectNode == null || !fProjectNode.hasChildren()) { fProjectNode= null; project = new AntModelProject(); projectHelper= prepareForFullParse(project, parsingClassLoader); } else { project= fProjectNode.getProject(); projectHelper= (ProjectHelper)project.getReference("ant.projectHelper"); //$NON-NLS-1$ projectHelper.setBuildFile(getEditedFile()); prepareForFullIncremental(); } beginReporting(); Map references= project.getReferences(); references.remove("ant.parsing.context"); //$NON-NLS-1$ ProjectHelper.setAntModel(this); projectHelper.parse(project, textToParse); } catch(BuildException e) { handleBuildException(e, null); } finally { if (parsed) { SecurityManager origSM= System.getSecurityManager(); processAntHome(true); try { //set a security manager to disallow system exit and system property setting // System.setSecurityManager(new AntSecurityManager(origSM, Thread.currentThread(), false)); resolveBuildfile(); endReporting(); } catch (AntSecurityException e) { } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); getClassLoader(null); System.setSecurityManager(origSM); project.fireBuildFinished(null); //cleanup (IntrospectionHelper) } } } } private ProjectHelper prepareForFullParse(Project project, ClassLoader parsingClassLoader) { initializeProject(project, parsingClassLoader); // Ant's parsing facilities always works on a file, therefore we need // to determine the actual location of the file. Though the file // contents will not be parsed. We parse the passed document string File file = getEditedFile(); String filePath= IPhingCoreConstants.EMPTY_STRING; if (file != null) { filePath= file.getAbsolutePath(); } project.setUserProperty("ant.file", filePath); //$NON-NLS-1$ project.setUserProperty("ant.version", Main.getAntVersion()); //$NON-NLS-1$ ProjectHelper projectHelper = getProjectHelper(); ProjectHelper.setAntModel(this); projectHelper.setBuildFile(file); project.addReference("ant.projectHelper", projectHelper); //$NON-NLS-1$ return projectHelper; } private void prepareForFullIncremental() { fProjectNode.reset(); fTaskToNode= new HashMap(); fTaskNodes= new ArrayList(); } private void initializeProject(Project project, ClassLoader loader) { processAntHome(false); project.init(); setProperties(project); setTasks(project, loader); setTypes(project, loader); } private void setTasks(Project project, ClassLoader loader) { List tasks = PhingCore.getPlugin().getPreferences().getTasks(); for (Iterator iterator = tasks.iterator(); iterator.hasNext();) { org.ganoro.phing.core.Task task = (org.ganoro.phing.core.Task) iterator.next(); AntTypeDefinition def= new AntTypeDefinition(); def.setName(task.getTaskName()); def.setClassName(task.getClassName()); def.setClassLoader(loader); def.setAdaptToClass(Task.class); def.setAdapterClass(TaskAdapter.class); ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def); } } private void setTypes(Project project, ClassLoader loader) { List types = PhingCore.getPlugin().getPreferences().getTypes(); for (Iterator iterator = types.iterator(); iterator.hasNext();) { Type type = (Type) iterator.next(); AntTypeDefinition def = new AntTypeDefinition(); def.setName(type.getTypeName()); def.setClassName(type.getClassName()); def.setClassLoader(loader); ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def); } } private void setProperties(Project project) { setBuiltInProperties(project); setExtraProperties(project); setGlobalProperties(project); loadExtraPropertyFiles(project); // loadPropertyFiles(project); } private void setExtraProperties(Project project) { if (fProperties != null) { Pattern pattern = Pattern.compile("\\$\\{.*_prompt.*\\}"); //$NON-NLS-1$ IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager(); for (Iterator iter = fProperties.keySet().iterator(); iter.hasNext();) { String name = (String) iter.next(); String value= (String) fProperties.get(name); if (!pattern.matcher(value).find()) { try { value = manager.performStringSubstitution(value); } catch (CoreException e) { } } if (value != null) { project.setUserProperty(name, value); } } } } private void loadExtraPropertyFiles(Project project) { if (fPropertyFiles != null) { try { List allProperties= AntCoreUtil.loadPropertyFiles(fPropertyFiles, project.getUserProperty("basedir"), getEditedFile().getAbsolutePath()); //$NON-NLS-1$ setPropertiesFromFiles(project, allProperties); } catch (IOException e1) { PhingUi.log(e1); } } } /** * Load all properties from the files */ private void loadPropertyFiles(Project project) { List fileNames= Arrays.asList(PhingCore.getPlugin().getPreferences().getCustomPropertyFiles()); try { List allProperties= AntCoreUtil.loadPropertyFiles(fileNames, project.getUserProperty("basedir"), getEditedFile().getAbsolutePath()); //$NON-NLS-1$ setPropertiesFromFiles(project, allProperties); } catch (IOException e1) { PhingUi.log(e1); } } private void setPropertiesFromFiles(Project project, List allProperties) { Iterator iter= allProperties.iterator(); while (iter.hasNext()) { Properties props = (Properties) iter.next(); Enumeration propertyNames = props.propertyNames(); while (propertyNames.hasMoreElements()) { String name = (String) propertyNames.nextElement(); //do not override extra local properties with the global settings if (project.getUserProperty(name) == null) { project.setUserProperty(name, props.getProperty(name)); } } } } private void setBuiltInProperties(Project project) { //set processAntHome for other properties set as system properties project.setUserProperty("ant.file", getEditedFile().getAbsolutePath()); //$NON-NLS-1$ project.setUserProperty("ant.version", Main.getAntVersion()); //$NON-NLS-1$ } private void processAntHome(boolean finished) { AntCorePreferences prefs= PhingCore.getPlugin().getPreferences(); String antHome= prefs.getAntHome(); if (finished || antHome == null) { System.getProperties().remove("ant.home"); //$NON-NLS-1$ System.getProperties().remove("ant.library.dir"); //$NON-NLS-1$ } else { System.setProperty("ant.home", antHome); //$NON-NLS-1$ File antLibDir= new File(antHome, "lib"); //$NON-NLS-1$ System.setProperty("ant.library.dir", antLibDir.getAbsolutePath()); //$NON-NLS-1$ } } private void setGlobalProperties(Project project) { List properties= PhingCore.getPlugin().getPreferences().getProperties(); if (properties != null) { for (Iterator iter = properties.iterator(); iter.hasNext();) { Property property = (Property) iter.next(); String value= property.getValue(true); if (value != null) { project.setUserProperty(property.getName(), value); } } } } private void resolveBuildfile() { Collection nodeCopy= new ArrayList(fTaskNodes); Iterator iter= nodeCopy.iterator(); while (iter.hasNext()) { AntTaskNode node = (AntTaskNode) iter.next(); fNodeBeingResolved= node; fNodeBeingResolvedIndex= -1; if (node.configure(false)) { //resolve any new elements that may have been added resolveBuildfile(); } } fNodeBeingResolved= null; fNodeBeingResolvedIndex= -1; checkTargets(); } /** * Check that if a default target is specified it exists and that the * target dependencies exist. */ private void checkTargets() { if (fProjectNode == null || doNotReportProblems()) { return; } String defaultTargetName= fProjectNode.getDefaultTargetName(); if (defaultTargetName != null && fProjectNode.getProject().getTargets().get(defaultTargetName) == null) { //no default target when one specified (default target does not have to be specified) String message= MessageFormat.format(AntModelMessages.AntModel_43, new String[]{defaultTargetName}); IProblem problem= createProblem(message, fProjectNode.getOffset(), fProjectNode.getSelectionLength(), AntModelProblem.SEVERITY_ERROR); acceptProblem(problem); markHierarchy(fProjectNode, AntModelProblem.SEVERITY_ERROR, message); } if (!fProjectNode.hasChildren()) { return; } List children= fProjectNode.getChildNodes(); Iterator iter= children.iterator(); boolean checkCircularDependencies= true; while (iter.hasNext()) { AntElementNode node = (AntElementNode) iter.next(); AntElementNode originalNode= node; if (node instanceof AntTargetNode) { if (checkCircularDependencies) { checkCircularDependencies= false; checkCircularDependencies(node); } checkMissingDependencies(node, originalNode); } } } /** * method assumes sendor has checked whether to report problems */ private void checkMissingDependencies(AntElementNode node, AntElementNode originalNode) { String missing= ((AntTargetNode)node).checkDependencies(); if (missing != null) { String message= MessageFormat.format(AntModelMessages.AntModel_44, new String[]{missing}); AntElementNode importNode= node.getImportNode(); if (importNode != null) { node= importNode; } IProblem problem= createProblem(message, node.getOffset(), node.getSelectionLength(), AntModelProblem.SEVERITY_ERROR); acceptProblem(problem); markHierarchy(originalNode, AntModelProblem.SEVERITY_ERROR, message); } } private boolean doNotReportProblems() { if (fReportingProblemsCurrent) { return fDoNotReportProblems; } fReportingProblemsCurrent= true; fDoNotReportProblems= false; if (PhingUi.getDefault().getCombinedPreferenceStore().getBoolean(AntEditorPreferenceConstants.BUILDFILE_IGNORE_ALL)) { fDoNotReportProblems= true; return fDoNotReportProblems; } String buildFileNames= PhingUi.getDefault().getCombinedPreferenceStore().getString(AntEditorPreferenceConstants.BUILDFILE_NAMES_TO_IGNORE); if (buildFileNames.length() > 0) { String[] names= AntUtil.parseString(buildFileNames, ","); //$NON-NLS-1$ String editedFileName= getEditedFile().getName(); for (int i = 0; i < names.length; i++) { String string = names[i]; if (string.trim().equals(editedFileName)) { fDoNotReportProblems= true; return fDoNotReportProblems; } } } return fDoNotReportProblems; } /** * method assumes sendor has checked whether to report problems */ private void checkCircularDependencies(AntElementNode node) { Target target= ((AntTargetNode)node).getTarget(); String name= target.getName(); if (name == null) { return; } try { target.getProject().topoSort(name, target.getProject().getTargets()); } catch (BuildException be) { //possible circular dependency String message = be.getMessage(); if (message.startsWith("Circular")) { //$NON-NLS-1$ //we do our own checking for missing dependencies IProblem problem= createProblem(message, node.getProjectNode().getOffset(), node.getProjectNode().getSelectionLength(), AntModelProblem.SEVERITY_ERROR); acceptProblem(problem); markHierarchy(node.getProjectNode(), AntModelProblem.SEVERITY_ERROR, message); } } } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#handleBuildException(org.apache.tools.ant.BuildException, org.eclipse.ant.internal.ui.model.AntElementNode, int) */ public void handleBuildException(BuildException e, AntElementNode node, int severity) { try { if (node != null) { markHierarchy(node, severity, e.getMessage()); } Location location= e.getLocation(); int line= 0; int originalOffset= 0; int nonWhitespaceOffset= 0; int length= 0; if (location == Location.UNKNOWN_LOCATION && node != null) { if (node.getImportNode() != null) { node= node.getImportNode(); } nonWhitespaceOffset= node.getOffset(); length= node.getLength(); } else { line= location.getLineNumber(); if (line == 0) { AntProjectNode projectNode= getProjectNode(); if (projectNode != null) { length= projectNode.getSelectionLength(); nonWhitespaceOffset= projectNode.getOffset(); if (severity == AntModelProblem.SEVERITY_ERROR) { projectNode.setProblemSeverity(AntModelProblem.NO_PROBLEM); projectNode.setProblemMessage(null); } } else { return; } } else { if (node == null) { originalOffset= getOffset(line, 1); nonWhitespaceOffset= originalOffset; try { nonWhitespaceOffset= getNonWhitespaceOffset(line, 1); } catch (BadLocationException be) { } length= getLastCharColumn(line) - (nonWhitespaceOffset - originalOffset); } else { if (node.getImportNode() != null) { node= node.getImportNode(); } nonWhitespaceOffset= node.getOffset(); length= node.getLength(); } } } notifyProblemRequestor(e, nonWhitespaceOffset, length, severity); } catch (BadLocationException e1) { } } public void handleBuildException(BuildException e, AntElementNode node) { handleBuildException(e, node, AntModelProblem.SEVERITY_ERROR); } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#getEditedFile() */ public File getEditedFile() { if (fLocationProvider != null && fEditedFile == null) { fEditedFile= fLocationProvider.getLocation().toFile(); } return fEditedFile; } private void markHierarchy(AntElementNode openElement, int severity, String message) { if (doNotReportProblems()) { return; } while (openElement != null) { openElement.setProblemSeverity(severity); openElement.setProblemMessage(message); openElement= openElement.getParentNode(); } } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#getLocationProvider() */ public LocationProvider getLocationProvider() { return fLocationProvider; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#addTarget(org.apache.tools.ant.Target, int, int) */ public void addTarget(Target newTarget, int line, int column) { AntTargetNode targetNode= new AntTargetNode(newTarget); fProjectNode.addChildNode(targetNode); fCurrentTargetNode= targetNode; fStillOpenElements.push(targetNode); if (fNodeBeingResolved instanceof AntImportNode) { targetNode.setImportNode(fNodeBeingResolved); targetNode.setExternal(true); targetNode.setFilePath(newTarget.getLocation().getFileName()); } else { String targetFileName= newTarget.getLocation().getFileName(); boolean external= isNodeExternal(targetFileName); targetNode.setExternal(external); if (external) { targetNode.setFilePath(targetFileName); } } computeOffset(targetNode, line, column); } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#addProject(org.apache.tools.ant.Project, int, int) */ public void addProject(Project project, int line, int column) { fProjectNode= new AntProjectNode((AntModelProject)project, this); fStillOpenElements.push(fProjectNode); computeOffset(fProjectNode, line, column); } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#addDTD(java.lang.String, int, int) */ public void addDTD(String name, int line, int column) { AntDTDNode node= new AntDTDNode(name); fStillOpenElements.push(node); int offset= -1; try { if (column <= 0) { offset= getOffset(line, 0); int lastCharColumn= getLastCharColumn(line); offset= computeOffsetUsingPrefix(line, offset, "<!DOCTYPE", lastCharColumn); //$NON-NLS-1$ } else { offset= getOffset(line, column); } } catch (BadLocationException e) { PhingUi.log(e); } node.setOffset(offset); fNonStructuralNodes.add(node); } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#addTask(org.apache.tools.ant.Task, org.apache.tools.ant.Task, org.xml.sax.Attributes, int, int) */ public void addTask(Task newTask, Task parentTask, Attributes attributes, int line, int column) { if (!canGetTaskInfo()) { //need to add top level tasks so imports are executed even when //the model is not interested in task level resolution Target owningTarget= newTask.getOwningTarget(); String name= owningTarget.getName(); if (name == null || name.length() != 0 ) { //not the top level implicit target return; } } AntTaskNode taskNode= null; if (parentTask == null) { taskNode= newTaskNode(newTask, attributes); if (fCurrentTargetNode == null) { fProjectNode.addChildNode(taskNode); } else { fCurrentTargetNode.addChildNode(taskNode); } } else { taskNode= newNotWellKnownTaskNode(newTask, attributes); AntTaskNode parentNode= (AntTaskNode)fTaskToNode.get(parentTask); parentNode.addChildNode(taskNode); } fTaskToNode.put(newTask, taskNode); fStillOpenElements.push(taskNode); computeOffset(taskNode, line, column); if (fNodeBeingResolved instanceof AntImportNode) { taskNode.setImportNode(fNodeBeingResolved); //place the node in the collection right after the import node if (fNodeBeingResolvedIndex == -1) { fNodeBeingResolvedIndex= fTaskNodes.indexOf(fNodeBeingResolved); } fNodeBeingResolvedIndex++; fTaskNodes.add(fNodeBeingResolvedIndex, taskNode); } else { fTaskNodes.add(taskNode); } } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#addEntity(java.lang.String, java.lang.String) */ public void addEntity(String entityName, String entityPath) { if (fEntityNameToPath == null) { fEntityNameToPath= new HashMap(); } fEntityNameToPath.put(entityName, entityPath); } private AntTaskNode newTaskNode(Task newTask, Attributes attributes) { AntTaskNode newNode= null; String taskName= newTask.getTaskName(); if (newTask instanceof UnknownElement) { //attempt to handle namespaces taskName= ((UnknownElement) newTask).getTag(); } if (isPropertySettingTask(taskName)) { newNode= new AntPropertyNode(newTask, attributes); } else if (taskName.equalsIgnoreCase("import")) { //$NON-NLS-1$ newNode= new AntImportNode(newTask, attributes); } else if (taskName.equalsIgnoreCase("macrodef") //$NON-NLS-1$ || taskName.equalsIgnoreCase("presetdef") //$NON-NLS-1$ || taskName.equalsIgnoreCase("typedef") //$NON-NLS-1$ || taskName.equalsIgnoreCase("taskdef")) { //$NON-NLS-1$ newNode= new AntDefiningTaskNode(newTask, attributes); } else if(taskName.equalsIgnoreCase("antcall")) { //$NON-NLS-1$ newNode= new AntTaskNode(newTask, generateLabel(taskName, attributes, IAntModelConstants.ATTR_TARGET)); } else if(taskName.equalsIgnoreCase("mkdir")) { //$NON-NLS-1$ newNode= new AntTaskNode(newTask, generateLabel(taskName, attributes, IPhingCoreConstants.DIR)); } else if(taskName.equalsIgnoreCase("copy")) { //$NON-NLS-1$ newNode= new AntTaskNode(newTask, generateLabel(taskName, attributes, IAntModelConstants.ATTR_DESTFILE)); } else if(taskName.equalsIgnoreCase("tar") //$NON-NLS-1$ || taskName.equalsIgnoreCase("jar") //$NON-NLS-1$ || taskName.equalsIgnoreCase("war") //$NON-NLS-1$ || taskName.equalsIgnoreCase("zip")) { //$NON-NLS-1$ newNode= new AntTaskNode(newTask, generateLabel(newTask.getTaskName(), attributes, IAntModelConstants.ATTR_DESTFILE)); } else if(taskName.equalsIgnoreCase("untar") //$NON-NLS-1$ || taskName.equalsIgnoreCase("unjar") //$NON-NLS-1$ || taskName.equalsIgnoreCase("unwar") //$NON-NLS-1$ || taskName.equalsIgnoreCase("gunzip") //$NON-NLS-1$ || taskName.equalsIgnoreCase("bunzip2") //$NON-NLS-1$ || taskName.equalsIgnoreCase("unzip")) { //$NON-NLS-1$ newNode= new AntTaskNode(newTask, generateLabel(newTask.getTaskName(), attributes, IAntModelConstants.ATTR_SRC)); } else if(taskName.equalsIgnoreCase("gzip") //$NON-NLS-1$ || taskName.equalsIgnoreCase("bzip2")) { //$NON-NLS-1$ newNode= new AntTaskNode(newTask, generateLabel(newTask.getTaskName(), attributes, IAntModelConstants.ATTR_ZIPFILE)); } else if(taskName.equalsIgnoreCase("exec")) { //$NON-NLS-1$ String label = "exec "; //$NON-NLS-1$ String command = attributes.getValue(IAntModelConstants.ATTR_COMMAND); if(command != null) { label += command; } command = attributes.getValue(IAntModelConstants.ATTR_EXECUTABLE); if(command != null) { label += command; } newNode= new AntTaskNode(newTask, label); } else if(taskName.equalsIgnoreCase("ant")) { //$NON-NLS-1$ newNode= new AntAntNode(newTask, attributes); } else if(taskName.equalsIgnoreCase("delete")) { //$NON-NLS-1$ String label = "delete "; //$NON-NLS-1$ String file = attributes.getValue(IPhingCoreConstants.FILE); if(file != null) { label+= file; } else { file = attributes.getValue(IPhingCoreConstants.DIR); if(file != null) { label+= file; } } newNode= new AntTaskNode(newTask, label); } else { newNode = newNotWellKnownTaskNode(newTask, attributes); } setExternalInformation(newTask, newNode); return newNode; } /** * @param taskName the name of the task to check * @return whether or not a task with this name sets properties */ private boolean isPropertySettingTask(String taskName) { return taskName.equalsIgnoreCase("property") //$NON-NLS-1$ || taskName.equalsIgnoreCase("available") //$NON-NLS-1$ || taskName.equalsIgnoreCase("basename") //$NON-NLS-1$ || taskName.equalsIgnoreCase("condition") //$NON-NLS-1$ || taskName.equalsIgnoreCase("dirname") //$NON-NLS-1$ || taskName.equalsIgnoreCase("loadfile") //$NON-NLS-1$ || taskName.equalsIgnoreCase("pathconvert") //$NON-NLS-1$ || taskName.equalsIgnoreCase("uptodate") //$NON-NLS-1$ || taskName.equalsIgnoreCase("xmlproperty") //$NON-NLS-1$ || taskName.equalsIgnoreCase("loadproperties"); //$NON-NLS-1$ } private boolean isNodeExternal(String fileName) { File taskFile= new File(fileName); return !taskFile.equals(getEditedFile()); } private AntTaskNode newNotWellKnownTaskNode(Task newTask, Attributes attributes) { AntTaskNode newNode= new AntTaskNode(newTask); String id= attributes.getValue("id"); //$NON-NLS-1$ if (id != null) { newNode.setId(id); } String taskName= newTask.getTaskName(); if ("attribute".equals(taskName) || "element".equals(taskName)) { //$NON-NLS-1$ //$NON-NLS-2$ String name= attributes.getValue(IPhingCoreConstants.NAME); if (name != null) { newNode.setBaseLabel(name); } } setExternalInformation(newTask, newNode); return newNode; } private void setExternalInformation(Task newTask, AntTaskNode newNode) { String taskFileName= newTask.getLocation().getFileName(); boolean external= isNodeExternal(taskFileName); newNode.setExternal(external); if (external) { newNode.setFilePath(taskFileName); } } private String generateLabel(String taskName, Attributes attributes, String attributeName) { StringBuffer label = new StringBuffer(taskName); String srcFile = attributes.getValue(attributeName); if(srcFile != null) { label.append(' '); label.append(srcFile); } return label.toString(); } private void computeLength(AntElementNode element, int line, int column) { if (element.isExternal()) { element.setExternalInfo(line, column); return; } try { int length; int offset; if (column <= 0) { column= getLastCharColumn(line); String lineText= fDocument.get(fDocument.getLineOffset(line - 1), column); StringBuffer searchString= new StringBuffer("</"); //$NON-NLS-1$ searchString.append(element.getName()); searchString.append('>'); int index= lineText.indexOf(searchString.toString()); if (index == -1) { index= lineText.indexOf("/>"); //$NON-NLS-1$ if (index == -1 ) { index= column; //set to the end of line } else { index= index + 3; } } else { index= index + searchString.length() + 1; } offset= getOffset(line, index); } else { offset= getOffset(line, column); } length= offset - element.getOffset(); element.setLength(length); } catch (BadLocationException e) { //ignore as the parser may be out of sync with the document during reconciliation } } private void computeOffset(AntElementNode element, int line, int column) { if (!canGetPositionInfo()) { return; } if (element.isExternal()) { element.setExternalInfo(line - 1, column); return; } try { String prefix= "<" + element.getName(); //$NON-NLS-1$ int offset = computeOffset(line, column, prefix); element.setOffset(offset + 1); element.setSelectionLength(element.getName().length()); } catch (BadLocationException e) { //ignore as the parser may be out of sync with the document during reconciliation } } private int computeOffset(int line, int column, String prefix) throws BadLocationException { int offset; if (column <= 0) { offset= getOffset(line, 0); int lastCharColumn= getLastCharColumn(line); offset= computeOffsetUsingPrefix(line, offset, prefix, lastCharColumn); } else { column= column -1; offset= getOffset(line, column); offset= computeOffsetUsingPrefix(line, offset, prefix, column); } return offset; } private int computeOffsetUsingPrefix(int line, int offset, String prefix, int column) throws BadLocationException { String lineText= fDocument.get(fDocument.getLineOffset(line - 1), column); int lastIndex= lineText.indexOf(prefix); if (lastIndex > -1) { offset= getOffset(line, lastIndex + 1); } else { return computeOffsetUsingPrefix(line - 1, offset, prefix, getLastCharColumn(line - 1)); } return offset; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#getOffset(int, int) */ public int getOffset(int line, int column) throws BadLocationException { return fDocument.getLineOffset(line - 1) + column - 1; } private int getNonWhitespaceOffset(int line, int column) throws BadLocationException { int offset= fDocument.getLineOffset(line - 1) + column - 1; while(Character.isWhitespace(fDocument.getChar(offset))) { offset++; } return offset; } public int getLine(int offset) { try { return fDocument.getLineOfOffset(offset) + 1; } catch (BadLocationException be) { return -1; } } private int getLastCharColumn(int line) throws BadLocationException { String lineDelimiter= fDocument.getLineDelimiter(line - 1); int lineDelimiterLength= lineDelimiter != null ? lineDelimiter.length() : 0; return fDocument.getLineLength(line - 1) - lineDelimiterLength; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#setCurrentElementLength(int, int) */ public void setCurrentElementLength(int lineNumber, int column) { fLastNode= (AntElementNode)fStillOpenElements.pop(); if (fLastNode == fCurrentTargetNode) { fCurrentTargetNode= null; //the current target element has been closed } if (canGetPositionInfo()) { computeLength(fLastNode, lineNumber, column); } } private void acceptProblem(IProblem problem) { if (fProblemRequestor != null) { fProblemRequestor.acceptProblem(problem); } if (fMarkerUpdater != null) { fMarkerUpdater.acceptProblem(problem); } } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#getFile() */ public IFile getFile() { IPath location= fLocationProvider.getLocation(); if (location == null) { return null; } IFile[] files= ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(location); if (files.length > 0) { return files[0]; } return null; } private void beginReporting() { if (fProblemRequestor != null) { fProblemRequestor.beginReporting(); } if (fMarkerUpdater != null) { fMarkerUpdater.beginReporting(); } } private void endReporting() { if (fProblemRequestor != null) { fProblemRequestor.endReporting(); } } private IProblem createProblem(Exception exception, int offset, int length, int severity) { return createProblem(exception.getMessage(), offset, length, severity); } private IProblem createProblem(String message, int offset, int length, int severity) { return new AntModelProblem(message, severity, offset, length, getLine(offset)); } private void notifyProblemRequestor(Exception exception, AntElementNode element, int severity) { if (doNotReportProblems()) { return; } AntElementNode importNode= element.getImportNode(); if (importNode != null) { element= importNode; } IProblem problem= createProblem(exception, element.getOffset(), element.getLength(), severity); acceptProblem(problem); element.associatedProblem(problem); } private void notifyProblemRequestor(Exception exception, int offset, int length, int severity) { if (doNotReportProblems()) { return; } if (fProblemRequestor != null) { IProblem problem= createProblem(exception, offset, length, severity); acceptProblem(problem); } } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#warning(java.lang.Exception) */ public void warning(Exception exception) { handleError(exception, AntModelProblem.SEVERITY_WARNING); } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#error(java.lang.Exception) */ public void error(Exception exception) { handleError(exception, AntModelProblem.SEVERITY_ERROR); } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#errorFromElementText(java.lang.Exception, int, int) */ public void errorFromElementText(Exception exception, int start, int count) { AntElementNode node= fLastNode; if (node == null) { if (!fStillOpenElements.empty()) { node= (AntElementNode)fStillOpenElements.peek(); } } if (node == null) { return; } computeEndLocationForErrorNode(node, start, count); notifyProblemRequestor(exception, start, count, AntModelProblem.SEVERITY_ERROR); markHierarchy(fLastNode, AntModelProblem.SEVERITY_ERROR, exception.getMessage()); } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#errorFromElement(java.lang.Exception, org.eclipse.ant.internal.ui.model.AntElementNode, int, int) */ public void errorFromElement(Exception exception, AntElementNode node, int lineNumber, int column) { if (node == null) { if (!fStillOpenElements.empty()) { node= (AntElementNode)fStillOpenElements.peek(); } else { node= fLastNode; } } computeEndLocationForErrorNode(node, lineNumber, column); notifyProblemRequestor(exception, node, AntModelProblem.SEVERITY_ERROR); markHierarchy(node, AntModelProblem.SEVERITY_ERROR, exception.getMessage()); } private AntElementNode createProblemElement(SAXParseException exception) { int lineNumber= exception.getLineNumber(); StringBuffer message= new StringBuffer(exception.getMessage()); if (lineNumber != -1){ message.append(AntModelMessages.AntModel_1 + lineNumber); } AntElementNode errorNode= new AntElementNode(message.toString()); errorNode.setFilePath(exception.getSystemId()); errorNode.setProblemSeverity(AntModelProblem.SEVERITY_ERROR); errorNode.setProblemMessage(exception.getMessage()); computeErrorLocation(errorNode, exception); return errorNode; } private void computeErrorLocation(AntElementNode element, SAXParseException exception) { if (element.isExternal()) { return; } int line= exception.getLineNumber(); int startColumn= exception.getColumnNumber(); computeEndLocationForErrorNode(element, line, startColumn); } private void computeEndLocationForErrorNode(AntElementNode element, int line, int startColumn) { try { if (line <= 0) { line= 1; } int endColumn; if (startColumn <= 0) { if (element.getOffset() > -1) { startColumn= element.getOffset() + 1; } else { startColumn= 1; } endColumn= getLastCharColumn(line) + 1; } else { if (startColumn > 1) { --startColumn; } endColumn= startColumn; if (startColumn <= getLastCharColumn(line)) { ++endColumn; } } int correction= 0; if (element.getOffset() == -1) { int originalOffset= getOffset(line, startColumn); int nonWhitespaceOffset= originalOffset; try { nonWhitespaceOffset= getNonWhitespaceOffset(line, startColumn); } catch (BadLocationException be) { } element.setOffset(nonWhitespaceOffset); correction= nonWhitespaceOffset - originalOffset; } if (endColumn - startColumn == 0) { int offset= getOffset(line, startColumn); element.setLength(offset - element.getOffset() - correction); } else { element.setLength(endColumn - startColumn - correction); } } catch (BadLocationException e) { //ignore as the parser may be out of sync with the document during reconciliation } } private void handleError(Exception exception, int severity) { AntElementNode node= null; if (fStillOpenElements.isEmpty()) { if (exception instanceof SAXParseException) { node= createProblemElement((SAXParseException)exception); } } else { node= (AntElementNode)fStillOpenElements.peek(); } if (node == null) { return; } markHierarchy(node, severity, exception.getMessage()); if (exception instanceof SAXParseException) { SAXParseException parseException= (SAXParseException)exception; if (node.getOffset() == -1) { computeEndLocationForErrorNode(node, parseException.getLineNumber() - 1, parseException.getColumnNumber()); } else { int lineNumber= parseException.getLineNumber(); int columnNumber= parseException.getColumnNumber(); if (columnNumber == -1) { columnNumber= 1; } try { AntElementNode childNode= node.getNode(getNonWhitespaceOffset(lineNumber, columnNumber) + 1); if (childNode != null && childNode != node) { node= childNode; node.setProblemSeverity(severity); node.setProblemMessage(exception.getMessage()); } else { node= createProblemElement(parseException); } } catch (BadLocationException be) { node= createProblemElement(parseException); } } } notifyProblemRequestor(exception, node, severity); if (node != null) { while (node.getParentNode() != null) { AntElementNode parentNode= node.getParentNode(); if (parentNode.getLength() == -1) { parentNode.setLength(node.getOffset() - parentNode.getOffset() + node.getLength()); } node= parentNode; } } } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#fatalError(java.lang.Exception) */ public void fatalError(Exception exception) { handleError(exception, AntModelProblem.SEVERITY_FATAL_ERROR); } public AntElementNode getOpenElement() { if (fStillOpenElements.isEmpty()) { return null; } return (AntElementNode)fStillOpenElements.peek(); } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#getEntityName(java.lang.String) */ public String getEntityName(String path) { if (fEntityNameToPath != null) { Iterator itr= fEntityNameToPath.keySet().iterator(); String entityPath; String name; while (itr.hasNext()) { name= (String) itr.next(); entityPath= (String) fEntityNameToPath.get(name); if (entityPath.equals(path)) { return name; } } } return null; } private ClassLoader getClassLoader(ClassLoader contextClassLoader) { return contextClassLoader; /* synchronized (loaderLock) { if (fLocalClassLoader != null) { // ((AntClassLoader) fLocalClassLoader).setPluginContextClassloader(contextClassLoader); return fLocalClassLoader; } if (fgClassLoader == null) { fgClassLoader= PhingCore.getPlugin().getNewClassLoader(true); } if (fgClassLoader instanceof AntClassLoader) { // ((AntClassLoader) fgClassLoader).setPluginContextClassloader(contextClassLoader); } return fgClassLoader; } */ } public String getTargetDescription(String targetName) { AntTargetNode target= getTargetNode(targetName); if (target != null) { return target.getTarget().getDescription(); } return null; } public AntTargetNode getTargetNode(String targetName ) { AntProjectNode projectNode= getProjectNode(); if (projectNode == null) { return null; } if (projectNode.hasChildren()) { List possibleTargets= projectNode.getChildNodes(); Iterator iter= possibleTargets.iterator(); while (iter.hasNext()) { AntElementNode node = (AntElementNode) iter.next(); if (node instanceof AntTargetNode) { AntTargetNode targetNode = (AntTargetNode) node; if (targetName.equalsIgnoreCase(targetNode.getTarget().getName())) { return targetNode; } } } } return null; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#getProjectNode(boolean) */ public AntProjectNode getProjectNode(boolean doReconcile) { if (doReconcile) { synchronized (getLockObject()) { //ensure to wait for any current synchronization reconcile(); } } return fProjectNode; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#getProjectNode() */ public AntProjectNode getProjectNode() { return getProjectNode(true); } public AntElementNode getNode(int offset, boolean waitForReconcile) { if (getProjectNode(waitForReconcile) != null) { return getProjectNode(waitForReconcile).getNode(offset); } return null; } /** * Removes any type definitions that no longer exist in the buildfile */ private void reconcileTaskAndTypes() { if (fCurrentNodeIdentifiers == null || fDefinerNodeIdentifierToDefinedTasks == null) { return; } Iterator iter= fDefinerNodeIdentifierToDefinedTasks.keySet().iterator(); ComponentHelper helper= ComponentHelper.getComponentHelper(fProjectNode.getProject()); while (iter.hasNext()) { String key = (String) iter.next(); if (fCurrentNodeIdentifiers.get(key) == null) { removeDefinerTasks(key, helper.getAntTypeTable()); } } } protected void removeDefinerTasks(String definerIdentifier, Hashtable typeTable) { if (fDefinerNodeIdentifierToDefinedTasks == null) { return; } List tasks= (List) fDefinerNodeIdentifierToDefinedTasks.get(definerIdentifier); if (tasks == null) { return; } Iterator iterator= tasks.iterator(); while (iterator.hasNext()) { typeTable.remove(iterator.next()); } } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#addComment(int, int, int) */ public void addComment(int lineNumber, int columnNumber, int length) { AntCommentNode commentNode= new AntCommentNode(); int offset= -1; try { offset= computeOffset(lineNumber, columnNumber, "-->"); //$NON-NLS-1$ } catch (BadLocationException e) { commentNode.setExternal(true); commentNode.setExternalInfo(lineNumber, columnNumber); offset= length-1; } commentNode.setOffset(offset - length); commentNode.setLength(length); fNonStructuralNodes.add(commentNode); } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#needsTaskResolution() */ public boolean canGetTaskInfo() { return fHasTaskInfo; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#needsLexicalResolution() */ public boolean canGetLexicalInfo() { return fHasLexicalInfo; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#setClassLoader(java.net.URLClassLoader) */ public void setClassLoader(URLClassLoader loader) { AntDefiningTaskNode.setJavaClassPath(loader.getURLs()); fLocalClassLoader= loader; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#needsPositionResolution() */ public boolean canGetPositionInfo() { return fHasPositionInfo; } public String getPath(String text, int offset) { if (fEntityNameToPath != null) { String path= (String)fEntityNameToPath.get(text); if (path != null) { return path; } } AntElementNode node= getNode(offset, true); if (node != null) { return node.getReferencedElement(offset); } return null; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#getText(int, int) */ public String getText(int offset, int length) { try { return fDocument.get(offset, length); } catch (BadLocationException e) { } return null; } private AntElementNode findPropertyNode(String text, List children) { Iterator iter= children.iterator(); while (iter.hasNext()) { AntElementNode element = (AntElementNode) iter.next(); if (element instanceof AntPropertyNode) { if (((AntPropertyNode)element).getProperty(text) != null){ return element; } } else if (element.hasChildren()) { AntElementNode found= findPropertyNode(text, element.getChildNodes()); if (found != null) { return found; } } } return null; } public AntElementNode getPropertyNode(String text) { AntProjectNode node= getProjectNode(); if (node == null || !node.hasChildren()) { return null; } return findPropertyNode(text, node.getChildNodes()); } public List getNonStructuralNodes() { return fNonStructuralNodes; } public void updateForInitialReconcile() { fMarkerUpdater.updateMarkers(); fShouldReconcile= PhingUi.getDefault().getPreferenceStore().getBoolean(AntEditorPreferenceConstants.EDITOR_RECONCILE); } public void updateMarkers() { boolean temp= fShouldReconcile; try { fShouldReconcile= true; reconcile(); fMarkerUpdater.updateMarkers(); } finally { fShouldReconcile= temp; } } public AntElementNode getReferenceNode(String text) { Object reference = getReferenceObject(text); if (reference == null) { return null; } Collection nodes = fTaskToNode.keySet(); Iterator iter = nodes.iterator(); while (iter.hasNext()) { Object original = iter.next(); Object object = original; if (object instanceof UnknownElement) { UnknownElement element = (UnknownElement) object; RuntimeConfigurable wrapper = element.getWrapper(); Map attributes = wrapper.getAttributeMap(); String id = (String) attributes.get("id"); //$NON-NLS-1$ if (text.equals(id)) { return (AntElementNode)fTaskToNode.get(original); } } } return null; } public Object getReferenceObject(String refId) { AntProjectNode projectNode= getProjectNode(); if (projectNode == null) { return null; } try { Project project= projectNode.getProject(); Object ref= project.getReference(refId); return ref; } catch (BuildException be) { handleBuildException(be, null); } return null; } public String getPropertyValue(String propertyName) { AntProjectNode projectNode= getProjectNode(); if (projectNode == null) { return null; } return projectNode.getProject().getProperty(propertyName); } /** * Only called if the AntModel is associated with an AntEditor */ public void install() { fListener= new IDocumentListener() { public void documentAboutToBeChanged(DocumentEvent event) { synchronized (fDirtyLock) { fIsDirty= true; } } public void documentChanged(DocumentEvent event) {} }; fDocument.addDocumentListener(fListener); } private void reconcileForPropertyChange(boolean classpathChanged) { if (classpathChanged) { fProjectNode= null; //need to reset tasks, types and properties fgClassLoader= null; AntDefiningTaskNode.setJavaClassPath(); ProjectHelper.reset(); } fIsDirty= true; reconcile(); AntModelCore.getDefault().notifyAntModelListeners(new AntModelChangeEvent(this, true)); fMarkerUpdater.updateMarkers(); } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#setProperties(java.util.Map) */ public void setProperties(Map properties) { fProperties= properties; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#setPropertyFiles(java.util.List) */ public void setPropertyFiles(String[] propertyFiles) { if (propertyFiles != null) { fPropertyFiles= Arrays.asList(propertyFiles); } } public void setDefiningTaskNodeText(AntDefiningTaskNode node) { if (fDefinersToText == null) { fDefinersToText= new HashMap(); fCurrentNodeIdentifiers= new HashMap(); } Object nodeIdentifier= node.getIdentifier(); String nodeText= null; if (fPreviousDefinersToText != null) { nodeText= (String) fPreviousDefinersToText.get(nodeIdentifier); } String newNodeText= getText(node.getOffset(), node.getLength()); if (nodeText != null) { if (nodeText.equals(newNodeText)) { node.setNeedsToBeConfigured(false); //update the data structures for the new node as the offset may have changed. List tasks= (List) fDefinerNodeIdentifierToDefinedTasks.get(nodeIdentifier); if (tasks != null) { for (Iterator iter = tasks.iterator(); iter.hasNext(); ) { String taskName = (String) iter.next(); fTaskNameToDefiningNode.put(taskName, node); } } } } if (newNodeText != null) { fDefinersToText.put(nodeIdentifier, newNodeText); } fCurrentNodeIdentifiers.put(nodeIdentifier, nodeIdentifier); } protected void removeDefiningTaskNodeInfo(AntDefiningTaskNode node) { Object identifier= node.getIdentifier(); if (identifier != null && fCurrentNodeIdentifiers != null) { fCurrentNodeIdentifiers.remove(identifier); fDefinersToText.remove(identifier); } } protected void addDefinedTasks(List newTasks, AntDefiningTaskNode node) { if (fTaskNameToDefiningNode == null) { fTaskNameToDefiningNode= new HashMap(); fDefinerNodeIdentifierToDefinedTasks= new HashMap(); } Object identifier= node.getIdentifier(); if (identifier == null) { return; } if (newTasks.isEmpty() && fCurrentNodeIdentifiers != null) { fCurrentNodeIdentifiers.remove(identifier); } fDefinerNodeIdentifierToDefinedTasks.put(identifier, newTasks); Iterator iter= newTasks.iterator(); while (iter.hasNext()) { String name = (String) iter.next(); fTaskNameToDefiningNode.put(name, node); } } public AntDefiningTaskNode getDefininingTaskNode(String nodeName) { if (fTaskNameToDefiningNode != null) { AntDefiningTaskNode node= (AntDefiningTaskNode)fTaskNameToDefiningNode.get(nodeName); if (node == null) { nodeName = getNamespaceCorrectName(nodeName); node= (AntDefiningTaskNode)fTaskNameToDefiningNode.get(nodeName); } return node; } return null; } public String getNamespaceCorrectName(String nodeName) { String prefix= org.apache.tools.ant.ProjectHelper.extractUriFromComponentName(nodeName); String uri= getPrefixMapping(prefix); nodeName= org.apache.tools.ant.ProjectHelper.genComponentName(uri, org.apache.tools.ant.ProjectHelper.extractNameFromComponentName(nodeName)); return nodeName; } public String getUserNamespaceCorrectName(String nodeName) { String prefix= org.apache.tools.ant.ProjectHelper.extractUriFromComponentName(nodeName); if (prefix.length() > 0) { String uri= getUserPrefixMapping(prefix); nodeName= org.apache.tools.ant.ProjectHelper.genComponentName(uri, org.apache.tools.ant.ProjectHelper.extractNameFromComponentName(nodeName)); } return nodeName; } public AntTaskNode getMacroDefAttributeNode(String macroDefAttributeName) { if (fTaskNameToDefiningNode == null) { return null; } Iterator iter = fTaskNameToDefiningNode.values().iterator(); while(iter.hasNext()) { AntDefiningTaskNode definingNode = (AntDefiningTaskNode) iter.next(); List attributes= definingNode.getChildNodes(); if (attributes != null) { Iterator attributeItr= attributes.iterator(); while (attributeItr.hasNext()) { AntTaskNode attributeNode= (AntTaskNode) attributeItr.next(); if (macroDefAttributeName.equals(attributeNode.getLabel())) { return attributeNode; } } } } return null; } /** * Sets whether the AntModel should reconcile if it become dirty. * If set to reconcile, a reconcile is triggered if the model is dirty. * @param shouldReconcile */ public void setShouldReconcile(boolean shouldReconcile) { fShouldReconcile= shouldReconcile; if (fShouldReconcile) { reconcile(); } } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#addPrefixMapping(java.lang.String, java.lang.String) */ public void addPrefixMapping(String prefix, String uri) { if (fNamespacePrefixMappings == null) { fNamespacePrefixMappings= new HashMap(); } fNamespacePrefixMappings.put(prefix, uri); } private String getPrefixMapping(String prefix) { if (fNamespacePrefixMappings != null) { return (String) fNamespacePrefixMappings.get(prefix); } return null; } private String getUserPrefixMapping(String prefix) { if (fNamespacePrefixMappings != null) { Set entrySet= fNamespacePrefixMappings.entrySet(); Iterator entries= entrySet.iterator(); while (entries.hasNext()) { Map.Entry entry = (Map.Entry) entries.next(); if (entry.getValue().equals(prefix)) { return (String) entry.getKey(); } } } return null; } /** * @see AntModel#cleanup() */ class Small { } /** * Compute the encoding for the backing build file * * @since 3.7 */ void computeEncoding() { try { IFile file = getFile(); if(file != null) { fEncoding = getFile().getCharset(true); return; } } catch (CoreException e) { //do nothing. default to UTF-8 } //try the file buffer manager - likely an external file IPath path = getLocationProvider().getLocation(); if(path != null) { File buildfile = path.toFile(); FileReader reader = null; try { reader = new FileReader(buildfile); QualifiedName[] options= new QualifiedName[] {IContentDescription.CHARSET}; IContentDescription desc = Platform.getContentTypeManager().getDescriptionFor(reader, buildfile.getName(), options); if(desc != null) { fEncoding = desc.getCharset(); return; } } catch(IOException ioe) {} finally { if(reader != null) { try { reader.close(); } catch (IOException e) {} } } } fEncoding = IPhingCoreConstants.UTF_8; } /* (non-Javadoc) * @see org.eclipse.ant.internal.ui.model.IAntModel#getEncoding() */ public String getEncoding() { return fEncoding; } }