package org.commcare.tasks; import android.util.Log; import org.commcare.CommCareApplication; import org.commcare.activities.CommCareWiFiDirectActivity; import org.commcare.logging.AndroidLogger; import org.commcare.tasks.templates.CommCareTask; import org.commcare.utils.FileUtil; import org.commcare.views.notifications.NotificationMessageFactory; import org.commcare.views.notifications.ProcessIssues; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * @author wspride * * This task zips the files in toBeZippedPath into the file specified by zipFilePath * Returns 1 for success, -1 for failure. */ public abstract class ZipTask extends CommCareTask<Void, String, ZipTask.ZipTaskResult, CommCareWiFiDirectActivity> { private static final String TAG = AndroidLogger.TYPE_FORM_DUMP; public enum ZipTaskResult { Success, Failure } // this is where the forms that have been pulled from FormRecord storage to the file system live public final static String FORM_PROPERTIES_FILE = "form.properties"; public final static String FORM_PROPERTY_POST_URL = "PostURL"; public static final int ZIP_TASK_ID = 72135; private final File toBeZippedFile; private final String zipFilePath; public ZipTask(String toBeZippedPath, String zipFilePath) { taskId = ZIP_TASK_ID; this.zipFilePath = zipFilePath; this.toBeZippedFile = new File(toBeZippedPath); } private static boolean zipParentFolder(File toBeZippedDirectory, String zipFilePath) throws IOException { Log.d(TAG, "Zipping directory" + toBeZippedDirectory.toString() + " to path " + zipFilePath); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFilePath))); try { if (!toBeZippedDirectory.isDirectory()) { throw new RuntimeException("toBeZippedDirecory was not a directory. Bad."); } // the to be zipped directory should contain a bunch of sub directories File[] formInstanceFolders = toBeZippedDirectory.listFiles(); for (File formInstanceFolder : formInstanceFolders) { File[] subFileArray = formInstanceFolder.listFiles(); Log.d(TAG, "Zipping instance folder with files: " + Arrays.toString(subFileArray) + ", zipFilePath: " + zipFilePath); zipInstanceFolder(subFileArray, out); } out.finish(); } finally { out.close(); } return false; } private static void zipInstanceFolder(File[] toBeZippedFiles, ZipOutputStream zos) throws IOException { int BUFFER_SIZE = 1024; BufferedInputStream origin; byte data[] = new byte[BUFFER_SIZE]; for (File file : toBeZippedFiles) { FileInputStream fi = new FileInputStream(file); origin = new BufferedInputStream(fi, BUFFER_SIZE); try { String tempPath = file.getPath(); Log.d(TAG, "Zipping instance folder with path: " + tempPath); String[] pathParts = tempPath.split("/"); int pathPartsLength = pathParts.length; String filePath = pathParts[pathPartsLength -2] + "/" + pathParts[pathPartsLength - 1]; Log.d(TAG, "Zipping instance folder with path: " + filePath); ZipEntry entry = new ZipEntry(filePath); zos.putNextEntry(entry); int count; while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) { zos.write(data, 0, count); } zos.closeEntry(); } finally { origin.close(); } } } @Override protected ZipTaskResult doTaskBackground(Void... params) { Log.d(TAG, "Doing UnzipTask"); try { FileUtil.deleteFileOrDir(zipFilePath); zipParentFolder(toBeZippedFile, zipFilePath); FileUtil.deleteFileOrDir(toBeZippedFile); } catch (IOException ioe) { Log.d(TAG, "IOException: " + ioe.getMessage()); return ZipTaskResult.Failure; } return ZipTaskResult.Success; } @Override protected void onCancelled() { super.onCancelled(); CommCareApplication.notificationManager().reportNotificationMessage(NotificationMessageFactory.message(ProcessIssues.LoggedOut)); } }