package com.openfeint.internal.request;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DeflaterOutputStream;
import com.openfeint.api.OpenFeintSettings;
import com.openfeint.internal.OpenFeintInternal;
import com.openfeint.internal.request.multipart.ByteArrayPartSource;
import com.openfeint.internal.request.multipart.PartSource;
import com.openfeint.internal.resource.BlobUploadParameters;
public class CompressedBlobPostRequest extends BlobPostRequest {
BlobUploadParameters mParameters;
String mFilename;
byte mUncompressedData;
public CompressedBlobPostRequest(BlobUploadParameters parameters, String filename, byte[] uncompressedData) {
super(parameters, _makePartSource(filename, uncompressedData), "application/octet-stream");
}
public static final byte[] MagicHeader = "OFZLHDR0".getBytes();
public enum CompressionMethod {
Default,
Uncompressed,
LegacyHeaderless,
};
public static CompressionMethod compressionMethod() {
String s = (String)OpenFeintInternal.getInstance().getSettings().get(OpenFeintSettings.SettingCloudStorageCompressionStrategy);
if (s == null)
return CompressionMethod.Default;
if (s.equals(OpenFeintSettings.CloudStorageCompressionStrategyLegacyHeaderlessCompression))
return CompressionMethod.LegacyHeaderless;
if (s.equals(OpenFeintSettings.CloudStorageCompressionStrategyNoCompression))
return CompressionMethod.Uncompressed;
return CompressionMethod.Default;
}
private static byte[] _compress(byte data[]) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream(baos);
dos.write(data);
dos.close();
return baos.toByteArray();
}
// This is little endian for compatibility with the iOS api. in a better world we'd use network byte order.
private static byte[] integerToLittleEndianByteArray(int i) {
byte rv[] = new byte[4];
rv[0] = (byte)(i >> 0);
rv[1] = (byte)(i >> 8);
rv[2] = (byte)(i >> 16);
rv[3] = (byte)(i >> 24);
return rv;
}
private static PartSource _makePartSource(String filename, byte[] uncompressedData) {
byte uploadData[] = uncompressedData;
try {
switch (compressionMethod()) {
case Default:
{
byte tenativeData[] = _compress(uncompressedData);
byte[] uncompressedSize = integerToLittleEndianByteArray(uncompressedData.length);
final int compressedLength = tenativeData.length + MagicHeader.length + uncompressedSize.length;
if (compressedLength < uncompressedData.length) {
uploadData = new byte[compressedLength];
System.arraycopy(MagicHeader, 0, uploadData, 0, MagicHeader.length);
System.arraycopy(uncompressedSize, 0, uploadData, MagicHeader.length, uncompressedSize.length);
System.arraycopy(tenativeData, 0, uploadData, MagicHeader.length + 4, tenativeData.length);
}
}
break;
case LegacyHeaderless:
uploadData = _compress(uncompressedData);
break;
default:
// default in this case is uncompressed, so just use the uncompressedData.
break;
}
} catch (IOException e) {
return null;
}
return new ByteArrayPartSource(filename, uploadData);
}
}