KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > lib > zlib > Zlib


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Charles Reich
28  */

29
30 package com.caucho.quercus.lib.zlib;
31
32 import com.caucho.quercus.QuercusModuleException;
33 import com.caucho.quercus.annotation.NotNull;
34 import com.caucho.quercus.annotation.Optional;
35 import com.caucho.quercus.annotation.ReturnNullAsFalse;
36 import com.caucho.quercus.env.*;
37 import com.caucho.quercus.lib.file.FileValue;
38 import com.caucho.quercus.lib.string.StringModule;
39 import com.caucho.util.L10N;
40 import com.caucho.vfs.TempBuffer;
41
42 import java.io.IOException JavaDoc;
43 import java.io.InputStream JavaDoc;
44 import java.util.logging.Level JavaDoc;
45 import java.util.logging.Logger JavaDoc;
46 import java.util.zip.DataFormatException JavaDoc;
47 import java.util.zip.Deflater JavaDoc;
48
49 /**
50  * Zlib object oriented API facade
51  */

52
53 public class Zlib {
54   private static final Logger JavaDoc log = Logger.getLogger(Zlib.class.getName());
55   private static final L10N L = new L10N(Zlib.class);
56
57   private InputStream JavaDoc _in;
58   private ZlibOutputStream _gzout;
59
60   private FileValue _fileValue;
61   private boolean _isGZIPInputStream;
62
63   /**
64    * XXX: todo - implement additional read/write modes (a,etc)
65    *
66    * Creates and sets GZIP stream if mode is 'w'
67    * Also creates _fileValue. All write functions are wrappers around
68    * the _fileValue functions using the private class GZFileValueWriter to
69    * compress the byte stream.
70    *
71    *
72    * @param fileName
73    * @param mode (ie: "w9" or "r7f")
74    * @param useIncludePath is always on
75    */

76   public Zlib(Env env, String JavaDoc filename, String JavaDoc mode, boolean useIncludePath)
77   {
78     String JavaDoc filemode = getFileMode(mode);
79     int compressionLevel = getCompressionLevel(mode);
80     int compressionStrategy = getCompressionStrategy(mode);
81
82     Value val = null;
83     // FileModule.fopen(env, filename, mode, useIncludePath, null);
84

85     if (val != BooleanValue.FALSE)
86       _fileValue = (FileValue)val;
87
88       /*
89     try {
90       if (filemode.equals("r")) {
91         _in = getGZIPInputStream();
92       }
93       else if (filemode.equals("w")) {
94         _gzout = new ZlibOutputStream(_fileValue.getPath().openWrite(),
95                       compressionLevel,
96                       compressionStrategy);
97       }
98       else if (filemode.equals("a")) {
99         _gzout = new ZlibOutputStream(_fileValue.getPath().openAppend(),
100                       compressionLevel,
101                       compressionStrategy);
102       }
103       else if (filemode.equals("x")) {
104         _gzout = new ZlibOutputStream(_fileValue.getPath().openWrite(),
105                       compressionLevel,
106                       compressionStrategy);
107       }
108     }
109     catch (IOException e) {
110       log.log(Level.FINE, e.getMessage(), e);
111       env.warning(L.l(e.getMessage()));
112     }
113       */

114   }
115
116
117   /**
118    * Reads from the input and writes to the gzip stream
119    * @param s
120    * @param length # of bytes to compress
121    * @return # of uncompressed bytes
122    */

123   public int gzwrite(Env env, InputStream JavaDoc is, @Optional("-1") int length)
124   {
125     if (_fileValue == null) {
126       env.warning(L.l("file could not be open for writing"));
127       return -1;
128     }
129
130     TempBuffer tb = TempBuffer.allocate();
131     byte[] buffer = tb.getBuffer();
132
133     int inputSize = 0;
134     int sublen;
135
136     if (length < 0)
137       length = Integer.MAX_VALUE;
138
139     try {
140       while (length > 0) {
141     if (buffer.length < length)
142       sublen = buffer.length;
143     else
144       sublen = length;
145
146     sublen = is.read(buffer, 0, sublen);
147
148     if (sublen <= 0)
149       break;
150
151     _gzout.write(buffer, 0, sublen);
152     
153     inputSize += sublen;
154     length -= sublen;
155       }
156     }
157     catch (IOException JavaDoc e) {
158       log.log(Level.FINE, e.getMessage(), e);
159       env.warning(L.l(e.getMessage()));
160     }
161     
162     TempBuffer.free(tb);
163     return inputSize;
164   }
165
166
167   /**
168    * Closes the gzip stream
169    * @return true if successful, false otherwise
170    */

171   public boolean gzclose()
172   {
173     if (_fileValue == null) {
174       return false;
175     }
176
177     try {
178       if (_gzout != null) {
179         _gzout.close();
180         _gzout = null;
181       }
182       
183       if (_in != null) {
184         _in.close();
185         _in = null;
186       }
187     }
188     catch (Exception JavaDoc e) {
189       throw QuercusModuleException.create(e);
190     }
191     return true;
192   }
193
194   /**
195    * alias of gzwrite
196    * @param env
197    * @param s
198    * @param length
199    * @return # of uncompressed bytes
200    */

201   public int gzputs(Env env,
202             @NotNull InputStream JavaDoc is,
203             @Optional("-1") int length)
204   {
205     return gzwrite(env, is, length);
206   }
207
208   /**
209    *
210    * @return the next character or BooleanValue.FALSE
211    */

212   public Value gzgetc()
213   {
214     try {
215       int ch = _in.read();
216
217       if (ch >= 0)
218     return new StringValueImpl(Character.toString((char) ch));
219       else
220     return BooleanValue.FALSE;
221     } catch (IOException JavaDoc e) {
222       throw QuercusModuleException.create(e);
223     }
224   }
225
226   /**
227    * Gets a (uncompressed) string of up to 'length' bytes read
228    * from the given file pointer. Reading ends when 'length' bytes
229    * have been read, on a newline, or on EOF (whichever comes first).
230    *
231    * @param length
232    * @return StringValue
233    */

234   @ReturnNullAsFalse
235   public StringValue gzgets(int length)
236   {
237     if (_in == null)
238       return null;
239
240     StringBuilderValue sbv = new StringBuilderValue();
241     int readChar;
242
243     try {
244       for (int i = 0; i < length - 1; i++) {
245         readChar = _in.read();
246     
247         if (readChar >= 0) {
248           sbv.append((char) readChar);
249       
250           if (readChar == '\n' || readChar == '\r')
251             break;
252         } else
253           break;
254       }
255     } catch (Exception JavaDoc e) {
256       throw QuercusModuleException.create(e);
257     }
258
259     if (sbv.length() > 0)
260       return sbv;
261     else
262       return null;
263   }
264
265   /**
266    * helper function for ZlibModule.gzfile
267    * need to have created a Zlib before calling this
268    *
269    * @return array of uncompressed lines
270    * @throws IOException
271    * @throws DataFormatException
272    */

273   public ArrayValue gzfile()
274   {
275     Value line;
276     int oldLength = 0;
277
278     ArrayValue array = new ArrayValueImpl();
279
280     try {
281       //read in String BuilderValue's initial capacity
282
while ((line = gzgets(Integer.MAX_VALUE)) != BooleanValue.FALSE) {
283         array.put(line);
284       }
285
286       return array;
287     } catch (Exception JavaDoc e) {
288       throw QuercusModuleException.create(e);
289     }
290   }
291
292   /**
293    * same as gzgets but does not stop at '\n' or '\r'
294    * @param length
295    * @return BinaryValue, an empty BinaryValue if no data read
296    * @throws IOException
297    * @throws DataFormatException
298    */

299   public BinaryValue gzread(int length)
300   {
301     BinaryBuilderValue sbv = new BinaryBuilderValue();
302     int readChar;
303
304     if (_in == null)
305       return sbv;
306
307     try {
308       for (int i = 0; i < length; i++) {
309         readChar = _in.read();
310     
311         if (readChar >= 0) {
312           sbv.append(readChar);
313         } else
314           break;
315       }
316     } catch (Exception JavaDoc e) {
317       throw QuercusModuleException.create(e);
318     }
319
320     return sbv;
321   }
322
323   /**
324    *
325    * @return true if eof
326    */

327   public boolean gzeof()
328   {
329     if (_isGZIPInputStream)
330       return ((GZIPInputStream)_in).isEOS();
331     else {
332       try {
333         _in.mark(1);
334         int ch = _in.read();
335         _in.reset();
336         return (ch == -1);
337       } catch (IOException JavaDoc e) {
338         throw new QuercusModuleException(e);
339       }
340     }
341   }
342
343   /**
344    *
345    * @param length
346    * @param allowedTags
347    * @return next line stripping tags
348    * @throws IOException
349    * @throws DataFormatException
350    */

351   @ReturnNullAsFalse
352   public StringValue gzgetss(int length,
353                  @Optional String JavaDoc allowedTags)
354   {
355     try {
356       if (_in == null)
357         return null;
358
359       StringBuilderValue sbv = new StringBuilderValue();
360       int readChar;
361       for (int i=0; i < length; i++) {
362         readChar = _in.read();
363         if (readChar >= 0) {
364           sbv.append((char)readChar);
365           if (readChar == '\n' || readChar == '\r')
366             break;
367         } else
368           break;
369       }
370       if (sbv.length() > 0)
371     return StringModule.strip_tags(sbv, allowedTags);
372       else
373     return null;
374     } catch (Exception JavaDoc e) {
375       throw QuercusModuleException.create(e);
376     }
377   }
378
379   /**
380    * resets to the beginning of the file stream.
381    *
382    * @return always true
383    * @throws IOException
384    */

385   public boolean gzrewind()
386   {
387     try {
388       if (_in != null )
389         _in.close();
390
391       _in = getGZIPInputStream();
392     }
393     catch (IOException JavaDoc e)
394     {
395       throw QuercusModuleException.create(e);
396     }
397     return true;
398   }
399
400   /**
401    * helper function to open file for reading when necessary
402    *
403    * @throws IOException
404    */

405   protected InputStream JavaDoc getGZIPInputStream()
406     throws IOException JavaDoc
407   {
408     try {
409       _isGZIPInputStream = true;
410       return new GZIPInputStream(_fileValue.getPath().openRead());
411     }
412     catch (IOException JavaDoc e) {
413       //GZIPInputStream throws an Exception if not in gzip format
414
//else open uncompressed stream
415
_isGZIPInputStream = false;
416
417       return _fileValue.getPath().openRead();
418     }
419   }
420
421   /**
422    * Helper function to retrieve the filemode closest to the end
423    * Note: PHP5 unexpectedly fails when 'x' is the mode.
424    *
425    * XXX todo: toss a warning if '+' is found (gzip cannot be open for both reading and writing at the same time)
426    *
427    */

428   private String JavaDoc getFileMode(String JavaDoc input)
429   {
430     String JavaDoc modifier = "";
431     String JavaDoc filemode = input.substring(0, 1);
432
433     for (int i = 1; i < input.length(); i++ )
434     {
435       char ch = input.charAt(i);
436       switch (ch) {
437         case 'r':
438           filemode = "r";
439           break;
440         case 'w':
441           filemode = "w";
442           break;
443         case 'a':
444           filemode = "a";
445           break;
446         case 'b':
447           modifier = "b";
448           break;
449         case 't':
450           modifier = "t";
451           break;
452       }
453     }
454     return filemode + modifier;
455   }
456
457   /**
458    * Helper function to retrieve the compression level like how PHP5 does it.
459    * 1. finds the compression level nearest to the end and returns that
460    */

461   private int getCompressionLevel(String JavaDoc input)
462   {
463     for( int i = input.length() - 1; i >= 0; i-- )
464     {
465       char ch = input.charAt(i);
466       if( ch >= '0' && ch <= '9' )
467         return ch - '0';
468     }
469     return Deflater.DEFAULT_COMPRESSION;
470   }
471
472   /**
473    * Helper function to retrieve the compression strategy like how PHP5 does it.
474    * 1. finds the compression strategy nearest to the end and returns that
475    */

476   private int getCompressionStrategy(String JavaDoc input)
477   {
478     for( int i = input.length() - 1; i >= 0; i-- )
479     {
480       char ch = input.charAt(i);
481       switch (ch) {
482       case 'f':
483         return Deflater.FILTERED;
484       case 'h':
485         return Deflater.HUFFMAN_ONLY;
486       }
487     }
488     return Deflater.DEFAULT_STRATEGY;
489   }
490
491   public String JavaDoc toString()
492   {
493     return "Zlib[]";
494   }
495 }
496
Popular Tags