/*
 * Copyright 2018 MovingBlocks
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.terasology.engine.module;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.engine.paths.PathManager;
import org.terasology.module.sandbox.API;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.function.Consumer;

/**
 * This class wrap common file operations so they're only allowed to happen
 * within Terasology/sandbox directory.
 *
 * It gives modules the ability to read and write to the file system in a safe way.
 */
@API
public class SandboxFileManager {

    private static final Logger logger = LoggerFactory.getLogger(SandboxFileManager.class);

    private PathManager pathManager;

    public SandboxFileManager() {
        this.pathManager = PathManager.getInstance();
    }

    /**
     * Reads the file that matches the passed filename.
     *
     * @param filename
     * @param consumer Consumer to read the file.
     */
    public void readFile(String filename, Consumer<ModuleInputStream> consumer) {
        String sandboxPath = pathManager.getSandboxPath(filename).toString();

        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
            try {
                InputStream inputStream = new FileInputStream(sandboxPath);
                ModuleInputStream moduleInputStream = new ModuleInputStream(inputStream);

                // consumer to read the file, if it exists
                consumer.accept(moduleInputStream);

                inputStream.close();
            } catch (IOException e) {
                logger.error("Could not read the file: " + filename, e);
            }

            return null;
        });
    }

    /**
     * Write a new file using the filename and data passed as parameter.
     *
     * @param filename
     * @param data The file's content.
     */
    public void writeFile(String filename, byte[] data) {
        Path sandboxPath = pathManager.getSandboxPath(filename);
        
        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
            try {
                Files.write(sandboxPath, data);
            } catch (IOException e) {
                logger.error("Could not write the file: " + filename, e);
            }

            return null;
        });
    }

    /**
     * Delete the file that matches the passed filename.
     *
     * @param filename
     */
    public void deleteFile(String filename) {
        Path sandboxPath = pathManager.getSandboxPath(filename);

        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
            try {
                Files.delete(sandboxPath);
            } catch (IOException e) {
                logger.error("Could not delete the file: " + filename, e);
            }

            return null;
        });
    }
}

@@ -1157,16 +1157,20 @@
 tory.%0A *
+ %3Cp%3E
 %0A * It g
@@ -1572,32 +1572,786 @@
 assed filename.%0A
+     * %3Cp%3E%0A     * How to use:%0A     * %3Cul%3E%0A     * %3Cli%3EFirst of all, we need to create a file read consumer, for example:%0A     * %3Cpre%3E%7B@code%0A     * Consumer%3CModuleInputStream%3E consumer = inputStream -%3E %7B%0A     *      try %7B%0A     *          int value = inputStream.read();%0A     *%0A     *          while (value != -1) %7B%0A     *              doSomething(value);%0A     *              value = inputStream.read();%0A     *          %7D%0A     *      %7D catch (IOException e) %7B%0A     *          logger.error(%22Cannot read file.%22)%0A     *      %7D%0A     * %7D;%0A     * %7D%3C/pre%3E%3C/li%3E%0A     * %3Cli%3ECall %7B@code readFile%7D passing in the filename and the consumer as parameter.%3C/li%3E%0A     * %3Cli%3EWhen the execution is completed the %7B@code InputStream%7D is automatically closed.%3C/li%3E%0A     * %3C/ul%3E%0A
      *%0A     * @p
@@ -2355,32 +2355,42 @@
  @param filename
+ Filename.
 %0A     * @param c
@@ -2680,34 +2680,17 @@
     try 
-%7B%0A                
+(
 InputStr
@@ -2731,33 +2731,35 @@
 eam(sandboxPath)
-;
+) %7B
 %0A               
@@ -2948,46 +2948,8 @@
 am);
-%0A%0A                inputStream.close();
 %0A   
@@ -3221,24 +3221,34 @@
 ram filename
+ Filename.
 %0A     * @par
@@ -3406,24 +3406,16 @@
 ename);%0A
-        
 %0A       
@@ -3809,16 +3809,26 @@
 filename
+ Filename.
 %0A     */

Improve javadoc