source: trunk/gsdl3/src/java/org/greenstone/core/util/Utility.java@ 10929

Last change on this file since 10929 was 10929, checked in by kjdon, 18 years ago

merged Chi's admin stuff from ant install branch into main repository

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