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

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

Moved Utility.getHelpFolder into HelpFrame, as part of tidying up the Utility class.

  • Property svn:keywords set to Author Date Id Revision
File size: 35.7 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 /** Method to retrieve an image icon with the given filename found in classpath or the resouces directory.
415 * @return The specified <strong>ImageIcon</strong>, or an error image replacement if no such images exists.
416 */
417 static public ImageIcon getImage(String filename) {
418 return getImage(filename, false);
419 }
420
421 static public ImageIcon getImage(String filename, boolean wait_until_complete)
422 {
423 ImageIcon image = new ImageIcon(base.getResource("/images/" + filename));
424 if (image == null) {
425 image = ERROR_ICON;
426 }
427
428 if (wait_until_complete) {
429 int load_status;
430 do {
431 load_status = image.getImageLoadStatus();
432 }
433 while (load_status != MediaTracker.ABORTED && load_status != MediaTracker.ERRORED && load_status != MediaTracker.COMPLETE);
434 }
435
436 return image;
437 }
438
439
440 /** Method which constructs the import directory given a certain collection.
441 * @param col_dir The location of the collection directory as a <strong>String</strong>.
442 * @return The location of the given collections import directory, also as a <strong>String</strong>.
443 */
444 public static String getImportDir(String col_dir) {
445 return col_dir + IMPORT_DIR;
446 }
447
448 /** Method which constructs the log directory given a certain collection.
449 * @param col_dir The location of the collection directory as a <strong>String</strong>.
450 * @return The location of the given collections log directory, also as a <strong>String</strong>.
451 */
452 public static String getLogDir(String col_dir) {
453 if(col_dir != null) {
454 return col_dir + LOG_DIR;
455 }
456 else {
457 return getGLIUserFolder().getAbsolutePath() + File.separator + LOG_DIR;
458 }
459 }
460 /** Determine this machines name.
461 * @return The name as a <strong>String</strong>.
462 */
463 static public String getMachineName() {
464 try {
465 return InetAddress.getLocalHost().getHostName();
466 }
467 catch(UnknownHostException ex) {
468 }
469 return "Unknown Machine";
470 }
471
472
473 static public boolean isInJar(String filename)
474 {
475 try {
476 InputStream fis = base.getResourceAsStream("/"+filename);
477
478 fis.close();
479
480 }
481 catch (Exception error) {
482 System.err.println("**** collect.zip not there!");
483 error.printStackTrace();
484
485
486 return false;
487 }
488 return true;
489 }
490
491
492
493 static public void extractFromJar(String filename, String dst_dir, boolean must_be_present)
494 {
495 try {
496 // setup input stream for slurping out file
497 InputStream fis = base.getResourceAsStream("/"+filename);
498 BufferedInputStream fbis = new BufferedInputStream(fis);
499 DataInputStream fdbis = new DataInputStream(fbis);
500
501 // set up output stream for writing to disk
502 String ofname = dst_dir + filename;
503 FileOutputStream fos = new FileOutputStream(ofname);
504 BufferedOutputStream bfos = new BufferedOutputStream(fos);
505
506 byte[] buf = new byte[1024];
507 int len;
508 int total_bytes = 0;
509 while ((len = fdbis.read(buf)) >= 0) {
510 bfos.write(buf,0,len);
511 total_bytes += len;
512 }
513
514 fdbis.close();
515 bfos.close();
516 }
517 catch (Exception error) {
518 if (must_be_present) {
519 error.printStackTrace();
520 }
521 }
522 }
523
524
525 /** Method which unzips a given metadata resoure
526 * @param zip_fname The name of the zip file as a <strong>String</strong>.
527 * @param dst_dir The destination directory for unzipping, also as a <strong>String</strong>.
528 * @param use_classloader Used to determine whether or not to look in resource bundle.
529 */
530 static public void unzipFromJar(String jar_zip_fname, String dst_dir) {
531
532 File file = null;
533 if (!dst_dir.endsWith(File.separator)) {
534 dst_dir += File.separator;
535 }
536
537 extractFromJar(jar_zip_fname,dst_dir,true);
538
539 String zip_ofname = dst_dir + jar_zip_fname;
540 File zip_file = new File(zip_ofname);
541
542 try {
543 ZipFile zipfile = new ZipFile(zip_file);
544
545 Enumeration e = zipfile.entries();
546 while (e.hasMoreElements()) {
547 ZipEntry zipentry = (ZipEntry) e.nextElement();
548 String zentryname = dst_dir + zipentry.getName();
549 DebugStream.println(" Unzipping: " + zentryname);
550
551 if (zipentry.isDirectory()) {
552 // Create named directory, if it doesn't already exist
553 File zip_entry_file = new File(zentryname);
554 if (!zip_entry_file.exists() && !zip_entry_file.mkdirs()) {
555 System.err.println("Error: unable to create directory " + zip_entry_file);
556 }
557 }
558 else {
559 // Write out file to disk
560
561 // set up input stream
562 InputStream zis = zipfile.getInputStream(zipentry);
563 BufferedInputStream bzis = new BufferedInputStream(zis);
564 DataInputStream dbzis = new DataInputStream(bzis);
565
566 // set up output stream
567 FileOutputStream fzos = new FileOutputStream(zentryname);
568 BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
569
570 byte[] buf = new byte[1024];
571 int len;
572 while ((len = dbzis.read(buf)) >= 0) {
573 bfzos.write(buf,0,len);
574 }
575
576 dbzis.close();
577 bfzos.close();
578 }
579 }
580 }
581 catch (ZipException error) {
582 System.err.println("Error: Unable to open '"+zip_file.getAbsolutePath()+"'");
583 DebugStream.printStackTrace(error);
584 }
585
586 catch (Exception error) {
587 error.printStackTrace();
588 }
589 }
590
591
592 static protected String unixStylePath(String path)
593 {
594 String unix_path = path.replace('\\','/');
595 return unix_path;
596 }
597
598 /*
599 Method to handle zipping up of a file. Called by zipup and dirFunc.
600
601 @param zos the zip output stream, as a <strong>ZipOutputStream</strong>
602 @param file_path the <strong>String</strong> containing the path to the file/directory tozip up
603 @param prefix_strip the <strong>int</strong> used to substring the file_path
604 @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.
605 @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
606 @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
607
608 @return boolean
609
610 @see dirFunc
611 @see zipup
612 */
613 static protected boolean zipFunc (ZipOutputStream zos, String file_path, int prefix_strip, GShell source, boolean encountered_file, String accept_expr, String reject_expr)
614 {
615 String new_file_path = file_path;
616
617 if((reject_expr != "") && (file_path.matches(reject_expr))) {
618 // matches reject expression
619 //DebugStream.println("File \'" + file_path + "\' matches the reject expression \'" + reject_expr + "\'");
620 return encountered_file;
621 }
622
623 if ((accept_expr != "") && (!file_path.matches(accept_expr))) {
624 // does not match accept expression
625 //DebugStream.println("File \'" + file_path + "\' doesn't match accept expression \'" + accept_expr + "\'");
626 return encountered_file;
627 }
628
629 //Special case: we only want the metadata. Parse the xml files.
630 if(accept_expr.compareTo(".*doc.xml") == 0) {
631 DebugStream.println("Only want to get metadata");
632 Document old_document = XMLTools.parseXMLFile(new File(file_path));
633 NodeList content = old_document.getElementsByTagName("Content");
634
635 try {
636 for(int i=content.getLength()-1; i >= 0; i--) {
637 //Remove all content - just leave the metadata.
638 content.item(i).getParentNode().removeChild(content.item(i));
639 }
640 }
641 catch (Exception ex) {
642 ex.printStackTrace();
643 }
644
645 new_file_path = file_path.substring(0, file_path.lastIndexOf(File.separator) + 1) + "new.xml";
646 //Is there any better way than writing out as a new file, then reading back in??
647 XMLTools.writeXMLFile(new File(new_file_path), old_document);
648 }
649
650 // Using try is required because of file io.
651 try {
652 // Exit if pressed cancel.
653 if (source != null && source.hasSignalledStop()) {
654 return false;
655 }
656
657 // Create a Zip Entry and put it into the archive (no data yet).
658
659 // Strip off col_dir prefix
660 String zip_path = file_path.substring(prefix_strip);
661 // Zip files use '/' for directory separator
662 String unix_style_path = unixStylePath(zip_path);
663
664 ZipEntry fileEntry = new ZipEntry(unix_style_path);
665 zos.putNextEntry(fileEntry);
666
667 // Create a file input stream and a buffered input stream.
668 FileInputStream fis = new FileInputStream(new_file_path);
669 BufferedInputStream bis = new BufferedInputStream(fis);
670
671 // Create a byte array object named data and declare byte count variable.
672 byte[] data = new byte[1024];
673 int byteCount;
674 // Create a loop that reads from the buffered input stream and writes
675 // to the zip output stream until the bis has been entirely read.
676 while ((byteCount = bis.read(data, 0, 1024)) > -1) {
677 //Check for cancell
678 if(source != null) {
679 if(source.hasSignalledStop()) {
680 break;
681 }
682 }
683 zos.write(data, 0, byteCount);
684 }
685 encountered_file = true;
686 }
687 catch (IOException e) {
688 e.printStackTrace();
689 }
690
691 DebugStream.println("Zipping up: " + file_path);
692 return encountered_file;
693 }
694
695 /*
696 Method to handle ziping up of a directory.
697
698 @param zos
699 @param dir_name
700 @param prefix_strip
701 @param source
702 @param encountered_file ??What's this??
703 @param accept_expr
704 @param reject_expr
705
706 @see zipup
707 @see zipFunc
708 */
709 static protected boolean dirFunc (ZipOutputStream zos, String dir_name, int prefix_strip, GShell source, boolean encountered_file, String accept_expr, String reject_expr)
710 {
711 File dirObj = new File(dir_name);
712
713 if (dirObj.exists() == true) {
714 if (dirObj.isDirectory() == true) {
715 // Create an array of File objects, one for each file or directory in dirObj.
716 File [] fileList = dirObj.listFiles();
717
718 // Loop through File array and display.
719 for (int i = 0; i < fileList.length; i++) {
720 if(source != null && source.hasSignalledStop()) { break; }
721 File file = fileList[i];
722 if (file.isDirectory()) {
723 String dir_path = file.getPath();
724 String zip_path = dir_path.substring(prefix_strip);
725 // Zip files use '/' for directory separator
726 String unix_style_path
727 = unixStylePath(zip_path+File.separator);
728 ZipEntry dirEntry = new ZipEntry(unix_style_path);
729
730 try {
731 zos.putNextEntry(dirEntry);
732 }
733 catch (IOException e) {
734 e.printStackTrace();
735 }
736
737 encountered_file = dirFunc(zos, dir_path, prefix_strip, source, encountered_file, accept_expr, reject_expr);
738 } else if (file.isFile()) {
739 // Call the zipFunc function
740 String file_path = fileList[i].getPath();
741 encountered_file = zipFunc(zos,file_path,prefix_strip, source, encountered_file, accept_expr, reject_expr);
742 }
743 }
744 }
745 else {
746 System.err.println (dir_name+" is not a directory.");
747 }
748 }
749 else {
750 System.err.println ("Directory "+dir_name+" does not exist.");
751 }
752 return encountered_file;
753 }
754
755 /**
756 Method to zip up a given file or directory
757
758 @param col_dir
759 @param col_name
760 @param dir_or_file
761 @param source
762 @param filter
763
764 @see zipFunc
765 @see dirFunc
766 */
767 static public boolean zipup(String col_dir, String col_name, String dir_or_file, GShell source, String accept_expr, String reject_expr)
768 {
769 if (!col_dir.endsWith(File.separator)) {
770 col_dir += File.separator;
771 }
772
773 int prefix_strip = col_dir.length();
774 boolean encountered_file = false;
775
776 String zip_fname = col_dir + col_name + ".zip";
777 String zip_dir_or_file = col_dir + col_name + File.separator + dir_or_file;
778 File zip_dof = new File(zip_dir_or_file);
779
780 try {
781 FileOutputStream fos = new FileOutputStream(zip_fname);
782 ZipOutputStream zos = new ZipOutputStream(fos);
783
784 if (zip_dof.exists()) {
785 if (zip_dof.isDirectory()) {
786 String zip_dir = zip_dir_or_file;
787 encountered_file = dirFunc(zos, zip_dir, prefix_strip, source, encountered_file, accept_expr, reject_expr);
788 }
789 else {
790 String zip_full_file = zip_dir_or_file;
791 String zip_path = zip_full_file.substring(prefix_strip);
792
793 for (int i=1; i<zip_path.length(); i++) {
794 String ch = String.valueOf(zip_path.charAt(i));
795
796 if (ch.equals(File.separator)) {
797 String dir_path = zip_path.substring(0,i);
798 // Zip files use '/' for directory separator
799 String unix_style_path
800 = unixStylePath(dir_path+File.separator);
801 ZipEntry dirEntry = new ZipEntry(unix_style_path);
802 zos.putNextEntry(dirEntry);
803 }
804 }
805 encountered_file = zipFunc(zos, zip_full_file, prefix_strip, source, encountered_file, accept_expr, reject_expr);
806 }
807 }
808 else {
809 System.err.println("Warning: " + zip_dir_or_file + " does not exist!");
810 }
811
812 // Close the file output streams for both the file and the zip.
813 zos.flush();
814 zos.close();
815 fos.close();
816 }
817 catch (IOException exception) {
818 DebugStream.printStackTrace(exception);
819 return false;
820 }
821 return encountered_file;
822 }
823
824
825 static public void unzip(String col_dir, String col_name)
826 {
827 if (!col_dir.endsWith(File.separator)) {
828 col_dir += File.separator;
829 }
830
831 String zip_fname = col_dir + col_name + ".zip";
832 // int zip_mode = ZipFile.OPEN_READ | ZipFile.OPEN_DELETE;
833 int zip_mode = ZipFile.OPEN_READ;
834
835 try {
836 File cfile = new File(zip_fname);
837 ZipFile zipfile = new ZipFile(cfile, zip_mode);
838
839 Enumeration e = zipfile.entries();
840 while (e.hasMoreElements()) {
841 ZipEntry zipentry = (ZipEntry) e.nextElement();
842 String zentryname = col_dir + zipentry.getName();
843 File zfile = new File(zentryname);
844 DebugStream.println(" Unzipping: " + zentryname);
845
846 if (zipentry.isDirectory()) {
847 // Create named directory, if it doesn't already exist
848 if (!zfile.exists() && !zfile.mkdirs()) {
849 System.err.println("Error: unable to create directory " + zfile);
850 }
851 }
852 else {
853 // Write out file to disk
854
855 //Make sure it's parent directory exists.
856 File dir = new File(zfile.getParent());
857 dir.mkdirs();
858
859 // set up input stream
860 InputStream zis = zipfile.getInputStream(zipentry);
861 BufferedInputStream bzis = new BufferedInputStream(zis);
862 DataInputStream dbzis = new DataInputStream(bzis);
863
864 // set up output stream
865 FileOutputStream fzos = new FileOutputStream(zentryname);
866 BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
867
868 byte[] buf = new byte[1024];
869 int len;
870 while ((len = dbzis.read(buf)) >= 0) {
871 bfzos.write(buf,0,len);
872 }
873
874 dbzis.close();
875 bzis.close();
876 zis.close();
877
878 bfzos.close();
879 fzos.close();
880 }
881 }
882
883 zipfile.close();
884
885 // delete zip file
886 boolean file_deleted = cfile.delete();
887 if (file_deleted) {
888 System.err.println("Zip file " + cfile.toString() + " deleted");
889 }
890 else {
891 System.err.println("Zip file " + cfile.toString() + " NOT deleted");
892 }
893
894
895 }
896 catch (ZipException error) {
897 System.err.println("Error: Unable to open '"+zip_fname+"'");
898 System.err.println("This maybe caused by the zip file being empty.");
899 DebugStream.printStackTrace(error);
900 }
901
902 catch (Exception error) {
903 error.printStackTrace();
904 }
905 }
906
907
908 static public String getSitesDir(String gsdl3_path) {
909 return gsdl3_path + File.separator + "web"
910 + File.separator + "sites" + File.separator;
911
912 }
913
914
915 /** returns the path to the greenstone version of wget */
916 static public String getWGetPath(String gsdl_path)
917 {
918 if (isWindows()) {
919 return gsdl_path + "bin" + File.separator + "windows" + File.separator + "wget.exe";
920 }
921 else if (isMac()) {
922 return gsdl_path + "bin" + File.separator + "darwin" + File.separator + "wget";
923 }
924 else {
925 return gsdl_path + "bin" + File.separator + "linux" + File.separator + "wget";
926 }
927 }
928
929
930 static public void initImages(Object base_object)
931 {
932 base = base_object.getClass();
933
934 BLANK_ICON = new ImageIcon(base.getResource("/images/blank.gif"));
935 ERROR_ICON = new ImageIcon(base.getResource("/images/error.gif"));
936 HELP_ICON = new ImageIcon(base.getResource("/images/help.gif"));
937 }
938
939
940 /** Method to determine if the host system is MacOS based.
941 * @return a boolean which is true if the platform is MacOS, false otherwise
942 */
943 public static boolean isMac() {
944 Properties props = System.getProperties();
945 String os_name = props.getProperty("os.name","");
946 if(os_name.startsWith("Mac OS")) {
947 return true;
948 }
949 return false;
950 }
951
952
953 /** Method to determine if the host system is Microsoft Windows based.
954 * @return A <i>boolean</i> which is <i>true</i> if the platform is Windows, <i>false</i> otherwise.
955 */
956 public static boolean isWindows() {
957 Properties props = System.getProperties();
958 String os_name = props.getProperty("os.name","");
959 if(os_name.startsWith("Windows")) {
960 return true;
961 }
962 return false;
963 }
964
965 public static boolean isWindows9x() {
966 Properties props = System.getProperties();
967 String os_name = props.getProperty("os.name","");
968 if(os_name.startsWith("Windows") && os_name.indexOf("9") != -1) {
969 return true;
970 }
971 return false;
972 }
973 /** Takes a string and a desired length and pads out the string to the length by adding spaces to the left.
974 * @param str The target <strong>String</strong> that needs to be padded.
975 * @param length The desired length of the string as an <i>int</i>.
976 * @return A <strong>String</strong> made from appending space characters with the string until it has a length equal to length.
977 */
978 static private String pad(String str_raw, int length, char fill, boolean end) {
979 StringBuffer str = new StringBuffer(str_raw);
980 while(str.length() < length) {
981 if(end) {
982 str.insert(0, fill);
983 }
984 else {
985 str.append(fill);
986 }
987 }
988 return str.toString();
989 }
990
991
992 static public StringBuffer readXMLStream(InputStream input_stream)
993 {
994 StringBuffer xml = new StringBuffer("");
995
996 try {
997 InputStreamReader isr = new InputStreamReader(input_stream, "UTF-8");
998 BufferedReader buffered_in = new BufferedReader(isr);
999
1000 String line = "";
1001 boolean xml_content = false;
1002 while((line = buffered_in.readLine()) != null) {
1003 if(xml_content) {
1004 xml.append(line);
1005 xml.append("\n");
1006 }
1007 else if(line.trim().startsWith("<?xml")) {
1008 xml_content = true;
1009 xml.append(line);
1010 xml.append("\n");
1011 }
1012 }
1013 buffered_in = null;
1014 }
1015 catch (Exception error) {
1016 System.err.println("Failed when trying to parse XML stream");
1017 error.printStackTrace();
1018 }
1019
1020 return xml;
1021 }
1022
1023
1024 /** I think this works a bit better on Unicode strings. */
1025 static public String stripNL(String raw_string)
1026 {
1027 String stripped_string = new String();
1028 for (int i = 0; i < raw_string.length(); i++) {
1029 char raw_character = raw_string.charAt(i);
1030 if (raw_character != '\n' && raw_character != '\t') {
1031 stripped_string = stripped_string + raw_character;
1032 }
1033 }
1034 return stripped_string;
1035 }
1036}
Note: See TracBrowser for help on using the repository browser.