gt:         while (read != -1)
context: /*
   * Copyright (C) 2005-2010 Alfresco Software Limited.
   *
   * This file is part of Alfresco
   *
   * Alfresco is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Lesser General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * Alfresco is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public License
   * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
   */
  package org.alfresco.repo.download;
  
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.util.Deque;
  import java.util.Iterator;
  import java.util.LinkedList;
  
  import org.alfresco.model.ContentModel;
  import org.alfresco.repo.transaction.RetryingTransactionHelper;
  import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
  import org.alfresco.service.cmr.coci.CheckOutCheckInService;
  import org.alfresco.service.cmr.download.DownloadStatus;
  import org.alfresco.service.cmr.download.DownloadStatus.Status;
  import org.alfresco.service.cmr.repository.ContentData;
  import org.alfresco.service.cmr.repository.NodeRef;
  import org.alfresco.service.cmr.repository.NodeService;
  import org.alfresco.service.cmr.view.ExporterContext;
  import org.alfresco.service.cmr.view.ExporterException;
  import org.alfresco.service.namespace.QName;
  import org.alfresco.util.Pair;
  import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
  import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
  import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.UnicodeExtraFieldPolicy;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  
  /**
   * Handler for exporting node content to a ZIP file
   * 
   * @author Alex Miller
   */
  public class ZipDownloadExporter extends BaseExporter
  {
      private static Logger log = LoggerFactory.getLogger(ZipDownloadExporter.class);
      
      private static final String PATH_SEPARATOR = "/";
  
      protected ZipArchiveOutputStream zipStream;
  
      private NodeRef downloadNodeRef;
      private int sequenceNumber = 1;
      private long total;
      private long done;
      private long totalFileCount;
      private long filesAddedCount;
      
      private RetryingTransactionHelper transactionHelper;
      private DownloadStorage downloadStorage;
      private DownloadStatusUpdateService updateService;
  
      private Deque<Pair<String, NodeRef>> path = new LinkedList<Pair<String, NodeRef>>();
      private String currentName;
  
      private OutputStream outputStream;
  
      /**
       * Construct
       *
       * @param zipFile File
       * @param checkOutCheckInService CheckOutCheckInService
       * @param nodeService NodeService
       * @param transactionHelper RetryingTransactionHelper
       * @param updateService DownloadStatusUpdateService
       * @param downloadStorage DownloadStorage
       * @param downloadNodeRef NodeRef
       * @param total long
       * @param totalFileCount long
       */
      public ZipDownloadExporter(File zipFile, CheckOutCheckInService checkOutCheckInService, NodeService nodeService, RetryingTransactionHelper transactionHelper, DownloadStatusUpdateService updateService, DownloadStorage downloadStorage, NodeRef downloadNodeRef, long total, long totalFileCount)
      {
          super(checkOutCheckInService, nodeService);
          try
          {
              this.outputStream = new FileOutputStream(zipFile);
              this.updateService = updateService;
              this.transactionHelper = transactionHelper;
              this.downloadStorage = downloadStorage;
              
              this.downloadNodeRef = downloadNodeRef;
              this.total = total;
              this.totalFileCount = totalFileCount;
          }
          catch (FileNotFoundException e)
          {
              throw new ExporterException("Failed to create zip file", e);
          }
      }
  
      @Override
      public void start(final ExporterContext context)
      {
          zipStream = new ZipArchiveOutputStream(outputStream);
          // NOTE: This encoding allows us to workaround bug...
          //       http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4820807
          zipStream.setEncoding("UTF-8");
          zipStream.setCreateUnicodeExtraFields(UnicodeExtraFieldPolicy.ALWAYS);
          zipStream.setUseLanguageEncodingFlag(true);
          zipStream.setFallbackToUTF8(true);
      }
  
      @Override
      public void startNode(NodeRef nodeRef)
      {
          this.currentName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
          path.push(new Pair<String, NodeRef>(currentName, nodeRef));
          if (ContentModel.TYPE_FOLDER.equals(nodeService.getType(nodeRef)))
          {
              String path = getPath() + PATH_SEPARATOR;
              ZipArchiveEntry archiveEntry = new ZipArchiveEntry(path);
              try
              {
                  zipStream.putArchiveEntry(archiveEntry);
                  zipStream.closeArchiveEntry();
              }
              catch (IOException e)
              {
                  throw new ExporterException("Unexpected IOException adding folder entry", e);
              }
          }
      }
      
      @Override
      public void contentImpl(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index)
      {
          // if the content stream to output is empty, then just return content descriptor as is
          if (content == null)
          {
              return;
          }
          
          try
          {
              // ALF-2016
              ZipArchiveEntry zipEntry=new ZipArchiveEntry(getPath());
              zipStream.putArchiveEntry(zipEntry);
              
              // copy export stream to zip
              copyStream(zipStream, content);
              
              zipStream.closeArchiveEntry();
              filesAddedCount = filesAddedCount + 1;
          }
          catch (IOException e)
          {
              throw new ExporterException("Failed to zip export stream", e);
          }
      }
      
      @Override
      public void endNode(NodeRef nodeRef)
      {
          path.pop();
      }
  
      @Override
      public void end()
      {
          try
          {
              zipStream.close();
          }
          catch (IOException error)
          {
              throw new ExporterException("Unexpected error closing zip stream!", error);
          }
      }
  
      private String getPath()
      {
          if (path.size() < 1) 
          {
              throw new IllegalStateException("No elements in path!");    
          }
          
          Iterator<Pair<String, NodeRef>> iter = path.descendingIterator();
          StringBuilder pathBuilder = new StringBuilder();
          
          while (iter.hasNext())
          {
              Pair<String, NodeRef> element = iter.next();
              
              pathBuilder.append(element.getFirst());
              if (iter.hasNext())
              {
                  pathBuilder.append(PATH_SEPARATOR);
              }
          }
          
          return pathBuilder.toString();
      }
  
      /**
       * Copy input stream to output stream
       * 
       * @param output  output stream
       * @param in  input stream
       * @throws IOException
       */
      private void copyStream(OutputStream output, InputStream in)
          throws IOException
      {
          byte[] buffer = new byte[2048 * 10];
          int read = in.read(buffer, 0, 2048 *10);
          int i = 0;
  