content: /*
  * Copyright 2010 Srikanth Reddy Lingala  
  * 
  * Licensed under the Apache License, Version 2.0 (the "License"); 
  * you may not use this file except in compliance with the License. 
  * You may obtain a copy of the License at 
  * 
  * https://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, 
  * software distributed under the License is distributed on an "AS IS" BASIS, 
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  * See the License for the specific language governing permissions and 
  * limitations under the License. 
  */
  
  package net.lingala.zip4j.io;
  
  import java.io.File;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.util.zip.Deflater;
  
  import net.lingala.zip4j.exception.ZipException;
  import net.lingala.zip4j.model.ZipModel;
  import net.lingala.zip4j.model.ZipParameters;
  import net.lingala.zip4j.util.InternalZipConstants;
  import net.lingala.zip4j.util.Zip4jConstants;
  
  public class DeflaterOutputStream extends CipherOutputStream {
  	
  	private byte[] buff;
  	protected Deflater deflater;
  	private boolean firstBytesRead;
  	
  	public DeflaterOutputStream(OutputStream outputStream, ZipModel zipModel) {
  		super(outputStream, zipModel);
  		deflater = new Deflater();
  		buff = new byte[InternalZipConstants.BUFF_SIZE];
  		firstBytesRead = false;
  	}
  	
  	public void putNextEntry(File file, ZipParameters zipParameters)
  			throws ZipException {
  		super.putNextEntry(file, zipParameters);
  		if (zipParameters.getCompressionMethod() == Zip4jConstants.COMP_DEFLATE) {
  			deflater.reset();
  			if ((zipParameters.getCompressionLevel() < 0 || zipParameters
  					.getCompressionLevel() > 9)
  					&& zipParameters.getCompressionLevel() != -1) {
  				throw new ZipException(
  						"invalid compression level for deflater. compression level should be in the range of 0-9");
  			}
  			deflater.setLevel(zipParameters.getCompressionLevel());
  		}
  	}
  
  	public void write(byte[] b) throws IOException {
  		write(b, 0, b.length);
  	}
  	
  	private void deflate () throws IOException {
  		int len = deflater.deflate(buff, 0, buff.length);
  		if (len > 0) {
  			if (deflater.finished()) {
  				if (len == 4) return;
  				if (len < 4) {
  					decrementCompressedFileSize(4 - len);
  					return;
  				}
  				len -= 4;
  			}
  			if (!firstBytesRead) {
  				super.write(buff, 2, len - 2);
  				firstBytesRead = true;
  			} else {
  				super.write(buff, 0, len);
  			}
  		}
  	}
  	
  	public void write(int bval) throws IOException {
  	    byte[] b = new byte[1];
  	    b[0] = (byte) bval;
  	    write(b, 0, 1);
  	}
  	
  	public void write(byte[] buf, int off, int len) throws IOException {
  		if (zipParameters.getCompressionMethod() != Zip4jConstants.COMP_DEFLATE) {
  			super.write(buf, off, len);
  		} else {
  			deflater.setInput(buf, off, len);
  			 while (!deflater.needsInput()) {
  				 deflate();
               }
  		}		
  	}
  	
  	public void closeEntry() throws IOException, ZipException {
  		if (zipParameters.getCompressionMethod() == Zip4jConstants.COMP_DEFLATE) {
  			if (!deflater.finished()) {
  				deflater.finish();
  				while (!deflater.finished()) {
  					deflate();
  				}
  			}
  			firstBytesRead = false;
  		}
  		super.closeEntry();
  	}
  	
  	public void finish() throws IOException, ZipException {
  		super.finish();
  	}
  }
  