source: trunk/gli/src/org/greenstone/gatherer/util/Utility.java@ 10008

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

Removed the Dimension objects from the Utility class, as part of tidying it up.

  • Property svn:keywords set to Author Date Id Revision
File size: 36.3 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.util;
38
39import java.awt.*;
40import java.io.*;
41import java.net.*;
42import java.util.*;
43import java.util.zip.*;
44import javax.swing.*;
45import javax.swing.tree.*;
46import org.apache.xerces.parsers.*;
47import org.apache.xerces.dom.DocumentImpl;
48import org.apache.xml.serialize.*;
49import org.greenstone.gatherer.Configuration;
50import org.greenstone.gatherer.DebugStream;
51import org.greenstone.gatherer.Dictionary;
52import org.greenstone.gatherer.shell.GShell;
53// Don't even think about adding import org.greenstone.gatherer.Gatherer in here!
54// The functions in this class should be independent of the Gatherer class. Put your function somewhere else buster!
55import org.w3c.dom.*;
56import org.xml.sax.*;
57
58/** To provide a library of common methods, in a static context, for use in the Gatherer.
59 * @author John Thompson, Greenstone Digital Library, University of Waikato
60 * @version 2.3b
61 */
62public class Utility
63{
64 /** The size of the io buffer, in bytes. */
65 static final public int BUFFER_SIZE = 1024;
66 /** Definition of an important directory name, in this case the base dir, or the working directory of the Gatherer. */
67
68 static public String BASE_DIR = System.getProperty("user.dir") + File.separator;
69 static final public String BUILD_CFG_FILENAME = "build.cfg";
70 static final public String CFG_COLLECTIONMETA_COLLECTIONNAME = "collectionmeta\tcollectionname";
71 static final public String CFG_COLLECTIONMETA_COLLECTIONEXTRA = "collectionmeta\tcollectionextra";
72 static final public String CFG_COLLECTIONMETA_ICONCOLLECTION = "collectionmeta\ticoncollection";
73 static final public String CFG_CLASSIFY = "classify";
74 static final public String CFG_CLASSIFY_BUTTONNAME = "-buttonname";
75 static final public String CFG_CLASSIFY_HFILE = "-hfile";
76 static final public String CFG_CLASSIFY_METADATA = "-metadata";
77 static final public String CFG_CLASSIFY_SORT = "-sort";
78 static final public String CFG_CREATOR = "creator";
79 static final public String CFG_FORMAT = "format";
80 static final public String CFG_MAINTAINER = "maintainer";
81 /** Definition of an important directory name, in this case the parent directory of all the collections in the gsdl. */
82 static final public String COL_DIR = "collect" + File.separator;
83 static final public String COLLECTION_TREE = "Collection";
84 /** Definition of an important directory name, in this case the file the collection configuration is expect to be in. */
85 static final public String CONFIG_FILE = "etc" + File.separator + "collect.cfg";
86 static final public String EXTRACTED_METADATA_NAMESPACE = "ex";
87 /** The location of the default greenstone metadata file. */
88 static final public String GREENSTONEDIRECTORYMETADATA_TEMPLATE = "xml/metadata.xml";
89 static final public String GLI_ARCHIVE = "GLI.jar";
90 static final public String GLI_EXTENSION = ".col";
91
92 static public String TMP_DIR = BASE_DIR + "tmp" + File.separator;
93
94 /** Definition of an important directory name, in this case the images directory for the collection. */
95 static final public String IMAGES_DIR = "images" + File.separator;
96 /** Definition of an important directory name, in this case the import directory for the collection. */
97 static final public String IMPORT_DIR = "import" + File.separator;
98 /** Definition of an important directory name, in this case the backup import directory for the collection. */
99 static final public String IMPORT_BAK_DIR = "import.bak" + File.separator;
100 /** Definition of an important directory name, in this case the log directory for the collection. */
101 static final public String LOG_DIR = "log" + File.separator;
102 /** Definition of an important directory name, in this case the macros directory for the collection. */
103 static final public String MACROS_DIR = "macros" + File.separator;
104 /** Definition of an important directory name, in this case the location of the expected collection metadata sets.. */
105 static final public String META_DIR = "metadata" + File.separator; // Col. Copy
106 /** Definition of an important directory name, in this case the location of the default metadata sets. */
107 static public String METADATA_DIR = BASE_DIR + "metadata" + File.separator;
108 /** Definition of an important zip file, in this case zipped up version of metadata file stored in JAR file */
109 static final public String METADATA_ZIP = "metadata.zip";
110 static final public String COLLECT_ZIP = "collect.zip";
111 /** The default name of the perl executable under unix. */
112 static final public String PERL_EXECUTABLE_UNIX = "perl";
113 /** The default name of the perl executable under windows. */
114 static final public String PERL_EXECUTABLE_WINDOWS = "Perl.exe";
115 /** The name of the Gatherer. */
116 static final public String PROGRAM_NAME = "Greenstone Librarian Interface";
117 /** The current version of the Gatherer. */
118 static final public String PROGRAM_VERSION = "v2.60";
119 static final public String WORKSPACE_TREE = "Workspace";
120 static final public String XML_DIRECTORY = "xml" + File.separator;
121
122 static protected File gli_user_folder = null;
123
124 // These are out of alphabetic order to avoid forward reference error.
125 /** The default icon to produce a 'help-icon' sized blank space before a menu entry. */
126 static public Class base = null;
127 static public ImageIcon BLANK_ICON = null;
128 /** The default error icon image. */
129 static public ImageIcon ERROR_ICON = null;
130 static public ImageIcon HELP_ICON = null;
131
132
133 /** It turns out that in Java you have to make sure a directory is empty before you delete it (much like unix I suppose), and so just like unix I'll have to set up a recursive delete function.
134 * @param file The <strong>File</strong> you want to delete.
135 * @return A <i>boolean</i> which is <i>true</i> if the file specified was successfully deleted, <i>false</i> otherwise.
136 */
137 static public boolean delete(File file)
138 {
139 // Nothing to do if it doesn't exist
140 if (!file.exists()) {
141 return true;
142 }
143
144 // If file is a directory, we have to recursively delete its contents first
145 if (file.isDirectory()) {
146 File files[] = file.listFiles();
147 for (int i = 0; i < files.length; i++) {
148 if (delete(files[i]) == false) {
149 System.err.println("Error: Could not delete folder " + file);
150 return false;
151 }
152 }
153 }
154
155 // Delete file
156 if (file.delete() == false) {
157 System.err.println("Error: Could not delete file " + file);
158 return false;
159 }
160
161 return true;
162 }
163
164
165 static public boolean delete(String filename) {
166 return delete(new File(filename));
167 }
168
169
170 /** Convert a long, detailing the length of a file in bytes, into a nice human readable string using b, kb, Mb and Gb. */
171 static final public String BYTE_SUFFIX = " b";
172 static final public long GIGABYTE = 1024000000l;
173 static final public String GIGABYTE_SUFFIX = " Gb";
174 static final public long KILOBYTE = 1024l;
175 static final public String KILOBYTE_SUFFIX = " kb";
176 static final public long MEGABYTE = 1024000l;
177 static final public String MEGABYTE_SUFFIX = " mb";
178 static final public String formatFileLength(long length) {
179 StringBuffer result = new StringBuffer("");
180 float number = 0f;
181 String suffix = null;
182 // Determine the floating point number and the suffix (radix) used.
183 if(length >= GIGABYTE) {
184 number = (float) length / (float) GIGABYTE;
185 suffix = GIGABYTE_SUFFIX;
186 }
187 else if(length >= MEGABYTE) {
188 number = (float) length / (float) MEGABYTE;
189 suffix = MEGABYTE_SUFFIX;
190 }
191 else if(length >= KILOBYTE) {
192 number = (float) length / (float) KILOBYTE;
193 suffix = KILOBYTE_SUFFIX;
194 }
195 else {
196 // Don't need to do anything fancy if the file is smaller than a kilobyte
197 return length + BYTE_SUFFIX;
198 }
199 // Create the formatted string remembering to round the number to 2.d.p. To do this copy everything in the number string from the start to the first occurance of '.' then copy two more digits. Finally search for and print anything that appears after (and including) the optional 'E' delimter.
200 String number_str = Float.toString(number);
201 char number_char[] = number_str.toCharArray();
202 int pos = 0;
203 // Print the characters up to the '.'
204 while(number_char != null && pos < number_char.length && number_char[pos] != '.') {
205 result.append(number_char[pos]);
206 pos++;
207 }
208 if(pos < number_char.length) {
209 // Print the '.' and at most two characters after it
210 result.append(number_char[pos]);
211 pos++;
212 for(int i = 0; i < 2 && pos < number_char.length; i++, pos++) {
213 result.append(number_char[pos]);
214 }
215 // Search through the remaining string for 'E'
216 while(pos < number_char.length && number_char[pos] != 'E') {
217 pos++;
218 }
219 // If we still have string then we found an E. Copy the remaining string.
220 while(pos < number_char.length) {
221 result.append(number_char[pos]);
222 pos++;
223 }
224 }
225 // Add suffix
226 result.append(suffix);
227 // Done
228 return result.toString();
229 }
230
231 /** This method formats a given string, using HTML markup, so its width does not exceed the given width and its appearance if justified.
232 * @param text The <strong>String</strong> requiring formatting.
233 * @param width The maximum width per line as an <i>int</i>.
234 * @return A <strong>String</strong> formatted so as to have no line longer than the specified width.
235 * TODO Currently HTML formatting tags are simply removed from the text, as the effects of spreading HTML tags over a break are undetermined. To solve this we need to associate tags with a certain text token so if it gets broken on to the next line the tags go with it, or if the tags cover a sequence of words that are broken we need to close then reopen the tags. However all this is a major task and well beyond anything I have time to 'muck-round' on.
236 */
237 static public String formatHTMLWidth(String text, int width) {
238 if(text == null) {
239 return "Error";
240 }
241 HTMLStringTokenizer html = new HTMLStringTokenizer(text);
242 int current_width = 0;
243 int threshold = width / 2;
244 Stack lines = new Stack();
245 String line = "";
246 while(html.hasMoreTokens()) {
247 String token = html.nextToken();
248 while(token != null) {
249 if(html.isTag()) {
250 // Insert smart HTML tag code here.
251 token = null;
252 }
253 else {
254 // If the token is bigger than two thirds width, before we've even started break it down.
255 if(current_width + 1 + token.length() > width && token.length() > threshold) {
256 if(width == current_width) {
257 lines.push(line);
258 line = token;
259 current_width = token.length();
260 }
261 else {
262 String prefix = token.substring(0, width - 1 - current_width);
263 token = token.substring(prefix.length());
264 if(current_width == 0) {
265 line = line + prefix;
266 }
267 else {
268 line = line + " " + prefix;
269 }
270 lines.push(line);
271 line = "";
272 current_width = 0;
273 }
274 }
275 // If adding the next token would push us over the maximum line width.
276 else if(current_width + 1 + token.length() > width) {
277 lines.push(line);
278 line = token;
279 current_width = token.length();
280 token = null;
281 }
282 // Otherwise we should be able to just add the token, give or take.
283 else {
284 if(current_width == 0) {
285 line = line + token;
286 current_width = token.length();
287 }
288 else {
289 // Special case for standard punctuation which may exist after a tag like so:
290 // My name is <scratchy>Slim Shady</scratchy>. <-- Annoying punctuation.
291 if(token.equals(".") || token.equals(",") || token.equals("!") || token.equals("?")) {
292 line = line + token;
293 current_width = current_width + 1;
294 }
295 else {
296 line = line + " " + token;
297 current_width = current_width + 1 + token.length();
298 }
299 }
300 token = null;
301 }
302 }
303 }
304 }
305 String result = line;
306 while(!lines.empty()) {
307 result = (String)lines.pop() + "<BR>" + result;
308 }
309 // Replace ' ' with "&nbsp;"
310 boolean tag = false;
311 int pos = 0;
312 while(pos < result.length()) {
313 if(result.charAt(pos) == '<') {
314 tag = true;
315 }
316 else if(result.charAt(pos) == '>') {
317 tag = false;
318 }
319 else if(result.charAt(pos) == ' ' && !tag) {
320 String prefix = result.substring(0, pos);
321 String suffix = result.substring(pos + 1);
322 result = prefix + "&nbsp;" + suffix;
323 }
324 pos++;
325 }
326 result = "<HTML>" + result + "</HTML>";
327 return result;
328 }
329
330
331 /** Builds the cache dir by appending the user path and 'cache'.
332 * @return a File representing the path to the private file cache within the current collection.
333 */
334 public static File getCacheDir() {
335 return new File(getGLIUserFolder(), StaticStrings.CACHE_FOLDER);
336 }
337
338
339 /** Method which constructs the configuration file given a certain collection.
340 * @param col_dir The location of the collection directory as a <strong>String</strong>.
341 * @return The location of the given collections configuration file, also as a <strong>String</strong>.
342 */
343 static public String getConfigFile(String col_dir) {
344 return col_dir + CONFIG_FILE;
345 }
346
347 static public String getDateString() {
348 Calendar current = Calendar.getInstance();
349 String day_name = null;
350 switch(current.get(Calendar.DAY_OF_WEEK)) {
351 case Calendar.MONDAY: day_name = "Dates.Mon"; break;
352 case Calendar.TUESDAY: day_name = "Dates.Tue"; break;
353 case Calendar.WEDNESDAY: day_name = "Dates.Wed"; break;
354 case Calendar.THURSDAY: day_name = "Dates.Thu"; break;
355 case Calendar.FRIDAY: day_name = "Dates.Fri"; break;
356 case Calendar.SATURDAY: day_name = "Dates.Sat"; break;
357 case Calendar.SUNDAY: day_name = "Dates.Sun"; break;
358 default: day_name = "";
359 }
360 String month_name = null;
361 switch(current.get(Calendar.MONTH)) {
362 case Calendar.JANUARY: month_name = "Dates.Jan"; break;
363 case Calendar.FEBRUARY: month_name = "Dates.Feb"; break;
364 case Calendar.MARCH: month_name = "Dates.Mar"; break;
365 case Calendar.APRIL: month_name = "Dates.Apr"; break;
366 case Calendar.MAY: month_name = "Dates.May"; break;
367 case Calendar.JUNE: month_name = "Dates.Jun"; break;
368 case Calendar.JULY: month_name = "Dates.Jul"; break;
369 case Calendar.AUGUST: month_name = "Dates.Aug"; break;
370 case Calendar.SEPTEMBER: month_name = "Dates.Sep"; break;
371 case Calendar.OCTOBER: month_name = "Dates.Oct"; break;
372 case Calendar.NOVEMBER: month_name = "Dates.Nov"; break;
373 case Calendar.DECEMBER: month_name = "Dates.Dec"; break;
374 default: month_name = "";
375 }
376 int day = current.get(Calendar.DAY_OF_MONTH);
377 int hour = current.get(Calendar.HOUR_OF_DAY);
378 int minute = current.get(Calendar.MINUTE);
379 int second = current.get(Calendar.SECOND);
380 int year = current.get(Calendar.YEAR);
381
382 return Dictionary.get(day_name) + " " + Dictionary.get(month_name) + " " + day + " " + year + " " + Utility.pad(String.valueOf(hour), 2, '0', true) + ":" + Utility.pad(String.valueOf(minute), 2, '0', true) + ":" + Utility.pad(String.valueOf(second), 2, '0', true);
383 }
384
385
386 static final private String APPLICATION_DATA_FOLDER = "Application Data";
387 static final private String UNIX_GLI_CONFIG_FOLDER = ".gli";
388 static final private String USER_HOME_PROPERTY = "user.home";
389 static final private String WIN_GLI_CONFIG_FOLDER = "Greenstone" + File.separator + "GLI";
390
391 static public File setGLIUserFolder(String windows_home) {
392 gli_user_folder = null;
393 if(Utility.isWindows()) {
394 if ((windows_home != null) && (windows_home != "")) {
395 gli_user_folder = new File(windows_home + File.separator + "GLI" + File.separator);
396 }
397 else {
398 gli_user_folder = new File(System.getProperty(USER_HOME_PROPERTY) + File.separator + APPLICATION_DATA_FOLDER + File.separator + WIN_GLI_CONFIG_FOLDER + File.separator);
399 }
400 }
401 else {
402 gli_user_folder = new File(System.getProperty(USER_HOME_PROPERTY) +
403File.separator + UNIX_GLI_CONFIG_FOLDER + File.separator);
404 }
405 return gli_user_folder;
406 }
407
408 static public File getGLIUserFolder()
409 {
410 return gli_user_folder;
411 }
412
413
414 /** Retrieve the full file path to the help index xml file.
415 * @return the full path as a String
416 */
417 static public String getHelpFolder() {
418
419 String help_folder = "help/" + Configuration.getLanguage() + "/";
420
421 // Try in the JAR/classes directory first
422 URL help_folder_url = base.getResource("/" + help_folder);
423 if (help_folder_url != null) {
424 return help_folder;
425 }
426
427 // Look in the base directory next
428 File help_folder_file = new File(help_folder);
429 if (help_folder_file.exists()) {
430 return help_folder;
431 }
432
433 // Resort to English
434 return "help/" + StaticStrings.ENGLISH_LANGUAGE_STR + "/";
435 }
436
437 /** Method to retrieve an image icon with the given filename found in classpath or the resouces directory.
438 * @return The specified <strong>ImageIcon</strong>, or an error image replacement if no such images exists.
439 */
440 static public ImageIcon getImage(String filename) {
441 return getImage(filename, false);
442 }
443
444 static public ImageIcon getImage(String filename, boolean wait_until_complete)
445 {
446 ImageIcon image = new ImageIcon(base.getResource("/images/" + filename));
447 if (image == null) {
448 image = ERROR_ICON;
449 }
450
451 if (wait_until_complete) {
452 int load_status;
453 do {
454 load_status = image.getImageLoadStatus();
455 }
456 while (load_status != MediaTracker.ABORTED && load_status != MediaTracker.ERRORED && load_status != MediaTracker.COMPLETE);
457 }
458
459 return image;
460 }
461
462
463 /** Method which constructs the import directory given a certain collection.
464 * @param col_dir The location of the collection directory as a <strong>String</strong>.
465 * @return The location of the given collections import directory, also as a <strong>String</strong>.
466 */
467 public static String getImportDir(String col_dir) {
468 return col_dir + IMPORT_DIR;
469 }
470
471 /** Method which constructs the log directory given a certain collection.
472 * @param col_dir The location of the collection directory as a <strong>String</strong>.
473 * @return The location of the given collections log directory, also as a <strong>String</strong>.
474 */
475 public static String getLogDir(String col_dir) {
476 if(col_dir != null) {
477 return col_dir + LOG_DIR;
478 }
479 else {
480 return getGLIUserFolder().getAbsolutePath() + File.separator + LOG_DIR;
481 }
482 }
483 /** Determine this machines name.
484 * @return The name as a <strong>String</strong>.
485 */
486 static public String getMachineName() {
487 try {
488 return InetAddress.getLocalHost().getHostName();
489 }
490 catch(UnknownHostException ex) {
491 }
492 return "Unknown Machine";
493 }
494
495
496 static public boolean isInJar(String filename)
497 {
498 try {
499 InputStream fis = base.getResourceAsStream("/"+filename);
500
501 fis.close();
502
503 }
504 catch (Exception error) {
505 System.err.println("**** collect.zip not there!");
506 error.printStackTrace();
507
508
509 return false;
510 }
511 return true;
512 }
513
514
515
516 static public void extractFromJar(String filename, String dst_dir, boolean must_be_present)
517 {
518 try {
519 // setup input stream for slurping out file
520 InputStream fis = base.getResourceAsStream("/"+filename);
521 BufferedInputStream fbis = new BufferedInputStream(fis);
522 DataInputStream fdbis = new DataInputStream(fbis);
523
524 // set up output stream for writing to disk
525 String ofname = dst_dir + filename;
526 FileOutputStream fos = new FileOutputStream(ofname);
527 BufferedOutputStream bfos = new BufferedOutputStream(fos);
528
529 byte[] buf = new byte[1024];
530 int len;
531 int total_bytes = 0;
532 while ((len = fdbis.read(buf)) >= 0) {
533 bfos.write(buf,0,len);
534 total_bytes += len;
535 }
536
537 fdbis.close();
538 bfos.close();
539 }
540 catch (Exception error) {
541 if (must_be_present) {
542 error.printStackTrace();
543 }
544 }
545 }
546
547
548 /** Method which unzips a given metadata resoure
549 * @param zip_fname The name of the zip file as a <strong>String</strong>.
550 * @param dst_dir The destination directory for unzipping, also as a <strong>String</strong>.
551 * @param use_classloader Used to determine whether or not to look in resource bundle.
552 */
553 static public void unzipFromJar(String jar_zip_fname, String dst_dir) {
554
555 File file = null;
556 if (!dst_dir.endsWith(File.separator)) {
557 dst_dir += File.separator;
558 }
559
560 extractFromJar(jar_zip_fname,dst_dir,true);
561
562 String zip_ofname = dst_dir + jar_zip_fname;
563 File zip_file = new File(zip_ofname);
564
565 try {
566 ZipFile zipfile = new ZipFile(zip_file);
567
568 Enumeration e = zipfile.entries();
569 while (e.hasMoreElements()) {
570 ZipEntry zipentry = (ZipEntry) e.nextElement();
571 String zentryname = dst_dir + zipentry.getName();
572 DebugStream.println(" Unzipping: " + zentryname);
573
574 if (zipentry.isDirectory()) {
575 // Create named directory, if it doesn't already exist
576 File zip_entry_file = new File(zentryname);
577 if (!zip_entry_file.exists() && !zip_entry_file.mkdirs()) {
578 System.err.println("Error: unable to create directory " + zip_entry_file);
579 }
580 }
581 else {
582 // Write out file to disk
583
584 // set up input stream
585 InputStream zis = zipfile.getInputStream(zipentry);
586 BufferedInputStream bzis = new BufferedInputStream(zis);
587 DataInputStream dbzis = new DataInputStream(bzis);
588
589 // set up output stream
590 FileOutputStream fzos = new FileOutputStream(zentryname);
591 BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
592
593 byte[] buf = new byte[1024];
594 int len;
595 while ((len = dbzis.read(buf)) >= 0) {
596 bfzos.write(buf,0,len);
597 }
598
599 dbzis.close();
600 bfzos.close();
601 }
602 }
603 }
604 catch (ZipException error) {
605 System.err.println("Error: Unable to open '"+zip_file.getAbsolutePath()+"'");
606 DebugStream.printStackTrace(error);
607 }
608
609 catch (Exception error) {
610 error.printStackTrace();
611 }
612 }
613
614
615 static protected String unixStylePath(String path)
616 {
617 String unix_path = path.replace('\\','/');
618 return unix_path;
619 }
620
621 /*
622 Method to handle zipping up of a file. Called by zipup and dirFunc.
623
624 @param zos the zip output stream, as a <strong>ZipOutputStream</strong>
625 @param file_path the <strong>String</strong> containing the path to the file/directory tozip up
626 @param prefix_strip the <strong>int</strong> used to substring the file_path
627 @param source the <strong>GShell</strong> that is calling this method, so that we can check to see if the process has been cancelled. null if GShell is not the calling object.
628 @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
629 @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
630
631 @return boolean
632
633 @see dirFunc
634 @see zipup
635 */
636 static protected boolean zipFunc (ZipOutputStream zos, String file_path, int prefix_strip, GShell source, boolean encountered_file, String accept_expr, String reject_expr)
637 {
638 String new_file_path = file_path;
639
640 if((reject_expr != "") && (file_path.matches(reject_expr))) {
641 // matches reject expression
642 //DebugStream.println("File \'" + file_path + "\' matches the reject expression \'" + reject_expr + "\'");
643 return encountered_file;
644 }
645
646 if ((accept_expr != "") && (!file_path.matches(accept_expr))) {
647 // does not match accept expression
648 //DebugStream.println("File \'" + file_path + "\' doesn't match accept expression \'" + accept_expr + "\'");
649 return encountered_file;
650 }
651
652 //Special case: we only want the metadata. Parse the xml files.
653 if(accept_expr.compareTo(".*doc.xml") == 0) {
654 DebugStream.println("Only want to get metadata");
655 Document old_document = XMLTools.parseXMLFile(new File(file_path));
656 NodeList content = old_document.getElementsByTagName("Content");
657
658 try {
659 for(int i=content.getLength()-1; i >= 0; i--) {
660 //Remove all content - just leave the metadata.
661 content.item(i).getParentNode().removeChild(content.item(i));
662 }
663 }
664 catch (Exception ex) {
665 ex.printStackTrace();
666 }
667
668 new_file_path = file_path.substring(0, file_path.lastIndexOf(File.separator) + 1) + "new.xml";
669 //Is there any better way than writing out as a new file, then reading back in??
670 XMLTools.writeXMLFile(new File(new_file_path), old_document);
671 }
672
673 // Using try is required because of file io.
674 try {
675 // Exit if pressed cancel.
676 if (source != null && source.hasSignalledStop()) {
677 return false;
678 }
679
680 // Create a Zip Entry and put it into the archive (no data yet).
681
682 // Strip off col_dir prefix
683 String zip_path = file_path.substring(prefix_strip);
684 // Zip files use '/' for directory separator
685 String unix_style_path = unixStylePath(zip_path);
686
687 ZipEntry fileEntry = new ZipEntry(unix_style_path);
688 zos.putNextEntry(fileEntry);
689
690 // Create a file input stream and a buffered input stream.
691 FileInputStream fis = new FileInputStream(new_file_path);
692 BufferedInputStream bis = new BufferedInputStream(fis);
693
694 // Create a byte array object named data and declare byte count variable.
695 byte[] data = new byte[1024];
696 int byteCount;
697 // Create a loop that reads from the buffered input stream and writes
698 // to the zip output stream until the bis has been entirely read.
699 while ((byteCount = bis.read(data, 0, 1024)) > -1) {
700 //Check for cancell
701 if(source != null) {
702 if(source.hasSignalledStop()) {
703 break;
704 }
705 }
706 zos.write(data, 0, byteCount);
707 }
708 encountered_file = true;
709 }
710 catch (IOException e) {
711 e.printStackTrace();
712 }
713
714 DebugStream.println("Zipping up: " + file_path);
715 return encountered_file;
716 }
717
718 /*
719 Method to handle ziping up of a directory.
720
721 @param zos
722 @param dir_name
723 @param prefix_strip
724 @param source
725 @param encountered_file ??What's this??
726 @param accept_expr
727 @param reject_expr
728
729 @see zipup
730 @see zipFunc
731 */
732 static protected boolean dirFunc (ZipOutputStream zos, String dir_name, int prefix_strip, GShell source, boolean encountered_file, String accept_expr, String reject_expr)
733 {
734 File dirObj = new File(dir_name);
735
736 if (dirObj.exists() == true) {
737 if (dirObj.isDirectory() == true) {
738 // Create an array of File objects, one for each file or directory in dirObj.
739 File [] fileList = dirObj.listFiles();
740
741 // Loop through File array and display.
742 for (int i = 0; i < fileList.length; i++) {
743 if(source != null && source.hasSignalledStop()) { break; }
744 File file = fileList[i];
745 if (file.isDirectory()) {
746 String dir_path = file.getPath();
747 String zip_path = dir_path.substring(prefix_strip);
748 // Zip files use '/' for directory separator
749 String unix_style_path
750 = unixStylePath(zip_path+File.separator);
751 ZipEntry dirEntry = new ZipEntry(unix_style_path);
752
753 try {
754 zos.putNextEntry(dirEntry);
755 }
756 catch (IOException e) {
757 e.printStackTrace();
758 }
759
760 encountered_file = dirFunc(zos, dir_path, prefix_strip, source, encountered_file, accept_expr, reject_expr);
761 } else if (file.isFile()) {
762 // Call the zipFunc function
763 String file_path = fileList[i].getPath();
764 encountered_file = zipFunc(zos,file_path,prefix_strip, source, encountered_file, accept_expr, reject_expr);
765 }
766 }
767 }
768 else {
769 System.err.println (dir_name+" is not a directory.");
770 }
771 }
772 else {
773 System.err.println ("Directory "+dir_name+" does not exist.");
774 }
775 return encountered_file;
776 }
777
778 /**
779 Method to zip up a given file or directory
780
781 @param col_dir
782 @param col_name
783 @param dir_or_file
784 @param source
785 @param filter
786
787 @see zipFunc
788 @see dirFunc
789 */
790 static public boolean zipup(String col_dir, String col_name, String dir_or_file, GShell source, String accept_expr, String reject_expr)
791 {
792 if (!col_dir.endsWith(File.separator)) {
793 col_dir += File.separator;
794 }
795
796 int prefix_strip = col_dir.length();
797 boolean encountered_file = false;
798
799 String zip_fname = col_dir + col_name + ".zip";
800 String zip_dir_or_file = col_dir + col_name + File.separator + dir_or_file;
801 File zip_dof = new File(zip_dir_or_file);
802
803 try {
804 FileOutputStream fos = new FileOutputStream(zip_fname);
805 ZipOutputStream zos = new ZipOutputStream(fos);
806
807 if (zip_dof.exists()) {
808 if (zip_dof.isDirectory()) {
809 String zip_dir = zip_dir_or_file;
810 encountered_file = dirFunc(zos, zip_dir, prefix_strip, source, encountered_file, accept_expr, reject_expr);
811 }
812 else {
813 String zip_full_file = zip_dir_or_file;
814 String zip_path = zip_full_file.substring(prefix_strip);
815
816 for (int i=1; i<zip_path.length(); i++) {
817 String ch = String.valueOf(zip_path.charAt(i));
818
819 if (ch.equals(File.separator)) {
820 String dir_path = zip_path.substring(0,i);
821 // Zip files use '/' for directory separator
822 String unix_style_path
823 = unixStylePath(dir_path+File.separator);
824 ZipEntry dirEntry = new ZipEntry(unix_style_path);
825 zos.putNextEntry(dirEntry);
826 }
827 }
828 encountered_file = zipFunc(zos, zip_full_file, prefix_strip, source, encountered_file, accept_expr, reject_expr);
829 }
830 }
831 else {
832 System.err.println("Warning: " + zip_dir_or_file + " does not exist!");
833 }
834
835 // Close the file output streams for both the file and the zip.
836 zos.flush();
837 zos.close();
838 fos.close();
839 }
840 catch (IOException exception) {
841 DebugStream.printStackTrace(exception);
842 return false;
843 }
844 return encountered_file;
845 }
846
847
848 static public void unzip(String col_dir, String col_name)
849 {
850 if (!col_dir.endsWith(File.separator)) {
851 col_dir += File.separator;
852 }
853
854 String zip_fname = col_dir + col_name + ".zip";
855 // int zip_mode = ZipFile.OPEN_READ | ZipFile.OPEN_DELETE;
856 int zip_mode = ZipFile.OPEN_READ;
857
858 try {
859 File cfile = new File(zip_fname);
860 ZipFile zipfile = new ZipFile(cfile, zip_mode);
861
862 Enumeration e = zipfile.entries();
863 while (e.hasMoreElements()) {
864 ZipEntry zipentry = (ZipEntry) e.nextElement();
865 String zentryname = col_dir + zipentry.getName();
866 File zfile = new File(zentryname);
867 DebugStream.println(" Unzipping: " + zentryname);
868
869 if (zipentry.isDirectory()) {
870 // Create named directory, if it doesn't already exist
871 if (!zfile.exists() && !zfile.mkdirs()) {
872 System.err.println("Error: unable to create directory " + zfile);
873 }
874 }
875 else {
876 // Write out file to disk
877
878 //Make sure it's parent directory exists.
879 File dir = new File(zfile.getParent());
880 dir.mkdirs();
881
882 // set up input stream
883 InputStream zis = zipfile.getInputStream(zipentry);
884 BufferedInputStream bzis = new BufferedInputStream(zis);
885 DataInputStream dbzis = new DataInputStream(bzis);
886
887 // set up output stream
888 FileOutputStream fzos = new FileOutputStream(zentryname);
889 BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
890
891 byte[] buf = new byte[1024];
892 int len;
893 while ((len = dbzis.read(buf)) >= 0) {
894 bfzos.write(buf,0,len);
895 }
896
897 dbzis.close();
898 bzis.close();
899 zis.close();
900
901 bfzos.close();
902 fzos.close();
903 }
904 }
905
906 zipfile.close();
907
908 // delete zip file
909 boolean file_deleted = cfile.delete();
910 if (file_deleted) {
911 System.err.println("Zip file " + cfile.toString() + " deleted");
912 }
913 else {
914 System.err.println("Zip file " + cfile.toString() + " NOT deleted");
915 }
916
917
918 }
919 catch (ZipException error) {
920 System.err.println("Error: Unable to open '"+zip_fname+"'");
921 System.err.println("This maybe caused by the zip file being empty.");
922 DebugStream.printStackTrace(error);
923 }
924
925 catch (Exception error) {
926 error.printStackTrace();
927 }
928 }
929
930
931 static public String getSitesDir(String gsdl3_path) {
932 return gsdl3_path + File.separator + "web"
933 + File.separator + "sites" + File.separator;
934
935 }
936
937
938 /** returns the path to the greenstone version of wget */
939 static public String getWGetPath(String gsdl_path)
940 {
941 if (isWindows()) {
942 return gsdl_path + "bin" + File.separator + "windows" + File.separator + "wget.exe";
943 }
944 else if (isMac()) {
945 return gsdl_path + "bin" + File.separator + "darwin" + File.separator + "wget";
946 }
947 else {
948 return gsdl_path + "bin" + File.separator + "linux" + File.separator + "wget";
949 }
950 }
951
952
953 static public void initImages(Object base_object)
954 {
955 base = base_object.getClass();
956
957 BLANK_ICON = new ImageIcon(base.getResource("/images/blank.gif"));
958 ERROR_ICON = new ImageIcon(base.getResource("/images/error.gif"));
959 HELP_ICON = new ImageIcon(base.getResource("/images/help.gif"));
960 }
961
962
963 /** Method to determine if the host system is MacOS based.
964 * @return a boolean which is true if the platform is MacOS, false otherwise
965 */
966 public static boolean isMac() {
967 Properties props = System.getProperties();
968 String os_name = props.getProperty("os.name","");
969 if(os_name.startsWith("Mac OS")) {
970 return true;
971 }
972 return false;
973 }
974
975
976 /** Method to determine if the host system is Microsoft Windows based.
977 * @return A <i>boolean</i> which is <i>true</i> if the platform is Windows, <i>false</i> otherwise.
978 */
979 public static boolean isWindows() {
980 Properties props = System.getProperties();
981 String os_name = props.getProperty("os.name","");
982 if(os_name.startsWith("Windows")) {
983 return true;
984 }
985 return false;
986 }
987
988 public static boolean isWindows9x() {
989 Properties props = System.getProperties();
990 String os_name = props.getProperty("os.name","");
991 if(os_name.startsWith("Windows") && os_name.indexOf("9") != -1) {
992 return true;
993 }
994 return false;
995 }
996 /** Takes a string and a desired length and pads out the string to the length by adding spaces to the left.
997 * @param str The target <strong>String</strong> that needs to be padded.
998 * @param length The desired length of the string as an <i>int</i>.
999 * @return A <strong>String</strong> made from appending space characters with the string until it has a length equal to length.
1000 */
1001 static private String pad(String str_raw, int length, char fill, boolean end) {
1002 StringBuffer str = new StringBuffer(str_raw);
1003 while(str.length() < length) {
1004 if(end) {
1005 str.insert(0, fill);
1006 }
1007 else {
1008 str.append(fill);
1009 }
1010 }
1011 return str.toString();
1012 }
1013
1014
1015 static public StringBuffer readXMLStream(InputStream input_stream)
1016 {
1017 StringBuffer xml = new StringBuffer("");
1018
1019 try {
1020 InputStreamReader isr = new InputStreamReader(input_stream, "UTF-8");
1021 BufferedReader buffered_in = new BufferedReader(isr);
1022
1023 String line = "";
1024 boolean xml_content = false;
1025 while((line = buffered_in.readLine()) != null) {
1026 if(xml_content) {
1027 xml.append(line);
1028 xml.append("\n");
1029 }
1030 else if(line.trim().startsWith("<?xml")) {
1031 xml_content = true;
1032 xml.append(line);
1033 xml.append("\n");
1034 }
1035 }
1036 buffered_in = null;
1037 }
1038 catch (Exception error) {
1039 System.err.println("Failed when trying to parse XML stream");
1040 error.printStackTrace();
1041 }
1042
1043 return xml;
1044 }
1045
1046
1047 /** I think this works a bit better on Unicode strings. */
1048 static public String stripNL(String raw_string)
1049 {
1050 String stripped_string = new String();
1051 for (int i = 0; i < raw_string.length(); i++) {
1052 char raw_character = raw_string.charAt(i);
1053 if (raw_character != '\n' && raw_character != '\t') {
1054 stripped_string = stripped_string + raw_character;
1055 }
1056 }
1057 return stripped_string;
1058 }
1059}
Note: See TracBrowser for help on using the repository browser.