2681 |
29 Sep 06 |
nicklas |
1 |
/** |
2681 |
29 Sep 06 |
nicklas |
$Id$ |
2681 |
29 Sep 06 |
nicklas |
3 |
|
3675 |
16 Aug 07 |
jari |
Copyright (C) 2006 Nicklas Nordborg |
3675 |
16 Aug 07 |
jari |
Copyright (C) 2007 Johan Enell |
2681 |
29 Sep 06 |
nicklas |
6 |
|
2681 |
29 Sep 06 |
nicklas |
This file is part of BASE - BioArray Software Environment. |
2681 |
29 Sep 06 |
nicklas |
Available at http://base.thep.lu.se/ |
2681 |
29 Sep 06 |
nicklas |
9 |
|
2681 |
29 Sep 06 |
nicklas |
BASE is free software; you can redistribute it and/or |
2681 |
29 Sep 06 |
nicklas |
modify it under the terms of the GNU General Public License |
4479 |
05 Sep 08 |
jari |
as published by the Free Software Foundation; either version 3 |
2681 |
29 Sep 06 |
nicklas |
of the License, or (at your option) any later version. |
2681 |
29 Sep 06 |
nicklas |
14 |
|
2681 |
29 Sep 06 |
nicklas |
BASE is distributed in the hope that it will be useful, |
2681 |
29 Sep 06 |
nicklas |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
2681 |
29 Sep 06 |
nicklas |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2681 |
29 Sep 06 |
nicklas |
GNU General Public License for more details. |
2681 |
29 Sep 06 |
nicklas |
19 |
|
2681 |
29 Sep 06 |
nicklas |
You should have received a copy of the GNU General Public License |
4515 |
11 Sep 08 |
jari |
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 |
This class can be used to unpack zip files into the BASE directory structure. |
2681 |
29 Sep 06 |
nicklas |
The class supports unpacking multiple zip files in the same transaction. |
2681 |
29 Sep 06 |
nicklas |
47 |
|
2681 |
29 Sep 06 |
nicklas |
@author nicklas |
2681 |
29 Sep 06 |
nicklas |
@version 2.0 |
2681 |
29 Sep 06 |
nicklas |
@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 |
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 |
Create a new zip unpacker. |
2681 |
29 Sep 06 |
nicklas |
@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 |
Unpack a zip file. |
2681 |
29 Sep 06 |
nicklas |
74 |
|
2681 |
29 Sep 06 |
nicklas |
@param rootDir The directory where the contents of the zip file should be placed |
2681 |
29 Sep 06 |
nicklas |
@param zip The contents of the zip file |
2681 |
29 Sep 06 |
nicklas |
@param overwrite If existing files should be overwritten or ignored |
2681 |
29 Sep 06 |
nicklas |
@param progress An optional progress reporter for displaying progress |
2689 |
02 Oct 06 |
nicklas |
@return The number of files unpacked |
2681 |
29 Sep 06 |
nicklas |
@throws IOException If there is an error when unpacking the zip file |
2681 |
29 Sep 06 |
nicklas |
@throws BaseException If there is a BASE error |
5758 |
23 Sep 11 |
nicklas |
@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 |
// 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 |
// 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 |
Get the directory for the specified path. We first check the internal cache. |
2689 |
02 Oct 06 |
nicklas |
If not found we try to load it from the database. If still not found we create |
2689 |
02 Oct 06 |
nicklas |
a new directory and save it to the database. |
2689 |
02 Oct 06 |
nicklas |
@param path The path |
2689 |
02 Oct 06 |
nicklas |
@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 |
// 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 |
// 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 |
// 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 |
// Directory is not in the cache and not in the database --> create a new one |
2681 |
29 Sep 06 |
nicklas |
// 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 |
} |