package cn.rongcloud.im.stetho;
/**
* Created by jiangecho on 2016/12/22.
*/
import android.content.Context;
import android.os.Environment;
import com.facebook.stetho.common.Util;
import com.facebook.stetho.dumpapp.ArgsHelper;
import com.facebook.stetho.dumpapp.DumpException;
import com.facebook.stetho.dumpapp.DumpUsageException;
import com.facebook.stetho.dumpapp.DumperContext;
import com.facebook.stetho.dumpapp.DumperPlugin;
import com.facebook.stetho.inspector.database.DatabaseFilesProvider;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class RongDbFilesDumperPlugin implements DumperPlugin {
private static final String NAME = "rongDbFile";
private final Context mContext;
private final DatabaseFilesProvider mDatabaseFilesProvider;
public RongDbFilesDumperPlugin(Context context, DatabaseFilesProvider databaseFilesProvider) {
mContext = context;
mDatabaseFilesProvider = databaseFilesProvider;
}
@Override
public String getName() {
return NAME;
}
@Override
public void dump(DumperContext dumpContext) throws DumpException {
Iterator<String> args = dumpContext.getArgsAsList().iterator();
String command = ArgsHelper.nextOptionalArg(args, "");
if ("download".equals(command)) {
doDownload(dumpContext.getStdout(), args);
} else {
doUsage(dumpContext.getStdout());
if (!"".equals(command)) {
throw new DumpUsageException("Unknown command: " + command);
}
}
}
private static File getBaseDir(Context context) {
// getFilesDir() yields /data/data/<package>/files, we want the base package dir.
return context.getFilesDir().getParentFile();
}
private void doDownload(PrintStream writer, Iterator<String> remainingArgs)
throws DumpUsageException {
String outputPath = ArgsHelper.nextArg(remainingArgs, "Must specify output file");
File outFile = resolvePossibleSdcardPath(outputPath);
if (outFile.exists()) {
writer.println("error: out file exists");
return;
}
List<File> selectedFiles = mDatabaseFilesProvider.getDatabaseFiles();
try {
OutputStream outputStream;
if ("-".equals(outputPath)) {
outputStream = writer;
} else {
outputStream = new FileOutputStream(resolvePossibleSdcardPath(outputPath));
}
ZipOutputStream output = new ZipOutputStream(new BufferedOutputStream(outputStream));
boolean success = false;
try {
byte[] buf = new byte[2048];
if (selectedFiles.size() > 0) {
addFiles(output, buf, selectedFiles.toArray(new File[selectedFiles.size()]));
} else {
addFiles(output, buf, getBaseDir(mContext).listFiles());
}
success = true;
} finally {
try {
output.close();
} catch (IOException e) {
Util.close(outputStream, !success);
if (success) {
throw e;
}
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void addFiles(ZipOutputStream output, byte[] buf, File[] files) throws IOException {
for (File file : files) {
if (file.isDirectory()) {
addFiles(output, buf, file.listFiles());
} else {
output.putNextEntry(
new ZipEntry(
relativizePath(
getBaseDir(mContext).getParentFile(),
file)));
FileInputStream input = new FileInputStream(file);
try {
copy(input, output, buf);
} finally {
input.close();
}
}
}
}
private static void copy(InputStream in, OutputStream out, byte[] buf) throws IOException {
int n;
while ((n = in.read(buf)) >= 0) {
out.write(buf, 0, n);
}
}
// Disclaimer: stupid implementation :)
private static String relativizePath(File base, File path) {
String baseStr = base.getAbsolutePath();
String pathStr = path.getAbsolutePath();
if (pathStr.startsWith(baseStr)) {
return pathStr.substring(baseStr.length() + 1);
} else {
return pathStr;
}
}
private static File resolvePossibleSdcardPath(String path) {
if (path.startsWith("/")) {
return new File(path);
} else {
return new File(Environment.getExternalStorageDirectory(), path);
}
}
private void doUsage(PrintStream writer) {
final String cmdName = "dumpapp " + NAME;
String usagePrefix = "Usage: " + cmdName + " ";
String blankPrefix = " " + cmdName + " ";
writer.println(usagePrefix + "<command>");
writer.println(blankPrefix + "download <output.zip>");
writer.println();
writer.println(cmdName + " download: Fetch internal application storage");
}
}