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

Last change on this file since 8766 was 8654, checked in by mdewsnip, 20 years ago

More minor tidy ups.

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