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

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

GLI applet: collection building is now much happier about being cancelled. By Matthew Whyte.

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