alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (JavacPathFileManager.java)

This example Java source code file (JavacPathFileManager.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

basicfileattributes, filesystem, illegalargumentexception, ioexception, iterable, javafileobject, kind, listbuffer, net, network, override, path, pathfileobject, pathsforlocation, set, string, util

The JavacPathFileManager.java Java example source code

/*
 * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.javac.nio;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.lang.model.SourceVersion;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation;

import static java.nio.file.FileVisitOption.*;
import static javax.tools.StandardLocation.*;

import com.sun.tools.javac.util.BaseFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;

import static com.sun.tools.javac.main.Option.*;


// NOTE the imports carefully for this compilation unit.
//
// Path:  java.nio.file.Path -- the new NIO type for which this file manager exists
//
// Paths: com.sun.tools.javac.file.Paths -- legacy javac type for handling path options
//      The other Paths (java.nio.file.Paths) is not used

// NOTE this and related classes depend on new API in JDK 7.
// This requires special handling while bootstrapping the JDK build,
// when these classes might not yet have been compiled. To workaround
// this, the build arranges to make stubs of these classes available
// when compiling this and related classes. The set of stub files
// is specified in make/build.properties.

/**
 *  Implementation of PathFileManager: a JavaFileManager based on the use
 *  of java.nio.file.Path.
 *
 *  <p>Just as a Path is somewhat analagous to a File, so too is this
 *  JavacPathFileManager analogous to JavacFileManager, as it relates to the
 *  support of FileObjects based on File objects (i.e. just RegularFileObject,
 *  not ZipFileObject and its variants.)
 *
 *  <p>The default values for the standard locations supported by this file
 *  manager are the same as the default values provided by JavacFileManager --
 *  i.e. as determined by the javac.file.Paths class. To override these values,
 *  call {@link #setLocation}.
 *
 *  <p>To reduce confusion with Path objects, the locations such as "class path",
 *  "source path", etc, are generically referred to here as "search paths".
 *
 *  <p>This is NOT part of any supported API.
 *  If you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */
public class JavacPathFileManager extends BaseFileManager implements PathFileManager {
    protected FileSystem defaultFileSystem;

    /**
     * Create a JavacPathFileManager using a given context, optionally registering
     * it as the JavaFileManager for that context.
     */
    public JavacPathFileManager(Context context, boolean register, Charset charset) {
        super(charset);
        if (register)
            context.put(JavaFileManager.class, this);
        pathsForLocation = new HashMap<Location, PathsForLocation>();
        fileSystems = new HashMap<Path,FileSystem>();
        setContext(context);
    }

    /**
     * Set the context for JavacPathFileManager.
     */
    @Override
    public void setContext(Context context) {
        super.setContext(context);
    }

    @Override
    public FileSystem getDefaultFileSystem() {
        if (defaultFileSystem == null)
            defaultFileSystem = FileSystems.getDefault();
        return defaultFileSystem;
    }

    @Override
    public void setDefaultFileSystem(FileSystem fs) {
        defaultFileSystem = fs;
    }

    @Override
    public void flush() throws IOException {
        contentCache.clear();
    }

    @Override
    public void close() throws IOException {
        for (FileSystem fs: fileSystems.values())
            fs.close();
    }

    @Override
    public ClassLoader getClassLoader(Location location) {
        nullCheck(location);
        Iterable<? extends Path> path = getLocation(location);
        if (path == null)
            return null;
        ListBuffer<URL> lb = new ListBuffer();
        for (Path p: path) {
            try {
                lb.append(p.toUri().toURL());
            } catch (MalformedURLException e) {
                throw new AssertionError(e);
            }
        }

        return getClassLoader(lb.toArray(new URL[lb.size()]));
    }

    @Override
    public boolean isDefaultBootClassPath() {
        return locations.isDefaultBootClassPath();
    }

    // <editor-fold defaultstate="collapsed" desc="Location handling">

    public boolean hasLocation(Location location) {
        return (getLocation(location) != null);
    }

    public Iterable<? extends Path> getLocation(Location location) {
        nullCheck(location);
        lazyInitSearchPaths();
        PathsForLocation path = pathsForLocation.get(location);
        if (path == null && !pathsForLocation.containsKey(location)) {
            setDefaultForLocation(location);
            path = pathsForLocation.get(location);
        }
        return path;
    }

    private Path getOutputLocation(Location location) {
        Iterable<? extends Path> paths = getLocation(location);
        return (paths == null ? null : paths.iterator().next());
    }

    public void setLocation(Location location, Iterable<? extends Path> searchPath)
            throws IOException
    {
        nullCheck(location);
        lazyInitSearchPaths();
        if (searchPath == null) {
            setDefaultForLocation(location);
        } else {
            if (location.isOutputLocation())
                checkOutputPath(searchPath);
            PathsForLocation pl = new PathsForLocation();
            for (Path p: searchPath)
                pl.add(p);  // TODO -Xlint:path warn if path not found
            pathsForLocation.put(location, pl);
        }
    }

    private void checkOutputPath(Iterable<? extends Path> searchPath) throws IOException {
        Iterator<? extends Path> pathIter = searchPath.iterator();
        if (!pathIter.hasNext())
            throw new IllegalArgumentException("empty path for directory");
        Path path = pathIter.next();
        if (pathIter.hasNext())
            throw new IllegalArgumentException("path too long for directory");
        if (!isDirectory(path))
            throw new IOException(path + ": not a directory");
    }

    private void setDefaultForLocation(Location locn) {
        Collection<File> files = null;
        if (locn instanceof StandardLocation) {
            switch ((StandardLocation) locn) {
                case CLASS_PATH:
                    files = locations.userClassPath();
                    break;
                case PLATFORM_CLASS_PATH:
                    files = locations.bootClassPath();
                    break;
                case SOURCE_PATH:
                    files = locations.sourcePath();
                    break;
                case CLASS_OUTPUT: {
                    String arg = options.get(D);
                    files = (arg == null ? null : Collections.singleton(new File(arg)));
                    break;
                }
                case SOURCE_OUTPUT: {
                    String arg = options.get(S);
                    files = (arg == null ? null : Collections.singleton(new File(arg)));
                    break;
                }
            }
        }

        PathsForLocation pl = new PathsForLocation();
        if (files != null) {
            for (File f: files)
                pl.add(f.toPath());
        }
        if (!pl.isEmpty())
            pathsForLocation.put(locn, pl);
    }

    private void lazyInitSearchPaths() {
        if (!inited) {
            setDefaultForLocation(PLATFORM_CLASS_PATH);
            setDefaultForLocation(CLASS_PATH);
            setDefaultForLocation(SOURCE_PATH);
            inited = true;
        }
    }
    // where
        private boolean inited = false;

    private Map<Location, PathsForLocation> pathsForLocation;

    private static class PathsForLocation extends LinkedHashSet<Path> {
        private static final long serialVersionUID = 6788510222394486733L;
    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="FileObject handling">

    @Override
    public Path getPath(FileObject fo) {
        nullCheck(fo);
        if (!(fo instanceof PathFileObject))
            throw new IllegalArgumentException();
        return ((PathFileObject) fo).getPath();
    }

    @Override
    public boolean isSameFile(FileObject a, FileObject b) {
        nullCheck(a);
        nullCheck(b);
        if (!(a instanceof PathFileObject))
            throw new IllegalArgumentException("Not supported: " + a);
        if (!(b instanceof PathFileObject))
            throw new IllegalArgumentException("Not supported: " + b);
        return ((PathFileObject) a).isSameFile((PathFileObject) b);
    }

    @Override
    public Iterable<JavaFileObject> list(Location location,
            String packageName, Set<Kind> kinds, boolean recurse)
            throws IOException {
        // validatePackageName(packageName);
        nullCheck(packageName);
        nullCheck(kinds);

        Iterable<? extends Path> paths = getLocation(location);
        if (paths == null)
            return List.nil();
        ListBuffer<JavaFileObject> results = new ListBuffer();

        for (Path path : paths)
            list(path, packageName, kinds, recurse, results);

        return results.toList();
    }

    private void list(Path path, String packageName, final Set<Kind> kinds,
            boolean recurse, final ListBuffer<JavaFileObject> results)
            throws IOException {
        if (!Files.exists(path))
            return;

        final Path pathDir;
        if (isDirectory(path))
            pathDir = path;
        else {
            FileSystem fs = getFileSystem(path);
            if (fs == null)
                return;
            pathDir = fs.getRootDirectories().iterator().next();
        }
        String sep = path.getFileSystem().getSeparator();
        Path packageDir = packageName.isEmpty() ? pathDir
                : pathDir.resolve(packageName.replace(".", sep));
        if (!Files.exists(packageDir))
            return;

/* Alternate impl of list, superceded by use of Files.walkFileTree */
//        Deque<Path> queue = new LinkedList();
//        queue.add(packageDir);
//
//        Path dir;
//        while ((dir = queue.poll()) != null) {
//            DirectoryStream<Path> ds = dir.newDirectoryStream();
//            try {
//                for (Path p: ds) {
//                    String name = p.getFileName().toString();
//                    if (isDirectory(p)) {
//                        if (recurse && SourceVersion.isIdentifier(name)) {
//                            queue.add(p);
//                        }
//                    } else {
//                        if (kinds.contains(getKind(name))) {
//                            JavaFileObject fe =
//                                PathFileObject.createDirectoryPathFileObject(this, p, pathDir);
//                            results.append(fe);
//                        }
//                    }
//                }
//            } finally {
//                ds.close();
//            }
//        }
        int maxDepth = (recurse ? Integer.MAX_VALUE : 1);
        Set<FileVisitOption> opts = EnumSet.of(FOLLOW_LINKS);
        Files.walkFileTree(packageDir, opts, maxDepth,
                new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
                Path name = dir.getFileName();
                if (name == null || SourceVersion.isIdentifier(name.toString())) // JSR 292?
                    return FileVisitResult.CONTINUE;
                else
                    return FileVisitResult.SKIP_SUBTREE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                if (attrs.isRegularFile() && kinds.contains(getKind(file.getFileName().toString()))) {
                    JavaFileObject fe =
                        PathFileObject.createDirectoryPathFileObject(
                            JavacPathFileManager.this, file, pathDir);
                    results.append(fe);
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

    @Override
    public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
        Iterable<? extends Path> paths) {
        ArrayList<PathFileObject> result;
        if (paths instanceof Collection<?>)
            result = new ArrayList<PathFileObject>(((Collection)paths).size());
        else
            result = new ArrayList<PathFileObject>();
        for (Path p: paths)
            result.add(PathFileObject.createSimplePathFileObject(this, nullCheck(p)));
        return result;
    }

    @Override
    public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) {
        return getJavaFileObjectsFromPaths(Arrays.asList(nullCheck(paths)));
    }

    @Override
    public JavaFileObject getJavaFileForInput(Location location,
            String className, Kind kind) throws IOException {
        return getFileForInput(location, getRelativePath(className, kind));
    }

    @Override
    public FileObject getFileForInput(Location location,
            String packageName, String relativeName) throws IOException {
        return getFileForInput(location, getRelativePath(packageName, relativeName));
    }

    private JavaFileObject getFileForInput(Location location, String relativePath)
            throws IOException {
        for (Path p: getLocation(location)) {
            if (isDirectory(p)) {
                Path f = resolve(p, relativePath);
                if (Files.exists(f))
                    return PathFileObject.createDirectoryPathFileObject(this, f, p);
            } else {
                FileSystem fs = getFileSystem(p);
                if (fs != null) {
                    Path file = getPath(fs, relativePath);
                    if (Files.exists(file))
                        return PathFileObject.createJarPathFileObject(this, file);
                }
            }
        }
        return null;
    }

    @Override
    public JavaFileObject getJavaFileForOutput(Location location,
            String className, Kind kind, FileObject sibling) throws IOException {
        return getFileForOutput(location, getRelativePath(className, kind), sibling);
    }

    @Override
    public FileObject getFileForOutput(Location location, String packageName,
            String relativeName, FileObject sibling)
            throws IOException {
        return getFileForOutput(location, getRelativePath(packageName, relativeName), sibling);
    }

    private JavaFileObject getFileForOutput(Location location,
            String relativePath, FileObject sibling) {
        Path dir = getOutputLocation(location);
        if (dir == null) {
            if (location == CLASS_OUTPUT) {
                Path siblingDir = null;
                if (sibling != null && sibling instanceof PathFileObject) {
                    siblingDir = ((PathFileObject) sibling).getPath().getParent();
                }
                return PathFileObject.createSiblingPathFileObject(this,
                        siblingDir.resolve(getBaseName(relativePath)),
                        relativePath);
            } else if (location == SOURCE_OUTPUT) {
                dir = getOutputLocation(CLASS_OUTPUT);
            }
        }

        Path file;
        if (dir != null) {
            file = resolve(dir, relativePath);
            return PathFileObject.createDirectoryPathFileObject(this, file, dir);
        } else {
            file = getPath(getDefaultFileSystem(), relativePath);
            return PathFileObject.createSimplePathFileObject(this, file);
        }

    }

    @Override
    public String inferBinaryName(Location location, JavaFileObject fo) {
        nullCheck(fo);
        // Need to match the path semantics of list(location, ...)
        Iterable<? extends Path> paths = getLocation(location);
        if (paths == null) {
            return null;
        }

        if (!(fo instanceof PathFileObject))
            throw new IllegalArgumentException(fo.getClass().getName());

        return ((PathFileObject) fo).inferBinaryName(paths);
    }

    private FileSystem getFileSystem(Path p) throws IOException {
        FileSystem fs = fileSystems.get(p);
        if (fs == null) {
            fs = FileSystems.newFileSystem(p, null);
            fileSystems.put(p, fs);
        }
        return fs;
    }

    private Map<Path,FileSystem> fileSystems;

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Utility methods">

    private static String getRelativePath(String className, Kind kind) {
        return className.replace(".", "/") + kind.extension;
    }

    private static String getRelativePath(String packageName, String relativeName) {
        return packageName.isEmpty()
                ? relativeName : packageName.replace(".", "/") + "/" + relativeName;
    }

    private static String getBaseName(String relativePath) {
        int lastSep = relativePath.lastIndexOf("/");
        return relativePath.substring(lastSep + 1); // safe if "/" not found
    }

    private static boolean isDirectory(Path path) throws IOException {
        BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
        return attrs.isDirectory();
    }

    private static Path getPath(FileSystem fs, String relativePath) {
        return fs.getPath(relativePath.replace("/", fs.getSeparator()));
    }

    private static Path resolve(Path base, String relativePath) {
        FileSystem fs = base.getFileSystem();
        Path rp = fs.getPath(relativePath.replace("/", fs.getSeparator()));
        return base.resolve(rp);
    }

    // </editor-fold>

}

Other Java examples (source code examples)

Here is a short list of links related to this Java JavacPathFileManager.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.