package com.nitorcreations.willow.deployer;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

import com.nitorcreations.willow.utils.ReplaceTokensInputStream;


public class FileUtil {
	public static final int BUFFER_LEN = 8 * 1024;
	public static synchronized boolean createDir(File dir) {
		return   dir.exists() || dir.mkdirs();
	}
	public static String getFileName(String name) {
		int lastSeparator = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\'));
		int queryIndex = name.lastIndexOf("?");
		if (queryIndex < 0) queryIndex = name.length();
		return name.substring(lastSeparator + 1, queryIndex);
	}
	public static long copy(InputStream in, File target) throws IOException {
		try (OutputStream out = new BufferedOutputStream(new FileOutputStream(target), BUFFER_LEN)) {
			return copy(in, out);
		}
	}
	public static long copy(InputStream in, OutputStream out) throws IOException {
		byte[] buffer = new byte[BUFFER_LEN];
		long count = 0;
		int n = 0;
		while (-1 != (n = in.read(buffer))) {
			out.write(buffer, 0, n);
			count += n;
		}
		out.flush();
		return count;
	}
	public static long filterStream(InputStream original, File target, Map<String, String> replaceTokens) throws IOException {
		try (OutputStream out = new FileOutputStream(target)) {
			return filterStream(original, out, replaceTokens);
		}
	}

	public static long filterStream(InputStream original, OutputStream out, Map<String, String> replaceTokens) throws IOException {
		try (InputStream in = new ReplaceTokensInputStream(
				new BufferedInputStream(original, BUFFER_LEN),replaceTokens, 
				ReplaceTokensInputStream.MAVEN_DELIMITERS);
				OutputStream bOut = new BufferedOutputStream(out, BUFFER_LEN)) {
			return copyByteByByte(in, bOut);
		}
	}

	public static long copyByteByByte(InputStream in, OutputStream out) throws IOException {
		try {
			long i = 0;
			int b;
			while ((b = in.read()) != -1) {
				out.write(b);
				i++;
			}
			return i;
		} catch (IOException e) {
			throw e;
		} finally {
			try {
				out.flush();
			} catch (IOException e0) {
				throw e0;
			} finally {
				try {
					if (in != null) in.close();
				} catch (IOException e1) {
					throw e1;
				} finally {
					if (out != null) out.close();
				}
			}
		}
	}
}

@@ -867,32 +867,36 @@
 eption %7B%0A%09%09try (
+File
 OutputStream out
@@ -906,97 +906,107 @@
 new 
-BufferedOutputStream(new FileOutputStream(target), BUFFER_LEN)) %7B%0A%09%09%09return copy(in, out)
+FileOutputStream(target)) %7B%0A%09%09%09long lenght = copy(in, out);%0A%09%09%09out.getFD().sync();%0A%09%09%09return lenght
 ;%0A%09%09
@@ -1413,16 +1413,20 @@
 %0A%09%09try (
+File
 OutputSt
@@ -1521,33 +1521,32 @@
 Tokens);%0A%09%09%7D%0A%09%7D%0A
-%0A
 %09public static l
@@ -1584,16 +1584,20 @@
 iginal, 
+File
 OutputSt
@@ -1832,88 +1832,28 @@
 ERS)
-;%0A%09%09%09%09OutputStream bOut = new BufferedOutputStream(out, BUFFER_LEN)) %7B%0A%09%09%09return
+) %7B%0A%09%09%09long length =
  cop
@@ -1872,23 +1872,39 @@
 in, 
-bO
+o
 ut);%0A
+%09%09%09return length;%0A
 %09%09%7D%0A%09%7D%0A
-%0A
 %09pub
@@ -1985,24 +1985,211 @@
 Exception %7B%0A
+%09%09BufferedOutputStream bOut = null;%0A%09%09if (out instanceof BufferedOutputStream) %7B%0A%09%09%09bOut = (BufferedOutputStream) out;%0A%09%09%7D else %7B%0A%09%09%09bOut = new BufferedOutputStream(out, BUFFER_LEN);%0A%09%09%7D%0A
 %09%09try %7B%0A%09%09%09l
@@ -2248,17 +2248,18 @@
 ) %7B%0A%09%09%09%09
-o
+bO
 ut.write
@@ -2357,17 +2357,18 @@
 y %7B%0A%09%09%09%09
-o
+bO
 ut.flush
@@ -2371,16 +2371,110 @@
 lush();%0A
+%09%09%09%09if (out instanceof FileOutputStream) %7B%0A%09%09%09%09%09((FileOutputStream)out).getFD().sync();%0A%09%09%09%09%7D%0A
 %09%09%09%7D cat
@@ -2638,17 +2638,18 @@
 %09%09%09%09if (
-o
+bO
 ut != nu
@@ -2652,17 +2652,18 @@
 = null) 
-o
+bO
 ut.close

Make file operations safer with FD.sync()