KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > tools > CompressTool


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.tools;
6
7 import java.io.IOException JavaDoc;
8 import java.io.InputStream JavaDoc;
9 import java.io.OutputStream JavaDoc;
10 import java.sql.SQLException JavaDoc;
11 import java.util.zip.DeflaterOutputStream JavaDoc;
12 import java.util.zip.GZIPInputStream JavaDoc;
13 import java.util.zip.GZIPOutputStream JavaDoc;
14 import java.util.zip.InflaterInputStream JavaDoc;
15 import java.util.zip.ZipEntry JavaDoc;
16 import java.util.zip.ZipInputStream JavaDoc;
17 import java.util.zip.ZipOutputStream JavaDoc;
18
19 import org.h2.compress.CompressDeflate;
20 import org.h2.compress.CompressLZF;
21 import org.h2.compress.CompressNo;
22 import org.h2.compress.Compresser;
23 import org.h2.compress.LZFInputStream;
24 import org.h2.compress.LZFOutputStream;
25 import org.h2.message.Message;
26 import org.h2.util.StringUtils;
27
28 /**
29  * A tool to losslessly compress data, and expand the compressed data again.
30  */

31 public class CompressTool {
32     
33     private static CompressTool instance = new CompressTool();
34     private static byte[] buffer;
35     private static int MAX_BUFFER_SIZE = 64 * 1024 * 1024;
36     
37     private static byte[] getBuffer(int min) {
38         if(min > MAX_BUFFER_SIZE) {
39             return new byte[min];
40         }
41         if(buffer == null || buffer.length < min) {
42             buffer = new byte[min];
43         }
44         return buffer;
45     }
46     
47     private CompressTool() {
48     }
49     
50     /**
51      * Get the singleton.
52      *
53      * @return the singleton
54      */

55     public static CompressTool getInstance() {
56         return instance;
57     }
58     
59     /**
60      * Compressed the data using the specified algorithm. If no algorithm is supplied, LZF is used
61      *
62      * @param in the byte array with the original data
63      * @param algorithm the algorithm (LZF, DEFLATE)
64      * @return the compressed data
65      * @throws SQLException if a error occurs
66      */

67     public byte[] compress(byte[] in, String JavaDoc algorithm) throws SQLException JavaDoc {
68         int len = in.length;
69         if(in.length < 5) {
70             algorithm = "NO";
71         }
72         Compresser compress = getCompresser(algorithm);
73         byte[] buff = getBuffer((len < 100 ? len + 100 : len) * 2);
74         int newLen = compress(in, in.length, compress, buff);
75         byte[] out = new byte[newLen];
76         System.arraycopy(buff, 0, out, 0, newLen);
77         return out;
78     }
79
80     /**
81      * INTERNAL
82      */

83     public synchronized int compress(byte[] in, int len, Compresser compress, byte[] out) {
84         int newLen = 0;
85         out[0] = (byte)compress.getAlgorithm();
86         int start = 1 + writeInt(out, 1, len);
87         newLen = compress.compress(in, len, out, start);
88         if(newLen > len + start || newLen <= 0) {
89             out[0] = Compresser.NO;
90             System.arraycopy(in, 0, out, start, len);
91             newLen = len + start;
92         }
93         return newLen;
94     }
95     
96     /**
97      * Expands the compressed data.
98      *
99      * @param in the byte array with the compressed data
100      * @return the uncompressed data
101      * @throws SQLException if a error occurs
102      */

103     public byte[] expand(byte[] in) throws SQLException JavaDoc {
104         int algorithm = in[0];
105         Compresser compress = getCompresser(algorithm);
106         try {
107             int len = readInt(in, 1);
108             int start = 1 + getLength(len);
109             byte[] buff = new byte[len];
110             compress.expand(in, start, in.length-start, buff, 0, len);
111             return buff;
112         } catch(Throwable JavaDoc e) {
113             throw Message.getSQLException(Message.COMPRESSION_ERROR, null, e);
114         }
115     }
116
117     /**
118      * INTERNAL
119      */

120     public void expand(byte[] in, byte[] out, int outPos) throws SQLException JavaDoc {
121         int algorithm = in[0];
122         Compresser compress = getCompresser(algorithm);
123         try {
124             int len = readInt(in, 1);
125             int start = 1 + getLength(len);
126             compress.expand(in, start, in.length-start, out, outPos, len);
127         } catch(Throwable JavaDoc e) {
128             throw Message.getSQLException(Message.COMPRESSION_ERROR, null, e);
129         }
130     }
131     
132     private int readInt(byte[] buff, int pos) {
133         int x = buff[pos++] & 0xff;
134         if (x < 0x80) {
135             return x;
136         }
137         if (x < 0xc0) {
138             return ((x & 0x3f) << 8) + (buff[pos++] & 0xff);
139         }
140         if (x < 0xe0) {
141             return ((x & 0x1f) << 16) + ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
142         }
143         if (x < 0xf0) {
144             return ((x & 0xf) << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
145         }
146         return ((buff[pos++] & 0xff) << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
147     }
148     
149     private int writeInt(byte[] buff, int pos, int x) {
150         if (x < 0) {
151             buff[pos++] = (byte) 0xf0;
152             buff[pos++] = (byte) (x >> 24);
153             buff[pos++] = (byte) (x >> 16);
154             buff[pos++] = (byte) (x >> 8);
155             buff[pos++] = (byte) x;
156             return 5;
157         } else if (x < 0x80) {
158             buff[pos++] = (byte) x;
159             return 1;
160         } else if (x < 0x4000) {
161             buff[pos++] = (byte) (0x80 | (x >> 8));
162             buff[pos++] = (byte) x;
163             return 2;
164         } else if (x < 0x200000) {
165             buff[pos++] = (byte) (0xc0 | (x >> 16));
166             buff[pos++] = (byte) (x >> 8);
167             buff[pos++] = (byte) x;
168             return 3;
169         } else if (x < 0x10000000) {
170             buff[pos++] = (byte) (0xe0 | (x >> 24));
171             buff[pos++] = (byte) (x >> 16);
172             buff[pos++] = (byte) (x >> 8);
173             buff[pos++] = (byte) x;
174             return 4;
175         } else {
176             buff[pos++] = (byte) 0xf0;
177             buff[pos++] = (byte) (x >> 24);
178             buff[pos++] = (byte) (x >> 16);
179             buff[pos++] = (byte) (x >> 8);
180             buff[pos++] = (byte) x;
181             return 5;
182         }
183     }
184     
185     private int getLength(int x) {
186         if(x<0) {
187             return 5;
188         } else if(x< 0x80) {
189             return 1;
190         } else if(x < 0x4000) {
191             return 2;
192         } else if(x < 0x200000) {
193             return 3;
194         } else if(x < 0x10000000) {
195             return 4;
196         } else {
197             return 5;
198         }
199     }
200     
201     private Compresser getCompresser(String JavaDoc algorithm) throws SQLException JavaDoc {
202         if(algorithm == null) {
203             algorithm = "LZF";
204         }
205         int idx = algorithm.indexOf(' ');
206         String JavaDoc options = null;
207         if(idx > 0) {
208             options = algorithm.substring(idx+1);
209             algorithm = algorithm.substring(0, idx);
210         }
211         int a = getCompressAlgorithm(algorithm);
212         Compresser compress = getCompresser(a);
213         compress.setOptions(options);
214         return compress;
215     }
216     
217     /**
218      * INTERNAL
219      */

220     public int getCompressAlgorithm(String JavaDoc algorithm) throws SQLException JavaDoc {
221         algorithm = StringUtils.toUpperEnglish(algorithm);
222         if("NO".equals(algorithm)) {
223             return Compresser.NO;
224         } else if("LZF".equals(algorithm)) {
225             return Compresser.LZF;
226         } else if("DEFLATE".equals(algorithm)) {
227             return Compresser.DEFLATE;
228         } else {
229             throw Message.getSQLException(Message.UNSUPPORTED_COMPRESSION_ALGORITHM_1, algorithm);
230         }
231     }
232     
233     private Compresser getCompresser(int algorithm) throws SQLException JavaDoc {
234         switch(algorithm) {
235         case Compresser.NO:
236             return new CompressNo();
237         case Compresser.LZF:
238             return new CompressLZF();
239         case Compresser.DEFLATE:
240             return new CompressDeflate();
241         default:
242             throw Message.getSQLException(Message.UNSUPPORTED_COMPRESSION_ALGORITHM_1, ""+algorithm);
243         }
244     }
245     
246     /**
247      * INTERNAL
248      */

249     public static OutputStream JavaDoc wrapOutputStream(OutputStream JavaDoc out, String JavaDoc compressionAlgorithm, String JavaDoc entryName) throws SQLException JavaDoc {
250         try {
251             if("GZIP".equals(compressionAlgorithm)) {
252                 out = new GZIPOutputStream JavaDoc(out);
253             } else if("ZIP".equals(compressionAlgorithm)) {
254                 ZipOutputStream JavaDoc z = new ZipOutputStream JavaDoc(out);
255                 z.putNextEntry(new ZipEntry JavaDoc(entryName));
256                 out = z;
257             } else if("DEFLATE".equals(compressionAlgorithm)) {
258                 out = new DeflaterOutputStream JavaDoc(out);
259             } else if("LZF".equals(compressionAlgorithm)) {
260                 out = new LZFOutputStream(out);
261             } else if(compressionAlgorithm != null) {
262                 throw Message.getSQLException(Message.UNSUPPORTED_COMPRESSION_ALGORITHM_1, compressionAlgorithm);
263             }
264             return out;
265         } catch (IOException JavaDoc e) {
266             throw Message.convert(e);
267         }
268     }
269
270     /**
271      * INTERNAL
272      */

273     public static InputStream JavaDoc wrapInputStream(InputStream JavaDoc in, String JavaDoc compressionAlgorithm, String JavaDoc entryName) throws SQLException JavaDoc {
274         try {
275             if("GZIP".equals(compressionAlgorithm)) {
276                 in = new GZIPInputStream JavaDoc(in);
277             } else if("ZIP".equals(compressionAlgorithm)) {
278                 ZipInputStream JavaDoc z = new ZipInputStream JavaDoc(in);
279                 while(true) {
280                     ZipEntry JavaDoc entry = z.getNextEntry();
281                     if(entry == null) {
282                         return null;
283                     }
284                     if(entryName.equals(entry.getName())) {
285                         break;
286                     }
287                 }
288                 in = z;
289             } else if("DEFLATE".equals(compressionAlgorithm)) {
290                 in = new InflaterInputStream JavaDoc(in);
291             } else if("LZF".equals(compressionAlgorithm)) {
292                 in = new LZFInputStream(in);
293             } else if(compressionAlgorithm != null) {
294                 throw Message.getSQLException(Message.UNSUPPORTED_COMPRESSION_ALGORITHM_1, compressionAlgorithm);
295             }
296             return in;
297         } catch (IOException JavaDoc e) {
298             throw Message.convert(e);
299         }
300     }
301
302 }
303
304
Popular Tags