/*
* Protocoder
* A prototyping platform for Android devices
*
* Victor Diaz Barrales victormdb@gmail.com
*
* Copyright (C) 2014 Victor Diaz
* Copyright (C) 2013 Motorola Mobility LLC
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package org.protocoderrunner.utils;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.util.Log;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import org.protocoderrunner.apprunner.AppRunnerSettings;
import org.protocoderrunner.project.ProjectManager;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.channels.FileChannel;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class FileIO {
private static final String TAG = "FILEIO";
/**
* Write the data to the file indicate by fileName. The file is created if
* it doesn't exist.
*/
public static void write(Activity activity, String data, String fileName) throws IOException {
FileOutputStream fo = activity.openFileOutput(fileName, 0);
BufferedWriter bf = new BufferedWriter(new FileWriter(fo.getFD()));
bf.write(data);
bf.flush();
bf.close();
}
/**
* Read the contents of the file indicated by fileName
*/
public static String read(Context activity, String fileName) throws IOException {
if (fileName.contains("/0/")) {
fileName = fileName.replace("/0/", "/legacy/");
}
FileInputStream is = activity.openFileInput(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
while (br.ready()) {
String line = br.readLine();
sb.append(line);
}
String data = sb.toString();
return data;
}
/**
* Read the contents of a file in the assets directory indicated by fileName
*/
public static String readFromAssets(Context activity, String fileName) throws IOException {
AssetManager am = activity.getAssets();
return read(am.open(fileName));
}
/**
* Read the contents of the file indicated by fileName
*/
public static String read(InputStream is) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
while (br.ready()) {
String line = br.readLine();
sb.append("\n");
sb.append(line);
}
String data = sb.toString();
return data;
}
// Read a file in the assets directory into a string
public static String readAssetFile(Context c, String path) {
String out = null;
AssetManager am = c.getAssets();
try {
InputStream in = am.open(path);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int i;
try {
i = in.read();
while (i != -1) {
buf.write(i);
i = in.read();
}
in.close();
} catch (IOException ex) {
}
out = buf.toString();
} catch (IOException e) {
e.printStackTrace();
MLog.e(TAG, e.toString());
}
return out;
}
// Write a string to a file
public static String writeStringToFile(String url, String name, String code) {
MLog.d(TAG, "Writing string to file name: " + name + " code: " + code);
String filename = name.replaceAll("[^a-zA-Z0-9-_\\. ]", "_");
String baseDir = url + File.separator + filename;
File dir = new File(baseDir);
dir.mkdirs();
File f = new File(dir.getAbsoluteFile() + File.separator + "main.js");
try {
if (!f.exists()) {
f.createNewFile();
} else {
// We should probably do something here to handle multiple file
// cases
}
FileOutputStream fo = new FileOutputStream(f);
byte[] data = code.getBytes();
fo.write(data);
fo.flush();
fo.close();
} catch (FileNotFoundException ex) {
MLog.e(TAG, ex.toString());
} catch (IOException e) {
e.printStackTrace();
MLog.e(TAG, e.toString());
}
return f.getAbsolutePath();
}
public static boolean copyAssetFolder(AssetManager assetManager, String fromAssetPath, String toPath) {
try {
String[] files = assetManager.list(fromAssetPath);
new File(toPath).mkdirs();
boolean res = true;
for (String file : files) {
if (file.contains(".")) {
res &= copyAsset(assetManager, fromAssetPath + "/" + file, toPath + "/" + file);
} else {
res &= copyAssetFolder(assetManager, fromAssetPath + "/" + file, toPath + "/" + file);
}
}
return res;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean copyAsset(AssetManager assetManager, String fromAssetPath, String toPath) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(fromAssetPath);
new File(toPath).createNewFile();
out = new FileOutputStream(toPath);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
public static void copyFileOrDir(Context c, String path) {
AssetManager assetManager = c.getAssets();
String assets[] = null;
try {
assets = assetManager.list(path);
if (assets.length == 0) {
copyFile(c, path);
} else {
String fullPath = ProjectManager.getInstance().getBaseDir() + "/" + path;
File dir = new File(fullPath);
if (!dir.exists()) {
dir.mkdir();
}
for (String asset : assets) {
copyFileOrDir(c, path + "/" + asset);
}
}
} catch (IOException ex) {
Log.e("tag", "I/O Exception", ex);
}
}
private static void copyFile(Context c, String filename) {
AssetManager assetManager = c.getAssets();
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
String newFileName = ProjectManager.getInstance().getBaseDir() + filename;
out = new FileOutputStream(newFileName);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
}
public static void copyFile(File src, File dst) throws IOException {
FileChannel inChannel = new FileInputStream(src).getChannel();
FileChannel outChannel = new FileOutputStream(dst).getChannel();
try {
inChannel.transferTo(0, inChannel.size(), outChannel);
} finally {
if (inChannel != null) {
inChannel.close();
}
if (outChannel != null) {
outChannel.close();
}
}
}
public static void deleteFileDir(String path, String name) {
String fullPath = path + "/" + name;
MLog.d(TAG, "deleting directory " + fullPath);
File dir = new File(fullPath);
if (dir.isDirectory()) {
MLog.d(TAG, "deleting directory " + dir.getAbsolutePath());
String[] children = dir.list();
for (String element : children) {
File f = new File(dir, element);
f.delete();
MLog.d(TAG, "deleting directory done" + f.getAbsolutePath());
}
} else {
dir.delete();
}
MLog.d(TAG, "deleting directory done" + name);
}
public static void deleteDir(File dir) {
MLog.d("DeleteRecursive", "DELETEPREVIOUS TOP" + dir.getPath());
if (dir.isDirectory()) {
String[] children = dir.list();
for (String element : children) {
File temp = new File(dir, element);
if (temp.isDirectory()) {
MLog.d("DeleteRecursive", "Recursive Call" + temp.getPath());
deleteDir(temp);
} else {
MLog.d("DeleteRecursive", "Delete File" + temp.getPath());
boolean b = temp.delete();
if (b == false) {
MLog.d("DeleteRecursive", "DELETE FAIL");
}
}
}
}
dir.delete();
}
/*
* Method borrowed from Processing PApplet.java
*/
public static void saveStrings(String filename, String strings[]) {
saveStrings(saveFile(filename), strings);
}
/*
* Method borrowed from Processing PApplet.java
*/
public static File saveFile(String where) {
return new File(AppRunnerSettings.get().project.getStoragePath() + File.separator + where);
}
/*
* Method borrowed from Processing PApplet.java
*/
static public void saveStrings(File file, String strings[]) {
try {
String location = file.getAbsolutePath();
createPath(location);
OutputStream output = new FileOutputStream(location);
if (file.getName().toLowerCase().endsWith(".gz")) {
output = new GZIPOutputStream(output);
}
saveStrings(output, strings);
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* Method borrowed from Processing PApplet.java
*/
static public void saveStrings(OutputStream output, String strings[]) {
try {
OutputStreamWriter osw = new OutputStreamWriter(output, "UTF-8");
PrintWriter writer = new PrintWriter(osw);
for (String string : strings) {
writer.println(string);
}
writer.flush();
} catch (UnsupportedEncodingException e) {
} // will not happen
}
/*
* Method borrowed from Processing PApplet.java
*/
public static String[] loadStrings(String filename) {
InputStream is = createInput(AppRunnerSettings.get().project.getStoragePath() + File.separator + filename);
if (is != null) {
return loadStrings(is);
}
System.err.println("The file \"" + filename + "\" " + "is missing or inaccessible, make sure "
+ "the URL is valid or that the file has been " + "added to your sketch and is readable.");
return null;
}
public static String loadFile(String filename) {
String[] arr = loadStrings(filename);
StringBuilder builder = new StringBuilder();
for (String s : arr) {
builder.append(s);
}
return builder.toString();
}
/*
* Method borrowed from Processing PApplet.java
*/
static public String[] loadStrings(InputStream input) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
String lines[] = new String[100];
int lineCount = 0;
String line = null;
while ((line = reader.readLine()) != null) {
if (lineCount == lines.length) {
String temp[] = new String[lineCount << 1];
System.arraycopy(lines, 0, temp, 0, lineCount);
lines = temp;
}
lines[lineCount++] = line;
}
reader.close();
if (lineCount == lines.length) {
return lines;
}
// resize array to appropriate amount for these lines
String output[] = new String[lineCount];
System.arraycopy(lines, 0, output, 0, lineCount);
return output;
} catch (IOException e) {
e.printStackTrace();
// throw new RuntimeException("Error inside loadStrings()");
}
return null;
}
/*
* Method borrowed from Processing PApplet.java
*/
public static InputStream createInput(String filename) {
InputStream input = createInputRaw(filename);
return input;
}
/*
* Method borrowed from Processing PApplet.java
*/
public static InputStream createInputRaw(String filename) {
// Additional considerations for Android version:
// http://developer.android.com/guide/topics/resources/resources-i18n.html
InputStream stream = null;
if (filename == null) {
return null;
}
if (filename.length() == 0) {
// an error will be called by the parent function
// System.err.println("The filename passed to openStream() was empty.");
return null;
}
// Maybe this is an absolute path, didja ever think of that?
File absFile = new File(filename);
if (absFile.exists()) {
try {
stream = new FileInputStream(absFile);
if (stream != null) {
return stream;
}
} catch (FileNotFoundException fnfe) {
// fnfe.printStackTrace();
}
}
return null;
}
/*
* Method borrowed from Processing PApplet.java
*/
static public InputStream createInput(File file) {
if (file == null) {
throw new IllegalArgumentException("File passed to createInput() was null");
}
try {
InputStream input = new FileInputStream(file);
if (file.getName().toLowerCase().endsWith(".gz")) {
return new GZIPInputStream(input);
}
return input;
} catch (IOException e) {
System.err.println("Could not createInput() for " + file);
e.printStackTrace();
return null;
}
}
/**
* Takes a path and creates any in-between folders if they don't already
* exist. Useful when trying to save to a subfolder that may not actually
* exist.
*/
static public void createPath(String path) {
createPath(new File(path));
}
static public void createPath(File file) {
try {
String parent = file.getParent();
if (parent != null) {
File unit = new File(parent);
if (!unit.exists()) {
unit.mkdirs();
}
}
} catch (SecurityException se) {
System.err.println("You don't have permissions to create " + file.getAbsolutePath());
}
}
static public void zipFolder(String src, String dst) throws Exception {
File f = new File(dst);
//make dirs if necessary
f.getParentFile().mkdirs();
ZipFile zipfile = new ZipFile(f.getAbsolutePath());
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
zipfile.addFolder(src, parameters);
}
static public void unZipFile(String src, String dst) throws ZipException {
ZipFile zipFile = new ZipFile(src);
zipFile.extractAll(dst);
}
static public void extractZip(String zipFile, String location) throws IOException {
int size;
int BUFFER_SIZE = 1024;
byte[] buffer = new byte[BUFFER_SIZE];
try {
if ( !location.endsWith("/") ) {
location += "/";
}
File f = new File(location);
if(!f.isDirectory()) {
f.mkdirs();
}
ZipInputStream zin = new ZipInputStream(new BufferedInputStream(new FileInputStream(zipFile), BUFFER_SIZE));
try {
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
String path = location + ze.getName();
File unzipFile = new File(path);
if (ze.isDirectory()) {
if(!unzipFile.isDirectory()) {
unzipFile.mkdirs();
}
} else {
// check for and create parent directories if they don't exist
File parentDir = unzipFile.getParentFile();
if ( null != parentDir ) {
if ( !parentDir.isDirectory() ) {
parentDir.mkdirs();
}
}
// unzip the file
FileOutputStream out = new FileOutputStream(unzipFile, false);
BufferedOutputStream fout = new BufferedOutputStream(out, BUFFER_SIZE);
try {
while ( (size = zin.read(buffer, 0, BUFFER_SIZE)) != -1 ) {
fout.write(buffer, 0, size);
}
zin.closeEntry();
}
finally {
fout.flush();
fout.close();
}
}
}
}
finally {
zin.close();
}
}
catch (Exception e) {
Log.e(TAG, "Unzip exception", e);
}
}
public static File[] listFiles(String url, final String extension) {
File f = new File(AppRunnerSettings.get().project.getStoragePath() + File.separator + url + File.separator);
return f.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String fileName) {
return fileName.endsWith(extension);
}
});
}
public static String getFileExtension(String fileName) {
String extension = "";
int i = fileName.lastIndexOf('.');
if (i > 0) {
extension = fileName.substring(i + 1);
}
return extension;
}
public static void appendStrings(String fileName, String[] lines) {
try {
String fileUrl = ProjectManager.getInstance().getCurrentProject().getStoragePath() + File.separator
+ fileName;
File f = new File(fileUrl);
if (!f.exists()) {
f.createNewFile();
}
FileOutputStream fo = new FileOutputStream(f, true);
for (String line : lines) {
fo.write(line.getBytes());
}
fo.flush();
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}