function files = extractArchive(outputDir, archiveInStream, fcnName)
%EXTRACTARCHIVE Extract archive file contents
%
%   EXTRACTARCHIVE extracts archive file contents to OUTPUTDIR from an
%   archive defined by ARCHIVEINSTREAM. The output FILES is a string cell
%   array of relative path filenames extracted from the archive.
%
%   OUTPUTDIR is a string containing the directory for the extracted files.
%
%   ARCHIVEINSTREAM is a Java stream object attached to the input archive
%   file.
%
%   FCNNAME is the string name of the calling function.

%   Copyright 2004-2005 The MathWorks, Inc.
%   $Revision: 1.1.6.1.2.1 $   $Date: 2005/01/18 16:06:45 $

% 
stop = false;
files = {};
verbose = false;

% Create a stream copier to copy files
streamCopier = ...
   com.mathworks.mlwidgets.io.InterruptibleStreamCopier.getInterruptibleStreamCopier;

% Extract each entry
while ~stop
   try
      entry = archiveInStream.getNextEntry;
   catch
      format = [upper(fcnName(3)) fcnName(4:end)];
      eid = sprintf('MATLAB:%s:invalid%sFileEntry',fcnName, format);
      error(eid,'Invalid %s file.', upper(format));
   end
   if isempty(entry)
      stop = true;
   else
      % Process the entry
      % Obtain the last modified time
      switch fcnName
         case 'untar'
            % Verify the TAR-file
            if (entry.getSize == 0) && ...
                  ~entry.isDirectory && ...
                  isempty(char(entry.getUserName)) && ...
                  isempty(char(entry.getGroupName))
               format = [upper(fcnName(3)) fcnName(4:end)];
               eid = sprintf('MATLAB:%s:invalid%sFile',fcnName, format);
               error(eid,'Invalid %s file.', upper(format));
            end
            lastModified = entry.getModTime;
            lastModified = lastModified.getTime;
         case 'unzip'
            lastModified = entry.getTime;
         otherwise
            eid = sprintf('MATLAB:%s:unknownFunctionName',fcnName);
            error(eid,'Internal error: Unknown function name: "%s"',fcnName);
      end

      % Obtain the entry's output name
      outputName = fullfile(outputDir,char(entry.getName));

      if ispc
         outputName = strrep(outputName,'\','/');
      end

      if numel(outputName) >2 && isequal(outputName(1:2),'./')
         files(end+1) = {outputName(3:end)};
      else
         files(end+1) = {outputName};
      end

      % If the file is a directory, create it,
      %  otherwise copy the entry to the output file
      file = java.io.File(outputName);
      if entry.isDirectory  
         if ~exist(outputName,'dir') 
            mkdir(outputName);
         end
      else
         parentDir = char(file.getParent.toString);
         if ~exist(parentDir,'dir')
            mkdir(parentDir)
         end
         try
            if verbose
               fprintf('inflating: %s\n',outputName);
            end
            fileOutputStream = java.io.FileOutputStream(file);
         catch
            eid = sprintf('MATLAB:%s:unableToCreate',fcnName);
            error(eid,'Could not create "%s".',outputName);
         end
         % Extract entry to output stream.
         streamCopier.copyStream(archiveInStream,fileOutputStream);
         % Close streams.
         fileOutputStream.close;

         % Set timestamp.
         file.setLastModified(lastModified);

      end
   end
end
