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.api.whitelist.support.WhiteListSupport; 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 problems = WhiteListSupport.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 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 p) { - checkCancel(); - return super.visitMethod(node, p); - } - - @Override - public Void visitClass(ClassTree node, List p) { - checkCancel(); - return super.visitClass(node, p); - } - - @Override - public Void visitIdentifier(IdentifierTree node, List p) { - handleNode(node,p); - return super.visitIdentifier(node, p); - } - - @Override - public Void visitMemberSelect(MemberSelectTree node, List p) { - handleNode(node,p); - return super.visitMemberSelect(node, p); - } - - @Override - public Void visitNewClass(NewClassTree node, List 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 p) { - methodInvocation.offerFirst(node); - super.visitMethodInvocation(node, p); - methodInvocation.removeFirst(); - return null; - } - - private void handleNode( - final Tree node, - final List 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.api.whitelist.index.WhiteListIndex; +import org.netbeans.api.whitelist.index.WhiteListIndexEvent; +import org.netbeans.api.whitelist.index.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.editing org.netbeans.modules.scala.editor org.netbeans.modules.web.core.syntax + org.netbeans.modules.whitelist org.netbeans.modules.java.preprocessorbridge.api org.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.editor org.netbeans.modules.java.source org.netbeans.modules.java.sourceui org.netbeans.modules.parsing.api + org.netbeans.modules.whitelist org.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,24 @@ + + + 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 @@ -78,6 +122,8 @@ org.netbeans.modules.java.editor org.netbeans.modules.web.project org.netbeans.api.whitelist + org.netbeans.api.whitelist.index + org.netbeans.api.whitelist.support org.netbeans.spi.whitelist org.netbeans.spi.whitelist.support diff --git a/whitelist/src/org/netbeans/api/whitelist/index/WhiteListIndex.java b/whitelist/src/org/netbeans/api/whitelist/index/WhiteListIndex.java new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/api/whitelist/index/WhiteListIndex.java @@ -0,0 +1,213 @@ +/* + * 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.api.whitelist.index; + +import java.net.URL; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +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.whitelist.WhiteListQuery; +import org.netbeans.api.whitelist.WhiteListQuery.Result; +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.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 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); + } + + /** + * 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); + } + } + // +} diff --git a/whitelist/src/org/netbeans/api/whitelist/index/WhiteListIndexEvent.java b/whitelist/src/org/netbeans/api/whitelist/index/WhiteListIndexEvent.java new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/api/whitelist/index/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.api.whitelist.index; + +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/api/whitelist/index/WhiteListIndexListener.java b/whitelist/src/org/netbeans/api/whitelist/index/WhiteListIndexListener.java new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/api/whitelist/index/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.api.whitelist.index; + +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); +} diff --git a/whitelist/src/org/netbeans/api/whitelist/support/WhiteListSupport.java b/whitelist/src/org/netbeans/api/whitelist/support/WhiteListSupport.java new file mode 100644 --- /dev/null +++ b/whitelist/src/org/netbeans/api/whitelist/support/WhiteListSupport.java @@ -0,0 +1,208 @@ +/* + * 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.api.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.util.ArrayDeque; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Callable; +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.openide.util.Exceptions; +import org.openide.util.Parameters; + +/** + * White list supporting methods. + * @author Tomas Zezula + * @since 1.2 + */ +public final class WhiteListSupport { + + private WhiteListSupport() {} + + /** + * 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 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; + } + } + + // + 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/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.api.whitelist.index.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,35 @@ * * 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.api.whitelist.index.WhiteListIndex; +import org.netbeans.api.whitelist.support.WhiteListSupport; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.filesystems.URLMapper; @@ -75,8 +81,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 +111,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 problems = WhiteListSupport.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 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 +137,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 +150,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 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 +212,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);