⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classreader.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
        } else if (checkClassFile && majorVersion == Target.MAX().majorVersion &&
                minorVersion > Target.MAX().minorVersion) {
            printCCF("found.later.version", Integer.toString(minorVersion));
        }
        indexPool();
        readClass(c);
    }

    /**
      * Is this the name of a zip file?
      */
    boolean isZip(String name) {
        return new File(name).isFile();
    }

    /**
      * An archive consists of a zipfile and a list of zip entries in
      *  that file.
      */
    static class Archive {
        ZipFile zdir;
        List entries;

        Archive(ZipFile zdir, List entries) {
            super();
            this.zdir = zdir;
            this.entries = entries;
        }
    }

    /**
      * A directory of zip files already opened.
      */
    Hashtable archives = Hashtable.make();

    /**
     * Open a new zip file directory.
     */
    Archive openArchive(String dirname) throws IOException {
        Archive archive = (ClassReader.Archive) archives.get(dirname);
        if (archive == null) {
            ZipFile zdir = new ZipFile(dirname);
            ListBuffer entries = new ListBuffer();
            for (java.util.Enumeration e = zdir.entries(); e.hasMoreElements();) {
                entries.append((ZipEntry) e.nextElement());
            }
            archive = new Archive(zdir, entries.toList());
            archives.put(dirname, archive);
        }
        return archive;
    }

    /**
      * Close the ClassReader, releasing resources.
      */
    public void close() {
        for (List dirnames = archives.keys(); dirnames.nonEmpty();
                dirnames = dirnames.tail) {
            Archive a = (ClassReader.Archive) archives.remove(dirnames.head);
            try {
                a.zdir.close();
            } catch (IOException e) {
            }
        }
    }

    /**
      * Define a new class given its name and owner.
      */
    public ClassSymbol defineClass(Name name, Symbol owner) {
        ClassSymbol c = new ClassSymbol(0, name, owner);
        c.completer = this;
        return c;
    }

    /**
      * Create a new toplevel or member class symbol with given name
      *  and owner and enter in `classes' unless already there.
      */
    public ClassSymbol enterClass(Name name, TypeSymbol owner) {
        Name flatname = TypeSymbol.formFlatName(name, owner);
        ClassSymbol c = (ClassSymbol) classes.get(flatname);
        if (c == null) {
            c = defineClass(name, owner);
            classes.put(flatname, c);
        } else if ((c.name != name || c.owner != owner) && owner.kind == TYP) {
            c.name = name;
            c.owner = owner;
            c.fullname = ClassSymbol.formFullName(name, owner);
        }
        return c;
    }

    /**
      * Create a new member or toplevel class symbol with given flat name
      *  and enter in `classes' unless already there.
      */
    public ClassSymbol enterClass(Name flatname) {
        ClassSymbol c = (ClassSymbol) classes.get(flatname);
        if (c == null) {
            Name packageName = Convert.packagePart(flatname);
            if (packageName == names.empty)
                packageName = names.emptyPackage;
            c = defineClass(Convert.shortName(flatname), enterPackage(packageName));
            classes.put(flatname, c);
        }
        return c;
    }

    /**
      * Completion for classes to be loaded. Before a class is loaded
      *  we make sure its enclosing class (if any) is loaded.
      */
    public void complete(Symbol sym) throws CompletionFailure {
        if (sym.kind == TYP) {
            ClassSymbol c = (ClassSymbol) sym;
            c.members_field = new Scope.ErrorScope(c);
            c.owner.complete();
            fillIn(c);
        } else if (sym.kind == PCK) {
            PackageSymbol p = (PackageSymbol) sym;
            fillIn(p);
        }
    }

    /**
      * We can only read a single class file at a time; this
      * flag keeps track of when we are currently reading a class
      * file.
      */
    private boolean filling = false;

    /**
     * Fill in definition of class `c' from corresponding class or
     *  source file.
     */
    private void fillIn(ClassSymbol c) {
        if (completionFailureName == c.fullname) {
            throw new CompletionFailure(c, "user-selected completion failure by class name");
        }
        currentOwner = c;
        FileEntry classfile = c.classfile;
        if (classfile != null) {
            try {
                assert ! filling;
                InputStream s = classfile.open();
                currentClassFileName = classfile.getPath();
                if (verbose) {
                    printVerbose("loading", currentClassFileName);
                }
                if (classfile.getName().endsWith(".class")) {
                    filling = true;
                    int size = (int) classfile.length();
                    if (buf.length < size)
                        buf = new byte[size];
                    int n = 0;
                    while (n < size)
                        n = n + s.read(buf, n, size - n);
                    s.close();
                    bp = 0;
                    readClassFile(c);
                } else {
                    sourceCompleter.complete(c, currentClassFileName, s);
                }
                return;
            } catch (IOException ex) {
                throw badClassFile("unable.to.access.file", ex.getMessage());
            }
            finally { filling = false;
                } } else {
            String fn = externalizeFileName(c.flatname);
            throw newCompletionFailure(c,
                    Log.getLocalizedString("dot.class.not.found", fn));
        }
    }

    /**
      * Static factory for CompletionFailure objects.
      *  In practice, only one can be used at a time, so we share one
      *  to reduce the expense of allocating new exception objects.
      */
    private CompletionFailure newCompletionFailure(ClassSymbol c, String localized) {
        CompletionFailure result = cachedCompletionFailure;
        result.sym = c;
        result.errmsg = localized;
        return result;
    }
    private CompletionFailure cachedCompletionFailure =
            new CompletionFailure(null, null);

    /**
     * Load a toplevel class with given fully qualified name
     *  The class is entered into `classes' only if load was successful.
     */
    public ClassSymbol loadClass(Name flatname) throws CompletionFailure {
        boolean absent = classes.get(flatname) == null;
        ClassSymbol c = enterClass(flatname);
        if (c.members_field == null && c.completer != null) {
            try {
                c.complete();
            } catch (CompletionFailure ex) {
                if (absent)
                    classes.remove(flatname);
                throw ex;
            }
        }
        return c;
    }

    /**
      * Check to see if a package exists, given its fully qualified name.
      */
    public boolean packageExists(Name fullname) {
        return enterPackage(fullname).exists();
    }

    /**
      * Make a package, given its fully qualified name.
      */
    public PackageSymbol enterPackage(Name fullname) {
        PackageSymbol p = (PackageSymbol) packages.get(fullname);
        if (p == null) {
            assert fullname.length() != 0 :
            "rootPackage missing!";
            p = new PackageSymbol(Convert.shortName(fullname),
                    enterPackage(Convert.packagePart(fullname)));
            p.completer = this;
            packages.put(fullname, p);
        }
        return p;
    }

    /**
      * Make a package, given its unqualified name and enclosing package.
      */
    public PackageSymbol enterPackage(Name name, PackageSymbol owner) {
        return enterPackage(TypeSymbol.formFullName(name, owner));
    }

    /**
      * Include class corresponding to given class file in package,
      *  unless (1) we already have one the same kind (.class or .java), or
      *         (2) we have one of the other kind, and the given class file
      *             is older.
      */
    private void includeClassFile(PackageSymbol p, FileEntry file) {
        if ((p.flags_field & EXISTS) == 0)
            for (Symbol q = p; q != null && q.kind == PCK; q = q.owner)
                q.flags_field |= EXISTS;
        String filename = file.getName();
        int seen;
        int extlen;
        if (filename.endsWith(".class")) {
            seen = CLASS_SEEN;
            extlen = 6;
        } else {
            seen = SOURCE_SEEN;
            extlen = 5;
        }
        Name classname =
                names.fromString(filename.substring(0, filename.length() - extlen));
        ClassSymbol c = (ClassSymbol) p.members_field.lookup(classname).sym;
        if (c == null) {
            c = enterClass(classname, p);
            c.classfile = file;
            if (c.owner == p)
                p.members_field.enter(c);
        } else if (c.classfile != null && (c.flags_field & seen) == 0) {
            if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0) {
                long fdate = file.lastModified();
                long cdate = c.classfile.lastModified();
                if (fdate >= 0 && cdate >= 0 && fdate > cdate) {
                    c.classfile = file;
                }
            }
        }
        c.flags_field |= seen;
    }

    /**
      * Insert all files in subdirectory `name' of `pathname'
      *  which end in one of the extensions in `extensions' into package.
      */
    private void list(String pathname, String name, String[] extensions,
            PackageSymbol p) {
        try {
            if (isZip(pathname)) {
                Archive archive = openArchive(pathname);
                if (name.length() != 0) {
                    name = name.replace('\\', '/');
                    if (!name.endsWith("/"))
                        name = name + "/";
                }
                int namelen = name.length();
                for (List l = archive.entries; l.nonEmpty(); l = l.tail) {
                    ZipEntry entry = (ZipEntry) l.head;
                    String ename = entry.getName();
                    if (ename.startsWith(name)) {
                        if (endsWith(ename, extensions)) {
                            String suffix = ename.substring(namelen);
                            if (suffix.length() > 0 && suffix.indexOf('/') < 0) {
                                includeClassFile(p,
                                        new FileEntry.Zipped(suffix,
                                        archive.zdir, entry));
                            }
                        } else
                            extraZipFileActions(p, ename, name, pathname);
                    }
                }
            } else {
                File f = name.length() != 0 ? new File(pathname, name) :
                        new File(pathname);
                String[] names = f.list();
                if (names != null && caseMapCheck(f, name)) {
                    for (int i = 0; i < names.length; i++) {
                        String fname = names[i];
                        if (isValidFile(fname, extensions)) {
                            includeClassFile(p,
                                    new FileEntry.Regular(fname, new File(f, fname)));
                        } else
                            extraFileActions(p, fname, f);
                    }
                }
            }
        } catch (IOException ex) {
        }
    }

    private boolean endsWith(String s, String[] extensions) {
        for (int i = 0; i < extensions.length; i++)
            if (s.endsWith(extensions[i]))
                return true;
        return false;
    }

    private boolean isValidFile(String s, String[] extensions) {
        for (int i = 0; i < extensions.length; i++) {
            String extension = extensions[i];
            if (s.endsWith(extension) && isJavaIdentifier(
                    s.substring(0, s.length() - extension.length())))
                return true;
        }
        return false;
    }

    private boolean isJavaIdentifier(String s) {
        if (s.length() < 1)
            return false;
        if (!Character.isJavaIdentifierStart(s.charAt(0)))
            return false;
        for (int j = 1; j < s.length(); j++)
            if (!Character.isJavaIdentifierPart(s.charAt(j)))
                return false;
        return true;
    }
    static final boolean fileSystemIsCaseSensitive = File.separatorChar == '/';

    /**
     * Hack to make Windows case sensitive. Test whether given path
     *  ends in a string of characters with the same case as given name.
     *  Ignore file separators in both path and name.
     */
    private boolean caseMapCheck(File f, String name) throws IOException {
        if (fileSystemIsCaseSensitive)
            return true;
        String path = f.getCanonicalPath();
        char[] pcs = path.toCharArray();
        char[] ncs = name.toCharArray();
        int i = pcs.length - 1;
        int j = ncs.length - 1;
        while (i >= 0 && j >= 0) {
            while (i >= 0 && pcs[i] == File.separatorChar)
                i--;
            while (j >= 0 && ncs[j] == File.separatorChar)
                j--;
            if (i >= 0 && j >= 0) {
                if (pcs[i] != ncs[j])
                    return false;
                i--;
                j--;
            }
        }
        return j < 0;
    }

    /**
      * These are used to support javadoc
      */
    protected void extraZipFileActions(PackageSymbol pack, String zipEntryName,
            String classPathName, String zipName) {
    }

    protected void extraFileActions(PackageSymbol pack, String fileName,
            File fileDir) {
    }

    /**
      * Insert all files in subdirectory `name' somewhere on
      *  class path `path' which end in one of the extensions in `extensions'
      *  into package.
      */
    private void listAll(String path, String name, String[] extensions,
            PackageSymbol p) {
        int i = 0;
        int plen = path.length();
        while (i < plen) {
            int end = path.indexOf(pathSep, i);
            String pathname = path.substring(i, end);
            list(pathname, name, extensions, p);
            i = end + 1;
        }
    }
    static final String[] classOnly = {".class"};
    static final String[] javaOnly = {".java"};
    static final String[] classOrJava = {".class", ".java"};

    /**
     * Load directory of package into members scope.
     */
    private void fillIn(PackageSymbol p) {
        if (p.members_field == null)
            p.members_field = new Scope(p);
        Name packageName = p.fullname;
        if (packageName == names.emptyPackage)
            packageName = names.empty;
        String dirname = externalizeFileName(packageName);
        listAll(bootClassPath, dirname, classOnly, p);
        if (sourceCompleter != null && sourceClassPath == null) {
            listAll(classPath, dirname, classOrJava, p);
        } else {
            listAll(classPath, dirname, classOnly, p);
            if (sourceCompleter != null) {
                listAll(sourceClassPath, dirname, javaOnly, p);
            }
        }
    }

    /**
      * Output for "-verbose" option.
      *  @param key The key to look up the correct internationalized string.
      *  @param arg An argument for substitution into the output string.
      */
    private void printVerbose(String key, String arg) {
        Log.printLines(log.noticeWriter,
                Log.getLocalizedString("verbose." + key, arg));
    }

    /**
      * Output for "-checkclassfile" option.
      *  @param key The key to look up the correct internationalized string.
      *  @param arg An argument for substitution into the output string.
      */
    private void printCCF(String key, String arg) {
        Log.printLines(log.noticeWriter,
                Log.getLocalizedString("verbose." + key, arg));
    }

    public interface SourceCompleter {

        void complete(ClassSymbol sym, String filename,
                InputStream f) throws CompletionFailure;
            }
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -