package fileLock;

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


public class FileResource {
    String resource_path;
    File file;
    FileInputStream in;
    FileOutputStream out;
        
    /**
     * @param args
     * @throws IOException
     * 
     * use File as a resource with lock
     *   file contains ascii represented number which means number of resources
     *   
     *   file must exists before execution and it must contain text represented
     *   number of resources.
     *   
     *   % echo 5 > hoge_resource
     *   
     */
    FileResource(String path) {
        resource_path = path;
    }    
    
    public void open_with_lock() throws IOException {
        file = new File(resource_path);
        if (! file.exists()) {
            System.out.print(resource_path);
            System.out.println(" does not exist.");
            return;
        }
        in = new FileInputStream(file);
        out = new FileOutputStream(file);
        in.getChannel().lock();
        // We will not use channel to release the lock, but close it.
    }
    
    public void release() throws IOException {
        in.close();
        out.close();
    }
    
    public boolean reserve() throws IOException {
        // use Scanner (java 1.5) to read integer value
        Scanner scanner = new Scanner(in);
        scanner.useDelimiter("\\s+");
        if (!scanner.hasNext()) {
                return false;
        }
        int value = scanner.nextInt(); 
        if (value--<=0) {
                return false;
        }

        // updated result have to be on the top of file
        // reset the position using FileChannel
        FileChannel chan = out.getChannel();
        chan.position(0);
        // We cannot print utf-8 represented number using OutputStream,
        // so get PrinterWriter from the OutputStream
        PrintWriter print = new PrintWriter(out);
        print.println(value);
        print.flush();
        // It may contains garbage after, shorten the file
        // just in case.
        chan.truncate(chan.position());
        return true;
    }
    
    public String resource_name() {  // bad name, but it's OK.
        return resource_path;
    }
}