diff options
author | nitind | 2005-06-03 20:10:06 +0000 |
---|---|---|
committer | nitind | 2005-06-03 20:10:06 +0000 |
commit | b2adeabdded1c81215c37e8bc6152d7f8dfec5c2 (patch) | |
tree | 399e0754d441da6074de24c7f430184520db9702 /bundles/org.eclipse.wst.sse.core/src-tasktags/org | |
parent | f74f77b039f2900392176d48632b4458dbdf5398 (diff) | |
download | webtools.sourceediting-b2adeabdded1c81215c37e8bc6152d7f8dfec5c2.tar.gz webtools.sourceediting-b2adeabdded1c81215c37e8bc6152d7f8dfec5c2.tar.xz webtools.sourceediting-b2adeabdded1c81215c37e8bc6152d7f8dfec5c2.zip |
update task tags for separate source folder, new preferences, naming
Diffstat (limited to 'bundles/org.eclipse.wst.sse.core/src-tasktags/org')
8 files changed, 1443 insertions, 0 deletions
diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/IFileTaskScanner.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/IFileTaskScanner.java new file mode 100644 index 0000000000..1b9d9f0a0f --- /dev/null +++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/IFileTaskScanner.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2001, 2004 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 + * Jens Lukowski/Innoopract - initial renaming/restructuring + * + *******************************************************************************/ +package org.eclipse.wst.sse.core.internal.provisional.tasks; + +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.wst.sse.core.internal.SSECorePlugin; + +/** + * Delegates for the main Task Scanner. Delegates may be contributed using the + * org.eclipse.wst.sse.core.taskscanner extension point. For resources and + * resource deltas with matching content types, the main scanner will first + * call the startup() method, scan(), and then shutdown() in sequence. Scanner + * instances will be reused across projects but are not shared per content + * type. Delegates should not hold on to references to models or resources + * after shutdown() and should take care not to leak memory or resources. + */ +public interface IFileTaskScanner { + String TASK_MARKER_ID = SSECorePlugin.ID + ".task"; //$NON-NLS-1$; + + /** + * Requests that the list of automatically discovered tasks for the given + * file be updated. Once completed, the list of tasks should correspond + * exactly to the file's contents. + * + * @param file - + * the file to be scanned + * @param taskTags - + * the list of task tags for which to scan + * @param monitor - + * a progress monitor + * @return an array of maps containing the attributes for task markers to + * be created + */ + Map[] scan(IFile file, TaskTag[] taskTags, IProgressMonitor monitor); + + /** + * Notifies the delegate that scanning is done for now. Resources held + * from startup should now be released. + * + * @param project - + * the project that was just scanned + */ + void shutdown(IProject project); + + /** + * Notifies the delegate that a sequence of scans is about to be + * requested. Ideally the time to load preferences and perform any + * expensive configuration for the given project. + * + * @param project - + * the project that is about to be scanned + * + */ + void startup(IProject project); +} diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/TaskTag.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/TaskTag.java new file mode 100644 index 0000000000..80353586fe --- /dev/null +++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/TaskTag.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2001, 2005 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 + * + *******************************************************************************/ +package org.eclipse.wst.sse.core.internal.provisional.tasks; + +import org.eclipse.core.resources.IMarker; + +public final class TaskTag { + + public static final int PRIORITY_HIGH = IMarker.PRIORITY_HIGH; + public static final int PRIORITY_LOW = IMarker.PRIORITY_LOW; + public static final int PRIORITY_NORMAL = IMarker.PRIORITY_NORMAL; + + private int fPriority = PRIORITY_NORMAL; + private String fTag = null; + + public TaskTag(String tag, int priority) { + super(); + fTag = tag; + fPriority = priority; + } + + public int getPriority() { + return fPriority; + } + + public String getTag() { + return fTag; + } + + public String toString() { + return getTag() + ":" + getPriority(); + } +} diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/FileTaskScannerRegistryReader.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/FileTaskScannerRegistryReader.java new file mode 100644 index 0000000000..d78354fd00 --- /dev/null +++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/FileTaskScannerRegistryReader.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright (c) 2001, 2004 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 + * Jens Lukowski/Innoopract - initial renaming/restructuring + * + *******************************************************************************/ +package org.eclipse.wst.sse.core.internal.tasks; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; +import org.eclipse.wst.sse.core.internal.Logger; +import org.eclipse.wst.sse.core.internal.SSECorePlugin; +import org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner; +import org.eclipse.wst.sse.core.internal.util.StringUtils; + +public class FileTaskScannerRegistryReader { + private class ScannerInfo { + String fId; + IFileTaskScanner fScanner; + + ScannerInfo(String id, IFileTaskScanner scanner) { + super(); + fId = id; + fScanner = scanner; + } + + public boolean equals(Object obj) { + return obj instanceof ScannerInfo && fId.equals(((ScannerInfo) obj).fId); + } + + public String getId() { + return fId; + } + + public IFileTaskScanner getScanner() { + return fScanner; + } + } + + private static final boolean _debugReader = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/registry")); //$NON-NLS-1$ //$NON-NLS-2$ + + private static FileTaskScannerRegistryReader _instance = null; + + public static FileTaskScannerRegistryReader getInstance() { + if (_instance == null) { + _instance = new FileTaskScannerRegistryReader(); + } + return _instance; + } + + private String ATT_CLASS = "class"; //$NON-NLS-1$ + + private String ATT_CONTENT_TYPES = "contentTypeIds"; //$NON-NLS-1$ + + private String ATT_ID = "id"; //$NON-NLS-1$ + + private IConfigurationElement[] fScannerElements; + + // a mapping from content types to ScannerInfo instances + private Map fScannerInfos = null; + + private String NAME_SCANNER = "scanner"; //$NON-NLS-1$ + + private String SCANNER_EXTENSION_POINT_ID = SSECorePlugin.ID + ".taskscanner"; //$NON-NLS-1$ + + private FileTaskScannerRegistryReader() { + super(); + } + + IFileTaskScanner[] getFileTaskScanners(IContentType[] contentTypes) { + if (fScannerElements == null) { + readRegistry(); + } + + List scannerInfos = new ArrayList(1); + + for (int i = 0; i < contentTypes.length; i++) { + ScannerInfo[] scannerInfosForContentType = (ScannerInfo[]) fScannerInfos.get(contentTypes[i].getId()); + if (scannerInfosForContentType == null) { + scannerInfosForContentType = loadScanners(contentTypes[i]); + } + // only add non-duplicate scanners + for (int j = 0; j < scannerInfosForContentType.length; j++) { + if (!scannerInfos.contains(scannerInfosForContentType[j])) { + scannerInfos.add(scannerInfosForContentType[j]); + } + } + } + IFileTaskScanner[] scanners = new IFileTaskScanner[scannerInfos.size()]; + for (int i = 0; i < scanners.length; i++) { + scanners[i] = ((ScannerInfo) scannerInfos.get(i)).getScanner(); + } + return scanners; + } + + public String[] getSupportedContentTypeIds() { + if (fScannerElements == null) { + readRegistry(); + } + + // find the relevant extensions + List types = new ArrayList(0); + IConfigurationElement[] scannerElements = fScannerElements; + for (int j = 0; j < scannerElements.length; j++) { + if (!scannerElements[j].getName().equals(NAME_SCANNER)) + continue; + String[] contentTypeIds = StringUtils.unpack(scannerElements[j].getAttribute(ATT_CONTENT_TYPES)); + for (int i = 0; i < contentTypeIds.length; i++) { + if (!types.contains(contentTypeIds[i])) { + types.add(contentTypeIds[i]); + } + } + } + + return (String[]) types.toArray(new String[types.size()]); + } + + private ScannerInfo[] loadScanners(IContentType contentType) { + List elements = new ArrayList(0); + ScannerInfo[] scannerInfos = null; + IConfigurationElement[] delegateElements = fScannerElements; + if (contentType != null) { + IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); + for (int j = 0; j < delegateElements.length; j++) { + if (!delegateElements[j].getName().equals(NAME_SCANNER)) + continue; + String[] supportedContentTypeIds = StringUtils.unpack(delegateElements[j].getAttribute(ATT_CONTENT_TYPES)); + IContentType[] supportedContentTypes = new IContentType[supportedContentTypeIds.length]; + for (int k = 0; k < supportedContentTypeIds.length; k++) { + supportedContentTypes[k] = contentTypeManager.getContentType(supportedContentTypeIds[k].trim()); + } + for (int k = 0; k < supportedContentTypeIds.length; k++) { + // allow subtypes to be returned as well + if (supportedContentTypes[k] != null && contentType.isKindOf(supportedContentTypes[k])) { + elements.add(delegateElements[j]); + } + } + } + // instantiate and save the scanners + List scannerInfoList = new ArrayList(elements.size()); + for (int i = 0; i < elements.size(); i++) { + try { + IFileTaskScanner scanner = (IFileTaskScanner) ((IConfigurationElement) elements.get(i)).createExecutableExtension(ATT_CLASS); + if (scanner != null) { + scannerInfoList.add(new ScannerInfo(((IConfigurationElement) elements.get(i)).getAttribute(ATT_ID), scanner)); + } + } + catch (CoreException e) { + Logger.logException("Non-fatal exception creating task scanner for " + contentType.getId(), e); //$NON-NLS-1$ + } + } + scannerInfos = (ScannerInfo[]) scannerInfoList.toArray(new ScannerInfo[scannerInfoList.size()]); + fScannerInfos.put(contentType.getId(), scannerInfos); + if (_debugReader) { + System.out.println("Created " + scannerInfos.length + " task scanner for " + contentType.getId()); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + return scannerInfos; + } + + private void readRegistry() { + fScannerInfos = new HashMap(); + // Just remember the elements, so plugins don't have to be activated, + // unless extension attributes match those of interest + IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(SCANNER_EXTENSION_POINT_ID); + if (point != null) { + fScannerElements = point.getConfigurationElements(); + } + } +} diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/StructuredFileTaskScanner.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/StructuredFileTaskScanner.java new file mode 100644 index 0000000000..c24ce9432f --- /dev/null +++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/StructuredFileTaskScanner.java @@ -0,0 +1,336 @@ +/******************************************************************************* + * Copyright (c) 2001, 2004 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 + * Jens Lukowski/Innoopract - initial renaming/restructuring + * + *******************************************************************************/ +package org.eclipse.wst.sse.core.internal.tasks; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.CharacterCodingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.content.IContentDescription; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.wst.sse.core.internal.Logger; +import org.eclipse.wst.sse.core.internal.document.DocumentReader; +import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler; +import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser; +import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionHandler; +import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionParser; +import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry; +import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument; +import org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner; +import org.eclipse.wst.sse.core.internal.provisional.tasks.TaskTag; +import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; +import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; +import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; +import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; + +/** + * A delegate to create IMarker.TASKs for "todos" and similiar comments. + */ +public abstract class StructuredFileTaskScanner implements IFileTaskScanner { + + private static final boolean _debug = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks")); //$NON-NLS-1$ //$NON-NLS-2$ + protected static final boolean _debugPerf = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/time")); //$NON-NLS-1$ //$NON-NLS-2$ + + // the list of attributes for the new tasks for the current file + protected List fNewMarkerAttributeMaps = null; + + List oldMarkers = null; + private long time0; + + public StructuredFileTaskScanner() { + super(); + fNewMarkerAttributeMaps = new ArrayList(); + if (_debug) { + System.out.println(getClass().getName() + " instance created"); //$NON-NLS-1$ + } + } + + /** + * Returns the attributes with which a newly created marker will be + * initialized. Modified from the method in MarkerRulerAction + * + * @return the initial marker attributes + */ + protected Map createInitialMarkerAttributes(String text, int documentLine, int startOffset, int length, int priority) { + Map attributes = new HashMap(6); + // marker line numbers are 1-based + attributes.put(IMarker.LINE_NUMBER, new Integer(documentLine + 1)); + attributes.put(IMarker.CHAR_START, new Integer(startOffset)); + attributes.put(IMarker.CHAR_END, new Integer(startOffset + length)); + attributes.put(IMarker.MESSAGE, text); + attributes.put(IMarker.USER_EDITABLE, Boolean.TRUE); + attributes.put("org.eclipse.ui.part.IShowInTarget", new String[]{""}); + + switch (priority) { + case IMarker.PRIORITY_HIGH : { + attributes.put(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_HIGH)); + } + break; + case IMarker.PRIORITY_LOW : { + attributes.put(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_LOW)); + } + break; + default : { + attributes.put(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_NORMAL)); + } + } + + return attributes; + } + + private String detectCharset(IFile file) { + if (file.getType() == IResource.FILE && file.isAccessible()) { + IContentDescription d = null; + try { + // optimized description lookup, might not succeed + d = file.getContentDescription(); + if (d != null) + return d.getCharset(); + } + catch (CoreException e) { + /* + * should not be possible given the accessible and file type + * check above + */ + } + InputStream contents = null; + try { + contents = file.getContents(); + IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(contents, file.getName(), new QualifiedName[]{IContentDescription.CHARSET}); + if (description != null) { + return description.getCharset(); + } + } + catch (IOException e) { + // will try to cleanup in finally + } + catch (CoreException e) { + Logger.logException(e); + } + finally { + if (contents != null) { + try { + contents.close(); + } + catch (Exception e) { + // not sure how to recover at this point + } + } + } + } + return ResourcesPlugin.getEncoding(); + } + + /** + * @param document + * @param documentRegion + * @param comment + */ + protected void findTasks(IDocument document, TaskTag[] taskTags, IStructuredDocumentRegion documentRegion, ITextRegion comment) { + if (isCommentRegion(documentRegion, comment)) { + int startOffset = documentRegion.getStartOffset(comment); + int endOffset = documentRegion.getTextEndOffset(comment); + try { + int startLine = document.getLineOfOffset(startOffset); + int endLine = document.getLineOfOffset(endOffset); + for (int lineNumber = startLine; lineNumber <= endLine; lineNumber++) { + IRegion line = document.getLineInformation(lineNumber); + int begin = Math.max(startOffset, line.getOffset()); + int end = Math.min(endOffset, line.getOffset() + line.getLength()); + int length = end - begin; + + /* XXX: This generates a lot of garbage objects */ + + String commentedText = getCommentedText(document, begin, length); + String comparisonText = commentedText.toLowerCase(Locale.ENGLISH); + + for (int i = 0; i < taskTags.length; i++) { + int tagIndex = comparisonText.indexOf(taskTags[i].getTag().toLowerCase(Locale.ENGLISH)); + if (tagIndex >= 0) { + String markerDescription = commentedText.substring(tagIndex); + int markerOffset = begin + tagIndex; + int markerLength = end - markerOffset; + fNewMarkerAttributeMaps.add(createInitialMarkerAttributes(markerDescription, lineNumber, markerOffset, markerLength, taskTags[i].getPriority())); + } + } + } + } + catch (BadLocationException e) { + Logger.logException(e); + } + } + } + + private void findTasks(IFile file, final TaskTag[] taskTags, IProgressMonitor monitor) { + try { + IModelHandler handler = ModelHandlerRegistry.getInstance().getHandlerFor(file); + + // records if the optimized streamish parse was possible + boolean didStreamParse = false; + final IProgressMonitor progressMonitor = monitor; + final IEncodedDocument defaultDocument = handler.getDocumentLoader().createNewStructuredDocument(); + if (defaultDocument instanceof IStructuredDocument) { + RegionParser parser = ((IStructuredDocument) defaultDocument).getParser(); + if (parser instanceof StructuredDocumentRegionParser) { + didStreamParse = true; + String charset = detectCharset(file); + StructuredDocumentRegionParser documentParser = (StructuredDocumentRegionParser) parser; + final IDocument textDocument = new Document(); + setDocumentContent(textDocument, file.getContents(true), charset); + documentParser.reset(new DocumentReader(textDocument)); + documentParser.addStructuredDocumentRegionHandler(new StructuredDocumentRegionHandler() { + public void nodeParsed(IStructuredDocumentRegion documentRegion) { + ITextRegionList regions = documentRegion.getRegions(); + for (int j = 0; j < regions.size(); j++) { + ITextRegion comment = regions.get(j); + findTasks(textDocument, taskTags, documentRegion, comment); + } + // disconnect the document regions + if (documentRegion.getPrevious() != null) { + documentRegion.getPrevious().setPrevious(null); + documentRegion.getPrevious().setNext(null); + } + if (progressMonitor.isCanceled()) { + textDocument.set(""); //$NON-NLS-1$ + } + } + + public void resetNodes() { + } + }); + documentParser.getDocumentRegions(); + } + } + if (!didStreamParse) { + // Use a StructuredDocument + IEncodedDocument document = handler.getDocumentLoader().createNewStructuredDocument(file); + if (document instanceof IStructuredDocument) { + IStructuredDocumentRegion documentRegion = ((IStructuredDocument) document).getFirstStructuredDocumentRegion(); + while (documentRegion != null) { + ITextRegionList regions = documentRegion.getRegions(); + for (int j = 0; j < regions.size(); j++) { + ITextRegion comment = regions.get(j); + findTasks(document, taskTags, documentRegion, comment); + } + documentRegion = documentRegion.getNext(); + } + } + } + } + catch (CoreException e) { + Logger.logException("Exception with " + file.getFullPath().toString(), e); //$NON-NLS-1$ + } + catch (CharacterCodingException e) { + Logger.log(Logger.INFO, "StructuredFileTaskScanner encountered CharacterCodingException reading " + file.getLocation()); //$NON-NLS-1$ + } + catch (IOException e) { + Logger.logException(e); + } + } + + protected String getCommentedText(IDocument document, int begin, int length) throws BadLocationException { + return document.get(begin, length); + } + + protected abstract boolean isCommentRegion(IStructuredDocumentRegion region, ITextRegion textRegion); + + public synchronized Map[] scan(IFile file, TaskTag[] taskTags, IProgressMonitor monitor) { + fNewMarkerAttributeMaps.clear(); + if (monitor.isCanceled() || !shouldScan(file)) { + return new Map[0]; + } + if (_debugPerf) { + time0 = System.currentTimeMillis(); + } + if (taskTags.length > 0) { + findTasks(file, taskTags, monitor); + } + if (_debugPerf) { + System.out.println("" + (System.currentTimeMillis() - time0) + "ms for " + file.getLocation()); //$NON-NLS-1$ //$NON-NLS-2$ + } + return (Map[]) fNewMarkerAttributeMaps.toArray(new Map[fNewMarkerAttributeMaps.size()]); + } + + /** + * Sets the document content from this stream and closes the stream + */ + protected void setDocumentContent(IDocument document, InputStream contentStream, String charset) { + Reader in = null; + try { + in = new BufferedReader(new InputStreamReader(contentStream, charset), 2048); + StringBuffer buffer = new StringBuffer(2048); + char[] readBuffer = new char[2048]; + int n = in.read(readBuffer); + while (n > 0) { + buffer.append(readBuffer, 0, n); + n = in.read(readBuffer); + } + document.set(buffer.toString()); + } + catch (IOException x) { + } + finally { + if (in != null) { + try { + in.close(); + } + catch (IOException x) { + } + } + } + } + + boolean shouldScan(IResource r) { + // skip "dot" files + String s = r.getName(); + return s.length() == 0 || s.charAt(0) != '.'; + } + + public void shutdown(IProject project) { + if (_debug) { + System.out.println(this + " shutdown for " + project.getName()); //$NON-NLS-1$ + } + } + + public void startup(IProject project) { + if (_debug) { + System.out.println(this + " startup for " + project.getName()); //$NON-NLS-1$ + } + if (_debugPerf) { + time0 = System.currentTimeMillis(); + } + if (_debugPerf) { + System.out.println("" + (System.currentTimeMillis() - time0) + "ms loading prefs for " + project.getName()); //$NON-NLS-1$ //$NON-NLS-2$ + } + } +} diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningJob.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningJob.java new file mode 100644 index 0000000000..a46b5cbdfd --- /dev/null +++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningJob.java @@ -0,0 +1,217 @@ +/******************************************************************************* + * Copyright (c) 2001, 2005 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 + * + *******************************************************************************/ +package org.eclipse.wst.sse.core.internal.tasks; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.wst.sse.core.internal.SSECoreMessages; +import org.eclipse.wst.sse.core.internal.SSECorePlugin; +import org.eclipse.wst.sse.core.internal.util.StringUtils; +import org.osgi.framework.Bundle; + +/** + * Queueing Job for processing deltas and projects. + */ +class TaskScanningJob extends Job { + public static final boolean _debugJob = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/job")); + static final String TASK_TAG_PROJECTS_ALREADY_SCANNED = "task-tag-projects-already-scanned"; //$NON-NLS-1$ + private List fQueue = null; + + /** symbolic name for OSGI framework */ + private final String OSGI_FRAMEWORK_ID = "org.eclipse.osgi"; //$NON-NLS-1$ + + TaskScanningJob() { + super(SSECoreMessages.TaskScanner_0); + fQueue = new ArrayList(); + setPriority(Job.DECORATE); + setSystem(false); + + SSECorePlugin.getDefault().getPluginPreferences().setDefault(TASK_TAG_PROJECTS_ALREADY_SCANNED, ""); + } + + synchronized void addDelta(IResourceDelta delta) { + fQueue.add(delta); + if (_debugJob) { + String kind = null; + switch (delta.getKind()) { + case IResourceDelta.ADDED : + kind = " [IResourceDelta.ADDED]"; //$NON-NLS-1$ + break; + case IResourceDelta.CHANGED : + kind = " [IResourceDelta.CHANGED]"; //$NON-NLS-1$ + break; + case IResourceDelta.REMOVED : + kind = " [IResourceDelta.REMOVED]"; //$NON-NLS-1$ + break; + case IResourceDelta.ADDED_PHANTOM : + kind = " [IResourceDelta.ADDED_PHANTOM]"; //$NON-NLS-1$ + break; + case IResourceDelta.REMOVED_PHANTOM : + kind = " [IResourceDelta.REMOVED_PHANTOM]"; //$NON-NLS-1$ + break; + } + System.out.println("Adding delta " + delta.getFullPath() + kind); + } + schedule(100); + } + + synchronized void addProject(IProject project) { + if (isEnabledProject(project)) { + fQueue.add(project); + if (_debugJob) { + System.out.println("Adding project " + project.getName()); + } + schedule(600); + } + } + + /** + * A check to see if the OSGI framework is shutting down. + * + * @return true if the System Bundle is stopped (ie. the framework is + * shutting down) + */ + boolean frameworkIsShuttingDown() { + // in the Framework class there's a note: + // set the state of the System Bundle to STOPPING. + // this must be done first according to section 4.19.2 from the OSGi + // R3 spec. + boolean shuttingDown = Platform.getBundle(OSGI_FRAMEWORK_ID).getState() == Bundle.STOPPING; + if (_debugJob && shuttingDown) { + System.out.println("TaskScanningJob: system is shutting down!"); //$NON-NLS-1$ + } + return shuttingDown; + } + + private boolean isEnabledProject(IResource project) { + String[] projectsScanned = StringUtils.unpack(SSECorePlugin.getDefault().getPluginPreferences().getString(TASK_TAG_PROJECTS_ALREADY_SCANNED)); + + boolean shouldScan = true; + String name = project.getName(); + for (int j = 0; shouldScan && j < projectsScanned.length; j++) { + if (projectsScanned[j].equals(name)) { + if (_debugJob) + System.out.println("Scanning Job skipping " + project.getName()); + shouldScan = false; + } + } + return shouldScan; + } + + synchronized List retrieveQueue() { + List queue = fQueue; + fQueue = new ArrayList(); + return queue; + } + + protected IStatus run(IProgressMonitor monitor) { + validateRememberedProjectList(TASK_TAG_PROJECTS_ALREADY_SCANNED); + + IStatus status = null; + List currentQueue = retrieveQueue(); + List errors = null; + int ticks = currentQueue.size(); + String taskName = null; + if (_debugJob) { + taskName = "Scanning (" + ticks + " work items)"; + } + else { + taskName = "Scanning"; + } + monitor.beginTask(taskName, ticks); + + IProgressMonitor scanMonitor = null; + while (!currentQueue.isEmpty()) { + Object o = currentQueue.remove(0); + if (frameworkIsShuttingDown()) + return Status.OK_STATUS; + try { + scanMonitor = new SubProgressMonitor(monitor, 1); + if (o instanceof IResourceDelta) { + WorkspaceTaskScanner.getInstance().scan((IResourceDelta) o, scanMonitor); + } + else if (o instanceof IProject) { + WorkspaceTaskScanner.getInstance().scan((IProject) o, scanMonitor); + String[] projectsPreviouslyScanned = StringUtils.unpack(SSECorePlugin.getDefault().getPluginPreferences().getString(TASK_TAG_PROJECTS_ALREADY_SCANNED)); + String[] updatedProjects = new String[projectsPreviouslyScanned.length + 1]; + updatedProjects[projectsPreviouslyScanned.length] = ((IResource) o).getName(); + System.arraycopy(projectsPreviouslyScanned, 0, updatedProjects, 0, projectsPreviouslyScanned.length); + SSECorePlugin.getDefault().getPluginPreferences().setValue(TASK_TAG_PROJECTS_ALREADY_SCANNED, StringUtils.pack(updatedProjects)); + } + } + catch (Exception e) { + if (errors == null) { + errors = new ArrayList(); + } + errors.add(new Status(IStatus.ERROR, SSECorePlugin.ID, IStatus.ERROR, "", e)); + } + } + monitor.done(); + + if (errors == null || errors.isEmpty()) { + status = Status.OK_STATUS; + } + else { + if (errors.size() == 1) { + status = (IStatus) errors.get(0); + } + else { + IStatus[] statii = (IStatus[]) errors.toArray(new IStatus[errors.size()]); + status = new MultiStatus(SSECorePlugin.ID, IStatus.ERROR, statii, "Errors while detecting Tasks", null); + } + } + + SSECorePlugin.getDefault().savePluginPreferences(); + return status; + } + + private void validateRememberedProjectList(String preferenceName) { + String[] rememberedProjectNames = StringUtils.unpack(SSECorePlugin.getDefault().getPluginPreferences().getString(preferenceName)); + IResource[] workspaceProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); + String[] projectNames = new String[workspaceProjects.length]; + for (int i = 0; i < projectNames.length; i++) { + projectNames[i] = workspaceProjects[i].getName(); + } + + List projectNamesToRemember = new ArrayList(rememberedProjectNames.length); + for (int i = 0; i < rememberedProjectNames.length; i++) { + boolean rememberedProjectExists = false; + for (int j = 0; !rememberedProjectExists && j < projectNames.length; j++) { + if (rememberedProjectNames[i].equals(projectNames[j])) { + rememberedProjectExists = true; + } + } + if (rememberedProjectExists) { + projectNamesToRemember.add(rememberedProjectNames[i]); + } + else if (_debugJob) { + System.out.println("Removing " + rememberedProjectNames[i] + " removed from " + preferenceName); + } + } + + if (projectNamesToRemember.size() != rememberedProjectNames.length) { + SSECorePlugin.getDefault().getPluginPreferences().setValue(preferenceName, StringUtils.pack((String[]) projectNamesToRemember.toArray(new String[projectNamesToRemember.size()]))); + } + } +}
\ No newline at end of file diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningScheduler.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningScheduler.java new file mode 100644 index 0000000000..ce8156f794 --- /dev/null +++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningScheduler.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2001, 2005 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 + * + *******************************************************************************/ +package org.eclipse.wst.sse.core.internal.tasks; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.wst.sse.core.internal.Logger; +import org.eclipse.wst.sse.core.internal.SSECorePlugin; +import org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner; +import org.eclipse.wst.sse.core.internal.util.StringUtils; + +public class TaskScanningScheduler { + private class ListenerVisitor implements IResourceChangeListener, IResourceDeltaVisitor { + public void resourceChanged(IResourceChangeEvent event) { + IResourceDelta delta = event.getDelta(); + if (delta.getResource() != null) { + int resourceType = delta.getResource().getType(); + if (resourceType == IResource.PROJECT || resourceType == IResource.ROOT) { + try { + delta.accept(this); + } + catch (CoreException e) { + Logger.logException("Exception handling resource change", e); //$NON-NLS-1$ + } + } + } + } + + public boolean visit(IResourceDelta delta) throws CoreException { + if ((delta.getKind() & IResourceDelta.MARKERS) > 0 || (delta.getKind() & IResourceDelta.ENCODING) > 0 || (delta.getKind() & IResourceDelta.NO_CHANGE) > 0) + return false; + + IResource resource = delta.getResource(); + if (resource != null) { + if (resource.getType() == IResource.ROOT) + return true; + else if (resource.getType() == IResource.PROJECT) { + fJob.addDelta(delta); + return false; + } + } + return false; + } + + } + + private static TaskScanningScheduler scheduler; + + public static void refresh() { + SSECorePlugin.getDefault().getPluginPreferences().setValue(TaskScanningJob.TASK_TAG_PROJECTS_ALREADY_SCANNED, ""); //$NON-NLS-1$ + scheduler.enqueue(ResourcesPlugin.getWorkspace().getRoot()); + } + + public static void refresh(IProject project) { + String[] projectNames = StringUtils.unpack(SSECorePlugin.getDefault().getPluginPreferences().getString(TaskScanningJob.TASK_TAG_PROJECTS_ALREADY_SCANNED)); //$NON-NLS-1$ + List freshProjectList = new ArrayList(); + for (int i = 0; i < projectNames.length; i++) { + if (!projectNames[i].equals(project.getName())) { + freshProjectList.add(projectNames[i]); + } + } + String freshProjects = StringUtils.pack((String[]) freshProjectList.toArray(new String[freshProjectList.size()])); + SSECorePlugin.getDefault().getPluginPreferences().setValue(TaskScanningJob.TASK_TAG_PROJECTS_ALREADY_SCANNED, freshProjects); //$NON-NLS-1$ + + scheduler.enqueue(project); + } + + + /** + * Only for use by SSECorePlugin class + */ + public static void shutdown() { + if (scheduler != null) { + ResourcesPlugin.getWorkspace().removeResourceChangeListener(scheduler.visitor); + } + } + + /** + * Only for use by SSECorePlugin class + */ + public static void startup() { + scheduler = new TaskScanningScheduler(); + + /* + * According to + * http://www.eclipse.org/eclipse/development/performance/bloopers.html, + * POST_CHANGE listeners add a trivial performance cost + */ + ResourcesPlugin.getWorkspace().addResourceChangeListener(scheduler.visitor, IResourceChangeEvent.POST_CHANGE); + + scheduler.enqueue(ResourcesPlugin.getWorkspace().getRoot()); + } + + TaskScanningJob fJob = null; + + ListenerVisitor visitor = null; + + private TaskScanningScheduler() { + super(); + fJob = new TaskScanningJob(); + visitor = new ListenerVisitor(); + } + + void enqueue(IProject project) { + try { + project.deleteMarkers(IFileTaskScanner.TASK_MARKER_ID, true, IResource.DEPTH_INFINITE); + } + catch (CoreException e) { + } + fJob.addProject(project); + } + + void enqueue(IWorkspaceRoot root) { + try { + root.deleteMarkers(IFileTaskScanner.TASK_MARKER_ID, true, IResource.DEPTH_INFINITE); + } + catch (CoreException e) { + } + IProject[] allProjects = root.getProjects(); + for (int i = 0; i < allProjects.length; i++) { + fJob.addProject(allProjects[i]); + } + } +} diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskTagPreferenceKeys.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskTagPreferenceKeys.java new file mode 100644 index 0000000000..bb3e305a84 --- /dev/null +++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskTagPreferenceKeys.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2001, 2005 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 + * + *******************************************************************************/ +package org.eclipse.wst.sse.core.internal.tasks; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.wst.sse.core.internal.SSECorePlugin; + +public final class TaskTagPreferenceKeys { + public static final String TASK_TAG_CONTENTTYPES_IGNORED = "ignored-contentTypes"; //$NON-NLS-1$ + public static final String TASK_TAG_ENABLE = "enabled"; //$NON-NLS-1$ + public static final String TASK_TAG_NODE = SSECorePlugin.ID + IPath.SEPARATOR + "task-tags"; //$NON-NLS-1$ + public static final String TASK_TAG_PER_PROJECT = "use-project-settings"; //$NON-NLS-1$ + public static final String TASK_TAG_PRIORITIES = "taskPriorities"; //$NON-NLS-1$ + public static final String TASK_TAG_TAGS = "taskTags"; //$NON-NLS-1$ +} diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/WorkspaceTaskScanner.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/WorkspaceTaskScanner.java new file mode 100644 index 0000000000..8d31ff647d --- /dev/null +++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/WorkspaceTaskScanner.java @@ -0,0 +1,427 @@ +/******************************************************************************* + * Copyright (c) 2001, 2004 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 + * Jens Lukowski/Innoopract - initial renaming/restructuring + * + *******************************************************************************/ +package org.eclipse.wst.sse.core.internal.tasks; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.content.IContentDescription; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.IPreferencesService; +import org.eclipse.core.runtime.preferences.IScopeContext; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.wst.sse.core.internal.Logger; +import org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner; +import org.eclipse.wst.sse.core.internal.provisional.tasks.TaskTag; +import org.eclipse.wst.sse.core.internal.util.StringUtils; + +/** + * Dispatcher for scanning based on deltas and requested projects + */ +class WorkspaceTaskScanner { + private static final boolean _debug = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks")); //$NON-NLS-1$ //$NON-NLS-2$ + private static final boolean _debugContentTypeDetection = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/detection")); //$NON-NLS-1$ //$NON-NLS-2$ + private static final boolean _debugOverallPerf = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/overalltime")); //$NON-NLS-1$ //$NON-NLS-2$ + private static final boolean _debugPreferences = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/preferences")); //$NON-NLS-1$ //$NON-NLS-2$ + + private static WorkspaceTaskScanner _instance = null; + + static synchronized WorkspaceTaskScanner getInstance() { + if (_instance == null) { + _instance = new WorkspaceTaskScanner(); + } + return _instance; + } + + static String getTaskMarkerType() { + return IFileTaskScanner.TASK_MARKER_ID; + } + + private List fActiveScanners = null; + private IContentType[] fCurrentIgnoreContentTypes = null; + private TaskTag[] fCurrentTaskTags = null; + private FileTaskScannerRegistryReader registry = null; + + private long time0; + + + /** + * + */ + private WorkspaceTaskScanner() { + super(); + registry = FileTaskScannerRegistryReader.getInstance(); + fActiveScanners = new ArrayList(); + fCurrentTaskTags = new TaskTag[0]; + fCurrentIgnoreContentTypes = new IContentType[0]; + } + + private IContentType[] detectContentTypes(IResource resource) { + IContentType[] types = null; + if (resource.getType() == IResource.FILE && resource.isAccessible()) { + types = Platform.getContentTypeManager().findContentTypesFor(resource.getName()); + if (types.length == 0) { + IContentDescription d = null; + try { + // optimized description lookup, might not succeed + d = ((IFile) resource).getContentDescription(); + if (d != null) { + types = new IContentType[]{d.getContentType()}; + } + } + catch (CoreException e) { + /* + * should not be possible given the accessible and file + * type check above + */ + } + } + if (types == null) { + types = Platform.getContentTypeManager().findContentTypesFor(resource.getName()); + } + if (_debugContentTypeDetection) { + if (types.length > 0) { + if (types.length > 1) { + System.out.println(resource.getFullPath() + ": " + "multiple based on name (probably hierarchical)"); //$NON-NLS-1$ //$NON-NLS-2$ + } + for (int i = 0; i < types.length; i++) { + System.out.println(resource.getFullPath() + " matched: " + types[i].getId()); //$NON-NLS-1$ + } + } + } + } + return types; + } + + /** + * @param resource + * @return + */ + private IProject getProject(IResource resource) { + IProject project = null; + if (resource.getType() == IResource.PROJECT) { + project = (IProject) resource; + } + else { + project = resource.getProject(); + } + return project; + } + + private boolean init(IResource resource) { + IProject project = getProject(resource); + + IPreferencesService preferencesService = Platform.getPreferencesService(); + IScopeContext[] lookupOrder = new IScopeContext[]{new ProjectScope(project), new InstanceScope(), new DefaultScope()}; + + boolean proceed = preferencesService.getBoolean(TaskTagPreferenceKeys.TASK_TAG_NODE, TaskTagPreferenceKeys.TASK_TAG_ENABLE, false, lookupOrder); + + if (_debugPreferences) { + System.out.println(getClass().getName() + " scan of " + resource.getFullPath() + ":" + proceed); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (proceed) { + String[] tags = StringUtils.unpack(preferencesService.getString(TaskTagPreferenceKeys.TASK_TAG_NODE, TaskTagPreferenceKeys.TASK_TAG_TAGS, null, lookupOrder)); + String[] priorities = StringUtils.unpack(preferencesService.getString(TaskTagPreferenceKeys.TASK_TAG_NODE, TaskTagPreferenceKeys.TASK_TAG_PRIORITIES, null, lookupOrder)); + String[] currentIgnoreContentTypeIDs = StringUtils.unpack(preferencesService.getString(TaskTagPreferenceKeys.TASK_TAG_NODE, TaskTagPreferenceKeys.TASK_TAG_CONTENTTYPES_IGNORED, null, lookupOrder)); + if (_debugPreferences) { + System.out.print(getClass().getName() + " tags: "); //$NON-NLS-1$ + for (int i = 0; i < tags.length; i++) { + if (i > 0) { + System.out.print(","); //$NON-NLS-1$ + } + System.out.print(tags[i]); + } + System.out.println(); + System.out.print(getClass().getName() + " priorities: "); //$NON-NLS-1$ + for (int i = 0; i < priorities.length; i++) { + if (i > 0) { + System.out.print(","); //$NON-NLS-1$ + } + System.out.print(priorities[i]); + } + System.out.println(); + System.out.print(getClass().getName() + " ignored content types: "); //$NON-NLS-1$ + for (int i = 0; i < currentIgnoreContentTypeIDs.length; i++) { + if (i > 0) { + System.out.print(","); //$NON-NLS-1$ + } + System.out.print(currentIgnoreContentTypeIDs[i]); + } + System.out.println(); + } + fCurrentIgnoreContentTypes = new IContentType[currentIgnoreContentTypeIDs.length]; + IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); + for (int i = 0; i < currentIgnoreContentTypeIDs.length; i++) { + fCurrentIgnoreContentTypes[i] = contentTypeManager.getContentType(currentIgnoreContentTypeIDs[i]); + } + int max = Math.min(tags.length, priorities.length); + fCurrentTaskTags = new TaskTag[max]; + for (int i = 0; i < max; i++) { + int priority = TaskTag.PRIORITY_NORMAL; + try { + priority = Integer.parseInt(priorities[i]); + } + catch (NumberFormatException e) { + // default to normal priority + } + fCurrentTaskTags[i] = new TaskTag(tags[i], priority); + } + } + return proceed; + } + + void internalScan(final IProject project, final IResource resource, final IProgressMonitor scanMonitor) { + if (scanMonitor.isCanceled()) + return; + try { + String name = resource.getName(); + if (!resource.isDerived() && !resource.isPhantom() && !resource.isTeamPrivateMember() && name.length() != 0 && name.charAt(0) != '.') { + if ((resource.getType() & IResource.FOLDER) > 0 || (resource.getType() & IResource.PROJECT) > 0) { + SubProgressMonitor childMonitor = new SubProgressMonitor(scanMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); + IResource[] children = ((IContainer) resource).members(); + childMonitor.beginTask("", children.length); //$NON-NLS-1$ + for (int i = 0; i < children.length; i++) { + internalScan(project, children[i], childMonitor); + } + childMonitor.done(); + } + else if ((resource.getType() & IResource.FILE) > 0) { + scanFile(project, fCurrentTaskTags, (IFile) resource, scanMonitor); + scanMonitor.worked(1); + } + } + else { + scanMonitor.worked(1); + + } + scanMonitor.done(); + } + catch (CoreException e) { + Logger.logException(e); + } + } + + void internalScan(IResourceDelta delta, final IProgressMonitor monitor) { + if (monitor.isCanceled()) + return; + try { + String name = delta.getFullPath().lastSegment(); + IResource resource = delta.getResource(); + if (!resource.isDerived() && !resource.isPhantom() && !resource.isTeamPrivateMember() && name.length() != 0 && name.charAt(0) != '.') { + if ((resource.getType() & IResource.FOLDER) > 0 || (resource.getType() & IResource.PROJECT) > 0) { + IResourceDelta[] children = delta.getAffectedChildren(); + if (name.length() != 0 && name.charAt(0) != '.' && children.length > 0) { + SubProgressMonitor childMonitor = new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); + childMonitor.beginTask("", children.length); //$NON-NLS-1$ + for (int i = children.length - 1; i >= 0; i--) { + internalScan(children[i], new SubProgressMonitor(childMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK)); + } + childMonitor.done(); + } + else { + monitor.worked(1); + } + } + else if ((resource.getType() & IResource.FILE) > 0) { + if ((delta.getKind() & IResourceDelta.ADDED) > 0 || ((delta.getKind() & IResourceDelta.CHANGED) > 0 && (delta.getFlags() & IResourceDelta.CONTENT) > 0)) { + IFile file = (IFile) resource; + scanFile(file.getProject(), fCurrentTaskTags, file, monitor); + } + monitor.worked(1); + } + } + else { + monitor.worked(1); + } + } + catch (Exception e) { + monitor.done(); + Logger.logException(e); + } + } + + private void replaceMarkers(final IFile file, final Map markerAttributes[], IProgressMonitor monitor) { + final IFile finalFile = file; + if (file.isAccessible()) { + try { + IWorkspaceRunnable r = new IWorkspaceRunnable() { + public void run(IProgressMonitor progressMonitor) throws CoreException { + try { + // Delete old Task markers + file.deleteMarkers(getTaskMarkerType(), true, IResource.DEPTH_ZERO); + } + catch (CoreException e) { + Logger.logException("exception deleting old tasks", e); //$NON-NLS-1$ + } + if (markerAttributes != null && markerAttributes.length > 0) { + if (_debug) { + System.out.println("" + markerAttributes.length + " tasks for " + file.getFullPath()); //$NON-NLS-1$ //$NON-NLS-2$ + } + for (int i = 0; i < markerAttributes.length; i++) { + IMarker marker = finalFile.createMarker(getTaskMarkerType()); + marker.setAttributes(markerAttributes[i]); + } + } + } + }; + finalFile.getWorkspace().run(r, file, IWorkspace.AVOID_UPDATE, monitor); + } + catch (CoreException e1) { + Logger.logException(e1); + } + } + } + + void scan(final IProject project, final IProgressMonitor scanMonitor) { + if (scanMonitor.isCanceled()) + return; + if (_debug) { + System.out.println(getClass().getName() + " scanning project " + project.getName()); //$NON-NLS-1$ + } + if (_debugOverallPerf) { + time0 = System.currentTimeMillis(); + } + try { + scanMonitor.beginTask("", project.members().length); //$NON-NLS-1$ + if (init(project)) { + internalScan(project, project, scanMonitor); + shutdownDelegates(project); + } + scanMonitor.done(); + } + catch (CoreException e) { + Logger.logException(e); + } + if (_debugOverallPerf) { + System.out.println("" + (System.currentTimeMillis() - time0) + "ms for " + project.getFullPath()); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + + void scan(IResourceDelta delta, final IProgressMonitor monitor) { + if (monitor.isCanceled()) + return; + if (_debugOverallPerf) { + time0 = System.currentTimeMillis(); + } + monitor.beginTask("", 1); //$NON-NLS-1$ + if (init(delta.getResource())) { + internalScan(delta, monitor); + shutdownDelegates(delta.getResource().getProject()); + } + monitor.done(); + if (_debugOverallPerf) { + System.out.println("" + (System.currentTimeMillis() - time0) + "ms for " + delta.getFullPath()); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + void scanFile(IProject project, TaskTag[] taskTags, IFile file, IProgressMonitor monitor) { + if (monitor.isCanceled()) + return; + + SubProgressMonitor scannerMonitor = new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); + scannerMonitor.setTaskName(file.getFullPath().toString()); + List markerAttributes = null; + IContentType[] types = detectContentTypes(file); + if (types != null) { + IFileTaskScanner[] fileScanners = null; + if (fCurrentIgnoreContentTypes.length == 0) { + fileScanners = registry.getFileTaskScanners(types); + } + else { + List validTypes = new ArrayList(); + // obtain a filtered list of delegates + for (int i = 0; i < types.length; i++) { + boolean ignoreContentType = false; + for (int j = 0; j < fCurrentIgnoreContentTypes.length; j++) { + ignoreContentType = ignoreContentType || types[i].isKindOf(fCurrentIgnoreContentTypes[j]); + } + if (!ignoreContentType) { + validTypes.add(types[i]); + } + } + fileScanners = registry.getFileTaskScanners((IContentType[]) validTypes.toArray(new IContentType[validTypes.size()])); + } + if (fileScanners.length > 0) { + for (int j = 0; fileScanners != null && j < fileScanners.length; j++) { + if (scannerMonitor.isCanceled()) + continue; + scannerMonitor.beginTask("", fileScanners.length); + try { + if (!fActiveScanners.contains(fileScanners[j]) && !monitor.isCanceled()) { + fileScanners[j].startup(file.getProject()); + fActiveScanners.add(fileScanners[j]); + } + Map[] taskMarkerAttributes = fileScanners[j].scan(file, taskTags, scannerMonitor); + /* + * TODO: pool the marker results so there's only one + * operation creating them + */ + for (int i = 0; i < taskMarkerAttributes.length; i++) { + if (markerAttributes == null) { + markerAttributes = new ArrayList(); + } + markerAttributes.add(taskMarkerAttributes[i]); + } + scannerMonitor.worked(1); + } + catch (Exception e) { + Logger.logException(file.getFullPath().toString(), e); + } + } + scannerMonitor.done(); + } + else { + monitor.worked(1); + } + } + if (markerAttributes != null) { + replaceMarkers(file, (Map[]) markerAttributes.toArray(new Map[markerAttributes.size()]), monitor); + } + else { + replaceMarkers(file, null, monitor); + } + } + + /** + * + */ + private void shutdownDelegates(IProject project) { + for (int j = 0; j < fActiveScanners.size(); j++) { + try { + ((IFileTaskScanner) fActiveScanners.get(j)).shutdown(project); + } + catch (Exception e) { + Logger.logException(project.getFullPath().toString(), e); + } + } + fActiveScanners = new ArrayList(1); + } +} |