source: trunk/gli/src/org/greenstone/gatherer/util/ZipTools.java@ 10267

Last change on this file since 10267 was 10267, checked in by mdewsnip, 19 years ago

Added some more general zip functions -- eventually the old ones will be deprecated.

  • Property svn:keywords set to Author Date Id Revision
File size: 20.5 KB
Line 
1/**
2 *############################################################################
3 * A component of the Greenstone Librarian Interface, part of the Greenstone
4 * digital library suite from the New Zealand Digital Library Project at the
5 * University of Waikato, New Zealand.
6 *
7 * Author: David Bainbridge, NZDL Project, University of Waikato, NZ
8 *
9 * Copyright (C) 2005 New Zealand Digital Library Project
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *############################################################################
25 */
26
27package org.greenstone.gatherer.util;
28
29
30import java.io.*;
31import java.util.*;
32import java.util.zip.*;
33import org.greenstone.gatherer.DebugStream;
34import org.greenstone.gatherer.shell.GShell;
35import org.w3c.dom.*;
36
37
38public class ZipTools
39{
40 static public void unzipFile(String zip_file_path, String base_directory_path)
41 {
42 try {
43 ZipFile zip_file = new ZipFile(new File(zip_file_path), ZipFile.OPEN_READ);
44
45 Enumeration e = zip_file.entries();
46 while (e.hasMoreElements()) {
47 ZipEntry zip_entry = (ZipEntry) e.nextElement();
48 File zip_entry_file = new File(base_directory_path + zip_entry.getName());
49 DebugStream.println(" Unzipping: " + zip_entry_file.getAbsolutePath());
50
51 // Directory case
52 if (zip_entry.isDirectory()) {
53 // Create named directory, if it doesn't already exist
54 if (!zip_entry_file.exists() && !zip_entry_file.mkdirs()) {
55 System.err.println("Error: unable to create directory " + zip_entry_file);
56 }
57 }
58
59 // File case
60 else {
61 // Write out file to disk
62
63 // Make sure it's parent directory exists.
64 File dir = new File(zip_entry_file.getParent());
65 dir.mkdirs();
66
67 // Set up input stream
68 InputStream zis = zip_file.getInputStream(zip_entry);
69 BufferedInputStream bzis = new BufferedInputStream(zis);
70 DataInputStream dbzis = new DataInputStream(bzis);
71
72 // Set up output stream
73 FileOutputStream fzos = new FileOutputStream(zip_entry_file);
74 BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
75
76 byte[] buf = new byte[1024];
77 int len;
78 while ((len = dbzis.read(buf)) >= 0) {
79 bfzos.write(buf,0,len);
80 }
81
82 dbzis.close();
83 bzis.close();
84 zis.close();
85
86 bfzos.close();
87 fzos.close();
88 }
89 }
90
91 zip_file.close();
92 }
93 catch (Exception exception) {
94 DebugStream.printStackTrace(exception);
95 }
96 }
97
98
99 static public void zipFiles(String zip_file_path, String base_directory_path, String[] relative_file_paths)
100 {
101 try {
102 ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip_file_path));
103 ZipFilter null_zip_filter = new NullZipFilter();
104
105 // Add each file/directory in turn to the zip file
106 for (int i = 0; i < relative_file_paths.length; i++) {
107 String relative_file_path = relative_file_paths[i];
108 addFileToZip(zos, base_directory_path, relative_file_path, null_zip_filter);
109 }
110
111 zos.close();
112 }
113 catch (Exception exception) {
114 DebugStream.printStackTrace(exception);
115 }
116 }
117
118
119 static public void addFileToZip(ZipOutputStream zos, String base_directory_path, String relative_file_path, ZipFilter zip_filter)
120 {
121 File file = new File(base_directory_path + File.separator + relative_file_path);
122
123 // Check that the file/directory exists
124 if (!file.exists()) {
125 System.err.println("File " + file + " does not exist!");
126 return;
127 }
128
129 try {
130 // Directory case
131 if (file.isDirectory()) {
132 // Add a zip entry for this directory
133 zos.putNextEntry(new ZipEntry(relative_file_path + File.separator));
134
135 // Apply recursively to each of the children of the directory
136 File[] child_files = file.listFiles();
137 for (int i = 0; i < child_files.length; i++) {
138 addFileToZip(zos, base_directory_path, relative_file_path + File.separator + child_files[i].getName(), zip_filter);
139 }
140 }
141
142 // File case
143 else {
144 // Add a zip entry for this file
145 if (zip_filter.shouldIncludeFile(relative_file_path)) {
146 zos.putNextEntry(new ZipEntry(relative_file_path));
147
148 if (zip_filter.shouldIncludeFileContent(relative_file_path)) {
149 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
150 byte[] data = new byte[1024];
151 int bytes_read;
152 while ((bytes_read = bis.read(data, 0, 1024)) > -1) {
153 zos.write(data, 0, bytes_read);
154 }
155 bis.close();
156 }
157 }
158 }
159 }
160 catch (Exception exception) {
161 DebugStream.printStackTrace(exception);
162 }
163 }
164
165
166 public interface ZipFilter
167 {
168 public boolean shouldIncludeFile(String relative_file_path);
169
170 public boolean shouldIncludeFileContent(String relative_file_path);
171 }
172
173
174 static public class NullZipFilter
175 implements ZipFilter
176 {
177 public boolean shouldIncludeFile(String relative_file_path)
178 {
179 // All files are included
180 return true;
181 }
182
183
184 public boolean shouldIncludeFileContent(String relative_file_path)
185 {
186 // Content for all files is included
187 return true;
188 }
189 }
190
191
192 // ----------------------------------------------------------------------------------------------------
193
194
195 static private String unixStylePath(String path)
196 {
197 String unix_path = path.replace('\\','/');
198 return unix_path;
199 }
200
201
202 /**
203 * Method to handle zipping up of a file (not a directory).
204 * Called by {@link zipup(String, String, String, GShell, String, String)} and {@link dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String)}
205 *
206 * @param zos the zip output stream, as a <strong>ZipOutputStream</strong>
207 * @param file_path the <strong>String</strong> containing the path to the file/directory tozip up
208 * @param prefix_strip the <strong>int</strong> used to substring the file_path
209 * @param source the <strong>GShell</strong> object that is calling this method, so that we can check to see if the process has been cancelled.
210 * This is null if GShell is not the calling object.
211 * @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
212 * There is a special case of ".*doc.xml", where the doc.xml files will be parsed to only include their metadata.
213 * @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
214 * @return boolean - true if the zip was created successfully(?).
215 * @see dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String)
216 * @see zipup(String, String, String, GShell, String, String)
217 */
218 static private boolean zipFunc(ZipOutputStream zos, String file_path, int prefix_strip, GShell source, boolean encountered_file, String accept_expr, String reject_expr)
219 {
220 String new_file_path = file_path;
221
222 if((reject_expr != "") && (file_path.matches(reject_expr))) {
223 // matches reject expression
224 //DebugStream.println("File \'" + file_path + "\' matches the reject expression \'" + reject_expr + "\'");
225 return encountered_file;
226 }
227
228 if ((accept_expr != "") && (!file_path.matches(accept_expr))) {
229 // does not match accept expression
230 //DebugStream.println("File \'" + file_path + "\' doesn't match accept expression \'" + accept_expr + "\'");
231 return encountered_file;
232 }
233
234 //Special case: we only want the metadata. Parse the xml files.
235 if(accept_expr.compareTo(".*doc.xml") == 0) {
236 DebugStream.println("Only want to get metadata");
237 Document old_document = XMLTools.parseXMLFile(new File(file_path));
238 NodeList content = old_document.getElementsByTagName("Content");
239
240 try {
241 for(int i=content.getLength()-1; i >= 0; i--) {
242 //Remove all content - just leave the metadata.
243 content.item(i).getParentNode().removeChild(content.item(i));
244 }
245 }
246 catch (Exception ex) {
247 ex.printStackTrace();
248 }
249
250 new_file_path = file_path.substring(0, file_path.lastIndexOf(File.separator) + 1) + "new.xml";
251 //Is there any better way than writing out as a new file, then reading back in??
252 XMLTools.writeXMLFile(new File(new_file_path), old_document);
253 }
254
255 // Using try is required because of file io.
256 try {
257 // Exit if pressed cancel.
258 if (source != null && source.hasSignalledStop()) {
259 return false;
260 }
261
262 // Create a Zip Entry and put it into the archive (no data yet).
263
264 // Strip off col_dir prefix
265 String zip_path = file_path.substring(prefix_strip);
266 // Zip files use '/' for directory separator
267 String unix_style_path = unixStylePath(zip_path);
268
269 ZipEntry fileEntry = new ZipEntry(unix_style_path);
270 zos.putNextEntry(fileEntry);
271
272 // Create a file input stream and a buffered input stream.
273 FileInputStream fis = new FileInputStream(new_file_path);
274 BufferedInputStream bis = new BufferedInputStream(fis);
275
276 // Create a byte array object named data and declare byte count variable.
277 byte[] data = new byte[1024];
278 int byteCount;
279 // Create a loop that reads from the buffered input stream and writes
280 // to the zip output stream until the bis has been entirely read.
281 while ((byteCount = bis.read(data, 0, 1024)) > -1) {
282 //Check for cancell
283 if(source != null) {
284 if(source.hasSignalledStop()) {
285 break;
286 }
287 }
288 zos.write(data, 0, byteCount);
289 }
290 encountered_file = true;
291 }
292 catch (IOException e) {
293 e.printStackTrace();
294 }
295
296 DebugStream.println("Zipping up: " + file_path);
297 return encountered_file;
298 }
299
300 /**
301 * Method to handle ziping up of a directory. This is called by {@link zipup(String, String, String, GShell, String, String)}
302 *
303 * @param zos the <strong>ZipOutputStream</strong> to output to.
304 * @param dir_name the directory name to zip, as a <strong>String</strong>
305 * @param prefix_strip the <strong>int</strong> used to substring the file_path
306 * @param source the <strong>GShell</strong> object that is calling this method, so that we can check to see if the process has been cancelled.
307 * This is null if GShell is not the calling object.
308 * @param encountered_file ??What's this??
309 * @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
310 * @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
311 *
312 * @see zipup(String, String, String, GShell, String, String)
313 * @see zipFunc(ZipOutputStream, String, int, GShell, boolean, String, String)
314 */
315 static private boolean dirFunc (ZipOutputStream zos, String dir_name, int prefix_strip, GShell source, boolean encountered_file, String accept_expr, String reject_expr)
316 {
317 File dirObj = new File(dir_name);
318
319 if (dirObj.exists() == true) {
320 if (dirObj.isDirectory() == true) {
321 // Create an array of File objects, one for each file or directory in dirObj.
322 File [] fileList = dirObj.listFiles();
323
324 // Loop through File array and display.
325 for (int i = 0; i < fileList.length; i++) {
326 if(source != null && source.hasSignalledStop()) { break; }
327 File file = fileList[i];
328 if (file.isDirectory()) {
329 String dir_path = file.getPath();
330 String zip_path = dir_path.substring(prefix_strip);
331 // Zip files use '/' for directory separator
332 String unix_style_path
333 = unixStylePath(zip_path+File.separator);
334 ZipEntry dirEntry = new ZipEntry(unix_style_path);
335
336 try {
337 zos.putNextEntry(dirEntry);
338 }
339 catch (IOException e) {
340 e.printStackTrace();
341 }
342
343 encountered_file = dirFunc(zos, dir_path, prefix_strip, source, encountered_file, accept_expr, reject_expr);
344 } else if (file.isFile()) {
345 // Call the zipFunc function
346 String file_path = fileList[i].getPath();
347 encountered_file = zipFunc(zos,file_path,prefix_strip, source, encountered_file, accept_expr, reject_expr);
348 }
349 }
350 }
351 else {
352 System.err.println (dir_name+" is not a directory.");
353 }
354 }
355 else {
356 System.err.println ("Directory "+dir_name+" does not exist.");
357 }
358 return encountered_file;
359 }
360
361 /**
362 * Method to zip up a given file or directory associated with a particular collection.
363 * This method mainly called from {@link GShell}, with a few exceptions. The zip files produced are used
364 * to pass files (new files to add, metadata, etc) between the GLI applet and the Greenstone server.
365 * The actual zipping of files and directories is handled by {@link zipFunc(ZipOutputStream, String, int, GShell, boolean, String, String) and
366 * {@link dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String)} respectfully.
367 *
368 * @param col_dir the path to the collect directory, as a <strong>String</strong>
369 * @param col_name the collection name, as as <strong>String</strong>
370 * @param dir_or_file the directory or file within the collection to zip up, as a <strong>String</strong>
371 * @param source the <strong>GShell</strong> object that is calling this method, so that we can check to see if the process has been cancelled.
372 * This is null if GShell is not the calling object.
373 * @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
374 * @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
375 *
376 * @see zipFunc(ZipOutputStream, String, int, GShell, boolean, String, String)
377 * @see dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String)
378 */
379 static public boolean zipup(String col_dir, String col_name, String dir_or_file, GShell source, String accept_expr, String reject_expr)
380 {
381 if (!col_dir.endsWith(File.separator)) {
382 col_dir += File.separator;
383 }
384
385 int prefix_strip = col_dir.length();
386 boolean encountered_file = false;
387
388 String zip_fname = col_dir + col_name + ".zip";
389 String zip_dir_or_file = col_dir + col_name + File.separator + dir_or_file;
390 File zip_dof = new File(zip_dir_or_file);
391
392 try {
393 FileOutputStream fos = new FileOutputStream(zip_fname);
394 ZipOutputStream zos = new ZipOutputStream(fos);
395
396 if (zip_dof.exists()) {
397 if (zip_dof.isDirectory()) {
398 String zip_dir = zip_dir_or_file;
399 encountered_file = dirFunc(zos, zip_dir, prefix_strip, source, encountered_file, accept_expr, reject_expr);
400 }
401 else {
402 String zip_full_file = zip_dir_or_file;
403 String zip_path = zip_full_file.substring(prefix_strip);
404
405 for (int i=1; i<zip_path.length(); i++) {
406 String ch = String.valueOf(zip_path.charAt(i));
407
408 if (ch.equals(File.separator)) {
409 String dir_path = zip_path.substring(0,i);
410 // Zip files use '/' for directory separator
411 String unix_style_path
412 = unixStylePath(dir_path+File.separator);
413 ZipEntry dirEntry = new ZipEntry(unix_style_path);
414 zos.putNextEntry(dirEntry);
415 }
416 }
417 encountered_file = zipFunc(zos, zip_full_file, prefix_strip, source, encountered_file, accept_expr, reject_expr);
418 }
419 }
420 else {
421 System.err.println("Warning: " + zip_dir_or_file + " does not exist!");
422 }
423
424 // Close the file output streams for both the file and the zip.
425 zos.flush();
426 zos.close();
427 fos.close();
428 }
429 catch (IOException exception) {
430 DebugStream.printStackTrace(exception);
431 return false;
432 }
433 return encountered_file;
434 }
435
436
437 /**
438 * Method to unzip a zip file associated with a particular collection.
439 * The location and name of the zip file should be derrived from the collection. Please see below for details.
440 *
441 * @param col_dir the path to the collection directory, as a <strong>String</strong>. This is where the zip file should be located.
442 * @param col_name the name of the collection, as a <strong>String</strong>. This should be the name of the zip file (with a .zip extension).
443 */
444 static public void unzip(String col_dir, String col_name)
445 {
446 if (!col_dir.endsWith(File.separator)) {
447 col_dir += File.separator;
448 }
449
450 String zip_fname = col_dir + col_name + ".zip";
451 // int zip_mode = ZipFile.OPEN_READ | ZipFile.OPEN_DELETE;
452 int zip_mode = ZipFile.OPEN_READ;
453
454 try {
455 File cfile = new File(zip_fname);
456 ZipFile zipfile = new ZipFile(cfile, zip_mode);
457
458 Enumeration e = zipfile.entries();
459 while (e.hasMoreElements()) {
460 ZipEntry zipentry = (ZipEntry) e.nextElement();
461 String zentryname = col_dir + zipentry.getName();
462 File zfile = new File(zentryname);
463 DebugStream.println(" Unzipping: " + zentryname);
464
465 if (zipentry.isDirectory()) {
466 // Create named directory, if it doesn't already exist
467 if (!zfile.exists() && !zfile.mkdirs()) {
468 System.err.println("Error: unable to create directory " + zfile);
469 }
470 }
471 else {
472 // Write out file to disk
473
474 //Make sure it's parent directory exists.
475 File dir = new File(zfile.getParent());
476 dir.mkdirs();
477
478 // set up input stream
479 InputStream zis = zipfile.getInputStream(zipentry);
480 BufferedInputStream bzis = new BufferedInputStream(zis);
481 DataInputStream dbzis = new DataInputStream(bzis);
482
483 // set up output stream
484 FileOutputStream fzos = new FileOutputStream(zentryname);
485 BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
486
487 byte[] buf = new byte[1024];
488 int len;
489 while ((len = dbzis.read(buf)) >= 0) {
490 bfzos.write(buf,0,len);
491 }
492
493 dbzis.close();
494 bzis.close();
495 zis.close();
496
497 bfzos.close();
498 fzos.close();
499 }
500 }
501
502 zipfile.close();
503
504 // delete zip file
505 boolean file_deleted = cfile.delete();
506 if (file_deleted) {
507 System.err.println("Zip file " + cfile.toString() + " deleted");
508 }
509 else {
510 System.err.println("Zip file " + cfile.toString() + " NOT deleted");
511 }
512
513
514 }
515 catch (ZipException error) {
516 System.err.println("Error: Unable to open '"+zip_fname+"'");
517 System.err.println("This maybe caused by the zip file being empty.");
518 DebugStream.printStackTrace(error);
519 }
520
521 catch (Exception error) {
522 error.printStackTrace();
523 }
524 }
525
526
527 /**
528 * Method which unzips a given metadata resoure.
529 * @param jar_zip_fname The name of the jar file as a <strong>String</strong>.
530 * @param dst_dir The destination directory for unzipping, also as a <strong>String</strong>.
531 * @see JarTools.extractFromJar(String, String, boolean)
532 */
533 static public void unzipFromJar(String jar_zip_fname, String dst_dir) {
534
535 File file = null;
536 if (!dst_dir.endsWith(File.separator)) {
537 dst_dir += File.separator;
538 }
539
540 JarTools.extractFromJar(jar_zip_fname,dst_dir,true);
541
542 String zip_ofname = dst_dir + jar_zip_fname;
543 File zip_file = new File(zip_ofname);
544
545 try {
546 ZipFile zipfile = new ZipFile(zip_file);
547
548 Enumeration e = zipfile.entries();
549 while (e.hasMoreElements()) {
550 ZipEntry zipentry = (ZipEntry) e.nextElement();
551 String zentryname = dst_dir + zipentry.getName();
552 DebugStream.println(" Unzipping: " + zentryname);
553
554 if (zipentry.isDirectory()) {
555 // Create named directory, if it doesn't already exist
556 File zip_entry_file = new File(zentryname);
557 if (!zip_entry_file.exists() && !zip_entry_file.mkdirs()) {
558 System.err.println("Error: unable to create directory " + zip_entry_file);
559 }
560 }
561 else {
562 // Write out file to disk
563
564 // set up input stream
565 InputStream zis = zipfile.getInputStream(zipentry);
566 BufferedInputStream bzis = new BufferedInputStream(zis);
567 DataInputStream dbzis = new DataInputStream(bzis);
568
569 // set up output stream
570 FileOutputStream fzos = new FileOutputStream(zentryname);
571 BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
572
573 byte[] buf = new byte[1024];
574 int len;
575 while ((len = dbzis.read(buf)) >= 0) {
576 bfzos.write(buf,0,len);
577 }
578
579 dbzis.close();
580 bfzos.close();
581 }
582 }
583 }
584 catch (ZipException error) {
585 System.err.println("Error: Unable to open '"+zip_file.getAbsolutePath()+"'");
586 DebugStream.printStackTrace(error);
587 }
588
589 catch (Exception error) {
590 error.printStackTrace();
591 }
592 }
593}
Note: See TracBrowser for help on using the repository browser.