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

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

Made major rearrangements to the way path variables are calculated. This is to facilitate being able to specify a "-collectdir" argument to the GLI so one GLI installation can be used in a networked, multi-user situation. Hope I haven't broken anything!

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