src/core/net/sf/basedb/util/zip/ZipUnpacker.java

Code
Comments
Other
Rev Date Author Line
2681 29 Sep 06 nicklas 1 /**
2681 29 Sep 06 nicklas 2   $Id$
2681 29 Sep 06 nicklas 3
3675 16 Aug 07 jari 4   Copyright (C) 2006 Nicklas Nordborg
3675 16 Aug 07 jari 5   Copyright (C) 2007 Johan Enell
2681 29 Sep 06 nicklas 6
2681 29 Sep 06 nicklas 7   This file is part of BASE - BioArray Software Environment.
2681 29 Sep 06 nicklas 8   Available at http://base.thep.lu.se/
2681 29 Sep 06 nicklas 9
2681 29 Sep 06 nicklas 10   BASE is free software; you can redistribute it and/or
2681 29 Sep 06 nicklas 11   modify it under the terms of the GNU General Public License
4479 05 Sep 08 jari 12   as published by the Free Software Foundation; either version 3
2681 29 Sep 06 nicklas 13   of the License, or (at your option) any later version.
2681 29 Sep 06 nicklas 14
2681 29 Sep 06 nicklas 15   BASE is distributed in the hope that it will be useful,
2681 29 Sep 06 nicklas 16   but WITHOUT ANY WARRANTY; without even the implied warranty of
2681 29 Sep 06 nicklas 17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2681 29 Sep 06 nicklas 18   GNU General Public License for more details.
2681 29 Sep 06 nicklas 19
2681 29 Sep 06 nicklas 20   You should have received a copy of the GNU General Public License
4515 11 Sep 08 jari 21   along with BASE. If not, see <http://www.gnu.org/licenses/>.
2681 29 Sep 06 nicklas 22 */
2681 29 Sep 06 nicklas 23 package net.sf.basedb.util.zip;
2681 29 Sep 06 nicklas 24
2681 29 Sep 06 nicklas 25 import java.io.IOException;
2681 29 Sep 06 nicklas 26 import java.io.OutputStream;
2681 29 Sep 06 nicklas 27 import java.util.HashMap;
2681 29 Sep 06 nicklas 28 import java.util.Map;
2681 29 Sep 06 nicklas 29 import java.util.zip.ZipEntry;
2681 29 Sep 06 nicklas 30 import java.util.zip.ZipInputStream;
2681 29 Sep 06 nicklas 31
2689 02 Oct 06 nicklas 32 import net.sf.basedb.core.AbsoluteProgressReporter;
2681 29 Sep 06 nicklas 33 import net.sf.basedb.core.BaseException;
2681 29 Sep 06 nicklas 34 import net.sf.basedb.core.DbControl;
2681 29 Sep 06 nicklas 35 import net.sf.basedb.core.Directory;
2681 29 Sep 06 nicklas 36 import net.sf.basedb.core.File;
2681 29 Sep 06 nicklas 37 import net.sf.basedb.core.ItemNotFoundException;
2681 29 Sep 06 nicklas 38 import net.sf.basedb.core.Location;
2681 29 Sep 06 nicklas 39 import net.sf.basedb.core.Path;
4118 01 Feb 08 nicklas 40 import net.sf.basedb.core.signal.ThreadSignalHandler;
2681 29 Sep 06 nicklas 41 import net.sf.basedb.util.FileUtil;
3068 18 Jan 07 enell 42 import net.sf.basedb.util.Values;
2681 29 Sep 06 nicklas 43
2681 29 Sep 06 nicklas 44 /**
2681 29 Sep 06 nicklas 45    This class can be used to unpack zip files into the BASE directory structure.
2681 29 Sep 06 nicklas 46    The class supports unpacking multiple zip files in the same transaction.
2681 29 Sep 06 nicklas 47
2681 29 Sep 06 nicklas 48   @author nicklas
2681 29 Sep 06 nicklas 49   @version 2.0
2681 29 Sep 06 nicklas 50   @base.modified $Date$
2681 29 Sep 06 nicklas 51 */
2681 29 Sep 06 nicklas 52 public class ZipUnpacker
2681 29 Sep 06 nicklas 53 {
2681 29 Sep 06 nicklas 54
2681 29 Sep 06 nicklas 55   private final DbControl dc;
2681 29 Sep 06 nicklas 56   
2689 02 Oct 06 nicklas 57   /**
2689 02 Oct 06 nicklas 58     Cache of directories.
2689 02 Oct 06 nicklas 59   */
2681 29 Sep 06 nicklas 60   private Map<String, Directory> paths;
2681 29 Sep 06 nicklas 61   
2681 29 Sep 06 nicklas 62   /**
2681 29 Sep 06 nicklas 63     Create a new zip unpacker.
2681 29 Sep 06 nicklas 64     @param dc The DbControl to use for database access
2681 29 Sep 06 nicklas 65   */
2681 29 Sep 06 nicklas 66   public ZipUnpacker(DbControl dc)
2681 29 Sep 06 nicklas 67   {
2681 29 Sep 06 nicklas 68     this.dc = dc;
2681 29 Sep 06 nicklas 69     this.paths = new HashMap<String, Directory>();
2681 29 Sep 06 nicklas 70   }
2681 29 Sep 06 nicklas 71   
2681 29 Sep 06 nicklas 72   /**
2681 29 Sep 06 nicklas 73     Unpack a zip file.
2681 29 Sep 06 nicklas 74
2681 29 Sep 06 nicklas 75     @param rootDir The directory where the contents of the zip file should be placed
2681 29 Sep 06 nicklas 76     @param zip The contents of the zip file
2681 29 Sep 06 nicklas 77     @param overwrite If existing files should be overwritten or ignored
2681 29 Sep 06 nicklas 78     @param progress An optional progress reporter for displaying progress
2689 02 Oct 06 nicklas 79     @return The number of files unpacked
2681 29 Sep 06 nicklas 80     @throws IOException If there is an error when unpacking the zip file
2681 29 Sep 06 nicklas 81     @throws BaseException If there is a BASE error
5758 23 Sep 11 nicklas 82     @since 3.0
2681 29 Sep 06 nicklas 83   */
5758 23 Sep 11 nicklas 84   public int unpackZipFile(Directory rootDir, ZipInputStream zip, File sourceFile, boolean overwrite, 
2689 02 Oct 06 nicklas 85     AbsoluteProgressReporter progress)
2681 29 Sep 06 nicklas 86     throws IOException, BaseException
2681 29 Sep 06 nicklas 87   {
2681 29 Sep 06 nicklas 88     ZipEntry entry = null;
2681 29 Sep 06 nicklas 89     String rootPath = rootDir.getPath().toString();
2681 29 Sep 06 nicklas 90     paths.put(rootPath, rootDir);
2681 29 Sep 06 nicklas 91     
2681 29 Sep 06 nicklas 92     long totalUnpacked = 0;
2689 02 Oct 06 nicklas 93     int numFiles = 0;
2681 29 Sep 06 nicklas 94     
2681 29 Sep 06 nicklas 95     while ((entry = zip.getNextEntry()) != null)
2681 29 Sep 06 nicklas 96     {
4118 01 Feb 08 nicklas 97       ThreadSignalHandler.checkInterrupted();
2681 29 Sep 06 nicklas 98       String subPath = entry.getName();
2681 29 Sep 06 nicklas 99       String completePath = rootPath + "/" + subPath;
2689 02 Oct 06 nicklas 100       
2681 29 Sep 06 nicklas 101       boolean isDirectory = entry.isDirectory();
2681 29 Sep 06 nicklas 102       if (progress != null)
2681 29 Sep 06 nicklas 103       {
2689 02 Oct 06 nicklas 104         progress.displayAbsolute(totalUnpacked, 
3068 18 Jan 07 enell 105           "Unpacking " + (isDirectory ? "directory: " : "file: ") + completePath + 
3068 18 Jan 07 enell 106           " (" +Values.formatBytes(entry.getSize()) + ")");
2681 29 Sep 06 nicklas 107       }
2681 29 Sep 06 nicklas 108       if (!isDirectory)
2681 29 Sep 06 nicklas 109       {
2681 29 Sep 06 nicklas 110         Path filePath = new Path(completePath, Path.Type.FILE);
2681 29 Sep 06 nicklas 111
2681 29 Sep 06 nicklas 112         // Get the parent directory
2681 29 Sep 06 nicklas 113         Directory parentDir = getDirectory(filePath);
2681 29 Sep 06 nicklas 114         
2681 29 Sep 06 nicklas 115         // Get the file or create a new one
2681 29 Sep 06 nicklas 116         File file = File.getFile(dc, parentDir, filePath.getFilename(), true);
2681 29 Sep 06 nicklas 117         if (!file.isInDatabase() || file.getLocation() == Location.OFFLINE || overwrite)
2681 29 Sep 06 nicklas 118         {
2681 29 Sep 06 nicklas 119           if (!file.isInDatabase()) dc.saveItem(file);
2691 03 Oct 06 nicklas 120           file.setMimeTypeAuto(null, null);
2681 29 Sep 06 nicklas 121           OutputStream upload = file.getUploadStream(false);
5758 23 Sep 11 nicklas 122           PackUtil.copyProperties(sourceFile, file);
2681 29 Sep 06 nicklas 123           try
2681 29 Sep 06 nicklas 124           {
2689 02 Oct 06 nicklas 125             FileUtil.copy(zip, upload);
2691 03 Oct 06 nicklas 126             numFiles++;
2681 29 Sep 06 nicklas 127           }
2681 29 Sep 06 nicklas 128           finally
2681 29 Sep 06 nicklas 129           {
2681 29 Sep 06 nicklas 130             upload.close();
2681 29 Sep 06 nicklas 131           }
2681 29 Sep 06 nicklas 132         }
2681 29 Sep 06 nicklas 133       }
2689 02 Oct 06 nicklas 134       totalUnpacked += entry.getCompressedSize();
2681 29 Sep 06 nicklas 135       zip.closeEntry();
2681 29 Sep 06 nicklas 136     }
2681 29 Sep 06 nicklas 137     if (progress != null) progress.display(100, "Done");
2689 02 Oct 06 nicklas 138     return numFiles;
2681 29 Sep 06 nicklas 139   }
2681 29 Sep 06 nicklas 140   
2689 02 Oct 06 nicklas 141   /**
2689 02 Oct 06 nicklas 142     Get the directory for the specified path. We first check the internal cache.
2689 02 Oct 06 nicklas 143     If not found we try to load it from the database. If still not found we create
2689 02 Oct 06 nicklas 144     a new directory and save it to the database.
2689 02 Oct 06 nicklas 145     @param path The path
2689 02 Oct 06 nicklas 146     @return The directory
2689 02 Oct 06 nicklas 147   */
2681 29 Sep 06 nicklas 148   private Directory getDirectory(Path path)
2681 29 Sep 06 nicklas 149   {
2681 29 Sep 06 nicklas 150     // Make sure it is a path to the directory
2681 29 Sep 06 nicklas 151     if (path.getType() == Path.Type.FILE) path = path.getParent();
2681 29 Sep 06 nicklas 152     String thePath = path.toString();
2681 29 Sep 06 nicklas 153     
2681 29 Sep 06 nicklas 154     // Load directory from cache
2681 29 Sep 06 nicklas 155     Directory dir = paths.get(thePath);
2681 29 Sep 06 nicklas 156     
2681 29 Sep 06 nicklas 157     if (dir == null)
2681 29 Sep 06 nicklas 158     {
2681 29 Sep 06 nicklas 159       // Load directory from database
2681 29 Sep 06 nicklas 160       try
2681 29 Sep 06 nicklas 161       {
2681 29 Sep 06 nicklas 162         dir = Directory.getByPath(dc, path);
2691 03 Oct 06 nicklas 163         dir.setRemoved(false);
2681 29 Sep 06 nicklas 164       }
2681 29 Sep 06 nicklas 165       catch (ItemNotFoundException ex)
2681 29 Sep 06 nicklas 166       {}
2681 29 Sep 06 nicklas 167     }
2681 29 Sep 06 nicklas 168     if (dir == null)
2681 29 Sep 06 nicklas 169     {
2681 29 Sep 06 nicklas 170       // Directory is not in the cache and not in the database --> create a new one
2681 29 Sep 06 nicklas 171       // Get the parent recursively
2681 29 Sep 06 nicklas 172       Directory parent = getDirectory(path.getParent());
2681 29 Sep 06 nicklas 173       dir = Directory.getNew(dc, parent);
2681 29 Sep 06 nicklas 174       dc.saveItem(dir);
2681 29 Sep 06 nicklas 175       dir.setName(path.getDirectory(path.getDirectoryCount()-1));
2681 29 Sep 06 nicklas 176     }
2681 29 Sep 06 nicklas 177     paths.put(thePath, dir);
2681 29 Sep 06 nicklas 178     return dir;  
2681 29 Sep 06 nicklas 179   }
2681 29 Sep 06 nicklas 180 }