/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.mozstumbler.client;
import android.content.Context;
import android.os.Environment;
import org.mozilla.mozstumbler.service.Prefs;
import org.mozilla.mozstumbler.service.core.logging.ClientLog;
import org.mozilla.mozstumbler.service.stumblerthread.datahandling.DataStorageManager;
import org.mozilla.mozstumbler.service.stumblerthread.datahandling.StorageIsEmptyTracker;
import org.mozilla.mozstumbler.service.stumblerthread.datahandling.base.SerializedJSONRows;
import org.mozilla.mozstumbler.svclocator.services.log.LoggerUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ClientDataStorageManager extends DataStorageManager {
private static final String LOG_TAG = LoggerUtil.makeLogTag(ClientDataStorageManager.class);
private ClientDataStorageManager(Context c, StorageIsEmptyTracker tracker, long maxBytesStoredOnDisk, int maxWeeksDataStored) {
super(c, tracker, maxBytesStoredOnDisk, maxWeeksDataStored);
mPersistedOnDiskUploadStats.forceBroadcastOfSyncStats();
}
public static String sdcardArchivePath() {
return Environment.getExternalStorageDirectory() + File.separator + "MozStumbler";
}
// This 'overrides' the static createGlobalInstance method
// DataStorageManager. Sorta. You can't really override static methods.
public static synchronized DataStorageManager createGlobalInstance(Context context, StorageIsEmptyTracker tracker,
long maxBytesStoredOnDisk, int maxWeeksDataStored) {
if (sInstance == null) {
sInstance = new ClientDataStorageManager(context, tracker, maxBytesStoredOnDisk, maxWeeksDataStored);
}
return sInstance;
}
/* Pass filename returned from dataToSend() */
@Override
public synchronized boolean delete(SerializedJSONRows data) {
if (data == mInMemoryFinalizedJSONRowsObject) {
return super.delete(data);
}
final File file = new File(mStorageDir, data.filename);
boolean ok = true;
if (Prefs.getInstanceWithoutContext().isSaveStumbleLogs()) {
File newFile = new File(sdcardArchivePath() + File.separator + data.filename);
ok = copyAndDelete(file, newFile);
if (!ok) {
ok = file.delete();
}
} else {
ok = file.delete();
}
mFileList.update();
return ok;
}
private boolean copyAndDelete(File aFile, File bFile) {
boolean ok = true;
FileInputStream inStream = null;
FileOutputStream outStream = null;
try {
inStream = new FileInputStream(aFile);
outStream = new FileOutputStream(bFile);
} catch (FileNotFoundException e) {
if (inStream != null) {
try {
inStream.close();
} catch (IOException ioEx) {
ClientLog.e(LOG_TAG, "error shutting down streams during a failed copy", ioEx);
}
}
if (outStream != null) {
try {
outStream.close();
} catch (IOException ioEx) {
ClientLog.e(LOG_TAG, "error shutting down streams during a failed copy", ioEx);
}
}
return false;
}
byte[] buffer = new byte[1024];
int length;
//copy the file content in bytes
try {
while ((length = inStream.read(buffer)) > 0) {
outStream.write(buffer, 0, length);
}
} catch (IOException e) {
ClientLog.e(LOG_TAG, "Error copying bytes over", e);
if (inStream != null) {
try {
inStream.close();
} catch (IOException ioEx) {
ClientLog.e(LOG_TAG, "error shutting down streams during a failed copy", ioEx);
}
}
if (outStream != null) {
try {
outStream.close();
} catch (IOException ioEx) {
ClientLog.e(LOG_TAG, "error shutting down streams during a failed copy", ioEx);
}
}
return false;
}
if (inStream != null) {
try {
inStream.close();
} catch (IOException ioEx) {
ClientLog.e(LOG_TAG, "error shutting down streams during a failed copy", ioEx);
ok = false;
}
}
if (outStream != null) {
try {
outStream.close();
} catch (IOException ioEx) {
ClientLog.e(LOG_TAG, "error shutting down streams during a failed copy", ioEx);
ok = false;
}
}
// delete the original file
return ok && aFile.delete();
}
}