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

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

Removed the full justification by adding spaces of plugin and classifier option descriptions. This is no longer useful now that a non-fixed width font is used.

  • Property svn:keywords set to Author Date Id Revision
File size: 34.5 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 MINIMUM_BUTTON_SIZE = new Dimension(100, 25);
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 lines.push(line);
266 line = token;
267 current_width = token.length();
268 token = null;
269 }
270 // Otherwise we should be able to just add the token, give or take.
271 else {
272 if(current_width == 0) {
273 line = line + token;
274 current_width = token.length();
275 }
276 else {
277 // Special case for standard punctuation which may exist after a tag like so:
278 // My name is <scratchy>Slim Shady</scratchy>. <-- Annoying punctuation.
279 if(token.equals(".") || token.equals(",") || token.equals("!") || token.equals("?")) {
280 line = line + token;
281 current_width = current_width + 1;
282 }
283 else {
284 line = line + " " + token;
285 current_width = current_width + 1 + token.length();
286 }
287 }
288 token = null;
289 }
290 }
291 }
292 }
293 String result = line;
294 while(!lines.empty()) {
295 result = (String)lines.pop() + "<BR>" + result;
296 }
297 // Replace ' ' with "&nbsp;"
298 boolean tag = false;
299 int pos = 0;
300 while(pos < result.length()) {
301 if(result.charAt(pos) == '<') {
302 tag = true;
303 }
304 else if(result.charAt(pos) == '>') {
305 tag = false;
306 }
307 else if(result.charAt(pos) == ' ' && !tag) {
308 String prefix = result.substring(0, pos);
309 String suffix = result.substring(pos + 1);
310 result = prefix + "&nbsp;" + suffix;
311 }
312 pos++;
313 }
314 result = "<HTML>" + result + "</HTML>";
315 return result;
316 }
317 /** Format the given filename path string so that it is no longer than the given width. If it is wider replace starting directories with ...
318 * @param key The key <strong>String</Strong> used to retrieve a phrase from the dictionary for this item.
319 * @param raw The raw filename path <strong>String</strong>.
320 * @param width The maximum width as an <i>int</i>.
321 * @return A path <strong>String</strong> no longer than width.
322 */
323 static public String formatPath(String key, String raw, int width) {
324 JLabel label = new JLabel(Dictionary.get(key, raw));
325 int position = -1;
326 while(label.getPreferredSize().width > width && (position = raw.indexOf(File.separator)) != -1) {
327 raw = "..." + raw.substring(position + 1);
328 label.setText(Dictionary.get(key, raw));
329 }
330 if(raw.indexOf(File.separator) == -1 && raw.startsWith("...")) {
331 raw = raw.substring(3);
332 }
333 return raw;
334 }
335
336
337 /** Builds the cache dir by appending the user path and 'cache'.
338 * @return a File representing the path to the private file cache within the current collection.
339 */
340 public static File getCacheDir() {
341 return new File(getGLIUserFolder(), StaticStrings.CACHE_FOLDER);
342 }
343 /** Method which constructs the collect directory for Greenstone.
344 * @param gsdl_path The location of the gsdl installation directory as a <strong>String</strong>.
345 * @return The location of the collection directory, also as a <strong>String</strong>.
346 */
347 public static String getCollectDir(String gsdl_path) {
348 return gsdl_path + COL_DIR;
349 }
350 static public String getCollectDir(String gsdl3_path, String site_name) {
351 return getSitesDir(gsdl3_path) + site_name + File.separator + COL_DIR;
352 }
353
354
355 /** Method which constructs a collection's top level directory
356 * @@param gsdl_path The location of the gsdl installation directory as a <strong>String</strong>.
357 * @param The name of the collection as a <strong>String</strong>.
358 * @return The location of the collection's base directory
359 */
360 public static String getCollectionDir(String gsdl_path, String coll_name) {
361 return getCollectDir(gsdl_path) + coll_name + File.separator;
362 }
363 public static String getCollectionDir(String gsdl3_path, String site_name, String coll_name) {
364 return getCollectDir(gsdl3_path, site_name) + coll_name + File.separator;
365 }
366
367
368 /** Method which constructs the configuration file given a certain collection.
369 * @param col_dir The location of the collection directory as a <strong>String</strong>.
370 * @return The location of the given collections configuration file, also as a <strong>String</strong>.
371 */
372 static public String getConfigFile(String col_dir) {
373 return col_dir + CONFIG_FILE;
374 }
375
376 static public String getDateString() {
377 Calendar current = Calendar.getInstance();
378 String day_name = null;
379 switch(current.get(Calendar.DAY_OF_WEEK)) {
380 case Calendar.MONDAY: day_name = "Dates.Mon"; break;
381 case Calendar.TUESDAY: day_name = "Dates.Tue"; break;
382 case Calendar.WEDNESDAY: day_name = "Dates.Wed"; break;
383 case Calendar.THURSDAY: day_name = "Dates.Thu"; break;
384 case Calendar.FRIDAY: day_name = "Dates.Fri"; break;
385 case Calendar.SATURDAY: day_name = "Dates.Sat"; break;
386 case Calendar.SUNDAY: day_name = "Dates.Sun"; break;
387 default: day_name = "";
388 }
389 String month_name = null;
390 switch(current.get(Calendar.MONTH)) {
391 case Calendar.JANUARY: month_name = "Dates.Jan"; break;
392 case Calendar.FEBRUARY: month_name = "Dates.Feb"; break;
393 case Calendar.MARCH: month_name = "Dates.Mar"; break;
394 case Calendar.APRIL: month_name = "Dates.Apr"; break;
395 case Calendar.MAY: month_name = "Dates.May"; break;
396 case Calendar.JUNE: month_name = "Dates.Jun"; break;
397 case Calendar.JULY: month_name = "Dates.Jul"; break;
398 case Calendar.AUGUST: month_name = "Dates.Aug"; break;
399 case Calendar.SEPTEMBER: month_name = "Dates.Sep"; break;
400 case Calendar.OCTOBER: month_name = "Dates.Oct"; break;
401 case Calendar.NOVEMBER: month_name = "Dates.Nov"; break;
402 case Calendar.DECEMBER: month_name = "Dates.Dec"; break;
403 default: month_name = "";
404 }
405 int day = current.get(Calendar.DAY_OF_MONTH);
406 int hour = current.get(Calendar.HOUR_OF_DAY);
407 int minute = current.get(Calendar.MINUTE);
408 int second = current.get(Calendar.SECOND);
409 int year = current.get(Calendar.YEAR);
410
411 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);
412 }
413
414
415 static final private String APPLICATION_DATA_FOLDER = "Application Data";
416 static final private String UNIX_GLI_CONFIG_FOLDER = ".gli";
417 static final private String USER_HOME_PROPERTY = "user.home";
418 static final private String WIN_GLI_CONFIG_FOLDER = "Greenstone" + File.separator + "GLI";
419
420 static public File getGLIUserFolder()
421 {
422 if (Utility.isWindows()) {
423 return new File(System.getProperty(USER_HOME_PROPERTY) + File.separator + APPLICATION_DATA_FOLDER + File.separator + WIN_GLI_CONFIG_FOLDER + File.separator);
424 }
425 else {
426 return new File(System.getProperty(USER_HOME_PROPERTY) + File.separator + UNIX_GLI_CONFIG_FOLDER + File.separator);
427 }
428 }
429
430
431 /** Retrieve the full file path to the help index xml file.
432 * @return the full path as a String
433 */
434 static public String getHelpFolder() {
435
436 String help_folder = "help/" + Configuration.getLanguage() + "/";
437
438 // Try in the JAR/classes directory first
439 URL help_folder_url = base.getResource("/" + help_folder);
440 if (help_folder_url != null) {
441 return help_folder;
442 }
443
444 // Look in the base directory next
445 File help_folder_file = new File(help_folder);
446 if (help_folder_file.exists()) {
447 return help_folder;
448 }
449
450 // Resort to English
451 return "help/" + StaticStrings.ENGLISH_LANGUAGE_STR + "/";
452 }
453
454 /** Method to retrieve an image icon with the given filename found in classpath or the resouces directory.
455 * @return The specified <strong>ImageIcon</strong>, or an error image replacement if no such images exists.
456 */
457 static public ImageIcon getImage(String filename) {
458 return getImage(filename, false);
459 }
460
461 static public ImageIcon getImage(String filename, boolean wait_until_complete) {
462 ImageIcon image = null;
463 try {
464 image = new ImageIcon(base.getResource("/images/" + Dictionary.get("Version") + "/" + filename));
465 }
466 catch(NullPointerException exception) {
467 image = new ImageIcon(base.getResource("/images/" + filename));
468 }
469 if(image == null) {
470 image = ERROR_ICON;
471 }
472
473 if(wait_until_complete) {
474 int load_status;
475 do {
476 load_status = image.getImageLoadStatus();
477 }
478 while(load_status != MediaTracker.ABORTED && load_status != MediaTracker.ERRORED && load_status != MediaTracker.COMPLETE);
479 }
480 return image;
481 }
482
483 /** Method which constructs the images directory given a certain collection.
484 * @param col_dir The location of the collection directory as a <strong>String</strong>.
485 * @return The location of the given collections images directory, also as a <strong>String</strong>.
486 */
487 public static String getImagesDir(String col_dir) {
488 return col_dir + IMAGES_DIR;
489 }
490 /** Method which constructs the import directory given a certain collection.
491 * @param col_dir The location of the collection directory as a <strong>String</strong>.
492 * @return The location of the given collections import directory, also as a <strong>String</strong>.
493 */
494 public static String getImportDir(String col_dir) {
495 return col_dir + IMPORT_DIR;
496 }
497
498 /** Method which constructs the log directory given a certain collection.
499 * @param col_dir The location of the collection directory as a <strong>String</strong>.
500 * @return The location of the given collections log directory, also as a <strong>String</strong>.
501 */
502 public static String getLogDir(String col_dir) {
503 if(col_dir != null) {
504 return col_dir + LOG_DIR;
505 }
506 else {
507 return getGLIUserFolder().getAbsolutePath() + File.separator + LOG_DIR;
508 }
509 }
510 /** Determine this machines name.
511 * @return The name as a <strong>String</strong>.
512 */
513 static public String getMachineName() {
514 try {
515 return InetAddress.getLocalHost().getHostName();
516 }
517 catch(UnknownHostException ex) {
518 }
519 return "Unknown Machine";
520 }
521
522
523 static public void extractFromJar(String filename, String dst_dir, boolean must_be_present)
524 {
525 try {
526 // setup input stream for slurping out file
527 InputStream fis = base.getResourceAsStream("/"+filename);
528 BufferedInputStream fbis = new BufferedInputStream(fis);
529 DataInputStream fdbis = new DataInputStream(fbis);
530
531 // set up output stream for writing to disk
532 String ofname = dst_dir + filename;
533 FileOutputStream fos = new FileOutputStream(ofname);
534 BufferedOutputStream bfos = new BufferedOutputStream(fos);
535
536 byte[] buf = new byte[1024];
537 int len;
538 int total_bytes = 0;
539 while ((len = fdbis.read(buf)) >= 0) {
540 bfos.write(buf,0,len);
541 total_bytes += len;
542 }
543
544 fdbis.close();
545 bfos.close();
546 }
547 catch (Exception error) {
548 if (must_be_present) {
549 error.printStackTrace();
550 }
551 }
552 }
553
554
555 /** Method which unzips a given metadata resoure
556 * @param zip_fname The name of the zip file as a <strong>String</strong>.
557 * @param dst_dir The destination directory for unzipping, also as a <strong>String</strong>.
558 * @param use_classloader Used to determine whether or not to look in resource bundle.
559 */
560 static public void unzipFromJar(String jar_zip_fname, String dst_dir) {
561
562 File file = null;
563 if (!dst_dir.endsWith(File.separator)) {
564 dst_dir += File.separator;
565 }
566
567 extractFromJar(jar_zip_fname,dst_dir,true);
568
569 String zip_ofname = dst_dir + jar_zip_fname;
570 File zip_file = new File(zip_ofname);
571
572 try {
573 ZipFile zipfile = new ZipFile(zip_file);
574
575 Enumeration e = zipfile.entries();
576 while (e.hasMoreElements()) {
577 ZipEntry zipentry = (ZipEntry) e.nextElement();
578 String zentryname = dst_dir + zipentry.getName();
579 DebugStream.println(" Unzipping: " + zentryname);
580
581 if (zipentry.isDirectory()) {
582 // Create named directory
583 boolean success = (new File(zentryname)).mkdir();
584 if (!success) {
585 System.err.println("Error: unable to create directory '"+zentryname+"'");
586 }
587 }
588 else {
589 // Write out file to disk
590
591 // set up input stream
592 InputStream zis = zipfile.getInputStream(zipentry);
593 BufferedInputStream bzis = new BufferedInputStream(zis);
594 DataInputStream dbzis = new DataInputStream(bzis);
595
596 // set up output stream
597 FileOutputStream fzos = new FileOutputStream(zentryname);
598 BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
599
600 byte[] buf = new byte[1024];
601 int len;
602 while ((len = dbzis.read(buf)) >= 0) {
603 bfzos.write(buf,0,len);
604 }
605
606 dbzis.close();
607 bfzos.close();
608 }
609 }
610 }
611 catch (ZipException error) {
612 System.err.println("Error: Unable to open '"+zip_file.getAbsolutePath()+"'");
613 DebugStream.printStackTrace(error);
614 }
615
616 catch (Exception error) {
617 error.printStackTrace();
618 }
619 }
620
621
622 static protected String unixStylePath(String path)
623 {
624 String unix_path = path.replace('\\','/');
625 return unix_path;
626 }
627
628 static protected void zipFunc (ZipOutputStream zos, String file_path, int prefix_strip)
629 {
630 // Using try is required because of file io.
631 try {
632 // Create a Zip Entry and put it into the archive (no data yet).
633
634 // Strip off col_dir prefix
635 String zip_path = file_path.substring(prefix_strip);
636 // Zip files use '/' for directory separator
637 String unix_style_path = unixStylePath(zip_path);
638 ZipEntry fileEntry = new ZipEntry(unix_style_path);
639 zos.putNextEntry(fileEntry);
640
641 // Create a file input stream and a buffered input stream.
642 FileInputStream fis = new FileInputStream(file_path);
643 BufferedInputStream bis = new BufferedInputStream(fis);
644
645 // Create a byte array object named data and declare byte count variable.
646 byte[] data = new byte[1024];
647 int byteCount;
648 // Create a loop that reads from the buffered input stream and writes
649 // to the zip output stream until the bis has been entirely read.
650 while ((byteCount = bis.read(data, 0, 1024)) > -1) {
651 zos.write(data, 0, byteCount);
652 }
653 }
654 catch (IOException e) {
655 e.printStackTrace();
656 }
657
658 DebugStream.println(" Zipping up: " + file_path);
659 }
660
661 static protected void dirFunc (ZipOutputStream zos, String dir_name, int prefix_strip)
662 {
663 File dirObj = new File(dir_name);
664
665 if (dirObj.exists() == true) {
666 if (dirObj.isDirectory() == true) {
667 // Create an array of File objects, one for each file or directory in dirObj.
668 File [] fileList = dirObj.listFiles();
669
670 // Loop through File array and display.
671 for (int i = 0; i < fileList.length; i++) {
672 File file = fileList[i];
673 if (file.isDirectory()) {
674 String dir_path = file.getPath();
675 String zip_path = dir_path.substring(prefix_strip);
676 // Zip files use '/' for directory separator
677 String unix_style_path
678 = unixStylePath(zip_path+File.separator);
679 ZipEntry dirEntry = new ZipEntry(unix_style_path);
680
681 try {
682 zos.putNextEntry(dirEntry);
683 }
684 catch (IOException e) {
685 e.printStackTrace();
686 }
687
688 dirFunc(zos,dir_path,prefix_strip);
689 } else if (file.isFile()) {
690 // Call the zipFunc function
691 String file_path = fileList[i].getPath();
692 zipFunc(zos,file_path,prefix_strip);
693 }
694 }
695 }
696 else {
697 System.err.println (dir_name+" is not a directory.");
698 }
699 }
700 else {
701 System.err.println ("Directory "+dir_name+" does not exist.");
702 }
703 }
704
705
706
707 static public void zipup(String col_name, String dir_or_file)
708 {
709 String col_dir = Utility.getCollectDir(Configuration.gsdl_path);
710 int prefix_strip = col_dir.length();
711
712 String zip_fname = col_dir + col_name + ".zip";
713 String zip_dir_or_file = col_dir + col_name + File.separator + dir_or_file;
714 File zip_dof = new File(zip_dir_or_file);
715
716 try {
717 FileOutputStream fos = new FileOutputStream(zip_fname);
718 ZipOutputStream zos = new ZipOutputStream(fos);
719
720 if (zip_dof.exists()) {
721 if (zip_dof.isDirectory()) {
722 String zip_dir = zip_dir_or_file;
723 dirFunc(zos,zip_dir,prefix_strip);
724 }
725 else {
726 String zip_full_file = zip_dir_or_file;
727
728 String zip_path = zip_full_file.substring(prefix_strip);
729
730 for (int i=1; i<zip_path.length(); i++) {
731 String ch = String.valueOf(zip_path.charAt(i));
732
733 if (ch.equals(File.separator)) {
734 String dir_path = zip_path.substring(0,i);
735 // Zip files use '/' for directory separator
736 String unix_style_path
737 = unixStylePath(dir_path+File.separator);
738 ZipEntry dirEntry = new ZipEntry(unix_style_path);
739 zos.putNextEntry(dirEntry);
740 }
741 }
742 zipFunc(zos,zip_full_file,prefix_strip);
743 }
744 }
745 else {
746 System.err.println("Warning: " + zip_dir_or_file + " does not exist!");
747 }
748
749 // Close the file output streams for both the file and the zip.
750 zos.flush();
751 zos.close();
752 fos.close();
753 }
754 catch (IOException e) {
755 e.printStackTrace();
756 }
757 }
758
759
760 static public void unzip(String col_name)
761 {
762 String col_dir = Utility.getCollectDir(Configuration.gsdl_path);
763 String zip_fname = col_dir + col_name + ".zip";
764 int zip_mode = ZipFile.OPEN_READ | ZipFile.OPEN_DELETE;
765
766 try {
767 ZipFile zipfile = new ZipFile(new File(zip_fname), zip_mode);
768
769 Enumeration e = zipfile.entries();
770 while (e.hasMoreElements()) {
771 ZipEntry zipentry = (ZipEntry) e.nextElement();
772 String zentryname = col_dir + zipentry.getName();
773 DebugStream.println(" Unzipping: " + zentryname);
774
775 if (zipentry.isDirectory()) {
776 // Create named directory
777 boolean success = (new File(zentryname)).mkdir();
778 if (!success) {
779 System.err.println("Error: unable to create directory '"+zentryname+"'");
780 }
781 }
782 else {
783 // Write out file to disk
784
785 // set up input stream
786 InputStream zis = zipfile.getInputStream(zipentry);
787 BufferedInputStream bzis = new BufferedInputStream(zis);
788 DataInputStream dbzis = new DataInputStream(bzis);
789
790 // set up output stream
791 FileOutputStream fzos = new FileOutputStream(zentryname);
792 BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
793
794 byte[] buf = new byte[1024];
795 int len;
796 while ((len = dbzis.read(buf)) >= 0) {
797 bfzos.write(buf,0,len);
798 }
799
800 dbzis.close();
801 bfzos.close();
802 }
803 }
804 }
805 catch (ZipException error) {
806 System.err.println("Error: Unable to open '"+zip_fname+"'");
807 DebugStream.printStackTrace(error);
808 }
809
810 catch (Exception error) {
811 error.printStackTrace();
812 }
813 }
814
815
816 static public String getSitesDir(String gsdl3_path) {
817 return gsdl3_path + File.separator + "web"
818 + File.separator + "sites" + File.separator;
819
820 }
821
822
823 /** returns the path to the greenstone version of wget */
824 static public String getWGetPath(String gsdl_path) {
825 if (isWindows()) {
826 return gsdl_path + "bin" + File.separator +
827 "windows" + File.separator +"wget.exe";
828 }
829 // is it the same for macs??
830 return gsdl_path + "bin" + File.separator +
831 "linux" + File.separator + "wget";
832 }
833
834
835 static public void initImages(Object base_object)
836 {
837 base = base_object.getClass();
838
839 BLANK_ICON = new ImageIcon(base.getResource("/images/blank.gif"));
840 ERROR_ICON = new ImageIcon(base.getResource("/images/error.gif"));
841 HELP_ICON = new ImageIcon(base.getResource("/images/help.gif"));
842 }
843
844
845 /** Method to determine if the host system is MacOS based.
846 * @return a boolean which is true if the platform is MacOS, false otherwise
847 */
848 public static boolean isMac() {
849 Properties props = System.getProperties();
850 String os_name = props.getProperty("os.name","");
851 if(os_name.startsWith("Mac OS")) {
852 return true;
853 }
854 return false;
855 }
856
857
858 /** Method to determine if the host system is Microsoft Windows based.
859 * @return A <i>boolean</i> which is <i>true</i> if the platform is Windows, <i>false</i> otherwise.
860 */
861 public static boolean isWindows() {
862 Properties props = System.getProperties();
863 String os_name = props.getProperty("os.name","");
864 if(os_name.startsWith("Windows")) {
865 return true;
866 }
867 return false;
868 }
869
870 public static boolean isWindows9x() {
871 Properties props = System.getProperties();
872 String os_name = props.getProperty("os.name","");
873 if(os_name.startsWith("Windows") && os_name.indexOf("9") != -1) {
874 return true;
875 }
876 return false;
877 }
878 /** Takes a string and a desired length and pads out the string to the length by adding spaces to the left.
879 * @param str The target <strong>String</strong> that needs to be padded.
880 * @param length The desired length of the string as an <i>int</i>.
881 * @return A <strong>String</strong> made from appending space characters with the string until it has a length equal to length.
882 */
883 public static String pad(String str_raw, int length, char fill, boolean end) {
884 StringBuffer str = new StringBuffer(str_raw);
885 while(str.length() < length) {
886 if(end) {
887 str.insert(0, fill);
888 }
889 else {
890 str.append(fill);
891 }
892 }
893 return str.toString();
894 }
895
896
897 /** 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. */
898 static public Document parse(String filename, boolean use_classloader)
899 {
900 // Try the class loader if desired (for the applet JAR file)
901 if (use_classloader) {
902 InputStream is = base.getResourceAsStream("/" + filename);
903 if (is != null) {
904 return XMLTools.parse(is, true);
905 }
906 }
907
908 // Try the file outside the classes directory
909 return XMLTools.parse(new File(filename), true);
910 }
911
912
913 static public StringBuffer readXMLStream(InputStream input_stream)
914 {
915 StringBuffer xml = new StringBuffer("");
916
917 try {
918 InputStreamReader isr = new InputStreamReader(input_stream, "UTF-8");
919 BufferedReader buffered_in = new BufferedReader(isr);
920
921 String line = "";
922 boolean xml_content = false;
923 while((line = buffered_in.readLine()) != null) {
924 if(xml_content) {
925 xml.append(line);
926 xml.append("\n");
927 }
928 else if(line.trim().startsWith("<?xml")) {
929 xml_content = true;
930 xml.append(line);
931 xml.append("\n");
932 }
933 }
934 buffered_in = null;
935 }
936 catch (Exception error) {
937 System.err.println("Failed when trying to parse XML stream");
938 error.printStackTrace();
939 }
940
941 return xml;
942 }
943
944
945 /** I think this works a bit better on Unicode strings. */
946 static public String stripNL(String raw_string)
947 {
948 String stripped_string = new String();
949 for (int i = 0; i < raw_string.length(); i++) {
950 char raw_character = raw_string.charAt(i);
951 if (raw_character != '\n' && raw_character != '\t') {
952 stripped_string = stripped_string + raw_character;
953 }
954 }
955 return stripped_string;
956 }
957}
Note: See TracBrowser for help on using the repository browser.