diff --git a/java.editor/nbproject/project.properties b/java.editor/nbproject/project.properties
--- a/java.editor/nbproject/project.properties
+++ b/java.editor/nbproject/project.properties
@@ -42,7 +42,7 @@
javadoc.title=Java Editor
-spec.version.base=2.37.0
+spec.version.base=2.38.0
test.qa-functional.cp.extra=${editor.dir}/modules/org-netbeans-modules-editor-fold.jar
javac.source=1.6
#test.unit.cp.extra=
diff --git a/java.editor/nbproject/project.xml b/java.editor/nbproject/project.xml
--- a/java.editor/nbproject/project.xml
+++ b/java.editor/nbproject/project.xml
@@ -285,15 +285,6 @@
- org.netbeans.modules.parsing.lucene
-
-
-
- 2
- 2.3
-
-
- org.netbeans.modules.projectapi
@@ -315,7 +306,7 @@
- 1.0
+ 1.2
diff --git a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListCheckTask.java b/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListCheckTask.java
--- a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListCheckTask.java
+++ b/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListCheckTask.java
@@ -42,12 +42,14 @@
package org.netbeans.modules.java.editor.whitelist;
import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.Tree;
import com.sun.source.util.SourcePositions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
import org.netbeans.api.editor.mimelookup.MimeRegistration;
import org.netbeans.api.java.source.CompilationInfo;
@@ -65,6 +67,7 @@
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
import org.netbeans.spi.editor.hints.HintsController;
import org.netbeans.spi.editor.hints.Severity;
+import org.netbeans.spi.whitelist.support.WhiteListIndex;
import org.openide.filesystems.FileObject;
/**
@@ -96,29 +99,34 @@
if (whiteList == null) {
return;
}
- final List problems = new LinkedList();
- final WhiteListScanner scanner = new WhiteListScanner(
+ final CompilationUnitTree cu = info.getCompilationUnit();
+ final Map extends Tree, ? extends WhiteListQuery.Result> problems = WhiteListIndex.getWhiteListViolations(
+ cu,
+ whiteList,
info.getTrees(),
- whiteList,
- canceled);
- final CompilationUnitTree cu = info.getCompilationUnit();
- try {
- scanner.scan(cu, problems);
- } catch (WhiteListScanner.Cancel cancel) {
+ new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ return canceled.get();
+ }
+ });
+ if (problems == null) {
+ //Canceled
return;
}
final SourcePositions sp = info.getTrees().getSourcePositions();
final List errors = new ArrayList(problems.size());
- for (WhiteListScanner.Problem problem : problems) {
+ for (Map.Entry extends Tree, ? extends WhiteListQuery.Result> problem : problems.entrySet()) {
if (canceled.get()) {
return;
}
- final int start = (int) sp.getStartPosition(cu, problem.tree);
- final int end = (int) sp.getEndPosition(cu, problem.tree);
+ final Tree tree = problem.getKey();
+ final int start = (int) sp.getStartPosition(cu, tree);
+ final int end = (int) sp.getEndPosition(cu, tree);
if (start >= 0 && end >= 0) {
errors.add(ErrorDescriptionFactory.createErrorDescription(
Severity.WARNING,
- problem.description,
+ problem.getValue().getViolatedRuleDescription(),
file,
start,
end));
diff --git a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListScanner.java b/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListScanner.java
deleted file mode 100644
--- a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListScanner.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
- *
- * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
- * Other names may be trademarks of their respective owners.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common
- * Development and Distribution License("CDDL") (collectively, the
- * "License"). You may not use this file except in compliance with the
- * License. You can obtain a copy of the License at
- * http://www.netbeans.org/cddl-gplv2.html
- * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
- * specific language governing permissions and limitations under the
- * License. When distributing the software, include this License Header
- * Notice in each file and include the License file at
- * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the GPL Version 2 section of the License file that
- * accompanied this code. If applicable, add the following below the
- * License Header, with the fields enclosed by brackets [] replaced by
- * your own identifying information:
- * "Portions Copyrighted [year] [name of copyright owner]"
- *
- * If you wish your version of this file to be governed by only the CDDL
- * or only the GPL Version 2, indicate your decision by adding
- * "[Contributor] elects to include this software in this distribution
- * under the [CDDL or GPL Version 2] license." If you do not indicate a
- * single choice of license, a recipient has the option to distribute
- * your version of this file under either the CDDL, the GPL Version 2 or
- * to extend the choice of license to its licensees as provided above.
- * However, if you add GPL Version 2 code and therefore, elected the GPL
- * Version 2 license, then the option applies only if the new code is
- * made subject to such option by the copyright holder.
- *
- * Contributor(s):
- *
- * Portions Copyrighted 2011 Sun Microsystems, Inc.
- */
-package org.netbeans.modules.java.editor.whitelist;
-
-import com.sun.source.tree.ClassTree;
-import com.sun.source.tree.IdentifierTree;
-import com.sun.source.tree.MemberSelectTree;
-import com.sun.source.tree.MethodInvocationTree;
-import com.sun.source.tree.MethodTree;
-import com.sun.source.tree.NewClassTree;
-import com.sun.source.tree.Tree;
-import com.sun.source.util.TreePathScanner;
-import com.sun.source.util.Trees;
-import java.util.ArrayDeque;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import org.netbeans.api.java.source.ElementHandle;
-import org.netbeans.api.whitelist.WhiteListQuery;
-import org.netbeans.api.whitelist.WhiteListQuery.WhiteList;
-
-/**
- *
- * @author Tomas Zezula
- */
-class WhiteListScanner extends TreePathScanner> {
-
- private final Trees trees;
- private final AtomicBoolean cancel;
- private final WhiteList whiteList;
- private final ArrayDeque methodInvocation;
-
- WhiteListScanner(
- final Trees trees,
- final WhiteList whiteList,
- final AtomicBoolean cancel) {
- this.trees = trees;
- this.whiteList = whiteList;
- this.cancel = cancel;
- methodInvocation = new ArrayDeque();
- }
-
- @Override
- public Void visitMethod(MethodTree node, List super Problem> p) {
- checkCancel();
- return super.visitMethod(node, p);
- }
-
- @Override
- public Void visitClass(ClassTree node, List super Problem> p) {
- checkCancel();
- return super.visitClass(node, p);
- }
-
- @Override
- public Void visitIdentifier(IdentifierTree node, List super Problem> p) {
- handleNode(node,p);
- return super.visitIdentifier(node, p);
- }
-
- @Override
- public Void visitMemberSelect(MemberSelectTree node, List super Problem> p) {
- handleNode(node,p);
- return super.visitMemberSelect(node, p);
- }
-
- @Override
- public Void visitNewClass(NewClassTree node, List super Problem> p) {
- final Element e = trees.getElement(getCurrentPath());
- final WhiteListQuery.Result res;
- if (e != null && !(res=whiteList.check(ElementHandle.create(e),WhiteListQuery.Operation.USAGE)).isAllowed()) {
- p.add(new Problem(node,res.getViolatedRuleDescription()));
- }
- scan(node.getTypeArguments(), p);
- scan(node.getArguments(), p);
- scan(node.getClassBody(), p);
- return null;
- }
-
- @Override
- public Void visitMethodInvocation(MethodInvocationTree node, List super Problem> p) {
- methodInvocation.offerFirst(node);
- super.visitMethodInvocation(node, p);
- methodInvocation.removeFirst();
- return null;
- }
-
- private void handleNode(
- final Tree node,
- final List super Problem> p) {
- final Element e = trees.getElement(getCurrentPath());
- if (e == null) {
- return;
- }
- final ElementKind k = e.getKind();
- Tree toReport = null;
- if (k.isClass() || k.isInterface()) {
- toReport=node;
- } else if ((k == ElementKind.METHOD || k == ElementKind.CONSTRUCTOR) &&
- !methodInvocation.isEmpty()) {
- toReport=methodInvocation.peekFirst();
- }
- final WhiteListQuery.Result res;
- if (toReport != null &&
- !(res=whiteList.check(ElementHandle.create(e),WhiteListQuery.Operation.USAGE)).isAllowed()) {
- p.add(new Problem(toReport,res.getViolatedRuleDescription()));
- }
- }
-
- private void checkCancel() {
- if (cancel.get()) {
- throw new Cancel();
- }
- }
-
- static final class Problem {
- final Tree tree;
- final String description;
-
- private Problem (
- final Tree tree,
- final String description) {
- this.tree = tree;
- this.description = description;
- }
- }
-
- static final class Cancel extends RuntimeException {
- }
-
-}
diff --git a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListTaskProvider.java b/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListTaskProvider.java
--- a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListTaskProvider.java
+++ b/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListTaskProvider.java
@@ -41,8 +41,6 @@
*/
package org.netbeans.modules.java.editor.whitelist;
-import java.io.File;
-import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
@@ -62,18 +60,15 @@
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
-import org.netbeans.modules.parsing.lucene.support.DocumentIndex;
-import org.netbeans.modules.parsing.lucene.support.Index;
-import org.netbeans.modules.parsing.lucene.support.IndexDocument;
-import org.netbeans.modules.parsing.lucene.support.IndexManager;
-import org.netbeans.modules.parsing.lucene.support.Queries.QueryKind;
import org.netbeans.spi.tasklist.PushTaskScanner;
import org.netbeans.spi.tasklist.Task;
import org.netbeans.spi.tasklist.TaskScanningScope;
+import org.netbeans.spi.whitelist.support.WhiteListIndex;
+import org.netbeans.spi.whitelist.support.WhiteListIndexEvent;
+import org.netbeans.spi.whitelist.support.WhiteListIndexListener;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
-import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.TaskListener;
@@ -109,28 +104,12 @@
super(Bundle.LBL_ProviderName(),
Bundle.LBL_ProviderDescription(),
null);
- INSTANCE = this;
- }
-
- @CheckForNull
- static WhiteListTaskProvider getInstance() {
- return INSTANCE;
- }
-
- void refresh(final @NonNull URL root) {
- final FileObject rootFo = URLMapper.findFileObject(root);
- final Set files;
- final Callback callback;
- synchronized (this) {
- files = currentFiles;
- callback = currentCallback;
- }
- if (rootFo != null &&
- files != null &&
- files.contains(rootFo)) {
- assert callback != null;
- enqueue(new Work(rootFo, currentCallback));
- }
+ WhiteListIndex.getDefault().addWhiteListIndexListener(new WhiteListIndexListener() {
+ @Override
+ public void indexChanged(WhiteListIndexEvent event) {
+ refresh(event.getRoot());
+ }
+ });
}
@Override
@@ -158,6 +137,23 @@
}
}
+ private void refresh(final @NonNull URL root) {
+ assert root != null;
+ final FileObject rootFo = URLMapper.findFileObject(root);
+ final Set files;
+ final Callback callback;
+ synchronized (this) {
+ files = currentFiles;
+ callback = currentCallback;
+ }
+ if (rootFo != null &&
+ files != null &&
+ files.contains(rootFo)) {
+ assert callback != null;
+ enqueue(new Work(rootFo, currentCallback));
+ }
+ }
+
private static void enqueue(Work w) {
synchronized (TASKS) {
final RequestProcessor.Task task = WORKER.post(w);
@@ -205,18 +201,16 @@
}
@CheckForNull
- private static Map.Entry createTask(
- @NonNull final FileObject root,
- @NonNull final IndexDocument doc) {
- final FileObject file = root.getFileObject(doc.getPrimaryKey());
+ private static Map.Entry createTask(@NonNull final WhiteListIndex.Problem problem) {
+ final FileObject file = problem.getFile();
if (file == null) {
return null;
}
final Task task = Task.create(
file,
"nb-whitelist-warning", //NOI18N
- doc.getValue(WhiteListIndexerPlugin.MSG),
- Integer.parseInt(doc.getValue(WhiteListIndexerPlugin.LINE)));
+ problem.getResult().getViolatedRuleDescription(),
+ problem.getLine());
return new Map.Entry() {
@Override
public FileObject getKey() {
@@ -233,20 +227,6 @@
};
}
- @CheckForNull
- private static DocumentIndex getIndex(@NonNull final FileObject root) {
- try {
- final File whiteListFolder = WhiteListIndexerPlugin.getWhiteListDir(root.getURL());
- if (whiteListFolder != null) {
- final DocumentIndex index = IndexManager.createDocumentIndex(whiteListFolder);
- return index.getStatus() == Index.Status.VALID ? index : null;
- }
- } catch (IOException ioe) {
- Exceptions.printStackTrace(ioe);
- }
- return null;
- }
-
private static void updateErrorsInRoot(
@NonNull final Callback callback,
@NonNull final FileObject root) {
@@ -255,35 +235,16 @@
filesWithErrors.clear();
Set nueFilesWithErrors = new HashSet();
final Map> filesToTasks = new HashMap>();
- try {
- IndexManager.readAccess(new IndexManager.Action() {
- @Override
- public Void run() throws IOException, InterruptedException {
- final DocumentIndex index = getIndex(root);
- if (index != null) {
- try {
- for (IndexDocument doc : index.findByPrimaryKey("", QueryKind.PREFIX)) { //NOI18N
- final Map.Entry task = createTask(root, doc);
- if (task != null) {
- List tasks = filesToTasks.get(task.getKey());
- if (tasks == null) {
- tasks = new ArrayList();
- filesToTasks.put(task.getKey(), tasks);
- }
- tasks.add(task.getValue());
- }
- }
- } finally {
- index.close();
- }
- }
- return null;
+ for (WhiteListIndex.Problem problem : WhiteListIndex.getDefault().getWhiteListViolations(root, null)) {
+ final Map.Entry task = createTask(problem);
+ if (task != null) {
+ List tasks = filesToTasks.get(task.getKey());
+ if (tasks == null) {
+ tasks = new ArrayList();
+ filesToTasks.put(task.getKey(), tasks);
}
- });
- } catch (IOException e) {
- Exceptions.printStackTrace(e);
- } catch (InterruptedException e) {
- Exceptions.printStackTrace(e);
+ tasks.add(task.getValue());
+ }
}
for (Map.Entry> e : filesToTasks.entrySet()) {
LOG.log(Level.FINE, "Setting {1} for {0}\n",
@@ -304,40 +265,21 @@
@NonNull final Callback callback,
@NonNull final FileObject root,
@NonNull final FileObject file) {
- try {
- IndexManager.readAccess(new IndexManager.Action(){
- @Override
- public Void run() throws IOException, InterruptedException {
- final List tasks = new ArrayList();
- final DocumentIndex index = getIndex(root);
- if (index != null) {
- try {
- for (IndexDocument doc : index.findByPrimaryKey(FileUtil.getRelativePath(root, file), QueryKind.PREFIX)) {
- final Map.Entry task = createTask(root, doc);
- if (task != null) {
- tasks.add(task.getValue());
- }
- }
- } finally {
- index.close();
- }
- }
- Set filesWithErrors = getFilesWithAttachedErrors(root);
- if (tasks.isEmpty()) {
- filesWithErrors.remove(file);
- } else {
- filesWithErrors.add(file);
- }
- LOG.log(Level.FINE, "setting {1} for {0}", new Object[]{file, tasks});
- callback.setTasks(file, tasks);
- return null;
- }
- });
- } catch (IOException e) {
- Exceptions.printStackTrace(e);
- } catch (InterruptedException e) {
- Exceptions.printStackTrace(e);
+ final List tasks = new ArrayList();
+ for (WhiteListIndex.Problem problem : WhiteListIndex.getDefault().getWhiteListViolations(root, file)) {
+ final Map.Entry task = createTask(problem);
+ if (task != null) {
+ tasks.add(task.getValue());
+ }
}
+ final Set filesWithErrors = getFilesWithAttachedErrors(root);
+ if (tasks.isEmpty()) {
+ filesWithErrors.remove(file);
+ } else {
+ filesWithErrors.add(file);
+ }
+ LOG.log(Level.FINE, "setting {1} for {0}", new Object[]{file, tasks});
+ callback.setTasks(file, tasks);
}
private static final class Work implements Runnable {
diff --git a/java.preprocessorbridge/nbproject/project.xml b/java.preprocessorbridge/nbproject/project.xml
--- a/java.preprocessorbridge/nbproject/project.xml
+++ b/java.preprocessorbridge/nbproject/project.xml
@@ -70,6 +70,7 @@
org.netbeans.modules.scala.editingorg.netbeans.modules.scala.editororg.netbeans.modules.web.core.syntax
+ org.netbeans.modules.whitelistorg.netbeans.modules.java.preprocessorbridge.apiorg.netbeans.modules.java.preprocessorbridge.spi
diff --git a/parsing.lucene/nbproject/project.xml b/parsing.lucene/nbproject/project.xml
--- a/parsing.lucene/nbproject/project.xml
+++ b/parsing.lucene/nbproject/project.xml
@@ -56,10 +56,10 @@
- org.netbeans.modules.java.editororg.netbeans.modules.java.sourceorg.netbeans.modules.java.sourceuiorg.netbeans.modules.parsing.api
+ org.netbeans.modules.whitelistorg.netbeans.modules.parsing.lucene.support
diff --git a/whitelist/apichanges.xml b/whitelist/apichanges.xml
--- a/whitelist/apichanges.xml
+++ b/whitelist/apichanges.xml
@@ -75,6 +75,23 @@
+
+
+ Added WhiteListQuery to check violations of runtime restrictions
+
+
+
+
+
+
+ Added WhiteListIndex to provide persistent index of the white list violations.
+
+
+
+
+
+
+ Added WhiteListQuery to check violations of runtime restrictions
diff --git a/whitelist/manifest.mf b/whitelist/manifest.mf
--- a/whitelist/manifest.mf
+++ b/whitelist/manifest.mf
@@ -2,5 +2,5 @@
OpenIDE-Module: org.netbeans.modules.whitelist
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/whitelist/Bundle.properties
OpenIDE-Module-Layer: org/netbeans/modules/whitelist/resources/layer.xml
-OpenIDE-Module-Specification-Version: 1.1
+OpenIDE-Module-Specification-Version: 1.2
diff --git a/whitelist/nbproject/project.xml b/whitelist/nbproject/project.xml
--- a/whitelist/nbproject/project.xml
+++ b/whitelist/nbproject/project.xml
@@ -15,6 +15,15 @@
+ org.netbeans.api.java.classpath
+
+
+
+ 1
+ 1.30
+
+
+ org.netbeans.libs.javacapi
@@ -23,6 +32,23 @@
+ org.netbeans.modules.editor.mimelookup
+
+
+
+ 1
+ 1.23
+
+
+
+ org.netbeans.modules.java.preprocessorbridge
+
+
+
+ 1.22
+
+
+ org.netbeans.modules.java.source
@@ -31,6 +57,24 @@
+ org.netbeans.modules.parsing.api
+
+
+
+ 1
+ 1.43
+
+
+
+ org.netbeans.modules.parsing.lucene
+
+
+
+ 2
+ 2.3
+
+
+ org.netbeans.modules.projectapi
diff --git a/whitelist/src/org/netbeans/modules/whitelist/index/WhiteListIndexAccessor.java b/whitelist/src/org/netbeans/modules/whitelist/index/WhiteListIndexAccessor.java
new file mode 100644
--- /dev/null
+++ b/whitelist/src/org/netbeans/modules/whitelist/index/WhiteListIndexAccessor.java
@@ -0,0 +1,85 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2011 Sun Microsystems, Inc.
+ */
+package org.netbeans.modules.whitelist.index;
+
+import java.net.URL;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.whitelist.WhiteListQuery;
+import org.netbeans.spi.whitelist.support.WhiteListIndex;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+import org.openide.util.Parameters;
+
+/**
+ *
+ * @author Tomas Zezula
+ */
+public abstract class WhiteListIndexAccessor {
+
+ private static volatile WhiteListIndexAccessor instance;
+
+ @NonNull
+ public static synchronized WhiteListIndexAccessor getInstance() {
+ if (instance == null) {
+ try {
+ Class.forName(WhiteListIndex.class.getName(), true, WhiteListIndexAccessor.class.getClassLoader());
+ assert instance != null;
+ } catch (ClassNotFoundException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ return instance;
+
+ }
+
+ public static void setInstance(@NonNull final WhiteListIndexAccessor _instance) {
+ Parameters.notNull("_instance", _instance); //NOI18N
+ instance = _instance;
+ }
+
+ public abstract void refresh(@NonNull URL root);
+ public abstract WhiteListIndex.Problem createProblem(
+ @NonNull WhiteListQuery.Result result,
+ @NonNull FileObject root,
+ @NonNull String key,
+ int line);
+}
diff --git a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListIndexerPlugin.java b/whitelist/src/org/netbeans/modules/whitelist/index/WhiteListIndexerPlugin.java
rename from java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListIndexerPlugin.java
rename to whitelist/src/org/netbeans/modules/whitelist/index/WhiteListIndexerPlugin.java
--- a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListIndexerPlugin.java
+++ b/whitelist/src/org/netbeans/modules/whitelist/index/WhiteListIndexerPlugin.java
@@ -39,29 +39,34 @@
*
* Portions Copyrighted 2011 Sun Microsystems, Inc.
*/
-package org.netbeans.modules.java.editor.whitelist;
+package org.netbeans.modules.whitelist.index;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.LineMap;
+import com.sun.source.tree.Tree;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.Trees;
import java.io.File;
import java.io.IOException;
import java.net.URL;
-import java.util.LinkedList;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicBoolean;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.editor.mimelookup.MimeRegistration;
import org.netbeans.api.whitelist.WhiteListQuery;
import org.netbeans.modules.java.preprocessorbridge.spi.JavaIndexerPlugin;
import org.netbeans.modules.parsing.lucene.support.DocumentIndex;
+import org.netbeans.modules.parsing.lucene.support.Index;
import org.netbeans.modules.parsing.lucene.support.IndexDocument;
import org.netbeans.modules.parsing.lucene.support.IndexManager;
+import org.netbeans.modules.parsing.lucene.support.Queries.QueryKind;
import org.netbeans.modules.parsing.spi.indexing.Indexable;
+import org.netbeans.spi.whitelist.support.WhiteListIndex;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
@@ -75,8 +80,9 @@
public class WhiteListIndexerPlugin implements JavaIndexerPlugin {
private static final String WHITE_LIST_INDEX = "whitelist"; //NOI18N
- static final String MSG = "msg"; //NOI18N
- static final String LINE = "line"; //NOI18N
+ private static final String MSG = "msg"; //NOI18N
+ private static final String NAME = "name"; //NOI18N
+ private static final String LINE = "line"; //NOI18N
private static Map roots2whiteListDirs = new ConcurrentHashMap();
private final URL root;
@@ -104,20 +110,16 @@
@NonNull final Lookup services) {
final Trees trees = services.lookup(Trees.class);
assert trees != null;
- final WhiteListScanner scanner = new WhiteListScanner(
- trees,
- whiteList,
- new AtomicBoolean());
- final List problems = new LinkedList();
- scanner.scan(toProcess,problems);
+ final Map extends Tree, ? extends WhiteListQuery.Result> problems = WhiteListIndex.getWhiteListViolations(toProcess, whiteList, trees, null);
+ assert problems != null;
final LineMap lm = toProcess.getLineMap();
final SourcePositions sp = trees.getSourcePositions();
- for (WhiteListScanner.Problem p : problems) {
- final int start = (int) sp.getStartPosition(toProcess, p.tree);
+ for (Map.Entry extends Tree, ? extends WhiteListQuery.Result> p : problems.entrySet()) {
+ final int start = (int) sp.getStartPosition(toProcess, p.getKey());
int ln;
if (start>=0 && (ln=(int)lm.getLineNumber(start))>=0) {
final IndexDocument doc = IndexManager.createDocument(indexable.getRelativePath());
- doc.addPair(MSG, p.description, false, true);
+ doc.addPair(MSG, p.getValue().getViolatedRuleDescription(), false, true);
doc.addPair(LINE, Integer.toString(ln), false, true);
index.addDocument(doc);
}
@@ -134,10 +136,7 @@
try {
index.store(true);
roots2whiteListDirs.put(root, whiteListDir);
- final WhiteListTaskProvider tp = WhiteListTaskProvider.getInstance();
- if (tp != null) {
- tp.refresh(root);
- }
+ WhiteListIndexAccessor.getInstance().refresh(root);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} finally {
@@ -150,8 +149,61 @@
}
@CheckForNull
- static File getWhiteListDir(@NonNull final URL root) {
- return roots2whiteListDirs.get(root);
+ private static DocumentIndex getIndex(@NonNull final FileObject root) {
+ try {
+ final File whiteListFolder = roots2whiteListDirs.get(root.getURL());
+ if (whiteListFolder != null) {
+ final DocumentIndex index = IndexManager.createDocumentIndex(whiteListFolder);
+ return index.getStatus() == Index.Status.VALID ? index : null;
+ }
+ } catch (IOException ioe) {
+ Exceptions.printStackTrace(ioe);
+ }
+ return null;
+ }
+
+ @NonNull
+ public static Collection extends WhiteListIndex.Problem> getWhiteListViolations(
+ @NonNull final FileObject root,
+ @NullAllowed final FileObject resource) {
+ final List result = new ArrayList();
+ try {
+ IndexManager.readAccess(new IndexManager.Action() {
+ @Override
+ public Void run() throws IOException, InterruptedException {
+ final DocumentIndex index = getIndex(root);
+ if (index != null) {
+ try {
+ for (IndexDocument doc : index.findByPrimaryKey(
+ resource == null ? "" : FileUtil.getRelativePath(root,resource), //NOI18N
+ QueryKind.PREFIX)) {
+ try {
+ final String key = doc.getPrimaryKey();
+ String wlName = doc.getValue(NAME);
+ if (wlName == null) {
+ wlName = ""; //NOI18N
+ }
+ final String wlDesc = doc.getValue(MSG);
+ final int line = Integer.parseInt(doc.getValue(LINE));
+ final WhiteListQuery.Result wr = new WhiteListQuery.Result(false, wlName, wlDesc);
+ result.add(WhiteListIndexAccessor.getInstance().createProblem(wr, root, key, line));
+ } catch (ArithmeticException ae) {
+ Exceptions.printStackTrace(ae);
+ }
+ }
+ } finally {
+ index.close();
+ }
+ }
+ return null;
+ }
+ });
+ } catch (IOException e) {
+ Exceptions.printStackTrace(e);
+ } catch (InterruptedException e) {
+ Exceptions.printStackTrace(e);
+ }
+ return result;
}
@MimeRegistration(mimeType="text/x-java",service=JavaIndexerPlugin.Factory.class)
@@ -159,7 +211,7 @@
@Override
public JavaIndexerPlugin create(final URL root, final FileObject cacheFolder) {
try {
- File whiteListDir = getWhiteListDir(root);
+ File whiteListDir = roots2whiteListDirs.get(root);
if (whiteListDir == null) {
//First time
final FileObject whiteListFolder = FileUtil.createFolder(cacheFolder, WHITE_LIST_INDEX);
diff --git a/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndex.java b/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndex.java
new file mode 100644
--- /dev/null
+++ b/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndex.java
@@ -0,0 +1,358 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2011 Sun Microsystems, Inc.
+ */
+package org.netbeans.spi.whitelist.support;
+
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.NewClassTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+import java.net.URL;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.annotations.common.NullAllowed;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.api.whitelist.WhiteListQuery;
+import org.netbeans.api.whitelist.WhiteListQuery.Result;
+import org.netbeans.api.whitelist.WhiteListQuery.WhiteList;
+import org.netbeans.modules.whitelist.index.WhiteListIndexAccessor;
+import org.netbeans.modules.whitelist.index.WhiteListIndexerPlugin;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+import org.openide.util.Parameters;
+
+/**
+ * A persistent index of white list violations.
+ * @author Tomas Zezula
+ * @since 1.2
+ */
+public final class WhiteListIndex {
+
+ static {
+ WhiteListIndexAccessor.setInstance(new WhiteListIndexAccessorImpl());
+ }
+
+ private static WhiteListIndex instance;
+ private final List listeners = new CopyOnWriteArrayList();
+
+ private WhiteListIndex() {}
+
+ /**
+ * Returns the white list violations for given root or file.
+ * @param root the root to get white list violations for
+ * @param file the file to restrict the white list violation search or null
+ * @return a {@link Collection} of {@link Problem}s
+ * @throws IllegalArgumentException in case when file is not under the root or it's not a valid file
+ * @throws UnsupportedOperationException when the index is not supported by the IDE
+ */
+ @NonNull
+ public Collection extends Problem> getWhiteListViolations(
+ @NonNull final FileObject root,
+ @NullAllowed final FileObject file) throws IllegalArgumentException, UnsupportedOperationException {
+ Parameters.notNull("scope", root); //NOI18N
+ if (file != null && !(root.equals(file) || FileUtil.isParentOf(root, file))) {
+ throw new IllegalArgumentException(
+ "The file: " + //NOI18N
+ FileUtil.getFileDisplayName(file) +
+ " has to be inside the root: " + //NOI18N
+ FileUtil.getFileDisplayName(root));
+ }
+ if (file != null && !file.isData()) {
+ throw new IllegalArgumentException(
+ "The file: " + //NOI18N
+ FileUtil.getFileDisplayName(file) +
+ " has to be file."); //NOI18N
+ }
+ return WhiteListIndexerPlugin.getWhiteListViolations(root,file);
+ }
+
+ /**
+ * Adds {@link WhiteListIndexListener}.
+ * The listener is notified when the white list index is changed.
+ * @param listener the listener to be added
+ */
+ public void addWhiteListIndexListener(@NonNull final WhiteListIndexListener listener) {
+ Parameters.notNull("listener", listener); //NOI18N
+ listeners.add(listener);
+ }
+
+ /**
+ * Removes {@link WhiteListIndexListener}.
+ * @param listener the listener to be removed
+ */
+ public void removeWhiteListIndexListener(@NonNull final WhiteListIndexListener listener) {
+ Parameters.notNull("listener", listener); //NOI18N
+ listeners.remove(listener);
+ }
+
+ /**
+ * Utility method to check the given {@link CompilationUnitTree} for white list violations.
+ * @param unit the {@link CompilationUnitTree} to be analyzed
+ * @param whitelist the {@link WhiteList} to use to check the violations
+ * @param trees the {@link Trees} service
+ * @param cancel the cancel request. If the {@link Callable} returns true the check is canceled
+ * and null is returned.
+ * @return a {@link Map} of {@link Tree}s with attached white list violations or null when the
+ * scan was canceled.
+ */
+ @CheckForNull
+ public static Map extends Tree, ? extends WhiteListQuery.Result> getWhiteListViolations(
+ @NonNull final CompilationUnitTree unit,
+ @NonNull final WhiteListQuery.WhiteList whitelist,
+ @NonNull final Trees trees,
+ @NullAllowed final Callable cancel) {
+ Parameters.notNull("tree", unit); //NOI18N
+ Parameters.notNull("whitelist", whitelist); //NOI18N
+ Parameters.notNull("trees", trees); //NOI18N
+ final Map result = new HashMap();
+ final WhiteListScanner scanner = new WhiteListScanner(trees, whitelist, cancel);
+ try {
+ scanner.scan(unit, result);
+ return result;
+ } catch (WhiteListScanner.Cancel ce) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns an instance of {@link WhiteListIndex}
+ * @return the instance of {@link WhiteListIndex}
+ */
+ public static synchronized WhiteListIndex getDefault() {
+ if (instance == null) {
+ instance = new WhiteListIndex();
+ }
+ return instance;
+ }
+
+
+ /**
+ * Represent a white list violation
+ */
+ public static final class Problem {
+
+ private final WhiteListQuery.Result result;
+ private final FileObject root;
+ private final String relPath;
+ private final int line;
+
+ private Problem (
+ @NonNull final WhiteListQuery.Result result,
+ @NonNull final FileObject root,
+ @NonNull final String relPath,
+ final int line) {
+ Parameters.notNull("result", result); //NOI18N
+ Parameters.notNull("root", root); //NOI18N
+ Parameters.notNull("relPath", relPath); //NOI18N
+ this.result = result;
+ this.root = root;
+ this.relPath = relPath;
+ this.line = line;
+ }
+
+ /**
+ * Returns {@link WhiteListQuery.Result} describing the
+ * white list violation.
+ * @return the {@link WhiteListQuery.Result}
+ */
+ @NonNull
+ public WhiteListQuery.Result getResult() {
+ return result;
+ }
+
+ /**
+ * Returns the file in which the white list violation occured.
+ * @return the {@link FileObject}
+ */
+ @CheckForNull
+ public FileObject getFile() {
+ return root.getFileObject(relPath);
+ }
+
+ /**
+ * Returns the line number of white list violation.
+ * @return the line number
+ */
+ public int getLine() {
+ return line;
+ }
+ }
+
+ //
+ private void fireIndexChange(final URL root) {
+ final WhiteListIndexEvent event = new WhiteListIndexEvent(this, root);
+ for (WhiteListIndexListener l : listeners) {
+ l.indexChanged(event);
+ }
+ }
+
+ private static final class WhiteListIndexAccessorImpl extends WhiteListIndexAccessor {
+ @Override
+ public void refresh(@NonNull URL root) {
+ WhiteListIndex.getDefault().fireIndexChange(root);
+ }
+
+ @Override
+ @NonNull
+ public Problem createProblem(
+ @NonNull final Result result,
+ @NonNull final FileObject root,
+ @NonNull final String key,
+ int line) {
+ return new Problem(result, root, key, line);
+ }
+ }
+
+ private static class WhiteListScanner extends TreePathScanner> {
+
+ private final Trees trees;
+ private final Callable cancel;
+ private final WhiteList whiteList;
+ private final ArrayDeque methodInvocation;
+
+ WhiteListScanner(
+ final Trees trees,
+ final WhiteList whiteList,
+ final Callable cancel) {
+ this.trees = trees;
+ this.whiteList = whiteList;
+ this.cancel = cancel;
+ methodInvocation = new ArrayDeque();
+ }
+
+ @Override
+ public Void visitMethod(MethodTree node, Map p) {
+ checkCancel();
+ return super.visitMethod(node, p);
+ }
+
+ @Override
+ public Void visitClass(ClassTree node, Map p) {
+ checkCancel();
+ return super.visitClass(node, p);
+ }
+
+ @Override
+ public Void visitIdentifier(IdentifierTree node, Map p) {
+ handleNode(node,p);
+ return super.visitIdentifier(node, p);
+ }
+
+ @Override
+ public Void visitMemberSelect(MemberSelectTree node, Map p) {
+ handleNode(node,p);
+ return super.visitMemberSelect(node, p);
+ }
+
+ @Override
+ public Void visitNewClass(NewClassTree node, Map p) {
+ final Element e = trees.getElement(getCurrentPath());
+ final WhiteListQuery.Result res;
+ if (e != null && !(res=whiteList.check(ElementHandle.create(e),WhiteListQuery.Operation.USAGE)).isAllowed()) {
+ p.put(node,res);
+ }
+ scan(node.getTypeArguments(), p);
+ scan(node.getArguments(), p);
+ scan(node.getClassBody(), p);
+ return null;
+ }
+
+ @Override
+ public Void visitMethodInvocation(MethodInvocationTree node, Map p) {
+ methodInvocation.offerFirst(node);
+ super.visitMethodInvocation(node, p);
+ methodInvocation.removeFirst();
+ return null;
+ }
+
+ private void handleNode(
+ final Tree node,
+ final Map p) {
+ final Element e = trees.getElement(getCurrentPath());
+ if (e == null) {
+ return;
+ }
+ final ElementKind k = e.getKind();
+ Tree toReport = null;
+ if (k.isClass() || k.isInterface()) {
+ toReport=node;
+ } else if ((k == ElementKind.METHOD || k == ElementKind.CONSTRUCTOR) &&
+ !methodInvocation.isEmpty()) {
+ toReport=methodInvocation.peekFirst();
+ }
+ final WhiteListQuery.Result res;
+ if (toReport != null &&
+ !(res=whiteList.check(ElementHandle.create(e),WhiteListQuery.Operation.USAGE)).isAllowed()) {
+ p.put(toReport,res);
+ }
+ }
+
+ private void checkCancel() {
+ try {
+ if (cancel != null && cancel.call() == Boolean.TRUE) {
+ throw new Cancel();
+ }
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ static final class Cancel extends RuntimeException {
+ }
+ }
+ //
+}
diff --git a/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndexEvent.java b/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndexEvent.java
new file mode 100644
--- /dev/null
+++ b/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndexEvent.java
@@ -0,0 +1,73 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2011 Sun Microsystems, Inc.
+ */
+package org.netbeans.spi.whitelist.support;
+
+import java.net.URL;
+import java.util.EventObject;
+import org.netbeans.api.annotations.common.NonNull;
+import org.openide.util.Parameters;
+
+/**
+ * WhiteListIndexEvent is used to notify interested parties about
+ * changes in persistent index of white list violations.
+ * @author Tomas Zezula
+ * @since 1.2
+ */
+public class WhiteListIndexEvent extends EventObject {
+
+ private final URL root;
+
+ WhiteListIndexEvent(@NonNull final Object source, @NonNull final URL root) {
+ super(source);
+ Parameters.notNull("root", root); //NOI18N
+ this.root = root;
+ }
+
+ /**
+ * Returns a source root for which the index was changed.
+ * @return the {@link URL} of the source root.
+ */
+ @NonNull
+ public URL getRoot() {
+ return root;
+ }
+}
diff --git a/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndexListener.java b/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndexListener.java
new file mode 100644
--- /dev/null
+++ b/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndexListener.java
@@ -0,0 +1,58 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2011 Sun Microsystems, Inc.
+ */
+package org.netbeans.spi.whitelist.support;
+
+import java.util.EventListener;
+import org.netbeans.api.annotations.common.NonNull;
+
+/**
+ * The listener interface for receiving {@link WhiteListIndex} events.
+ * @author Tomas Zezula
+ * @since 1.2
+ */
+public interface WhiteListIndexListener extends EventListener {
+ /**
+ * Invoked when the index for a source root changed
+ * @param event the event providing the change details
+ */
+ void indexChanged (@NonNull WhiteListIndexEvent event);
+}