nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java
author sundar
Tue, 07 Jun 2016 19:13:26 +0530
changeset 38897 b92825d7708c
parent 34551 24317dc1c751
child 41426 aa60c8d89a92
permissions -rw-r--r--
8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too Reviewed-by: hannesw, mhaupt
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
     1
/*
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
     2
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
     4
 *
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    10
 *
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    15
 * accompanied this code).
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    16
 *
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    20
 *
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    23
 * questions.
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    24
 */
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    25
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    26
package jdk.nashorn.tools.jjs;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    27
38897
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
    28
import java.lang.reflect.Modifier;
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    29
import java.io.IOException;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    30
import java.io.File;
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    31
import java.net.URI;
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    32
import java.nio.file.DirectoryStream;
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    33
import java.nio.file.Files;
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    34
import java.nio.file.FileSystem;
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    35
import java.nio.file.FileSystems;
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    36
import java.nio.file.Path;
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    37
import java.util.ArrayList;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    38
import java.util.Collections;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    39
import java.util.EnumSet;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    40
import java.util.HashSet;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    41
import java.util.LinkedHashMap;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    42
import java.util.List;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    43
import java.util.Map;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    44
import java.util.Set;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    45
import java.util.stream.Collectors;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    46
import java.util.stream.Stream;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    47
import javax.tools.JavaCompiler;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    48
import javax.tools.JavaFileManager.Location;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    49
import javax.tools.JavaFileObject;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    50
import javax.tools.StandardJavaFileManager;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    51
import javax.tools.StandardLocation;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    52
import javax.tools.ToolProvider;
38897
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
    53
import jdk.nashorn.internal.runtime.Context;
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    54
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    55
/**
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    56
 * A helper class to compute properties of a Java package object. Properties of
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    57
 * package object are (simple) top level class names in that java package and
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    58
 * immediate subpackages of that package.
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    59
 */
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    60
final class PackagesHelper {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    61
    // JavaCompiler may be null on certain platforms (eg. JRE)
33334
1c629852b339 8139852: jjs interactive mode fails to work with security manager
sundar
parents: 32317
diff changeset
    62
    private static final JavaCompiler compiler;
1c629852b339 8139852: jjs interactive mode fails to work with security manager
sundar
parents: 32317
diff changeset
    63
    static {
1c629852b339 8139852: jjs interactive mode fails to work with security manager
sundar
parents: 32317
diff changeset
    64
        // Use javac only if security manager is not around!
1c629852b339 8139852: jjs interactive mode fails to work with security manager
sundar
parents: 32317
diff changeset
    65
        compiler = System.getSecurityManager() == null? ToolProvider.getSystemJavaCompiler() : null;
1c629852b339 8139852: jjs interactive mode fails to work with security manager
sundar
parents: 32317
diff changeset
    66
    }
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    67
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    68
    /**
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    69
     * Is javac available?
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    70
     *
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    71
     * @return true if javac is available
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    72
     */
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    73
    private static boolean isJavacAvailable() {
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    74
        return compiler != null;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    75
    }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    76
38897
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
    77
    private final Context context;
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    78
    private final StandardJavaFileManager fm;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    79
    private final Set<JavaFileObject.Kind> fileKinds;
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    80
    private final FileSystem jrtfs;
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    81
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    82
    /**
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    83
     * Construct a new PackagesHelper.
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    84
     *
38897
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
    85
     * @param context the current Nashorn Context
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    86
     */
38897
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
    87
    PackagesHelper(final Context context) throws IOException {
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
    88
        this.context = context;
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
    89
        final String classPath = context.getEnv()._classpath;
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    90
        if (isJavacAvailable()) {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    91
            fm = compiler.getStandardFileManager(null, null, null);
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    92
            fileKinds = EnumSet.of(JavaFileObject.Kind.CLASS);
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
    93
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    94
            if (classPath != null && !classPath.isEmpty()) {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    95
                fm.setLocation(StandardLocation.CLASS_PATH, getFiles(classPath));
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    96
            } else {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    97
                // no classpath set. Make sure that it is empty and not any default like "."
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    98
                fm.setLocation(StandardLocation.CLASS_PATH, Collections.<File>emptyList());
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
    99
            }
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   100
            jrtfs = null;
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   101
        } else {
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   102
            // javac is not available - directly use jrt fs
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   103
            // to support at least platform classes.
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   104
            fm = null;
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   105
            fileKinds = null;
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   106
            jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   107
        }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   108
    }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   109
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   110
    // LRU cache for java package properties lists
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   111
    private final LinkedHashMap<String, List<String>> propsCache =
32317
2b653e4e7d65 8134279: jjs should support multiple line input to complete incomplete code
sundar
parents: 32314
diff changeset
   112
        new LinkedHashMap<String, List<String>>(32, 0.75f, true) {
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   113
            private static final int CACHE_SIZE = 100;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   114
            private static final long serialVersionUID = 1;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   115
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   116
            @Override
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   117
            protected boolean removeEldestEntry(final Map.Entry<String, List<String>> eldest) {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   118
                return size() > CACHE_SIZE;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   119
            }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   120
        };
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   121
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   122
    /**
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   123
     * Return the list of properties of the given Java package or package prefix
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   124
     *
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   125
     * @param pkg Java package name or package prefix name
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   126
     * @return the list of properties of the given Java package or package prefix
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   127
     */
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   128
    List<String> getPackageProperties(final String pkg) {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   129
        // check the cache first
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   130
        if (propsCache.containsKey(pkg)) {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   131
            return propsCache.get(pkg);
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   132
        }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   133
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   134
        try {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   135
            // make sorted list of properties
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   136
            final List<String> props = new ArrayList<>(listPackage(pkg));
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   137
            Collections.sort(props);
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   138
            propsCache.put(pkg, props);
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   139
            return props;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   140
        } catch (final IOException exp) {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   141
            if (Main.DEBUG) {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   142
                exp.printStackTrace();
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   143
            }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   144
            return Collections.<String>emptyList();
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   145
        }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   146
    }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   147
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   148
    public void close() throws IOException {
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   149
        if (fm != null) {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   150
            fm.close();
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   151
        }
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   152
    }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   153
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   154
    private Set<String> listPackage(final String pkg) throws IOException {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   155
        final Set<String> props = new HashSet<>();
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   156
        if (fm != null) {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   157
            listPackage(StandardLocation.PLATFORM_CLASS_PATH, pkg, props);
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   158
            listPackage(StandardLocation.CLASS_PATH, pkg, props);
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   159
        } else if (jrtfs != null) {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   160
            // look for the /packages/<package_name> directory
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   161
            Path pkgDir = jrtfs.getPath("/packages/" + pkg);
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   162
            if (Files.exists(pkgDir)) {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   163
                String pkgSlashName = pkg.replace('.', '/');
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   164
                try (DirectoryStream<Path> ds = Files.newDirectoryStream(pkgDir)) {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   165
                    // it has module links under which this package occurs
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   166
                    for (Path mod : ds) {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   167
                        // get the package directory under /modules
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   168
                        Path pkgUnderMod = jrtfs.getPath(mod.toString() + "/" + pkgSlashName);
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   169
                        try (DirectoryStream<Path> ds2 = Files.newDirectoryStream(pkgUnderMod)) {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   170
                            for (Path p : ds2) {
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   171
                                String str = p.getFileName().toString();
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   172
                                // get rid of ".class", if any
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   173
                                if (str.endsWith(".class")) {
38897
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   174
                                    final String clsName = str.substring(0, str.length() - ".class".length());
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   175
                                    if (clsName.indexOf('$') == -1 && isClassAccessible(pkg + "." + clsName)) {
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   176
                                        props.add(str);
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   177
                                    }
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   178
                                } else if (isPackageAccessible(pkg + "." + str)) {
34551
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   179
                                    props.add(str);
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   180
                                }
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   181
                            }
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   182
                        }
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   183
                    }
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   184
                }
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   185
            }
24317dc1c751 8145186: jjs package completion should have a fallback when javac is not available
sundar
parents: 33334
diff changeset
   186
        }
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   187
        return props;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   188
    }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   189
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   190
    private void listPackage(final Location loc, final String pkg, final Set<String> props)
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   191
            throws IOException {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   192
        for (JavaFileObject file : fm.list(loc, pkg, fileKinds, true)) {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   193
            final String binaryName = fm.inferBinaryName(loc, file);
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   194
            // does not start with the given package prefix
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   195
            if (!binaryName.startsWith(pkg + ".")) {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   196
                continue;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   197
            }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   198
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   199
            final int nextDot = binaryName.indexOf('.', pkg.length() + 1);
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   200
            final int start = pkg.length() + 1;
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   201
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   202
            if (nextDot != -1) {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   203
                // subpackage - eg. "regex" for "java.util"
38897
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   204
                final String pkgName = binaryName.substring(start, nextDot);
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   205
                if (isPackageAccessible(binaryName.substring(0, nextDot))) {
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   206
                    props.add(binaryName.substring(start, nextDot));
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   207
                }
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   208
            } else {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   209
                // class - filter out nested, inner, anonymous, local classes.
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   210
                // Dynalink supported public nested classes as properties of
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   211
                // StaticClass object anyway. We don't want to expose those
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   212
                // "$" internal names as properties of package object.
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   213
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   214
                final String clsName = binaryName.substring(start);
38897
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   215
                if (clsName.indexOf('$') == -1 && isClassAccessible(binaryName)) {
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   216
                    props.add(clsName);
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   217
                }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   218
            }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   219
        }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   220
    }
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   221
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   222
    // return list of File objects for the given class path
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   223
    private static List<File> getFiles(final String classPath) {
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   224
        return Stream.of(classPath.split(File.pathSeparator))
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   225
                    .map(File::new)
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   226
                    .collect(Collectors.toList());
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   227
    }
38897
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   228
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   229
    private boolean isClassAccessible(final String className) {
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   230
        try {
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   231
            final Class<?> clz = context.findClass(className);
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   232
            return Modifier.isPublic(clz.getModifiers());
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   233
        } catch (final ClassNotFoundException cnfe) {
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   234
        }
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   235
        return false;
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   236
    }
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   237
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   238
    private boolean isPackageAccessible(final String pkgName) {
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   239
        try {
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   240
            Context.checkPackageAccess(pkgName);
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   241
            return true;
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   242
        } catch (final SecurityException se) {
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   243
            return false;
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   244
        }
b92825d7708c 8158922: jjs tab completion of Java classes shows package-private, "hidden" classes too
sundar
parents: 34551
diff changeset
   245
    }
32314
8f7d23d3b1ad 8134255: Implement tab-completion for java package prefixes and package names
sundar
parents:
diff changeset
   246
}