001: package org.bouncycastle.openpgp;
002:
003: import org.bouncycastle.apache.bzip2.CBZip2OutputStream;
004: import org.bouncycastle.bcpg.BCPGOutputStream;
005: import org.bouncycastle.bcpg.CompressionAlgorithmTags;
006: import org.bouncycastle.bcpg.PacketTags;
007:
008: import java.io.IOException;
009: import java.io.OutputStream;
010: import java.util.zip.Deflater;
011: import java.util.zip.DeflaterOutputStream;
012:
013: /**
014: *class for producing compressed data packets.
015: */
016: public class PGPCompressedDataGenerator implements
017: CompressionAlgorithmTags, StreamGenerator {
018: private int algorithm;
019: private int compression;
020:
021: private OutputStream out;
022: private OutputStream dOut;
023: private BCPGOutputStream pkOut;
024:
025: public PGPCompressedDataGenerator(int algorithm) {
026: this (algorithm, Deflater.DEFAULT_COMPRESSION);
027: }
028:
029: public PGPCompressedDataGenerator(int algorithm, int compression) {
030: if (algorithm != PGPCompressedData.UNCOMPRESSED
031: && algorithm != PGPCompressedData.ZIP
032: && algorithm != PGPCompressedData.ZLIB
033: && algorithm != PGPCompressedData.BZIP2) {
034: throw new IllegalArgumentException(
035: "unknown compression algorithm");
036: }
037:
038: if (compression != Deflater.DEFAULT_COMPRESSION) {
039: if ((compression < 0) || (compression > 9)) {
040: throw new IllegalArgumentException(
041: "unknown compression level: " + compression);
042: }
043: }
044:
045: this .algorithm = algorithm;
046: this .compression = compression;
047: }
048:
049: /**
050: * Return an outputstream which will save the data being written to
051: * the compressed object. The stream can be closed off by either calling close()
052: * on the stream or close() on the generator.
053: *
054: * @param out
055: * @return OutputStream
056: * @throws IOException, IllegalStateException
057: */
058: public OutputStream open(OutputStream out) throws IOException {
059: if (dOut != null) {
060: throw new IllegalStateException(
061: "generator already in open state");
062: }
063:
064: this .out = out;
065:
066: switch (algorithm) {
067: case PGPCompressedData.ZIP:
068: pkOut = new BCPGOutputStream(out,
069: PacketTags.COMPRESSED_DATA);
070: pkOut.write(PGPCompressedData.ZIP);
071: dOut = new DeflaterOutputStream(pkOut, new Deflater(
072: compression, true));
073: break;
074: case PGPCompressedData.ZLIB:
075: pkOut = new BCPGOutputStream(out,
076: PacketTags.COMPRESSED_DATA);
077: pkOut.write(PGPCompressedData.ZLIB);
078: dOut = new DeflaterOutputStream(pkOut, new Deflater(
079: compression));
080: break;
081: case BZIP2:
082: pkOut = new BCPGOutputStream(out,
083: PacketTags.COMPRESSED_DATA);
084: pkOut.write(PGPCompressedData.BZIP2);
085: dOut = new CBZip2OutputStream(pkOut);
086: break;
087: case PGPCompressedData.UNCOMPRESSED:
088: pkOut = new BCPGOutputStream(out,
089: PacketTags.COMPRESSED_DATA);
090: pkOut.write(PGPCompressedData.UNCOMPRESSED);
091: dOut = pkOut;
092: break;
093: default:
094: throw new IllegalStateException("generator not initialised");
095: }
096:
097: return new WrappedGeneratorStream(dOut, this );
098: }
099:
100: /**
101: * Return an outputstream which will compress the data as it is written
102: * to it. The stream will be written out in chunks according to the size of the
103: * passed in buffer and can be closed off by either calling close() on the stream or close() on
104: * the generator.
105: * <p>
106: * <b>Note</b>: if the buffer is not a power of 2 in length only the largest power of 2
107: * bytes worth of the buffer will be used.
108: * </p>
109: * <p>
110: * <b>Note</b>: using this may break compatability with RFC 1991 compliant tools. Only recent OpenPGP
111: * implementations are capable of accepting these streams.
112: * </p>
113: *
114: * @param out
115: * @param buffer the buffer to use.
116: * @return OutputStream
117: * @throws IOException
118: * @throws PGPException
119: */
120: public OutputStream open(OutputStream out, byte[] buffer)
121: throws IOException, PGPException {
122: if (dOut != null) {
123: throw new IllegalStateException(
124: "generator already in open state");
125: }
126:
127: this .out = out;
128:
129: switch (algorithm) {
130: case PGPCompressedData.ZIP:
131: pkOut = new BCPGOutputStream(out,
132: PacketTags.COMPRESSED_DATA, buffer);
133: pkOut.write(PGPCompressedData.ZIP);
134: dOut = new DeflaterOutputStream(pkOut, new Deflater(
135: compression, true));
136: break;
137: case PGPCompressedData.ZLIB:
138: pkOut = new BCPGOutputStream(out,
139: PacketTags.COMPRESSED_DATA, buffer);
140: pkOut.write(PGPCompressedData.ZLIB);
141: dOut = new DeflaterOutputStream(pkOut, new Deflater(
142: compression));
143: break;
144: case PGPCompressedData.BZIP2:
145: pkOut = new BCPGOutputStream(out,
146: PacketTags.COMPRESSED_DATA, buffer);
147: pkOut.write(PGPCompressedData.BZIP2);
148: dOut = new CBZip2OutputStream(pkOut);
149: break;
150: case PGPCompressedData.UNCOMPRESSED:
151: pkOut = new BCPGOutputStream(out,
152: PacketTags.COMPRESSED_DATA, buffer);
153: pkOut.write(PGPCompressedData.UNCOMPRESSED);
154: dOut = pkOut;
155: break;
156: default:
157: throw new IllegalStateException("generator not initialised");
158: }
159:
160: return new WrappedGeneratorStream(dOut, this );
161: }
162:
163: /**
164: * Close the compressed object - this is equivalent to calling close on the stream
165: * returned by the open() method.
166: *
167: * @throws IOException
168: */
169: public void close() throws IOException {
170: if (dOut != null) {
171: if (dOut instanceof DeflaterOutputStream) {
172: DeflaterOutputStream dfOut = (DeflaterOutputStream) dOut;
173:
174: dfOut.finish();
175: } else if (dOut instanceof CBZip2OutputStream) {
176: CBZip2OutputStream cbOut = (CBZip2OutputStream) dOut;
177:
178: cbOut.finish();
179: }
180:
181: dOut.flush();
182:
183: pkOut.finish();
184: pkOut.flush();
185: out.flush();
186:
187: dOut = null;
188: pkOut = null;
189: out = null;
190: }
191: }
192: }
|