/*
 * Copyright (c) 2001, 2006, 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.
 *
 * 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.
 */

/* @test
 * @bug 4429043 4493595 6332756
 * @summary The FileChannel file locking
 */

import java.io.*;
import java.nio.channels.*;
import java.nio.*;

/**
 * Testing FileChannel's lock method.
 */

public class Lock {

    public static void main(String[] args) throws Exception {
        if (args.length > 0) {
            if(args[0].equals("1")) {
                MadWriter mw = new MadWriter(args[1], false);
            } else {
                MadWriter mw = new MadWriter(args[1], true);
            }
            return;
        }
        File blah = File.createTempFile("blah", null);
        blah.deleteOnExit();
        RandomAccessFile raf = new RandomAccessFile(blah, "rw");
        raf.write(1);
        raf.close();
        test1(blah, "1");
        test1(blah, "2");
        test2(blah, true);
        test2(blah, false);
        test3(blah);
    }

    private static void test2(File blah, boolean b) throws Exception {
        RandomAccessFile raf = new RandomAccessFile(blah, "rw");
        FileChannel channel = raf.getChannel();
        FileLock lock;
        if (b)
            lock = channel.lock();
        else
            lock = channel.tryLock();
        lock.release();
        channel.close();
    }

    static void test1(File blah, String str) throws Exception {

        // Grab the lock
        RandomAccessFile fis = new RandomAccessFile(blah, "rw");
        FileChannel fc = fis.getChannel();
        FileLock lock = null;

        if (str.equals("1")) {
            lock = fc.lock(0, 10, false);
            if (lock == null)
                throw new RuntimeException("Lock should not return null");
            try {
                FileLock lock2 = fc.lock(5, 10, false);
                throw new RuntimeException("Overlapping locks allowed");
            } catch (OverlappingFileLockException e) {
                // Correct result
            }
        }

        // Exec the tamperer
        String command = System.getProperty("java.home") +
            File.separator + "bin" + File.separator + "java Lock " + str + " " + blah;
        Process p = Runtime.getRuntime().exec(command);

        BufferedReader in = new BufferedReader
            (new InputStreamReader(p.getInputStream()));

        String s;
        int count = 0;
        while ((s = in.readLine()) != null) {
            if (!s.equals("good")) {
                if (File.separatorChar == '/') {
                    // Fails on windows over NFS...
                    throw new RuntimeException("Failed: "+s);
                }
            }
            count++;
        }

        if (count == 0) {
            in = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            while ((s = in.readLine()) != null) {
                System.err.println("Error output: " + s);
            }
            throw new RuntimeException("Failed, no output");
        }

        // Clean up
        if (lock != null) {
            /* Check multiple releases */
            lock.release();
            lock.release();
        }
        fc.close();
        fis.close();
    }

    // The overlap check for file locks should be JVM-wide
    private static void test3(File blah) throws Exception {
        FileChannel fc1 = new RandomAccessFile(blah, "rw").getChannel();
        FileChannel fc2 = new RandomAccessFile(blah, "rw").getChannel();

        // lock via one channel, and then attempt to lock the same file
        // using a second channel
        FileLock fl1 = fc1.lock();
        try {
            fc2.tryLock();
            throw new RuntimeException("Overlapping locks allowed");
        } catch (OverlappingFileLockException x) {
        }
        try {
            fc2.lock();
            throw new RuntimeException("Overlapping locks allowed");
        } catch (OverlappingFileLockException x) {
        }

        // release lock and the attempt to lock with the second channel
        // should succeed.
        fl1.release();
        FileLock fl2 = fc2.lock();
        try {
            fc1.lock();
            throw new RuntimeException("Overlapping locks allowed");
        } catch (OverlappingFileLockException x) {
        }

        fc1.close();
        fc2.close();
    }
}

class MadWriter {
    public MadWriter(String s, boolean b) throws Exception {
        File f = new File(s);
        RandomAccessFile fos = new RandomAccessFile(f, "rw");
        FileChannel fc = fos.getChannel();
        if (fc.tryLock(10, 10, false) == null) {
            System.out.println("bad: Failed to grab adjacent lock");
        }
        FileLock lock = fc.tryLock(0, 10, false);
        if (lock == null) {
            if (b)
                System.out.println("bad");
            else
                System.out.println("good");
        } else {
            if (b)
                System.out.println("good");
            else
                System.out.println("bad");
        }
        fc.close();
        fos.close();
    }

}
