/*
 * 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.channels.*;
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.*;

import com.sun.nio.file.ExtendedOpenOption;

import sun.nio.ch.FileChannelImpl;
import sun.nio.ch.ThreadPool;
import sun.nio.ch.WindowsAsynchronousFileChannelImpl;
import sun.misc.SharedSecrets;
import sun.misc.JavaIOFileDescriptorAccess;

import static sun.nio.fs.WindowsNativeDispatcher.*;
import static sun.nio.fs.WindowsConstants.*;

/**
 * Factory to create FileChannels and AsynchronousFileChannels.
 */

class WindowsChannelFactory {
    private static final JavaIOFileDescriptorAccess fdAccess =
        SharedSecrets.getJavaIOFileDescriptorAccess();

    private WindowsChannelFactory() { }

    /**
     * Do not follow reparse points when opening an existing file. Do not fail
     * if the file is a reparse point.
     */
    static final OpenOption OPEN_REPARSE_POINT = new OpenOption() { };

    /**
     * Represents the flags from a user-supplied set of open options.
     */
    private static class Flags {
        boolean read;
        boolean write;
        boolean append;
        boolean truncateExisting;
        boolean create;
        boolean createNew;
        boolean deleteOnClose;
        boolean sparse;
        boolean overlapped;
        boolean sync;
        boolean dsync;

        // non-standard
        boolean shareRead = true;
        boolean shareWrite = true;
        boolean shareDelete = true;
        boolean noFollowLinks;
        boolean openReparsePoint;

        static Flags toFlags(Set<? extends OpenOption> options) {
            Flags flags = new Flags();
            for (OpenOption option: options) {
                if (option instanceof StandardOpenOption) {
                    switch ((StandardOpenOption)option) {
                        case READ : flags.read = true; break;
                        case WRITE : flags.write = true; break;
                        case APPEND : flags.append = true; break;
                        case TRUNCATE_EXISTING : flags.truncateExisting = true; break;
                        case CREATE : flags.create = true; break;
                        case CREATE_NEW : flags.createNew = true; break;
                        case DELETE_ON_CLOSE : flags.deleteOnClose = true; break;
                        case SPARSE : flags.sparse = true; break;
                        case SYNC : flags.sync = true; break;
                        case DSYNC : flags.dsync = true; break;
                        default: throw new UnsupportedOperationException();
                    }
                    continue;
                }
                if (option instanceof ExtendedOpenOption) {
                    switch ((ExtendedOpenOption)option) {
                        case NOSHARE_READ : flags.shareRead = false; break;
                        case NOSHARE_WRITE : flags.shareWrite = false; break;
                        case NOSHARE_DELETE : flags.shareDelete = false; break;
                        default: throw new UnsupportedOperationException();
                    }
                    continue;
                }
                if (option == LinkOption.NOFOLLOW_LINKS) {
                    flags.noFollowLinks = true;
                    continue;
                }
                if (option == OPEN_REPARSE_POINT) {
                    flags.openReparsePoint = true;
                    continue;
                }
                if (option == null)
                    throw new NullPointerException();
                throw new UnsupportedOperationException();
            }
            return flags;
        }
    }

    /**
     * Open/creates file, returning FileChannel to access the file
     *
     * @param   pathForWindows
     *          The path of the file to open/create
     * @param   pathToCheck
     *          The path used for permission checks (if security manager)
     */
    static FileChannel newFileChannel(String pathForWindows,
                                      String pathToCheck,
                                      Set<? extends OpenOption> options,
                                      long pSecurityDescriptor)
        throws WindowsException
    {
        Flags flags = Flags.toFlags(options);

        // default is reading; append => writing
        if (!flags.read && !flags.write) {
            if (flags.append) {
                flags.write = true;
            } else {
                flags.read = true;
            }
        }

        // validation
        if (flags.read && flags.append)
            throw new IllegalArgumentException("READ + APPEND not allowed");
        if (flags.append && flags.truncateExisting)
            throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");

        FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor);
        return FileChannelImpl.open(fdObj, flags.read, flags.write, null);
    }

    /**
     * Open/creates file, returning AsynchronousFileChannel to access the file
     *
     * @param   pathForWindows
     *          The path of the file to open/create
     * @param   pathToCheck
     *          The path used for permission checks (if security manager)
     * @param   pool
     *          The thread pool that the channel is associated with
     */
    static AsynchronousFileChannel newAsynchronousFileChannel(String pathForWindows,
                                                              String pathToCheck,
                                                              Set<? extends OpenOption> options,
                                                              long pSecurityDescriptor,
                                                              ThreadPool pool)
        throws IOException
    {
        Flags flags = Flags.toFlags(options);

        // Overlapped I/O required
        flags.overlapped = true;

        // default is reading
        if (!flags.read && !flags.write) {
            flags.read = true;
        }

        // validation
        if (flags.append)
            throw new UnsupportedOperationException("APPEND not allowed");

        // open file for overlapped I/O
        FileDescriptor fdObj;
        try {
            fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor);
        } catch (WindowsException x) {
            x.rethrowAsIOException(pathForWindows);
            return null;
        }

        // create the AsynchronousFileChannel
        try {
            return WindowsAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool);
        } catch (IOException x) {
            // IOException is thrown if the file handle cannot be associated
            // with the completion port. All we can do is close the file.
            long handle = fdAccess.getHandle(fdObj);
            CloseHandle(handle);
            throw x;
        }
    }

    /**
     * Opens file based on parameters and options, returning a FileDescriptor
     * encapsulating the handle to the open file.
     */
    private static FileDescriptor open(String pathForWindows,
                                       String pathToCheck,
                                       Flags flags,
                                       long pSecurityDescriptor)
        throws WindowsException
    {
        // set to true if file must be truncated after open
        boolean truncateAfterOpen = false;

        // map options
        int dwDesiredAccess = 0;
        if (flags.read)
            dwDesiredAccess |= GENERIC_READ;
        if (flags.write)
            dwDesiredAccess |= (flags.append) ? FILE_APPEND_DATA : GENERIC_WRITE;

        int dwShareMode = 0;
        if (flags.shareRead)
            dwShareMode |= FILE_SHARE_READ;
        if (flags.shareWrite)
            dwShareMode |= FILE_SHARE_WRITE;
        if (flags.shareDelete)
            dwShareMode |= FILE_SHARE_DELETE;

        int dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
        int dwCreationDisposition = OPEN_EXISTING;
        if (flags.write) {
            if (flags.createNew) {
                dwCreationDisposition = CREATE_NEW;
                // force create to fail if file is orphaned reparse point
                dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;
            } else {
                if (flags.create)
                    dwCreationDisposition = OPEN_ALWAYS;
                if (flags.truncateExisting) {
                    // Windows doesn't have a creation disposition that exactly
                    // corresponds to CREATE + TRUNCATE_EXISTING so we use
                    // the OPEN_ALWAYS mode and then truncate the file.
                    if (dwCreationDisposition == OPEN_ALWAYS) {
                        truncateAfterOpen = true;
                    } else {
                        dwCreationDisposition = TRUNCATE_EXISTING;
                    }
                }
            }
        }

        if (flags.dsync || flags.sync)
            dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
        if (flags.overlapped)
            dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
        if (flags.deleteOnClose)
            dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;

        // NOFOLLOW_LINKS and NOFOLLOW_REPARSEPOINT mean open reparse point
        boolean okayToFollowLinks = true;
        if (dwCreationDisposition != CREATE_NEW &&
            (flags.noFollowLinks ||
             flags.openReparsePoint ||
             flags.deleteOnClose))
        {
            if (flags.noFollowLinks || flags.deleteOnClose)
                okayToFollowLinks = false;
            dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT;
        }

        // permission check
        if (pathToCheck != null) {
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                if (flags.read)
                    sm.checkRead(pathToCheck);
                if (flags.write)
                    sm.checkWrite(pathToCheck);
                if (flags.deleteOnClose)
                    sm.checkDelete(pathToCheck);
            }
        }

        // open file
        long handle = CreateFile(pathForWindows,
                                 dwDesiredAccess,
                                 dwShareMode,
                                 pSecurityDescriptor,
                                 dwCreationDisposition,
                                 dwFlagsAndAttributes);

        // make sure this isn't a symbolic link.
        if (!okayToFollowLinks) {
            try {
                if (WindowsFileAttributes.readAttributes(handle).isSymbolicLink())
                    throw new WindowsException("File is symbolic link");
            } catch (WindowsException x) {
                CloseHandle(handle);
                throw x;
            }
        }

        // truncate file (for CREATE + TRUNCATE_EXISTING case)
        if (truncateAfterOpen) {
            try {
                SetEndOfFile(handle);
            } catch (WindowsException x) {
                CloseHandle(handle);
                throw x;
            }
        }

        // make the file sparse if needed
        if (dwCreationDisposition == CREATE_NEW && flags.sparse) {
            try {
                DeviceIoControlSetSparse(handle);
            } catch (WindowsException x) {
                // ignore as sparse option is hint
            }
        }

        // create FileDescriptor and return
        FileDescriptor fdObj = new FileDescriptor();
        fdAccess.setHandle(fdObj, handle);
        return fdObj;
    }
}
