package com.jbidwatcher.util;
/*
* Copyright (c) 2000-2007, CyberFOX Software, Inc. All Rights Reserved.
*
* Developed by mrs (Morgan Schweers)
*/
import com.jbidwatcher.util.config.JConfig;
import java.io.*;
import java.util.zip.*;
public class GZip extends Backupable {
private static byte[] _byteHold = new byte[1];
private static final Boolean _sync = Boolean.TRUE;
private static final byte[] gzipHdrData = { 0x1f, -117, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00,
0x02, -1 };
byte[] _gzTest = new byte[2];
byte[] _data;
int _uclength;
int _uccrc32;
boolean nowrap = true;
CRC32 _crc32Calculator = new CRC32();
static int incrementme;
public byte[] getCompressedData() { return _data; }
public StringBuffer getUncompressedData() { return uncompress(_data, nowrap); }
public StringBuffer getUncompressedData(boolean xt_nowrap) { return uncompress(_data, xt_nowrap); }
public long getLength() { return _uclength; }
public long getCRC() { return _uccrc32; }
public void reset() { _data = null; _uclength = 0; _uccrc32 = 0; _crc32Calculator.reset(); }
public void setData(byte[] newData, int len, int crc) {
_data = newData;
_uclength = len;
_uccrc32 = crc;
}
public void setData(byte[] newData) {
_crc32Calculator.reset();
_crc32Calculator.update(newData);
_uccrc32 = (int) _crc32Calculator.getValue();
_uclength = newData.length;
_data = compress(newData);
}
public int readInt(FileInputStream fis) throws IOException {
int a, b, c, d;
a = fis.read();
b = fis.read();
c = fis.read();
d = fis.read();
return(a + b << 8 + c << 16 + d << 24);
}
/**
* Load a GZipped file into memory.
*
* @noinspection ResultOfMethodCallIgnored
*
* @param fp - The file to load from.
*
* @throws IOException - If there are any errors reading from the file.
*/
public void load(File fp) throws IOException {
FileInputStream fis = new FileInputStream(fp);
fis.read(_gzTest);
// If it's a 'real' GZipped file...
if(_gzTest[0] == 0x1f && _gzTest[1] == -117) {
if(fis.skip(8)==8) {
_data = new byte[(int)fp.length() - 18 + 16];
fis.read(_data, 0, (int)fp.length() - 18);
_uccrc32 = readInt(fis);
_uclength= readInt(fis);
nowrap = true;
}
} else {
_data = new byte[(int)fp.length()];
System.arraycopy(_gzTest, 0, _data, 0, 2);
nowrap = false;
fis.read(_data, 2, _data.length-2);
}
fis.close();
}
private byte[] compress(byte[] inBytes) {
Deflater df = new Deflater(9);
byte[] newData;
int deflatedBytes;
// We can't compress null.
if(inBytes == null) return null;
synchronized(_sync) {
if(_byteHold == null || _byteHold.length < inBytes.length) {
_byteHold = new byte[inBytes.length * 2];
}
df.setInput(inBytes);
df.finish();
deflatedBytes = df.deflate(_byteHold);
deflatedBytes -= 4;
newData = new byte[deflatedBytes];
System.arraycopy(_byteHold, 0, newData, 0, deflatedBytes);
}
return newData;
}
public static StringBuffer uncompress(byte[] curPage, boolean nowrap) {
Inflater infl = new Inflater(nowrap);
byte[] outdata;
int accumOutputBytes, inflatedBytes;
int prevLength;
// We can't uncompress null.
if(curPage == null) return null;
synchronized(_sync) {
prevLength = _byteHold.length;
if(prevLength < curPage.length) {
_byteHold = new byte[curPage.length];
}
infl.setInput(curPage);
try {
inflatedBytes = infl.inflate(_byteHold);
accumOutputBytes = inflatedBytes;
while(!infl.finished() && inflatedBytes != 0) {
outdata = _byteHold;
prevLength = _byteHold.length;
if(accumOutputBytes >= (prevLength - 2048)) {
try {
inflatedBytes = 0;
_byteHold = new byte[_byteHold.length * 3];
System.arraycopy(outdata, 0, _byteHold, 0, accumOutputBytes);
inflatedBytes = infl.inflate(_byteHold, accumOutputBytes, prevLength * 2);
} catch(OutOfMemoryError oome) {
JConfig.log().handleException("FAILING to allocate more bytes @ " + _byteHold.length * 3, oome);
}
} else {
inflatedBytes = infl.inflate(_byteHold, accumOutputBytes, prevLength - accumOutputBytes);
}
accumOutputBytes += inflatedBytes;
}
return new StringBuffer(new String(_byteHold, 0, accumOutputBytes));
} catch(DataFormatException dfe) {
JConfig.log().handleException("Failed to uncompress data: " + dfe, dfe);
return null;
}
}
}
/**
* Write out the given int in LSB->MSB format.
*
* @param fos - Output stream to write to.
* @param outie - Int value to write out in LSB->MSB format.
*
* @throws java.io.IOException - If the writing fails.
*/
private void writeInt(FileOutputStream fos, int outie) throws IOException {
byte a = (byte) ((outie & 0xff000000) >> 24);
byte b = (byte) ((outie & 0x00ff0000) >> 16);
byte c = (byte) ((outie & 0x0000ff00) >> 8);
byte d = (byte) (outie & 0x000000ff);
fos.write(d);
fos.write(c);
fos.write(b);
fos.write(a);
}
public void save(String fileName) {
File fp = fileWithBackup(fileName);
try {
FileOutputStream fos = new FileOutputStream(fp);
// Write 0x1f,0x8b,0x8,0x0,0x00000000,2,255,{Data},crc32,{datalen}
fos.write(gzipHdrData, 0, gzipHdrData.length);
fos.write(_data, 2, _data.length-2);
writeInt(fos, _uccrc32);
writeInt(fos, _uclength);
fos.close();
} catch(IOException ioe) {
// We dont throw the exception back up the chain, and let
// something with UI put up a display box because this can
// happen during unattended operation.
//
// In fact, this can occur because the user deleted the
// directory, and many other reasons, so we do NOT report the
// error anymore, unless debugging. This caused one user
// to have >28 megs of error logs. Stop that!
JConfig.log().handleDebugException("Error writing " + fileName, ioe);
}
}
}