This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 202063
Collapse All | Expand All

(-)a/java.editor/nbproject/project.properties (-1 / +1 lines)
Lines 42-48 Link Here
42
42
43
javadoc.title=Java Editor
43
javadoc.title=Java Editor
44
44
45
spec.version.base=2.37.0
45
spec.version.base=2.38.0
46
test.qa-functional.cp.extra=${editor.dir}/modules/org-netbeans-modules-editor-fold.jar
46
test.qa-functional.cp.extra=${editor.dir}/modules/org-netbeans-modules-editor-fold.jar
47
javac.source=1.6
47
javac.source=1.6
48
#test.unit.cp.extra=
48
#test.unit.cp.extra=
(-)a/java.editor/nbproject/project.xml (-10 / +1 lines)
Lines 285-299 Link Here
285
                    </run-dependency>
285
                    </run-dependency>
286
                </dependency>
286
                </dependency>
287
                <dependency>
287
                <dependency>
288
                    <code-name-base>org.netbeans.modules.parsing.lucene</code-name-base>
289
                    <build-prerequisite/>
290
                    <compile-dependency/>
291
                    <run-dependency>
292
                        <release-version>2</release-version>
293
                        <specification-version>2.3</specification-version>
294
                    </run-dependency>
295
                </dependency>
296
                <dependency>
297
                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
288
                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
298
                    <build-prerequisite/>
289
                    <build-prerequisite/>
299
                    <compile-dependency/>
290
                    <compile-dependency/>
Lines 315-321 Link Here
315
                    <build-prerequisite/>
306
                    <build-prerequisite/>
316
                    <compile-dependency/>
307
                    <compile-dependency/>
317
                    <run-dependency>
308
                    <run-dependency>
318
                        <specification-version>1.0</specification-version>
309
                        <specification-version>1.2</specification-version>
319
                    </run-dependency>
310
                    </run-dependency>
320
                </dependency>
311
                </dependency>
321
                <dependency>
312
                <dependency>
(-)a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListCheckTask.java (-13 / +21 lines)
Lines 42-53 Link Here
42
package org.netbeans.modules.java.editor.whitelist;
42
package org.netbeans.modules.java.editor.whitelist;
43
43
44
import com.sun.source.tree.CompilationUnitTree;
44
import com.sun.source.tree.CompilationUnitTree;
45
import com.sun.source.tree.Tree;
45
import com.sun.source.util.SourcePositions;
46
import com.sun.source.util.SourcePositions;
46
import java.util.ArrayList;
47
import java.util.ArrayList;
47
import java.util.Collection;
48
import java.util.Collection;
48
import java.util.Collections;
49
import java.util.Collections;
49
import java.util.LinkedList;
50
import java.util.List;
50
import java.util.List;
51
import java.util.Map;
52
import java.util.concurrent.Callable;
51
import java.util.concurrent.atomic.AtomicBoolean;
53
import java.util.concurrent.atomic.AtomicBoolean;
52
import org.netbeans.api.editor.mimelookup.MimeRegistration;
54
import org.netbeans.api.editor.mimelookup.MimeRegistration;
53
import org.netbeans.api.java.source.CompilationInfo;
55
import org.netbeans.api.java.source.CompilationInfo;
Lines 65-70 Link Here
65
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
67
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
66
import org.netbeans.spi.editor.hints.HintsController;
68
import org.netbeans.spi.editor.hints.HintsController;
67
import org.netbeans.spi.editor.hints.Severity;
69
import org.netbeans.spi.editor.hints.Severity;
70
import org.netbeans.spi.whitelist.support.WhiteListIndex;
68
import org.openide.filesystems.FileObject;
71
import org.openide.filesystems.FileObject;
69
72
70
/**
73
/**
Lines 96-124 Link Here
96
        if (whiteList == null) {
99
        if (whiteList == null) {
97
            return;
100
            return;
98
        }
101
        }
99
        final List<WhiteListScanner.Problem> problems = new LinkedList<WhiteListScanner.Problem>();
102
        final CompilationUnitTree cu = info.getCompilationUnit();
100
        final WhiteListScanner scanner = new WhiteListScanner(
103
        final Map<? extends Tree, ? extends WhiteListQuery.Result> problems = WhiteListIndex.getWhiteListViolations(
104
                cu,
105
                whiteList,
101
                info.getTrees(),
106
                info.getTrees(),
102
                whiteList,
107
                new Callable<Boolean>() {
103
                canceled);
108
                    @Override
104
        final CompilationUnitTree cu = info.getCompilationUnit();
109
                    public Boolean call() throws Exception {
105
        try {
110
                        return canceled.get();
106
            scanner.scan(cu, problems);
111
                    }
107
        } catch (WhiteListScanner.Cancel cancel) {
112
                });
113
        if (problems == null) {
114
            //Canceled
108
            return;
115
            return;
109
        }
116
        }
110
        final SourcePositions sp = info.getTrees().getSourcePositions();
117
        final SourcePositions sp = info.getTrees().getSourcePositions();
111
        final List<ErrorDescription> errors = new ArrayList<ErrorDescription>(problems.size());
118
        final List<ErrorDescription> errors = new ArrayList<ErrorDescription>(problems.size());
112
        for (WhiteListScanner.Problem problem : problems) {
119
        for (Map.Entry<? extends Tree, ? extends WhiteListQuery.Result> problem : problems.entrySet()) {
113
            if (canceled.get()) {
120
            if (canceled.get()) {
114
                return;
121
                return;
115
            }
122
            }
116
            final int start = (int) sp.getStartPosition(cu, problem.tree);
123
            final Tree tree = problem.getKey();
117
            final int end = (int) sp.getEndPosition(cu, problem.tree);
124
            final int start = (int) sp.getStartPosition(cu, tree);
125
            final int end = (int) sp.getEndPosition(cu, tree);
118
            if (start >= 0 && end >= 0) {
126
            if (start >= 0 && end >= 0) {
119
                errors.add(ErrorDescriptionFactory.createErrorDescription(
127
                errors.add(ErrorDescriptionFactory.createErrorDescription(
120
                        Severity.WARNING,
128
                        Severity.WARNING,
121
                        problem.description,
129
                        problem.getValue().getViolatedRuleDescription(),
122
                        file,
130
                        file,
123
                        start,
131
                        start,
124
                        end));
132
                        end));
(-)a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListScanner.java (-171 lines)
Lines 1-171 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.java.editor.whitelist;
43
44
import com.sun.source.tree.ClassTree;
45
import com.sun.source.tree.IdentifierTree;
46
import com.sun.source.tree.MemberSelectTree;
47
import com.sun.source.tree.MethodInvocationTree;
48
import com.sun.source.tree.MethodTree;
49
import com.sun.source.tree.NewClassTree;
50
import com.sun.source.tree.Tree;
51
import com.sun.source.util.TreePathScanner;
52
import com.sun.source.util.Trees;
53
import java.util.ArrayDeque;
54
import java.util.List;
55
import java.util.concurrent.atomic.AtomicBoolean;
56
import javax.lang.model.element.Element;
57
import javax.lang.model.element.ElementKind;
58
import org.netbeans.api.java.source.ElementHandle;
59
import org.netbeans.api.whitelist.WhiteListQuery;
60
import org.netbeans.api.whitelist.WhiteListQuery.WhiteList;
61
62
/**
63
 *
64
 * @author Tomas Zezula
65
 */
66
class WhiteListScanner extends TreePathScanner<Void, List<? super WhiteListScanner.Problem>> {
67
68
    private final Trees trees;
69
    private final AtomicBoolean cancel;
70
    private final WhiteList whiteList;
71
    private final ArrayDeque<MethodInvocationTree> methodInvocation;
72
73
    WhiteListScanner(
74
        final Trees trees,
75
        final WhiteList whiteList,
76
        final AtomicBoolean cancel) {
77
        this.trees = trees;
78
        this.whiteList = whiteList;
79
        this.cancel = cancel;
80
        methodInvocation = new ArrayDeque<MethodInvocationTree>();
81
    }
82
83
    @Override
84
    public Void visitMethod(MethodTree node, List<? super Problem> p) {
85
        checkCancel();
86
        return super.visitMethod(node, p);
87
    }
88
89
    @Override
90
    public Void visitClass(ClassTree node, List<? super Problem> p) {
91
        checkCancel();
92
        return super.visitClass(node, p);
93
    }
94
95
    @Override
96
    public Void visitIdentifier(IdentifierTree node, List<? super Problem> p) {
97
        handleNode(node,p);
98
        return super.visitIdentifier(node, p);
99
    }
100
101
    @Override
102
    public Void visitMemberSelect(MemberSelectTree node, List<? super Problem> p) {
103
        handleNode(node,p);
104
        return super.visitMemberSelect(node, p);
105
    }
106
107
    @Override
108
    public Void visitNewClass(NewClassTree node, List<? super Problem> p) {
109
        final Element e = trees.getElement(getCurrentPath());
110
        final WhiteListQuery.Result res;
111
        if (e != null && !(res=whiteList.check(ElementHandle.create(e),WhiteListQuery.Operation.USAGE)).isAllowed()) {
112
                p.add(new Problem(node,res.getViolatedRuleDescription()));
113
        }
114
        scan(node.getTypeArguments(), p);
115
        scan(node.getArguments(), p);
116
	scan(node.getClassBody(), p);
117
        return null;
118
    }
119
120
    @Override
121
    public Void visitMethodInvocation(MethodInvocationTree node, List<? super Problem> p) {
122
        methodInvocation.offerFirst(node);
123
        super.visitMethodInvocation(node, p);
124
        methodInvocation.removeFirst();
125
        return null;
126
    }
127
128
    private void handleNode(
129
            final Tree node,
130
            final List<? super Problem> p) {
131
        final Element e = trees.getElement(getCurrentPath());
132
        if (e == null) {
133
            return;
134
        }
135
        final ElementKind k = e.getKind();
136
        Tree toReport =  null;
137
        if (k.isClass() || k.isInterface()) {
138
            toReport=node;
139
        } else if ((k == ElementKind.METHOD || k == ElementKind.CONSTRUCTOR) &&
140
                !methodInvocation.isEmpty()) {
141
            toReport=methodInvocation.peekFirst();
142
        }
143
        final WhiteListQuery.Result res;
144
        if (toReport != null &&
145
            !(res=whiteList.check(ElementHandle.create(e),WhiteListQuery.Operation.USAGE)).isAllowed()) {
146
                p.add(new Problem(toReport,res.getViolatedRuleDescription()));
147
        }
148
    }
149
150
    private void checkCancel() {
151
        if (cancel.get()) {
152
            throw new Cancel();
153
        }
154
    }
155
156
    static final class Problem {
157
        final Tree tree;
158
        final String description;
159
160
        private Problem (
161
                final Tree tree,
162
                final String description) {
163
            this.tree = tree;
164
            this.description = description;
165
        }
166
    }
167
168
    static final class Cancel extends RuntimeException {
169
    }
170
171
}
(-)a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListTaskProvider.java (-111 / +53 lines)
Lines 41-48 Link Here
41
 */
41
 */
42
package org.netbeans.modules.java.editor.whitelist;
42
package org.netbeans.modules.java.editor.whitelist;
43
43
44
import java.io.File;
45
import java.io.IOException;
46
import java.net.URL;
44
import java.net.URL;
47
import java.util.ArrayList;
45
import java.util.ArrayList;
48
import java.util.Collections;
46
import java.util.Collections;
Lines 62-79 Link Here
62
import org.netbeans.api.project.Project;
60
import org.netbeans.api.project.Project;
63
import org.netbeans.api.project.ProjectUtils;
61
import org.netbeans.api.project.ProjectUtils;
64
import org.netbeans.api.project.SourceGroup;
62
import org.netbeans.api.project.SourceGroup;
65
import org.netbeans.modules.parsing.lucene.support.DocumentIndex;
66
import org.netbeans.modules.parsing.lucene.support.Index;
67
import org.netbeans.modules.parsing.lucene.support.IndexDocument;
68
import org.netbeans.modules.parsing.lucene.support.IndexManager;
69
import org.netbeans.modules.parsing.lucene.support.Queries.QueryKind;
70
import org.netbeans.spi.tasklist.PushTaskScanner;
63
import org.netbeans.spi.tasklist.PushTaskScanner;
71
import org.netbeans.spi.tasklist.Task;
64
import org.netbeans.spi.tasklist.Task;
72
import org.netbeans.spi.tasklist.TaskScanningScope;
65
import org.netbeans.spi.tasklist.TaskScanningScope;
66
import org.netbeans.spi.whitelist.support.WhiteListIndex;
67
import org.netbeans.spi.whitelist.support.WhiteListIndexEvent;
68
import org.netbeans.spi.whitelist.support.WhiteListIndexListener;
73
import org.openide.filesystems.FileObject;
69
import org.openide.filesystems.FileObject;
74
import org.openide.filesystems.FileUtil;
70
import org.openide.filesystems.FileUtil;
75
import org.openide.filesystems.URLMapper;
71
import org.openide.filesystems.URLMapper;
76
import org.openide.util.Exceptions;
77
import org.openide.util.NbBundle;
72
import org.openide.util.NbBundle;
78
import org.openide.util.RequestProcessor;
73
import org.openide.util.RequestProcessor;
79
import org.openide.util.TaskListener;
74
import org.openide.util.TaskListener;
Lines 109-136 Link Here
109
        super(Bundle.LBL_ProviderName(),
104
        super(Bundle.LBL_ProviderName(),
110
              Bundle.LBL_ProviderDescription(),
105
              Bundle.LBL_ProviderDescription(),
111
              null);
106
              null);
112
        INSTANCE = this;
107
        WhiteListIndex.getDefault().addWhiteListIndexListener(new WhiteListIndexListener() {
113
    }
108
            @Override
114
109
            public void indexChanged(WhiteListIndexEvent event) {
115
    @CheckForNull
110
                refresh(event.getRoot());
116
    static WhiteListTaskProvider getInstance() {
111
            }
117
        return INSTANCE;
112
        });
118
    }
119
120
    void refresh(final @NonNull URL root) {
121
        final FileObject rootFo = URLMapper.findFileObject(root);
122
        final Set<FileObject> files;
123
        final Callback callback;
124
        synchronized (this) {
125
            files = currentFiles;
126
            callback = currentCallback;
127
        }
128
        if (rootFo != null &&
129
            files != null &&
130
            files.contains(rootFo)) {
131
            assert callback != null;
132
            enqueue(new Work(rootFo, currentCallback));
133
        }
134
    }
113
    }
135
114
136
    @Override
115
    @Override
Lines 158-163 Link Here
158
        }
137
        }
159
    }
138
    }
160
139
140
    private void refresh(final @NonNull URL root) {
141
        assert root != null;
142
        final FileObject rootFo = URLMapper.findFileObject(root);
143
        final Set<FileObject> files;
144
        final Callback callback;
145
        synchronized (this) {
146
            files = currentFiles;
147
            callback = currentCallback;
148
        }
149
        if (rootFo != null &&
150
            files != null &&
151
            files.contains(rootFo)) {
152
            assert callback != null;
153
            enqueue(new Work(rootFo, currentCallback));
154
        }
155
    }
156
161
    private static void enqueue(Work w) {
157
    private static void enqueue(Work w) {
162
        synchronized (TASKS) {
158
        synchronized (TASKS) {
163
            final RequestProcessor.Task task = WORKER.post(w);
159
            final RequestProcessor.Task task = WORKER.post(w);
Lines 205-222 Link Here
205
    }
201
    }
206
202
207
    @CheckForNull
203
    @CheckForNull
208
    private static Map.Entry<FileObject,Task> createTask(
204
    private static Map.Entry<FileObject,Task> createTask(@NonNull final WhiteListIndex.Problem problem) {
209
            @NonNull final FileObject root,
205
        final FileObject file = problem.getFile();
210
            @NonNull final IndexDocument doc) {
211
        final FileObject file = root.getFileObject(doc.getPrimaryKey());
212
        if (file == null) {
206
        if (file == null) {
213
            return null;
207
            return null;
214
        }
208
        }
215
        final Task task = Task.create(
209
        final Task task = Task.create(
216
            file,
210
            file,
217
            "nb-whitelist-warning", //NOI18N
211
            "nb-whitelist-warning", //NOI18N
218
            doc.getValue(WhiteListIndexerPlugin.MSG),
212
            problem.getResult().getViolatedRuleDescription(),
219
            Integer.parseInt(doc.getValue(WhiteListIndexerPlugin.LINE)));
213
            problem.getLine());
220
        return new Map.Entry<FileObject, Task>() {
214
        return new Map.Entry<FileObject, Task>() {
221
            @Override
215
            @Override
222
            public FileObject getKey() {
216
            public FileObject getKey() {
Lines 233-252 Link Here
233
        };
227
        };
234
    }
228
    }
235
229
236
    @CheckForNull
237
    private static DocumentIndex getIndex(@NonNull final FileObject root) {
238
        try {
239
            final File whiteListFolder = WhiteListIndexerPlugin.getWhiteListDir(root.getURL());
240
            if (whiteListFolder != null) {
241
                final DocumentIndex index = IndexManager.createDocumentIndex(whiteListFolder);
242
                return index.getStatus() == Index.Status.VALID ? index : null;
243
            }
244
        } catch (IOException ioe) {
245
            Exceptions.printStackTrace(ioe);
246
        }
247
        return null;
248
    }
249
250
    private static void updateErrorsInRoot(
230
    private static void updateErrorsInRoot(
251
            @NonNull final Callback callback,
231
            @NonNull final Callback callback,
252
            @NonNull final FileObject root) {
232
            @NonNull final FileObject root) {
Lines 255-289 Link Here
255
        filesWithErrors.clear();
235
        filesWithErrors.clear();
256
        Set<FileObject> nueFilesWithErrors = new HashSet<FileObject>();
236
        Set<FileObject> nueFilesWithErrors = new HashSet<FileObject>();
257
        final Map<FileObject,List<Task>> filesToTasks = new HashMap<FileObject,List<Task>>();
237
        final Map<FileObject,List<Task>> filesToTasks = new HashMap<FileObject,List<Task>>();
258
        try {
238
        for (WhiteListIndex.Problem problem : WhiteListIndex.getDefault().getWhiteListViolations(root, null)) {
259
            IndexManager.readAccess(new IndexManager.Action<Void>() {
239
            final Map.Entry<FileObject,Task> task = createTask(problem);
260
                @Override
240
            if (task != null) {
261
                public Void run() throws IOException, InterruptedException {
241
                List<Task> tasks = filesToTasks.get(task.getKey());
262
                    final DocumentIndex index = getIndex(root);
242
                if (tasks == null) {
263
                    if (index != null) {
243
                    tasks = new ArrayList<Task>();
264
                        try {
244
                    filesToTasks.put(task.getKey(), tasks);
265
                            for (IndexDocument doc : index.findByPrimaryKey("", QueryKind.PREFIX)) {    //NOI18N
266
                                final Map.Entry<FileObject,Task> task = createTask(root, doc);
267
                                if (task != null) {
268
                                    List<Task> tasks = filesToTasks.get(task.getKey());
269
                                    if (tasks == null) {
270
                                        tasks = new ArrayList<Task>();
271
                                        filesToTasks.put(task.getKey(), tasks);
272
                                    }
273
                                    tasks.add(task.getValue());
274
                                }
275
                            }
276
                        } finally {
277
                            index.close();
278
                        }
279
                    }
280
                    return null;
281
                }
245
                }
282
            });
246
                tasks.add(task.getValue());
283
        } catch (IOException e) {
247
            }
284
            Exceptions.printStackTrace(e);
285
        } catch (InterruptedException e) {
286
            Exceptions.printStackTrace(e);
287
        }
248
        }
288
        for (Map.Entry<FileObject,List<Task>> e : filesToTasks.entrySet()) {
249
        for (Map.Entry<FileObject,List<Task>> e : filesToTasks.entrySet()) {
289
            LOG.log(Level.FINE, "Setting {1} for {0}\n",
250
            LOG.log(Level.FINE, "Setting {1} for {0}\n",
Lines 304-343 Link Here
304
        @NonNull final Callback callback,
265
        @NonNull final Callback callback,
305
        @NonNull final FileObject root,
266
        @NonNull final FileObject root,
306
        @NonNull final FileObject file) {
267
        @NonNull final FileObject file) {
307
        try {
268
        final List<Task> tasks = new ArrayList<Task>();
308
            IndexManager.readAccess(new IndexManager.Action<Void>(){
269
        for (WhiteListIndex.Problem problem : WhiteListIndex.getDefault().getWhiteListViolations(root, file)) {
309
                @Override
270
            final Map.Entry<FileObject,Task> task = createTask(problem);
310
                public Void run() throws IOException, InterruptedException {
271
            if (task != null) {
311
                    final List<Task> tasks = new ArrayList<Task>();
272
                tasks.add(task.getValue());
312
                    final DocumentIndex index = getIndex(root);
273
            }
313
                    if (index != null) {
314
                        try {
315
                            for (IndexDocument doc : index.findByPrimaryKey(FileUtil.getRelativePath(root, file), QueryKind.PREFIX)) {
316
                                final Map.Entry<FileObject,Task> task = createTask(root, doc);
317
                                if (task != null) {
318
                                    tasks.add(task.getValue());
319
                                }
320
                            }
321
                        } finally {
322
                            index.close();
323
                        }
324
                    }
325
                    Set<FileObject> filesWithErrors = getFilesWithAttachedErrors(root);
326
                    if (tasks.isEmpty()) {
327
                        filesWithErrors.remove(file);
328
                    } else {
329
                        filesWithErrors.add(file);
330
                    }
331
                    LOG.log(Level.FINE, "setting {1} for {0}", new Object[]{file, tasks});
332
                    callback.setTasks(file, tasks);
333
                    return null;
334
                }
335
            });
336
        } catch (IOException e) {
337
            Exceptions.printStackTrace(e);
338
        } catch (InterruptedException e) {
339
            Exceptions.printStackTrace(e);
340
        }
274
        }
275
        final Set<FileObject> filesWithErrors = getFilesWithAttachedErrors(root);
276
        if (tasks.isEmpty()) {
277
            filesWithErrors.remove(file);
278
        } else {
279
            filesWithErrors.add(file);
280
        }
281
        LOG.log(Level.FINE, "setting {1} for {0}", new Object[]{file, tasks});
282
        callback.setTasks(file, tasks);
341
    }
283
    }
342
284
343
    private static final class Work implements Runnable {
285
    private static final class Work implements Runnable {
(-)a/java.preprocessorbridge/nbproject/project.xml (+1 lines)
Lines 70-75 Link Here
70
                <friend>org.netbeans.modules.scala.editing</friend>
70
                <friend>org.netbeans.modules.scala.editing</friend>
71
                <friend>org.netbeans.modules.scala.editor</friend>
71
                <friend>org.netbeans.modules.scala.editor</friend>
72
                <friend>org.netbeans.modules.web.core.syntax</friend>
72
                <friend>org.netbeans.modules.web.core.syntax</friend>
73
                <friend>org.netbeans.modules.whitelist</friend>
73
                <package>org.netbeans.modules.java.preprocessorbridge.api</package>
74
                <package>org.netbeans.modules.java.preprocessorbridge.api</package>
74
                <package>org.netbeans.modules.java.preprocessorbridge.spi</package>
75
                <package>org.netbeans.modules.java.preprocessorbridge.spi</package>
75
            </friend-packages>
76
            </friend-packages>
(-)a/parsing.lucene/nbproject/project.xml (-1 / +1 lines)
Lines 56-65 Link Here
56
                </test-type>
56
                </test-type>
57
            </test-dependencies>
57
            </test-dependencies>
58
            <friend-packages>
58
            <friend-packages>
59
                <friend>org.netbeans.modules.java.editor</friend>
60
                <friend>org.netbeans.modules.java.source</friend>
59
                <friend>org.netbeans.modules.java.source</friend>
61
                <friend>org.netbeans.modules.java.sourceui</friend>
60
                <friend>org.netbeans.modules.java.sourceui</friend>
62
                <friend>org.netbeans.modules.parsing.api</friend>
61
                <friend>org.netbeans.modules.parsing.api</friend>
62
                <friend>org.netbeans.modules.whitelist</friend>
63
                <package>org.netbeans.modules.parsing.lucene.support</package>
63
                <package>org.netbeans.modules.parsing.lucene.support</package>
64
            </friend-packages>
64
            </friend-packages>
65
        </data>
65
        </data>
(-)a/whitelist/apichanges.xml (+17 lines)
Lines 75-80 Link Here
75
<!-- ACTUAL CHANGES BEGIN HERE: -->
75
<!-- ACTUAL CHANGES BEGIN HERE: -->
76
76
77
<changes>
77
<changes>
78
        <change id="WhiteListIndex">
79
            <api name="whitelist"/>
80
            <summary>Added WhiteListQuery to check violations of runtime restrictions</summary>
81
            <version major="1" minor="2"/>
82
            <date day="14" month="9" year="2011"/>
83
            <author login="tzezula"/>
84
            <compatibility addition="yes" modification="no" semantic="compatible" source="compatible" binary="compatible"/>
85
            <description>
86
                <p>
87
                    Added WhiteListIndex to provide persistent index of the white list violations.
88
                </p>
89
            </description>
90
            <class package="org.netbeans.api.whitelist.support" name="WhiteListIndex"/>
91
            <class package="org.netbeans.spi.whitelist.support" name="WhiteListIndexListener"/>
92
            <class package="org.netbeans.spi.whitelist.support" name="WhiteListIndexEvent"/>
93
            <issue number="202063"/>
94
        </change>
78
        <change id="WhiteListQuery">
95
        <change id="WhiteListQuery">
79
            <api name="whitelist"/>
96
            <api name="whitelist"/>
80
            <summary>Added WhiteListQuery to check violations of runtime restrictions</summary>
97
            <summary>Added WhiteListQuery to check violations of runtime restrictions</summary>
(-)a/whitelist/manifest.mf (-1 / +1 lines)
Lines 2-6 Link Here
2
OpenIDE-Module: org.netbeans.modules.whitelist
2
OpenIDE-Module: org.netbeans.modules.whitelist
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/whitelist/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/whitelist/Bundle.properties
4
OpenIDE-Module-Layer: org/netbeans/modules/whitelist/resources/layer.xml
4
OpenIDE-Module-Layer: org/netbeans/modules/whitelist/resources/layer.xml
5
OpenIDE-Module-Specification-Version: 1.1
5
OpenIDE-Module-Specification-Version: 1.2
6
6
(-)a/whitelist/nbproject/project.xml (+44 lines)
Lines 15-20 Link Here
15
                    </run-dependency>
15
                    </run-dependency>
16
                </dependency>
16
                </dependency>
17
                <dependency>
17
                <dependency>
18
                    <code-name-base>org.netbeans.api.java.classpath</code-name-base>
19
                    <build-prerequisite/>
20
                    <compile-dependency/>
21
                    <run-dependency>
22
                        <release-version>1</release-version>
23
                        <specification-version>1.30</specification-version>
24
                    </run-dependency>
25
                </dependency>
26
                <dependency>
18
                    <code-name-base>org.netbeans.libs.javacapi</code-name-base>
27
                    <code-name-base>org.netbeans.libs.javacapi</code-name-base>
19
                    <build-prerequisite/>
28
                    <build-prerequisite/>
20
                    <compile-dependency/>
29
                    <compile-dependency/>
Lines 23-28 Link Here
23
                    </run-dependency>
32
                    </run-dependency>
24
                </dependency>
33
                </dependency>
25
                <dependency>
34
                <dependency>
35
                    <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
36
                    <build-prerequisite/>
37
                    <compile-dependency/>
38
                    <run-dependency>
39
                        <release-version>1</release-version>
40
                        <specification-version>1.23</specification-version>
41
                    </run-dependency>
42
                </dependency>
43
                <dependency>
44
                    <code-name-base>org.netbeans.modules.java.preprocessorbridge</code-name-base>
45
                    <build-prerequisite/>
46
                    <compile-dependency/>
47
                    <run-dependency>
48
                        <specification-version>1.22</specification-version>
49
                    </run-dependency>
50
                </dependency>
51
                <dependency>
26
                    <code-name-base>org.netbeans.modules.java.source</code-name-base>
52
                    <code-name-base>org.netbeans.modules.java.source</code-name-base>
27
                    <build-prerequisite/>
53
                    <build-prerequisite/>
28
                    <compile-dependency/>
54
                    <compile-dependency/>
Lines 31-36 Link Here
31
                    </run-dependency>
57
                    </run-dependency>
32
                </dependency>
58
                </dependency>
33
                <dependency>
59
                <dependency>
60
                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
61
                    <build-prerequisite/>
62
                    <compile-dependency/>
63
                    <run-dependency>
64
                        <release-version>1</release-version>
65
                        <specification-version>1.43</specification-version>
66
                    </run-dependency>
67
                </dependency>
68
                <dependency>
69
                    <code-name-base>org.netbeans.modules.parsing.lucene</code-name-base>
70
                    <build-prerequisite/>
71
                    <compile-dependency/>
72
                    <run-dependency>
73
                        <release-version>2</release-version>
74
                        <specification-version>2.3</specification-version>
75
                    </run-dependency>
76
                </dependency>
77
                <dependency>
34
                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
78
                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
35
                    <build-prerequisite/>
79
                    <build-prerequisite/>
36
                    <compile-dependency/>
80
                    <compile-dependency/>
(-)a/whitelist/src/org/netbeans/modules/whitelist/index/WhiteListIndexAccessor.java (+85 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.whitelist.index;
43
44
import java.net.URL;
45
import org.netbeans.api.annotations.common.NonNull;
46
import org.netbeans.api.whitelist.WhiteListQuery;
47
import org.netbeans.spi.whitelist.support.WhiteListIndex;
48
import org.openide.filesystems.FileObject;
49
import org.openide.util.Exceptions;
50
import org.openide.util.Parameters;
51
52
/**
53
 *
54
 * @author Tomas Zezula
55
 */
56
public abstract class WhiteListIndexAccessor {
57
58
    private static volatile WhiteListIndexAccessor instance;
59
60
    @NonNull
61
    public static synchronized WhiteListIndexAccessor getInstance() {
62
        if (instance == null) {
63
            try {
64
                Class.forName(WhiteListIndex.class.getName(), true, WhiteListIndexAccessor.class.getClassLoader());
65
                assert instance != null;
66
            } catch (ClassNotFoundException ex) {
67
                Exceptions.printStackTrace(ex);
68
            }
69
        }
70
        return instance;
71
72
    }
73
74
    public static void setInstance(@NonNull final WhiteListIndexAccessor _instance) {
75
        Parameters.notNull("_instance", _instance); //NOI18N
76
        instance = _instance;
77
    }
78
79
    public abstract void refresh(@NonNull URL root);
80
    public abstract WhiteListIndex.Problem createProblem(
81
            @NonNull WhiteListQuery.Result result,
82
            @NonNull FileObject root,
83
            @NonNull String key,
84
            int line);
85
}
(-)a/java.editor/src/org/netbeans/modules/java/editor/whitelist/WhiteListIndexerPlugin.java (-21 / +73 lines)
Lines 39-67 Link Here
39
 *
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
41
 */
42
package org.netbeans.modules.java.editor.whitelist;
42
package org.netbeans.modules.whitelist.index;
43
43
44
import com.sun.source.tree.CompilationUnitTree;
44
import com.sun.source.tree.CompilationUnitTree;
45
import com.sun.source.tree.LineMap;
45
import com.sun.source.tree.LineMap;
46
import com.sun.source.tree.Tree;
46
import com.sun.source.util.SourcePositions;
47
import com.sun.source.util.SourcePositions;
47
import com.sun.source.util.Trees;
48
import com.sun.source.util.Trees;
48
import java.io.File;
49
import java.io.File;
49
import java.io.IOException;
50
import java.io.IOException;
50
import java.net.URL;
51
import java.net.URL;
51
import java.util.LinkedList;
52
import java.util.ArrayList;
53
import java.util.Collection;
52
import java.util.List;
54
import java.util.List;
53
import java.util.Map;
55
import java.util.Map;
54
import java.util.concurrent.ConcurrentHashMap;
56
import java.util.concurrent.ConcurrentHashMap;
55
import java.util.concurrent.atomic.AtomicBoolean;
56
import org.netbeans.api.annotations.common.CheckForNull;
57
import org.netbeans.api.annotations.common.CheckForNull;
57
import org.netbeans.api.annotations.common.NonNull;
58
import org.netbeans.api.annotations.common.NonNull;
59
import org.netbeans.api.annotations.common.NullAllowed;
58
import org.netbeans.api.editor.mimelookup.MimeRegistration;
60
import org.netbeans.api.editor.mimelookup.MimeRegistration;
59
import org.netbeans.api.whitelist.WhiteListQuery;
61
import org.netbeans.api.whitelist.WhiteListQuery;
60
import org.netbeans.modules.java.preprocessorbridge.spi.JavaIndexerPlugin;
62
import org.netbeans.modules.java.preprocessorbridge.spi.JavaIndexerPlugin;
61
import org.netbeans.modules.parsing.lucene.support.DocumentIndex;
63
import org.netbeans.modules.parsing.lucene.support.DocumentIndex;
64
import org.netbeans.modules.parsing.lucene.support.Index;
62
import org.netbeans.modules.parsing.lucene.support.IndexDocument;
65
import org.netbeans.modules.parsing.lucene.support.IndexDocument;
63
import org.netbeans.modules.parsing.lucene.support.IndexManager;
66
import org.netbeans.modules.parsing.lucene.support.IndexManager;
67
import org.netbeans.modules.parsing.lucene.support.Queries.QueryKind;
64
import org.netbeans.modules.parsing.spi.indexing.Indexable;
68
import org.netbeans.modules.parsing.spi.indexing.Indexable;
69
import org.netbeans.spi.whitelist.support.WhiteListIndex;
65
import org.openide.filesystems.FileObject;
70
import org.openide.filesystems.FileObject;
66
import org.openide.filesystems.FileUtil;
71
import org.openide.filesystems.FileUtil;
67
import org.openide.filesystems.URLMapper;
72
import org.openide.filesystems.URLMapper;
Lines 75-82 Link Here
75
public class WhiteListIndexerPlugin implements JavaIndexerPlugin {
80
public class WhiteListIndexerPlugin implements JavaIndexerPlugin {
76
81
77
    private static final String WHITE_LIST_INDEX = "whitelist"; //NOI18N
82
    private static final String WHITE_LIST_INDEX = "whitelist"; //NOI18N
78
    static final String MSG = "msg";    //NOI18N
83
    private static final String MSG = "msg";    //NOI18N
79
    static final String LINE = "line";  //NOI18N
84
    private static final String NAME = "name";  //NOI18N
85
    private static final String LINE = "line";  //NOI18N
80
    private static Map<URL,File> roots2whiteListDirs = new ConcurrentHashMap<URL, File>();
86
    private static Map<URL,File> roots2whiteListDirs = new ConcurrentHashMap<URL, File>();
81
87
82
    private final URL root;
88
    private final URL root;
Lines 104-123 Link Here
104
            @NonNull final Lookup services) {
110
            @NonNull final Lookup services) {
105
        final Trees trees = services.lookup(Trees.class);
111
        final Trees trees = services.lookup(Trees.class);
106
        assert trees != null;
112
        assert trees != null;
107
        final WhiteListScanner scanner = new WhiteListScanner(
113
        final Map<? extends Tree, ? extends WhiteListQuery.Result> problems = WhiteListIndex.getWhiteListViolations(toProcess, whiteList, trees, null);
108
                trees,
114
        assert problems != null;
109
                whiteList,
110
                new AtomicBoolean());
111
        final List<WhiteListScanner.Problem> problems = new LinkedList<WhiteListScanner.Problem>();
112
        scanner.scan(toProcess,problems);
113
        final LineMap lm = toProcess.getLineMap();
115
        final LineMap lm = toProcess.getLineMap();
114
        final SourcePositions sp = trees.getSourcePositions();
116
        final SourcePositions sp = trees.getSourcePositions();
115
        for (WhiteListScanner.Problem p : problems) {
117
        for (Map.Entry<? extends Tree, ? extends WhiteListQuery.Result> p : problems.entrySet()) {
116
            final int start = (int) sp.getStartPosition(toProcess, p.tree);
118
            final int start = (int) sp.getStartPosition(toProcess, p.getKey());
117
            int ln;
119
            int ln;
118
            if (start>=0 && (ln=(int)lm.getLineNumber(start))>=0) {
120
            if (start>=0 && (ln=(int)lm.getLineNumber(start))>=0) {
119
                final IndexDocument doc = IndexManager.createDocument(indexable.getRelativePath());
121
                final IndexDocument doc = IndexManager.createDocument(indexable.getRelativePath());
120
                doc.addPair(MSG, p.description, false, true);
122
                doc.addPair(MSG, p.getValue().getViolatedRuleDescription(), false, true);
121
                doc.addPair(LINE, Integer.toString(ln), false, true);
123
                doc.addPair(LINE, Integer.toString(ln), false, true);
122
                index.addDocument(doc);
124
                index.addDocument(doc);
123
            }
125
            }
Lines 134-143 Link Here
134
        try {
136
        try {
135
            index.store(true);
137
            index.store(true);
136
            roots2whiteListDirs.put(root, whiteListDir);
138
            roots2whiteListDirs.put(root, whiteListDir);
137
            final WhiteListTaskProvider tp = WhiteListTaskProvider.getInstance();
139
            WhiteListIndexAccessor.getInstance().refresh(root);
138
            if (tp != null) {
139
                tp.refresh(root);
140
            }
141
        } catch (IOException ex) {
140
        } catch (IOException ex) {
142
            Exceptions.printStackTrace(ex);
141
            Exceptions.printStackTrace(ex);
143
        } finally {
142
        } finally {
Lines 150-157 Link Here
150
    }
149
    }
151
150
152
    @CheckForNull
151
    @CheckForNull
153
    static File getWhiteListDir(@NonNull final URL root) {
152
    private static DocumentIndex getIndex(@NonNull final FileObject root) {
154
        return roots2whiteListDirs.get(root);
153
        try {
154
            final File whiteListFolder = roots2whiteListDirs.get(root.getURL());
155
            if (whiteListFolder != null) {
156
                final DocumentIndex index = IndexManager.createDocumentIndex(whiteListFolder);
157
                return index.getStatus() == Index.Status.VALID ? index : null;
158
            }
159
        } catch (IOException ioe) {
160
            Exceptions.printStackTrace(ioe);
161
        }
162
        return null;
163
    }
164
165
    @NonNull
166
    public static Collection<? extends WhiteListIndex.Problem> getWhiteListViolations(
167
            @NonNull final FileObject root,
168
            @NullAllowed final FileObject resource) {
169
        final List<WhiteListIndex.Problem> result = new ArrayList<WhiteListIndex.Problem>();
170
        try {
171
            IndexManager.readAccess(new IndexManager.Action<Void>() {
172
                @Override
173
                public Void run() throws IOException, InterruptedException {
174
                    final DocumentIndex index = getIndex(root);
175
                    if (index != null) {
176
                        try {
177
                            for (IndexDocument doc : index.findByPrimaryKey(
178
                                    resource == null ? "" : FileUtil.getRelativePath(root,resource),    //NOI18N
179
                                    QueryKind.PREFIX)) {
180
                                try {
181
                                    final String key = doc.getPrimaryKey();
182
                                    String wlName = doc.getValue(NAME);
183
                                    if (wlName == null) {
184
                                        wlName = "";    //NOI18N
185
                                    }
186
                                    final String wlDesc = doc.getValue(MSG);
187
                                    final int line = Integer.parseInt(doc.getValue(LINE));
188
                                    final WhiteListQuery.Result wr = new WhiteListQuery.Result(false, wlName, wlDesc);
189
                                    result.add(WhiteListIndexAccessor.getInstance().createProblem(wr, root, key, line));
190
                                } catch (ArithmeticException ae) {
191
                                    Exceptions.printStackTrace(ae);
192
                                }
193
                            }
194
                        } finally {
195
                            index.close();
196
                        }
197
                    }
198
                    return null;
199
                }
200
            });
201
        } catch (IOException e) {
202
            Exceptions.printStackTrace(e);
203
        } catch (InterruptedException e) {
204
            Exceptions.printStackTrace(e);
205
        }
206
        return result;
155
    }
207
    }
156
208
157
    @MimeRegistration(mimeType="text/x-java",service=JavaIndexerPlugin.Factory.class)
209
    @MimeRegistration(mimeType="text/x-java",service=JavaIndexerPlugin.Factory.class)
Lines 159-165 Link Here
159
        @Override
211
        @Override
160
        public JavaIndexerPlugin create(final URL root, final FileObject cacheFolder) {
212
        public JavaIndexerPlugin create(final URL root, final FileObject cacheFolder) {
161
            try {
213
            try {
162
                File whiteListDir = getWhiteListDir(root);
214
                File whiteListDir = roots2whiteListDirs.get(root);
163
                if (whiteListDir == null) {
215
                if (whiteListDir == null) {
164
                    //First time
216
                    //First time
165
                    final FileObject whiteListFolder = FileUtil.createFolder(cacheFolder, WHITE_LIST_INDEX);
217
                    final FileObject whiteListFolder = FileUtil.createFolder(cacheFolder, WHITE_LIST_INDEX);
(-)a/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndex.java (+358 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.whitelist.support;
43
44
import com.sun.source.tree.ClassTree;
45
import com.sun.source.tree.CompilationUnitTree;
46
import com.sun.source.tree.IdentifierTree;
47
import com.sun.source.tree.MemberSelectTree;
48
import com.sun.source.tree.MethodInvocationTree;
49
import com.sun.source.tree.MethodTree;
50
import com.sun.source.tree.NewClassTree;
51
import com.sun.source.tree.Tree;
52
import com.sun.source.util.TreePathScanner;
53
import com.sun.source.util.Trees;
54
import java.net.URL;
55
import java.util.ArrayDeque;
56
import java.util.Collection;
57
import java.util.HashMap;
58
import java.util.List;
59
import java.util.Map;
60
import java.util.concurrent.Callable;
61
import java.util.concurrent.CopyOnWriteArrayList;
62
import javax.lang.model.element.Element;
63
import javax.lang.model.element.ElementKind;
64
import org.netbeans.api.annotations.common.CheckForNull;
65
import org.netbeans.api.annotations.common.NonNull;
66
import org.netbeans.api.annotations.common.NullAllowed;
67
import org.netbeans.api.java.source.ElementHandle;
68
import org.netbeans.api.whitelist.WhiteListQuery;
69
import org.netbeans.api.whitelist.WhiteListQuery.Result;
70
import org.netbeans.api.whitelist.WhiteListQuery.WhiteList;
71
import org.netbeans.modules.whitelist.index.WhiteListIndexAccessor;
72
import org.netbeans.modules.whitelist.index.WhiteListIndexerPlugin;
73
import org.openide.filesystems.FileObject;
74
import org.openide.filesystems.FileUtil;
75
import org.openide.util.Exceptions;
76
import org.openide.util.Parameters;
77
78
/**
79
 * A persistent index of white list violations.
80
 * @author Tomas Zezula
81
 * @since 1.2
82
 */
83
public final class WhiteListIndex {
84
85
    static {
86
        WhiteListIndexAccessor.setInstance(new WhiteListIndexAccessorImpl());
87
    }
88
89
    private static WhiteListIndex instance;
90
    private final List<WhiteListIndexListener> listeners = new CopyOnWriteArrayList<WhiteListIndexListener>();
91
92
    private WhiteListIndex() {}
93
94
    /**
95
     * Returns the white list violations for given root or file.
96
     * @param root the root to get white list violations for
97
     * @param file the file to restrict the white list violation search or null
98
     * @return a {@link Collection} of {@link Problem}s
99
     * @throws IllegalArgumentException in case when file is not under the root or it's not a valid file
100
     * @throws UnsupportedOperationException when the index is not supported by the IDE
101
     */
102
    @NonNull
103
    public Collection<? extends Problem> getWhiteListViolations(
104
            @NonNull final FileObject root,
105
            @NullAllowed final FileObject file) throws IllegalArgumentException, UnsupportedOperationException {
106
        Parameters.notNull("scope", root); //NOI18N
107
        if (file != null && !(root.equals(file) || FileUtil.isParentOf(root, file))) {
108
            throw new IllegalArgumentException(
109
                    "The file: " + //NOI18N
110
                    FileUtil.getFileDisplayName(file) +
111
                    " has to be inside the root: " + //NOI18N
112
                    FileUtil.getFileDisplayName(root));
113
        }
114
        if (file != null && !file.isData()) {
115
            throw new IllegalArgumentException(
116
                    "The file: " + //NOI18N
117
                    FileUtil.getFileDisplayName(file) +
118
                    " has to be file.");    //NOI18N
119
        }
120
        return WhiteListIndexerPlugin.getWhiteListViolations(root,file);
121
    }
122
123
    /**
124
     * Adds {@link WhiteListIndexListener}.
125
     * The listener is notified when the white list index is changed.
126
     * @param listener the listener to be added
127
     */
128
    public void addWhiteListIndexListener(@NonNull final WhiteListIndexListener listener) {
129
        Parameters.notNull("listener", listener);   //NOI18N
130
        listeners.add(listener);
131
    }
132
133
    /**
134
     * Removes {@link WhiteListIndexListener}.
135
     * @param listener the listener to be removed
136
     */
137
    public void removeWhiteListIndexListener(@NonNull final WhiteListIndexListener listener) {
138
        Parameters.notNull("listener", listener);   //NOI18N
139
        listeners.remove(listener);
140
    }
141
142
    /**
143
     * Utility method to check the given {@link CompilationUnitTree} for white list violations.
144
     * @param unit the {@link CompilationUnitTree} to be analyzed
145
     * @param whitelist the {@link WhiteList} to use to check the violations
146
     * @param trees the {@link Trees} service
147
     * @param cancel the cancel request. If the {@link Callable} returns true the check is canceled
148
     * and null is returned.
149
     * @return a {@link Map} of {@link Tree}s with attached white list violations or null when the
150
     * scan was canceled.
151
     */
152
    @CheckForNull
153
    public static Map<? extends Tree, ? extends WhiteListQuery.Result> getWhiteListViolations(
154
            @NonNull final CompilationUnitTree unit,
155
            @NonNull final WhiteListQuery.WhiteList whitelist,
156
            @NonNull final Trees trees,
157
            @NullAllowed final Callable<Boolean> cancel) {
158
        Parameters.notNull("tree", unit);           //NOI18N
159
        Parameters.notNull("whitelist", whitelist); //NOI18N
160
        Parameters.notNull("trees", trees);         //NOI18N
161
        final Map<Tree,WhiteListQuery.Result> result = new HashMap<Tree, Result>();
162
        final WhiteListScanner scanner = new WhiteListScanner(trees, whitelist, cancel);
163
        try {
164
            scanner.scan(unit, result);
165
            return result;
166
        } catch (WhiteListScanner.Cancel ce) {
167
            return null;
168
        }
169
    }
170
171
    /**
172
     * Returns an instance of {@link WhiteListIndex}
173
     * @return the instance of {@link WhiteListIndex}
174
     */
175
    public static synchronized WhiteListIndex getDefault() {
176
        if (instance == null) {
177
            instance = new WhiteListIndex();
178
        }
179
        return instance;
180
    }
181
182
183
    /**
184
     * Represent a white list violation
185
     */
186
    public static final class Problem {
187
188
        private final WhiteListQuery.Result result;
189
        private final FileObject root;
190
        private final String relPath;
191
        private final int line;
192
193
        private Problem (
194
                @NonNull final WhiteListQuery.Result result,
195
                @NonNull final FileObject root,
196
                @NonNull final String relPath,
197
                final int line) {
198
            Parameters.notNull("result", result);   //NOI18N
199
            Parameters.notNull("root", root);   //NOI18N
200
            Parameters.notNull("relPath", relPath); //NOI18N
201
            this.result = result;
202
            this.root = root;
203
            this.relPath = relPath;
204
            this.line = line;
205
        }
206
207
        /**
208
         * Returns {@link WhiteListQuery.Result} describing the
209
         * white list violation.
210
         * @return the {@link WhiteListQuery.Result}
211
         */
212
        @NonNull
213
        public WhiteListQuery.Result getResult() {
214
            return result;
215
        }
216
217
        /**
218
         * Returns the file in which the white list violation occured.
219
         * @return the {@link FileObject}
220
         */
221
        @CheckForNull
222
        public FileObject getFile() {
223
            return root.getFileObject(relPath);
224
        }
225
226
        /**
227
         * Returns the line number of white list violation.
228
         * @return the line number
229
         */
230
        public int getLine() {
231
            return line;
232
        }
233
    }
234
235
    //<editor-fold defaultstate="collapsed" desc="Private implementation">
236
    private void fireIndexChange(final URL root) {
237
        final WhiteListIndexEvent event = new WhiteListIndexEvent(this, root);
238
        for (WhiteListIndexListener l : listeners) {
239
            l.indexChanged(event);
240
        }
241
    }
242
243
    private static final class WhiteListIndexAccessorImpl extends WhiteListIndexAccessor {
244
        @Override
245
        public void refresh(@NonNull URL root) {
246
            WhiteListIndex.getDefault().fireIndexChange(root);
247
        }
248
249
        @Override
250
        @NonNull
251
        public Problem createProblem(
252
                @NonNull final Result result,
253
                @NonNull final FileObject root,
254
                @NonNull final String key,
255
                int line) {
256
            return new Problem(result, root, key, line);
257
        }
258
    }
259
260
    private static class WhiteListScanner extends TreePathScanner<Void, Map<Tree,WhiteListQuery.Result>> {
261
262
        private final Trees trees;
263
        private final Callable<Boolean> cancel;
264
        private final WhiteList whiteList;
265
        private final ArrayDeque<MethodInvocationTree> methodInvocation;
266
267
        WhiteListScanner(
268
            final Trees trees,
269
            final WhiteList whiteList,
270
            final Callable<Boolean> cancel) {
271
            this.trees = trees;
272
            this.whiteList = whiteList;
273
            this.cancel = cancel;
274
            methodInvocation = new ArrayDeque<MethodInvocationTree>();
275
        }
276
277
        @Override
278
        public Void visitMethod(MethodTree node, Map<Tree,WhiteListQuery.Result> p) {
279
            checkCancel();
280
            return super.visitMethod(node, p);
281
        }
282
283
        @Override
284
        public Void visitClass(ClassTree node, Map<Tree,WhiteListQuery.Result> p) {
285
            checkCancel();
286
            return super.visitClass(node, p);
287
        }
288
289
        @Override
290
        public Void visitIdentifier(IdentifierTree node, Map<Tree,WhiteListQuery.Result> p) {
291
            handleNode(node,p);
292
            return super.visitIdentifier(node, p);
293
        }
294
295
        @Override
296
        public Void visitMemberSelect(MemberSelectTree node, Map<Tree,WhiteListQuery.Result> p) {
297
            handleNode(node,p);
298
            return super.visitMemberSelect(node, p);
299
        }
300
301
        @Override
302
        public Void visitNewClass(NewClassTree node, Map<Tree,WhiteListQuery.Result> p) {
303
            final Element e = trees.getElement(getCurrentPath());
304
            final WhiteListQuery.Result res;
305
            if (e != null && !(res=whiteList.check(ElementHandle.create(e),WhiteListQuery.Operation.USAGE)).isAllowed()) {
306
                p.put(node,res);
307
            }
308
            scan(node.getTypeArguments(), p);
309
            scan(node.getArguments(), p);
310
            scan(node.getClassBody(), p);
311
            return null;
312
        }
313
314
        @Override
315
        public Void visitMethodInvocation(MethodInvocationTree node, Map<Tree,WhiteListQuery.Result> p) {
316
            methodInvocation.offerFirst(node);
317
            super.visitMethodInvocation(node, p);
318
            methodInvocation.removeFirst();
319
            return null;
320
        }
321
322
        private void handleNode(
323
                final Tree node,
324
                final Map<Tree,WhiteListQuery.Result> p) {
325
            final Element e = trees.getElement(getCurrentPath());
326
            if (e == null) {
327
                return;
328
            }
329
            final ElementKind k = e.getKind();
330
            Tree toReport =  null;
331
            if (k.isClass() || k.isInterface()) {
332
                toReport=node;
333
            } else if ((k == ElementKind.METHOD || k == ElementKind.CONSTRUCTOR) &&
334
                    !methodInvocation.isEmpty()) {
335
                toReport=methodInvocation.peekFirst();
336
            }
337
            final WhiteListQuery.Result res;
338
            if (toReport != null &&
339
                !(res=whiteList.check(ElementHandle.create(e),WhiteListQuery.Operation.USAGE)).isAllowed()) {
340
                    p.put(toReport,res);
341
            }
342
        }
343
344
        private void checkCancel() {
345
            try {
346
                if (cancel != null && cancel.call() == Boolean.TRUE) {
347
                    throw new Cancel();
348
                }
349
            } catch (Exception ex) {
350
                Exceptions.printStackTrace(ex);
351
            }
352
        }
353
354
        static final class Cancel extends RuntimeException {
355
        }
356
    }
357
    //</editor-fold>
358
}
(-)a/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndexEvent.java (+73 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.whitelist.support;
43
44
import java.net.URL;
45
import java.util.EventObject;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.openide.util.Parameters;
48
49
/**
50
 * WhiteListIndexEvent is used to notify interested parties about
51
 * changes in persistent index of white list violations.
52
 * @author Tomas Zezula
53
 * @since 1.2
54
 */
55
public class WhiteListIndexEvent extends EventObject {
56
57
    private final URL root;
58
59
    WhiteListIndexEvent(@NonNull final Object source, @NonNull final URL root) {
60
        super(source);
61
        Parameters.notNull("root", root);   //NOI18N
62
        this.root = root;
63
    }
64
65
    /**
66
     * Returns a source root for which the index was changed.
67
     * @return the {@link URL} of the source root.
68
     */
69
    @NonNull
70
    public URL getRoot() {
71
        return root;
72
    }
73
}
(-)a/whitelist/src/org/netbeans/spi/whitelist/support/WhiteListIndexListener.java (+58 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.whitelist.support;
43
44
import java.util.EventListener;
45
import org.netbeans.api.annotations.common.NonNull;
46
47
/**
48
 * The listener interface for receiving {@link WhiteListIndex} events.
49
 * @author Tomas Zezula
50
 * @since 1.2
51
 */
52
public interface WhiteListIndexListener extends EventListener {
53
    /**
54
     * Invoked when the index for a source root changed
55
     * @param event the event providing the change details
56
     */
57
    void indexChanged (@NonNull WhiteListIndexEvent event);
58
}

Return to bug 202063