jdk/src/share/classes/java/util/zip/Deflater.java
changeset 5173 36ad2c5fbb51
parent 4178 61284fdd478f
child 5194 ba7f04720557
equal deleted inserted replaced
5172:3e3db347f963 5173:36ad2c5fbb51
     1 /*
     1 /*
     2  * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
     2  * Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     7  * published by the Free Software Foundation.  Sun designates this
    70  * @see         Inflater
    70  * @see         Inflater
    71  * @author      David Connelly
    71  * @author      David Connelly
    72  */
    72  */
    73 public
    73 public
    74 class Deflater {
    74 class Deflater {
    75     private long strm;
    75 
       
    76     private final ZStreamRef zsRef;
    76     private byte[] buf = new byte[0];
    77     private byte[] buf = new byte[0];
    77     private int off, len;
    78     private int off, len;
    78     private int level, strategy;
    79     private int level, strategy;
    79     private boolean setParams;
    80     private boolean setParams;
    80     private boolean finish, finished;
    81     private boolean finish, finished;
   163      * @param nowrap if true then use GZIP compatible compression
   164      * @param nowrap if true then use GZIP compatible compression
   164      */
   165      */
   165     public Deflater(int level, boolean nowrap) {
   166     public Deflater(int level, boolean nowrap) {
   166         this.level = level;
   167         this.level = level;
   167         this.strategy = DEFAULT_STRATEGY;
   168         this.strategy = DEFAULT_STRATEGY;
   168         strm = init(level, DEFAULT_STRATEGY, nowrap);
   169         this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));
   169     }
   170     }
   170 
   171 
   171     /**
   172     /**
   172      * Creates a new compressor using the specified compression level.
   173      * Creates a new compressor using the specified compression level.
   173      * Compressed data will be generated in ZLIB format.
   174      * Compressed data will be generated in ZLIB format.
   191      * @param b the input data bytes
   192      * @param b the input data bytes
   192      * @param off the start offset of the data
   193      * @param off the start offset of the data
   193      * @param len the length of the data
   194      * @param len the length of the data
   194      * @see Deflater#needsInput
   195      * @see Deflater#needsInput
   195      */
   196      */
   196     public synchronized void setInput(byte[] b, int off, int len) {
   197     public void setInput(byte[] b, int off, int len) {
   197         if (b== null) {
   198         if (b== null) {
   198             throw new NullPointerException();
   199             throw new NullPointerException();
   199         }
   200         }
   200         if (off < 0 || len < 0 || off > b.length - len) {
   201         if (off < 0 || len < 0 || off > b.length - len) {
   201             throw new ArrayIndexOutOfBoundsException();
   202             throw new ArrayIndexOutOfBoundsException();
   202         }
   203         }
   203         this.buf = b;
   204         synchronized (zsRef) {
   204         this.off = off;
   205             this.buf = b;
   205         this.len = len;
   206             this.off = off;
       
   207             this.len = len;
       
   208         }
   206     }
   209     }
   207 
   210 
   208     /**
   211     /**
   209      * Sets input data for compression. This should be called whenever
   212      * Sets input data for compression. This should be called whenever
   210      * needsInput() returns true indicating that more input data is required.
   213      * needsInput() returns true indicating that more input data is required.
   225      * @param off the start offset of the data
   228      * @param off the start offset of the data
   226      * @param len the length of the data
   229      * @param len the length of the data
   227      * @see Inflater#inflate
   230      * @see Inflater#inflate
   228      * @see Inflater#getAdler
   231      * @see Inflater#getAdler
   229      */
   232      */
   230     public synchronized void setDictionary(byte[] b, int off, int len) {
   233     public void setDictionary(byte[] b, int off, int len) {
   231         if (strm == 0 || b == null) {
   234         if (b == null) {
   232             throw new NullPointerException();
   235             throw new NullPointerException();
   233         }
   236         }
   234         if (off < 0 || len < 0 || off > b.length - len) {
   237         if (off < 0 || len < 0 || off > b.length - len) {
   235             throw new ArrayIndexOutOfBoundsException();
   238             throw new ArrayIndexOutOfBoundsException();
   236         }
   239         }
   237         setDictionary(strm, b, off, len);
   240         synchronized (zsRef) {
       
   241             ensureOpen();
       
   242             setDictionary(zsRef.address(), b, off, len);
       
   243         }
   238     }
   244     }
   239 
   245 
   240     /**
   246     /**
   241      * Sets preset dictionary for compression. A preset dictionary is used
   247      * Sets preset dictionary for compression. A preset dictionary is used
   242      * when the history buffer can be predetermined. When the data is later
   248      * when the history buffer can be predetermined. When the data is later
   255      * Sets the compression strategy to the specified value.
   261      * Sets the compression strategy to the specified value.
   256      * @param strategy the new compression strategy
   262      * @param strategy the new compression strategy
   257      * @exception IllegalArgumentException if the compression strategy is
   263      * @exception IllegalArgumentException if the compression strategy is
   258      *                                     invalid
   264      *                                     invalid
   259      */
   265      */
   260     public synchronized void setStrategy(int strategy) {
   266     public void setStrategy(int strategy) {
   261         switch (strategy) {
   267         switch (strategy) {
   262           case DEFAULT_STRATEGY:
   268           case DEFAULT_STRATEGY:
   263           case FILTERED:
   269           case FILTERED:
   264           case HUFFMAN_ONLY:
   270           case HUFFMAN_ONLY:
   265             break;
   271             break;
   266           default:
   272           default:
   267             throw new IllegalArgumentException();
   273             throw new IllegalArgumentException();
   268         }
   274         }
   269         if (this.strategy != strategy) {
   275         synchronized (zsRef) {
   270             this.strategy = strategy;
   276             if (this.strategy != strategy) {
   271             setParams = true;
   277                 this.strategy = strategy;
       
   278                 setParams = true;
       
   279             }
   272         }
   280         }
   273     }
   281     }
   274 
   282 
   275     /**
   283     /**
   276      * Sets the current compression level to the specified value.
   284      * Sets the current compression level to the specified value.
   277      * @param level the new compression level (0-9)
   285      * @param level the new compression level (0-9)
   278      * @exception IllegalArgumentException if the compression level is invalid
   286      * @exception IllegalArgumentException if the compression level is invalid
   279      */
   287      */
   280     public synchronized void setLevel(int level) {
   288     public void setLevel(int level) {
   281         if ((level < 0 || level > 9) && level != DEFAULT_COMPRESSION) {
   289         if ((level < 0 || level > 9) && level != DEFAULT_COMPRESSION) {
   282             throw new IllegalArgumentException("invalid compression level");
   290             throw new IllegalArgumentException("invalid compression level");
   283         }
   291         }
   284         if (this.level != level) {
   292         synchronized (zsRef) {
   285             this.level = level;
   293             if (this.level != level) {
   286             setParams = true;
   294                 this.level = level;
       
   295                 setParams = true;
       
   296             }
   287         }
   297         }
   288     }
   298     }
   289 
   299 
   290     /**
   300     /**
   291      * Returns true if the input data buffer is empty and setInput()
   301      * Returns true if the input data buffer is empty and setInput()
   299 
   309 
   300     /**
   310     /**
   301      * When called, indicates that compression should end with the current
   311      * When called, indicates that compression should end with the current
   302      * contents of the input buffer.
   312      * contents of the input buffer.
   303      */
   313      */
   304     public synchronized void finish() {
   314     public void finish() {
   305         finish = true;
   315         synchronized (zsRef) {
       
   316             finish = true;
       
   317         }
   306     }
   318     }
   307 
   319 
   308     /**
   320     /**
   309      * Returns true if the end of the compressed data output stream has
   321      * Returns true if the end of the compressed data output stream has
   310      * been reached.
   322      * been reached.
   311      * @return true if the end of the compressed data output stream has
   323      * @return true if the end of the compressed data output stream has
   312      * been reached
   324      * been reached
   313      */
   325      */
   314     public synchronized boolean finished() {
   326     public boolean finished() {
   315         return finished;
   327         synchronized (zsRef) {
       
   328             return finished;
       
   329         }
   316     }
   330     }
   317 
   331 
   318     /**
   332     /**
   319      * Compresses the input data and fills specified buffer with compressed
   333      * Compresses the input data and fills specified buffer with compressed
   320      * data. Returns actual number of bytes of compressed data. A return value
   334      * data. Returns actual number of bytes of compressed data. A return value
   397      *         the output buffer
   411      *         the output buffer
   398      *
   412      *
   399      * @throws IllegalArgumentException if the flush mode is invalid
   413      * @throws IllegalArgumentException if the flush mode is invalid
   400      * @since 1.7
   414      * @since 1.7
   401      */
   415      */
   402     public synchronized int deflate(byte[] b, int off, int len, int flush) {
   416     public int deflate(byte[] b, int off, int len, int flush) {
   403         if (b == null) {
   417         if (b == null) {
   404             throw new NullPointerException();
   418             throw new NullPointerException();
   405         }
   419         }
   406         if (off < 0 || len < 0 || off > b.length - len) {
   420         if (off < 0 || len < 0 || off > b.length - len) {
   407             throw new ArrayIndexOutOfBoundsException();
   421             throw new ArrayIndexOutOfBoundsException();
   408         }
   422         }
   409         if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
   423         synchronized (zsRef) {
   410             flush == FULL_FLUSH)
   424             ensureOpen();
   411             return deflateBytes(b, off, len, flush);
   425             if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
   412         throw new IllegalArgumentException();
   426                 flush == FULL_FLUSH)
       
   427                 return deflateBytes(zsRef.address(), b, off, len, flush);
       
   428             throw new IllegalArgumentException();
       
   429         }
   413     }
   430     }
   414 
   431 
   415     /**
   432     /**
   416      * Returns the ADLER-32 value of the uncompressed data.
   433      * Returns the ADLER-32 value of the uncompressed data.
   417      * @return the ADLER-32 value of the uncompressed data
   434      * @return the ADLER-32 value of the uncompressed data
   418      */
   435      */
   419     public synchronized int getAdler() {
   436     public int getAdler() {
   420         ensureOpen();
   437         synchronized (zsRef) {
   421         return getAdler(strm);
   438             ensureOpen();
       
   439             return getAdler(zsRef.address());
       
   440         }
   422     }
   441     }
   423 
   442 
   424     /**
   443     /**
   425      * Returns the total number of uncompressed bytes input so far.
   444      * Returns the total number of uncompressed bytes input so far.
   426      *
   445      *
   438      * Returns the total number of uncompressed bytes input so far.</p>
   457      * Returns the total number of uncompressed bytes input so far.</p>
   439      *
   458      *
   440      * @return the total (non-negative) number of uncompressed bytes input so far
   459      * @return the total (non-negative) number of uncompressed bytes input so far
   441      * @since 1.5
   460      * @since 1.5
   442      */
   461      */
   443     public synchronized long getBytesRead() {
   462     public long getBytesRead() {
   444         ensureOpen();
   463         synchronized (zsRef) {
   445         return getBytesRead(strm);
   464             ensureOpen();
       
   465             return getBytesRead(zsRef.address());
       
   466         }
   446     }
   467     }
   447 
   468 
   448     /**
   469     /**
   449      * Returns the total number of compressed bytes output so far.
   470      * Returns the total number of compressed bytes output so far.
   450      *
   471      *
   462      * Returns the total number of compressed bytes output so far.</p>
   483      * Returns the total number of compressed bytes output so far.</p>
   463      *
   484      *
   464      * @return the total (non-negative) number of compressed bytes output so far
   485      * @return the total (non-negative) number of compressed bytes output so far
   465      * @since 1.5
   486      * @since 1.5
   466      */
   487      */
   467     public synchronized long getBytesWritten() {
   488     public long getBytesWritten() {
   468         ensureOpen();
   489         synchronized (zsRef) {
   469         return getBytesWritten(strm);
   490             ensureOpen();
       
   491             return getBytesWritten(zsRef.address());
       
   492         }
   470     }
   493     }
   471 
   494 
   472     /**
   495     /**
   473      * Resets deflater so that a new set of input data can be processed.
   496      * Resets deflater so that a new set of input data can be processed.
   474      * Keeps current compression level and strategy settings.
   497      * Keeps current compression level and strategy settings.
   475      */
   498      */
   476     public synchronized void reset() {
   499     public void reset() {
   477         ensureOpen();
   500         synchronized (zsRef) {
   478         reset(strm);
   501             ensureOpen();
   479         finish = false;
   502             reset(zsRef.address());
   480         finished = false;
   503             finish = false;
   481         off = len = 0;
   504             finished = false;
       
   505             off = len = 0;
       
   506         }
   482     }
   507     }
   483 
   508 
   484     /**
   509     /**
   485      * Closes the compressor and discards any unprocessed input.
   510      * Closes the compressor and discards any unprocessed input.
   486      * This method should be called when the compressor is no longer
   511      * This method should be called when the compressor is no longer
   487      * being used, but will also be called automatically by the
   512      * being used, but will also be called automatically by the
   488      * finalize() method. Once this method is called, the behavior
   513      * finalize() method. Once this method is called, the behavior
   489      * of the Deflater object is undefined.
   514      * of the Deflater object is undefined.
   490      */
   515      */
   491     public synchronized void end() {
   516     public void end() {
   492         if (strm != 0) {
   517         synchronized (zsRef) {
   493             end(strm);
   518             long addr = zsRef.address();
   494             strm = 0;
   519             zsRef.clear();
   495             buf = null;
   520             if (addr != 0) {
       
   521                 end(addr);
       
   522                 buf = null;
       
   523             }
   496         }
   524         }
   497     }
   525     }
   498 
   526 
   499     /**
   527     /**
   500      * Closes the compressor when garbage is collected.
   528      * Closes the compressor when garbage is collected.
   502     protected void finalize() {
   530     protected void finalize() {
   503         end();
   531         end();
   504     }
   532     }
   505 
   533 
   506     private void ensureOpen() {
   534     private void ensureOpen() {
   507         if (strm == 0)
   535         assert Thread.holdsLock(zsRef);
   508             throw new NullPointerException();
   536         if (zsRef.address() == 0)
       
   537             throw new NullPointerException("Deflater has been closed");
   509     }
   538     }
   510 
   539 
   511     private static native void initIDs();
   540     private static native void initIDs();
   512     private native static long init(int level, int strategy, boolean nowrap);
   541     private native static long init(int level, int strategy, boolean nowrap);
   513     private native static void setDictionary(long strm, byte[] b, int off,
   542     private native static void setDictionary(long addr, byte[] b, int off, int len);
   514                                              int len);
   543     private native int deflateBytes(long addr, byte[] b, int off, int len,
   515     private native int deflateBytes(byte[] b, int off, int len, int flush);
   544                                     int flush);
   516     private native static int getAdler(long strm);
   545     private native static int getAdler(long addr);
   517     private native static long getBytesRead(long strm);
   546     private native static long getBytesRead(long addr);
   518     private native static long getBytesWritten(long strm);
   547     private native static long getBytesWritten(long addr);
   519     private native static void reset(long strm);
   548     private native static void reset(long addr);
   520     private native static void end(long strm);
   549     private native static void end(long addr);
   521 }
   550 }