Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 6460 Details for
Bug 45071
don't allocate builder progress for closed projects
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
Builder class code that causes this problem
Majordomo.java.java (text/plain), 26.65 KB, created by
Timothy Halloran
on 2003-10-16 22:06:23 EDT
(
hide
)
Description:
Builder class code that causes this problem
Filename:
MIME Type:
Creator:
Timothy Halloran
Created:
2003-10-16 22:06:23 EDT
Size:
26.65 KB
patch
obsolete
>package edu.cmu.cs.fluid.dc; > >import java.util.*; >import java.util.logging.Level; >import java.util.logging.Logger; > >import org.eclipse.core.resources.*; >import org.eclipse.core.runtime.*; >import org.eclipse.jdt.core.*; >import org.eclipse.jdt.core.dom.AST; >import org.eclipse.jdt.core.dom.CompilationUnit; > >/** > * The central controller to notify analysis modules that changes to the state > * of a Java project have occured. > */ >public final class Majordomo > extends IncrementalProjectBuilder > implements IResourceVisitor, IResourceDeltaVisitor { > > private static Logger LOG = Logger.getLogger("edu.cmu.cs.fluid.dc"); > > /** > * Holds the {@link IProgressMonitor} passed in by calls to {@link #build}. > */ > private IProgressMonitor buildMonitor = null; > > /** > * Holds the list of analysis modules at the current level during > * a call to {@link #build}. > */ > private Set currentLevel; > > /** > * Holds a cache of Eclipse ASTs that have been generated during > * a single change to the Eclipse workspace. Designed to speed > * analyses by not rebuilding the Eclipse AST many times. > */ > private Map astCache = new HashMap(); // of ICompilationUnit > > /** > * Class constructor. > */ > public Majordomo() { > // do nothing > } > > /** > * Since we do not persist, we forget our state at startup to trigger a > * rebuild for only our builder. > * > * @see org.eclipse.core.internal.events.InternalBuilder#startupOnInitialize() > */ > protected void startupOnInitialize() { > super.startupOnInitialize(); > forgetLastBuiltState(); > } > > /** > * The core driver {@link Majordomo} uses to invoke analysis modules. This > * is the method invoked by Eclipse for a full or incremental build. > * However, we can only invoke analysis modules <I>if</I> the Java project > * compiles without any errors. > * > * @see org.eclipse.core.internal.events.InternalBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) > */ > protected IProject[] build(int kind, Map args, IProgressMonitor monitor) > throws CoreException { > setProgressMonitor(monitor); > > // cache Eclipse provide workspace changes > IResourceDelta delta = getDelta(getProject()); > if ((kind == IncrementalProjectBuilder.FULL_BUILD) || (delta == null)) { > getCacheInstance(getProject()).cacheRebuild(); > } else { > delta.accept(this); // add changes to our per-project resource cache > } > > IJavaProject javaProject = JavaCore.create(getProject()); > if (noCompilationErrors(javaProject)) { > // we are OK to do analysis -- no errors > getCacheInstance(getProject()).flushCache(); > clearCacheInstance(getProject()); // wipe the cache for this project > } > > showBuildIsDone(); > > // we could return a list of projects for which we require > // a resource delta the next time we are run -- but we don't > return null; > } > > /** > * Resource visitor method for a full re-analysis. > * > * @see org.eclipse.core.resources.IResourceVisitor#visit(org.eclipse.core.resources.IResource) > */ > public boolean visit(IResource resource) throws CoreException { > analyzeResourceCurrentLevel(resource, IResourceDelta.ADDED); > return true; > } > > /** > * Resource visitor method for caching resources that have changed within > * the Eclipse workspace during an incremental build. > * > * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) > */ > public boolean visit(IResourceDelta delta) throws CoreException { > IResource resource = delta.getResource(); > getCacheInstance(getProject()).cacheAResource(resource, delta.getKind()); > return true; > } > > /** > * {@link Majordomo}'s map from projects to project resource caches > * (i.e., {@link ProjectCache} instances). > */ > private Map projectCache = new HashMap(); // of ProjectCache > > /** > * Looks up, or creates, a resource cache for <code>project</code>. > * > * @param project the project of interest > * @return the resource cache for <code>project</code> > */ > private ProjectCache getCacheInstance(IProject project) { > if (projectCache.containsKey(project)) { > return (ProjectCache) projectCache.get(project); > } else { > ProjectCache newCache = new ProjectCache(project); > projectCache.put(project, newCache); // add cache > return newCache; > } > } > > /*** > * Clears the overall cache for <code>project</code>. > * > * @param project the project to wipe from the cache > */ > private void clearCacheInstance(IProject project) { > projectCache.remove(project); // clear resource cache for this project > } > > /** > * A class to manage build caching for a specific project. This is needed > * because {@link Majordomo} can only invoke analysis modules (on changed > * resources ) when a Java project compiles without errors. > */ > private class ProjectCache { > > private IProject project; > private boolean doRebuild = false; > private List resourceCache = new LinkedList(); // of CacheEntry > > /** > * Private constructor to avoid stray instances. > * > * @param project project to construct a resource cache for > */ > ProjectCache(IProject project) { > this.project = project; > } > > /** > * Cache a resource for analysis when the project compiles without errors. > * > * @param resource the resource to add to the project resource cache > * @param kind one of {@link IResourceDelta#ADDED}, > * {@link IResourceDelta#REMOVED}, or {@link IResourceDelta#CHANGED} > */ > void cacheAResource(IResource resource, int kind) { > if (!doRebuild) { // ignore if we are already rebuild everything > // remove any duplicates > for (Iterator iter = resourceCache.iterator(); iter.hasNext();) { > CacheEntry element = (CacheEntry) iter.next(); > if ((element.getResource().equals(resource)) > && (element.getKind() == kind)) { > iter.remove(); > } > } > // add to the end of the list (so we maintain Eclipse order) > resourceCache.add(new CacheEntry(resource, kind)); > } > } > > /** > * Cache a fullrebuild (i.e., redo all analyses) when the project compiles > * without errors. > */ > void cacheRebuild() { > doRebuild = true; > resourceCache = null; // wipe any resources we have collected > } > > /** > * Adds Java files that have been recompiled without source changes > * (i.e., due to binding changes) to be re-analyzed. This is > * accomplished by examining the cached resources to see if any ".class" > * files have been modified without a coresponding change to a ".java" > * file. > */ > void inferJavaFileCompiled() throws JavaModelException { > > List toAddResources = new LinkedList(); // of IResource > > // don't do anything for a full build > if (resourceCache == null) > return; > > for (Iterator i = resourceCache.iterator(); i.hasNext();) { > CacheEntry cacheEntry = (CacheEntry) i.next(); > if (cacheEntry.getKind() != IResourceDelta.REMOVED) { > IResource resource = cacheEntry.getResource(); > String extension = resource.getFileExtension(); > if (extension == null || !extension.equals(".class")) { > continue; // can't be a class file > } > IJavaElement jElement = JavaCore.create(resource); > if (jElement != null) { > if (jElement instanceof IClassFile) { > // is a ".class" file > IClassFile classFile = (IClassFile) jElement; > IJavaProject prj = classFile.getJavaProject(); > if (prj != null) { > String fauxJavaFileName = > generateFauxJavaFileName(classFile, prj); > > boolean inCache = > fauxJavaFileNameExistsInCache(fauxJavaFileName); > > if (inCache) { > // Need to lookup resource in project > IResource javaFile = > lookupResourceForJavaFileName(fauxJavaFileName, prj); > if (javaFile != null) { > toAddResources.add(javaFile); > LOG.info( > "Java file " > + fauxJavaFileName > + " added to analysis due to class file change"); > } > } > } else { > // Couldn't find the project > LOG.severe("Unable to find the Java project for " + classFile); > } > } > } else { > // JavaCore returned null attempting to create IJavaElement > LOG.severe("Unable to create Java element for " + resource); > } > } > } > > // Add new items to our main cache > for (Iterator i = toAddResources.iterator(); i.hasNext();) { > IResource newFile = (IResource) i.next(); > resourceCache.add(new CacheEntry(newFile, IResourceDelta.CHANGED)); > } > } > > /** > * Checks if the fauxJavaFileName-prefix is already in the cache to be > * analyzed (i.e., a change to the ".java" file caused the compiler > * to change the ".class" file). > * > * @param fauxJavaFileName a made up ".java" file name from a changed > * ".class" file > * @return <code>true</code> if the name of a cached file ends with > * fauxJavaFileName, <code>false</code> otherwise > */ > private boolean fauxJavaFileNameExistsInCache(String fauxJavaFileName) { > > boolean found = false; > > for (Iterator i1 = resourceCache.iterator(); i1.hasNext();) { > CacheEntry element = (CacheEntry) i1.next(); > if (element > .getResource() > .getFullPath() > .toString() > .endsWith(fauxJavaFileName)) { > found = true; > break; > } > } > return found; > } > > /** > * Infers a source path relative Java filename (i.e., a ".java" file) > * from a ".class" file. > * > * @param classFile the binary ".class" file we want the ".java" name for > * @param prj the Eclipse Java project the class file is contained within > * @return a source path relative Java file name for the given > * classfile, <code>null</code> otherwise > */ > private String generateFauxJavaFileName( > IClassFile classFile, > IJavaProject prj) > throws JavaModelException { > > String result = null; // default if we can't generate a name > String classFilePath = classFile.getPath().toString(); > > // check to ensure that this filename ends with "class" > if (classFilePath > .substring(classFilePath.length() - 5) > .equalsIgnoreCase("class")) { > // change ".class" to ".java" > String javaFilePath = > classFilePath.substring(0, classFilePath.length() - 5) + "java"; > > IPath outputPath = prj.getOutputLocation(); > String outputPathPrefix = outputPath.toString(); > if (javaFilePath.startsWith(outputPathPrefix)) { > result = javaFilePath.substring(outputPathPrefix.length()); > } else { > LOG.severe( > "Eclipse output directory of classfile " > + classFilePath > + " is not in the default location of " > + outputPathPrefix); > } > } else { > LOG.info( > "Modified classfile " > + classFilePath > + "does not end with \".class\""); > } > return result; > } > > /** > * Attempts, by examining each and every Eclipse package fragment root, > * to lookup the <code>IResource</code> for the given source path > * relative ".java" file name. Returns <code>null</code> if the file > * cannot be found. > * > * @param resourceJavaFilePath the Java filename to lookup > * @param prj the Eclipse Java project the file is contained within > * @return the Eclipse resource related to the given filename, > * <code>null</code> otherwise > */ > private IResource lookupResourceForJavaFileName( > String resourceJavaFilePath, > IJavaProject prj) > throws JavaModelException { > > IResource result = null; // default is null > > for (int i = 0; i < prj.getAllPackageFragmentRoots().length; i++) { > IPackageFragmentRoot curPkgFragRoot = > prj.getAllPackageFragmentRoots()[i]; > > // only check if this package fragement root contains source code > if (curPkgFragRoot.getKind() == IPackageFragmentRoot.K_SOURCE) { > String srcPath = > curPkgFragRoot.getRawClasspathEntry().getPath().toString(); > String javaFileName = srcPath + resourceJavaFilePath; > IPath javaFilePath = new Path(javaFileName); > result = > prj.getProject().findMember(javaFilePath.removeFirstSegments(1)); > } > } > return result; > } > > /** > * Engages analysis modules on all changed project resources (which have > * been cached) when the project compiles with no errors. > * > * @throws CoreException if visiting project resource encounters problems > */ > void flushCache() throws CoreException { > > astCache.clear(); // clear the Eclipse AST cache > > inferJavaFileCompiled(); > > if (doRebuild) { > // full re-analysis > LOG.fine( > "flushing cache on " + getProject().getName() + " via full analysis"); > CounterVisitor counter = new CounterVisitor(); > getProject().accept(counter); > int totalWork = counter.getResourceCount() * analysisDepth(); > showBuildIsStarting(totalWork); > resetAnalysesForFullBuild(getProject()); > for (int i = 0; i < analysisDepth(); ++i) { > currentLevel = (Set) Plugin.getDefault().analysisExtensionSets.get(i); > analyzeBeginCurrentLevel(getProject()); > getProject().accept(Majordomo.this); > analyzeEndCurrentLevel(getProject()); > } > } else { > // incremental analyses based upon the cached resource delta > LOG.fine( > "flushing cache on " > + getProject().getName() > + " via incremental analysis"); > int totalWork = resourceCache.size() * analysisDepth(); > showBuildIsStarting(totalWork); > for (int i = 0; i < analysisDepth(); ++i) { > currentLevel = (Set) Plugin.getDefault().analysisExtensionSets.get(i); > analyzeBeginCurrentLevel(getProject()); > for (Iterator j = resourceCache.iterator(); j.hasNext();) { > CacheEntry element = (CacheEntry) j.next(); > Majordomo.this.analyzeResourceCurrentLevel( > element.getResource(), > element.getKind()); > } > analyzeEndCurrentLevel(getProject()); > } > } > } > > /** > * A simple class to save a single {@link IResource} and what type of > * change (e.g., {@link IResourceDelta#ADDED}, > * {@link IResourceDelta#REMOVED}, or {@link IResourceDelta#CHANGED}) > * was done to it within the project workspace. > */ > private class CacheEntry { > > private IResource resource; > private int kind; > > /** > * Constructs a fully defined new project resource builder cache entry. > * > * @param resource the resource > * @param kind one of {@link IResourceDelta#ADDED}, > * {@link IResourceDelta#REMOVED}, or {@link IResourceDelta#CHANGED} > */ > CacheEntry(IResource resource, int kind) { > this.resource = resource; > this.kind = kind; > } > > /** > * @return one of {@link IResourceDelta#ADDED}, > * {@link IResourceDelta#REMOVED}, or {@link IResourceDelta#CHANGED} > */ > int getKind() { > return kind; > } > > /** > * @return cached resource > */ > IResource getResource() { > return resource; > } > > } > > } > > /** > * Returns the number of distinct levels, or passes, needed to properly > * invoke all registered analysis modules and respect their prerequisties. > * > * @return number of levels of analysis needed > */ > public int analysisDepth() { > // how many levels do we have > return Plugin.getDefault().analysisExtensionSets.size(); > } > > /** > * Informs all registered analysis modules that a rebuild is going to be > * done for a specific Eclipse project. > * > * @param project the Eclipse project about to be rebuilt > */ > private void resetAnalysesForFullBuild(IProject project) { > Plugin plugin = Plugin.getDefault(); > IExtension[] extensions = plugin.analysisExtensions; > for (int i = 0; i < extensions.length; ++i) { > plugin.getAnalysisModule(extensions[i]).resetForAFullBuild(project); > } > } > > /** > * Invokes {@link IAnalysis#analyzeBegin} on all analysis modules at the > * current level. > * > * @param project the Eclipse project referenced > */ > public void analyzeBeginCurrentLevel(IProject project) { > for (Iterator i = currentLevel.iterator(); i.hasNext();) { > IExtension ext = (IExtension) i.next(); > Plugin.getDefault().getAnalysisModule(ext).analyzeBegin(project); > } > } > > /** > * Invokes {@link IAnalysis#analyzeResource} on all analysis modules at the > * current level. > * > * @param resource the resource within the project to analyze > * @param kind one of {@link IResourceDelta#ADDED}, > * {@link IResourceDelta#REMOVED}, or {@link IResourceDelta#CHANGED} > */ > private void analyzeResourceCurrentLevel(IResource resource, int kind) { > for (Iterator i = currentLevel.iterator(); i.hasNext();) { > IExtension ext = (IExtension) i.next(); > IAnalysis analysisModule = Plugin.getDefault().getAnalysisModule(ext); > analysisModule.setLabel(ext.getLabel()); > analyzeResource(analysisModule, resource, kind); > } > showProgress(); > checkForUserCancel(); > } > > /** > * Invokes {@link IAnalysis#analyzeResource} on <code>analysisModule</code> > * and checks if {@link IAnalysis#analyzeCompilationUnit} needs to be invoked. > * > * @param analysisModule the analysis module target > * @param resource the resource to analyze > * @param kind one of {@link IResourceDelta#ADDED}, > * {@link IResourceDelta#REMOVED}, or {@link IResourceDelta#CHANGED} > */ > private void analyzeResource( > IAnalysis analysisModule, > IResource resource, > int kind) { > String msg = > "double-checking [" > + analysisModule.getLabel() > + "] " > + resource.getName(); > setProgressSubTaskName(msg); > LOG.fine(msg); > boolean sendCompilationUnit = > !analysisModule.analyzeResource(resource, kind); > if (sendCompilationUnit) { > sendCompilationUnit(analysisModule, resource); > } > } > > /** > * Invokes {@link IAnalysis#analyzeCompilationUnit} on > * <code>analysisModule</code> if <code>resource</code> is a Java > * compilation unit that is on the project classpath. > * > * @param analysisModule the analysis module target > * @param resource the resource to analyze > */ > private void sendCompilationUnit( > IAnalysis analysisModule, > IResource resource) { > IJavaElement javaResource = JavaCore.create(resource); > if ((javaResource != null) > && (javaResource.getElementType() == IJavaElement.COMPILATION_UNIT)) { > ICompilationUnit compUnit = (ICompilationUnit) javaResource; > if (compUnit.getJavaProject().isOnClasspath(compUnit)) { > > // check if the Eclise AST has been cached (generated before) > Object o = astCache.get(compUnit); > CompilationUnit ast; > if (o != null) { > // Yes, was in the cache > ast = (CompilationUnit) o; > } else { > // No, generate the Eclise AST and add it to our cache > ast = AST.parseCompilationUnit(compUnit, true); > astCache.put(compUnit, ast); > } > analysisModule.analyzeCompilationUnit(compUnit, ast); > } > } > } > > /** > * Invokes {@link #analyzeEnd} on all analysis modules at the current level. > * > * @param project the Eclipse project referenced > */ > private void analyzeEndCurrentLevel(IProject project) throws CoreException { > for (Iterator i = currentLevel.iterator(); i.hasNext();) { > IAnalysis analysisModule = > Plugin.getDefault().getAnalysisModule((IExtension) i.next()); > analyzeEnd(project, analysisModule); > } > } > > /** > * Invokes {@link IAnalysis#analyzeEnd} on <code>analysisModule</code> > * and performs any reanalysis requested by the analysis module. If > * reanalysis is done then recursive calls are made to this method. > * > * @param project the Eclipse project referenced > * @param analysisModule the analysis module targeted > */ > private void analyzeEnd(IProject project, IAnalysis analysisModule) > throws CoreException { > IResource[] reanalyze = analysisModule.analyzeEnd(project); > if (reanalyze == null) { > if (LOG.isLoggable(Level.FINE)) { > LOG.fine("Re-analysis of " + project + " for " + analysisModule); > } > project.accept(new ReanalysisVisitor(analysisModule)); > analyzeEnd(project, analysisModule); // recursive call > } else if (reanalyze.length > 0) { > if (LOG.isLoggable(Level.FINE)) { > LOG.fine( > "Targeted re-analysis of " + project + " for " + analysisModule); > } > for (int j = 0; j < reanalyze.length; j++) { > analyzeResource(analysisModule, reanalyze[j], IResourceDelta.ADDED); > analyzeEnd(project, analysisModule); // recursive call > } > } > } > > /** > * Used by {@link #flushCache} to count the number of resources in the > * entire project. Haven't found a better way (i.e., more efficent) way > * to accomplish this. > */ > private class CounterVisitor implements IResourceVisitor { > > int resourceCount = 0; > > /** > * Provides the result of counting the resources within a project. > * > * @return the number of resources found in the visited project > */ > int getResourceCount() { > return resourceCount; > } > > /** > * @see org.eclipse.core.resources.IResourceVisitor#visit(org.eclipse.core.resources.IResource) > */ > public boolean visit(IResource resource) throws CoreException { > resourceCount++; > return true; > } > > } > > /** > * Used by {@link #analyzeEnd} to support reanalysis of an entire project. > * This class is needed because the main {@link IResourceVisitor} implemented > * by {@link Majordomo} targets <I>all</I> analysis modules rather than > * a specified single analysis module. > */ > private class ReanalysisVisitor implements IResourceVisitor { > > /** > * The analysis module to invoke method calls on. > */ > private IAnalysis analysisModule; > > ReanalysisVisitor(IAnalysis targetAnalysisModule) { > analysisModule = targetAnalysisModule; > } > > /** > * Invokes the {@link IAnalysis#analyzeResource} method on the > * analysis module stored in the field {@link #analysisModule} for > * <code>resource</code>. > * > * @see org.eclipse.core.resources.IResourceVisitor#visit(org.eclipse.core.resources.IResource) > */ > public boolean visit(IResource resource) throws CoreException { > analyzeResource(analysisModule, resource, IResourceDelta.ADDED); > return true; > } > } > > /** > * Creates and returns the set of prerequisite analysis modules for > * a specific analysis module. The set contains the identifiers > * as {@link String} values that have been intern'ed. > * > * @param analysisExtension the analysis module extension information > * @return a {@link Set} containing all prerequisite analysis module > * identifiers from the plugin manifest > */ > private Set getPrerequisiteAnalysisIdSet(IExtension analysisExtension) { > Set result = new HashSet(); // of String > IConfigurationElement[] analysisConfigElements = > analysisExtension.getConfigurationElements(); > for (int j = 0; j < analysisConfigElements.length; ++j) { > IConfigurationElement currentConfigElement = analysisConfigElements[j]; > if (currentConfigElement.getName().equalsIgnoreCase("prerequisite")) { > result.add(currentConfigElement.getAttribute("id").intern()); > } > } > return result; > } > > /** > * Sets the value of the {@link #buildMonitor} field to a progress monitor. > * > * @param monitor the {@link IProgressMonitor} reference > */ > private void setProgressMonitor(IProgressMonitor monitor) { > buildMonitor = monitor; > } > > /** > * Sets up the {@link #buildMonitor} for our portion of the build. > * > * @param totalWork number of <I>work units</I> (i.e., files) we are going to > * examine. > */ > private void showBuildIsStarting(int totalWork) { > if (buildMonitor != null) { > LOG.fine("Progress monitor work set to " + totalWork); > buildMonitor.beginTask("JavaAssure", totalWork); > } > } > > /** > * Informs {@link #buildMonitor} that one <I>work unit</I> (i.e., a file) > * has been completed. > */ > private void showProgress() { > if (buildMonitor != null) { > buildMonitor.worked(1); > } > } > > /** > * Sets the {@link #buildMonitor} sub task name (i.e., a file) > * in the progress monitor dialog. > */ > private void setProgressSubTaskName(String msg) { > if (buildMonitor != null) { > buildMonitor.subTask(msg); > } > } > > /** > * Checks of the {@link IProgressMonitor} referenced by the > * {@link #buildMonitor} field indicates that the user has cancelled the > * build. If so we forget our build state and throw a > * {@link OperationCanceledException}. > * > */ > private void checkForUserCancel() { > if (buildMonitor != null) { > if (buildMonitor.isCanceled()) { > forgetLastBuiltState(); > throw new OperationCanceledException(); > } > } > } > > /** > * Shows that a build is complete by updating our {@link #buildMonitor}. > */ > private void showBuildIsDone() { > buildMonitor.done(); > buildMonitor = null; > } > > /** > * Check if the compilation state of an {@link IJavaProject} has errors. > * > * @param javaProject the {@link IJavaProject} to check for errors > * @return <code>true</code> if the project has no compilation errors, > * <code>false</code> if errors exist or the project has never been built > * @throws CoreException if we have trouble getting the project's > * {@link IMarker} list > */ > private boolean noCompilationErrors(IJavaProject javaProject) > throws CoreException { > boolean result = false; // assume it has errors or has never been built > if (javaProject.hasBuildState()) { > result = true; // ok, we have a build state so assume no errors > IMarker[] problems = > javaProject.getProject().findMarkers( > IMarker.PROBLEM, > true, > IResource.DEPTH_INFINITE); > // check if any of these have a severity attribute that indicates an error > for (int problemsIndex = 0; > problemsIndex < problems.length; > problemsIndex++) { > if (IMarker.SEVERITY_ERROR > == problems[problemsIndex].getAttribute( > IMarker.SEVERITY, > IMarker.SEVERITY_INFO)) { > return false; // we found an error (bail out) > } > } > } > return result; > } > >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 45071
: 6460