/*
 * Copyright (c) 2008, 2009, 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 sun.nio.fs;

import java.nio.file.*;
import java.nio.file.attribute.*;
import java.nio.file.spi.*;
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
import java.security.AccessController;
import sun.security.action.GetPropertyAction;

/**
 * Base implementation of FileSystem for Unix-like implementations.
 */

abstract class UnixFileSystem
    extends FileSystem
{
    private final UnixFileSystemProvider provider;
    private final byte[] defaultDirectory;
    private final boolean needToResolveAgainstDefaultDirectory;
    private final UnixPath rootDirectory;

    // package-private
    UnixFileSystem(UnixFileSystemProvider provider, String dir) {
        this.provider = provider;
        this.defaultDirectory = UnixPath.normalizeAndCheck(dir).getBytes();
        if (this.defaultDirectory[0] != '/') {
            throw new RuntimeException("default directory must be absolute");
        }

        // if process-wide chdir is allowed or default directory is not the
        // process working directory then paths must be resolved against the
        // default directory.
        String propValue = AccessController.doPrivileged(
            new GetPropertyAction("sun.nio.fs.chdirAllowed", "false"));
        boolean chdirAllowed = (propValue.length() == 0) ?
            true : Boolean.valueOf(propValue);
        if (chdirAllowed) {
            this.needToResolveAgainstDefaultDirectory = true;
        } else {
            byte[] cwd = UnixNativeDispatcher.getcwd();
            boolean defaultIsCwd = (cwd.length == defaultDirectory.length);
            if (defaultIsCwd) {
                for (int i=0; i<cwd.length; i++) {
                    if (cwd[i] != defaultDirectory[i]) {
                        defaultIsCwd = false;
                        break;
                    }
                }
            }
            this.needToResolveAgainstDefaultDirectory = !defaultIsCwd;
        }

        // the root directory
        this.rootDirectory = new UnixPath(this, "/");
    }

    // package-private
    byte[] defaultDirectory() {
        return defaultDirectory;
    }

    boolean needToResolveAgainstDefaultDirectory() {
        return needToResolveAgainstDefaultDirectory;
    }

    UnixPath rootDirectory() {
        return rootDirectory;
    }

    boolean isSolaris() {
        return false;
    }

    @Override
    public final FileSystemProvider provider() {
        return provider;
    }

    @Override
    public final String getSeparator() {
        return "/";
    }

    @Override
    public final boolean isOpen() {
        return true;
    }

    @Override
    public final boolean isReadOnly() {
        return false;
    }

    @Override
    public final void close() throws IOException {
        throw new UnsupportedOperationException();
    }

    /**
     * Copies non-POSIX attributes from the source to target file.
     *
     * Copying a file preserving attributes, or moving a file, will preserve
     * the file owner/group/permissions/timestamps but it does not preserve
     * other non-POSIX attributes. This method is invoked by the
     * copy or move operation to preserve these attributes. It should copy
     * extended attributes, ACLs, or other attributes.
     *
     * @param   sfd
     *          Open file descriptor to source file
     * @param   tfd
     *          Open file descriptor to target file
     */
    void copyNonPosixAttributes(int sfd, int tfd) {
        // no-op by default
    }

    /**
     * Unix systems only have a single root directory (/)
     */
    @Override
    public final Iterable<Path> getRootDirectories() {
        final List<Path> allowedList =
           Collections.unmodifiableList(Arrays.asList((Path)rootDirectory));
        return new Iterable<Path>() {
            public Iterator<Path> iterator() {
                try {
                    SecurityManager sm = System.getSecurityManager();
                    if (sm != null)
                        sm.checkRead(rootDirectory.toString());
                    return allowedList.iterator();
                } catch (SecurityException x) {
                    List<Path> disallowed = Collections.emptyList();
                    return disallowed.iterator();
                }
            }
        };
    }

    /**
     * Returns object to iterate over entries in mounttab or equivalent
     */
    abstract Iterable<UnixMountEntry> getMountEntries();

    /**
     * Returns a FileStore to represent the file system where the given file
     * reside.
     */
    abstract FileStore getFileStore(UnixPath path) throws IOException;

    /**
     * Returns a FileStore to represent the file system for the given mount
     * mount.
     */
    abstract FileStore getFileStore(UnixMountEntry entry) throws IOException;

    /**
     * Iterator returned by getFileStores method.
     */
    private class FileStoreIterator implements Iterator<FileStore> {
        private final Iterator<UnixMountEntry> entries;
        private FileStore next;

        FileStoreIterator() {
            this.entries = getMountEntries().iterator();
        }

        private FileStore readNext() {
            assert Thread.holdsLock(this);
            for (;;) {
                if (!entries.hasNext())
                    return null;
                UnixMountEntry entry = entries.next();

                // skip entries with the "ignore" option
                if (entry.isIgnored())
                    continue;

                // check permission to read mount point
                SecurityManager sm = System.getSecurityManager();
                if (sm != null) {
                    try {
                        sm.checkRead(new String(entry.dir()));
                    } catch (SecurityException x) {
                        continue;
                    }
                }
                try {
                    return getFileStore(entry);
                } catch (IOException ignore) {
                    // ignore as per spec
                }
            }
        }

        @Override
        public synchronized boolean hasNext() {
            if (next != null)
                return true;
            next = readNext();
            return next != null;
        }

        @Override
        public synchronized FileStore next() {
            if (next == null)
                next = readNext();
            if (next == null) {
                throw new NoSuchElementException();
            } else {
                FileStore result = next;
                next = null;
                return result;
            }
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    @Override
    public final Iterable<FileStore> getFileStores() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            try {
                sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
            } catch (SecurityException se) {
                return Collections.emptyList();
            }
        }
        return new Iterable<FileStore>() {
            public Iterator<FileStore> iterator() {
                return new FileStoreIterator();
            }
        };
    }

    @Override
    public final UnixPath getPath(String path) {
        return new UnixPath(this, path);
    }

    @Override
    public PathMatcher getPathMatcher(String syntaxAndInput) {
        int pos = syntaxAndInput.indexOf(':');
        if (pos <= 0 || pos == syntaxAndInput.length())
            throw new IllegalArgumentException();
        String syntax = syntaxAndInput.substring(0, pos);
        String input = syntaxAndInput.substring(pos+1);

        String expr;
        if (syntax.equals(GLOB_SYNTAX)) {
            expr = Globs.toUnixRegexPattern(input);
        } else {
            if (syntax.equals(REGEX_SYNTAX)) {
                expr = input;
            } else {
                throw new UnsupportedOperationException("Syntax '" + syntax +
                    "' not recognized");
            }
        }

        // return matcher
        final Pattern pattern = Pattern.compile(expr);
        return new PathMatcher() {
            @Override
            public boolean matches(Path path) {
                return pattern.matcher(path.toString()).matches();
            }
        };
    }
    private static final String GLOB_SYNTAX = "glob";
    private static final String REGEX_SYNTAX = "regex";

    protected boolean followLinks(LinkOption... options) {
        boolean followLinks = true;
        for (LinkOption option: options) {
            if (option == LinkOption.NOFOLLOW_LINKS) {
                followLinks = false;
                continue;
            }
            if (option == null)
                throw new NullPointerException();
            throw new AssertionError("Should not get here");
        }
        return followLinks;
    }

    @SuppressWarnings("unchecked")
    protected <V extends FileAttributeView> V newFileAttributeView(Class<V> view,
                                                                   UnixPath file,
                                                                   LinkOption... options)
    {
        if (view == null)
            throw new NullPointerException();
        boolean followLinks = followLinks(options);
        Class<?> c = view;
        if (c == BasicFileAttributeView.class)
            return (V) UnixFileAttributeViews.createBasicView(file, followLinks);
        if (c == PosixFileAttributeView.class)
            return (V) UnixFileAttributeViews.createPosixView(file, followLinks);
        if (c == FileOwnerAttributeView.class)
            return (V) UnixFileAttributeViews.createOwnerView(file, followLinks);
        return (V) null;
    }

    static List<String> standardFileAttributeViews() {
        return Arrays.asList("basic", "posix", "unix", "owner");
    }

    protected DynamicFileAttributeView newFileAttributeView(String name,
                                                            UnixPath file,
                                                            LinkOption... options)
    {
        boolean followLinks = followLinks(options);
        if (name.equals("basic"))
            return UnixFileAttributeViews.createBasicView(file, followLinks);
        if (name.equals("posix"))
            return UnixFileAttributeViews.createPosixView(file, followLinks);
        if (name.equals("unix"))
            return UnixFileAttributeViews.createUnixView(file, followLinks);
        if (name.equals("owner"))
            return UnixFileAttributeViews.createOwnerView(file, followLinks);
        return null;
    }

    @Override
    public final UserPrincipalLookupService getUserPrincipalLookupService() {
        return theLookupService;
    }

    private static final UserPrincipalLookupService theLookupService =
        new UserPrincipalLookupService() {
            @Override
            public UserPrincipal lookupPrincipalByName(String name)
                throws IOException
            {
                return UnixUserPrincipals.lookupUser(name);
            }

            @Override
            public GroupPrincipal lookupPrincipalByGroupName(String group)
                throws IOException
            {
                return UnixUserPrincipals.lookupGroup(group);
            }
        };
}
