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

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

Moved some applet specific code out of Gatherer.java and into GathererApplet.java.

  • Property svn:keywords set to Author Date Id Revision
File size: 16.9 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
39// Don't even think about adding import java.awt.* here!
40// The functions in this class should not use any graphical classes. Put your function somewhere else buster!
41import java.io.*;
42import java.net.*;
43import java.util.*;
44// Don't even think about adding import javax.swing.* here!
45// The functions in this class should not use any graphical classes. Put your function somewhere else buster!
46import org.apache.xerces.parsers.*;
47import org.apache.xerces.dom.DocumentImpl;
48import org.apache.xml.serialize.*;
49import org.greenstone.gatherer.Configuration;
50import org.greenstone.gatherer.DebugStream;
51import org.greenstone.gatherer.Dictionary;
52import org.greenstone.gatherer.shell.GShell;
53// Don't even think about adding import org.greenstone.gatherer.Gatherer in here!
54// The functions in this class should be independent of the Gatherer class. Put your function somewhere else buster!
55import org.w3c.dom.*;
56import org.xml.sax.*;
57
58
59/** To provide a library of common methods, in a static context, for use in the Gatherer.
60 * @author John Thompson, Greenstone Digital Library, University of Waikato
61 * @version 2.3b
62 */
63public class Utility
64{
65 /** The size of the io buffer, in bytes. */
66 static final public int BUFFER_SIZE = 1024;
67 static final public String CFG_CLASSIFY = "classify";
68 static final public String CFG_CLASSIFY_BUTTONNAME = "-buttonname";
69 static final public String CFG_CLASSIFY_HFILE = "-hfile";
70 static final public String CFG_CLASSIFY_METADATA = "-metadata";
71 static final public String CFG_CLASSIFY_SORT = "-sort";
72 static final public String CFG_FORMAT = "format";
73 static final public String COLLECTION_TREE = "Collection";
74 /** Definition of an important directory name, in this case the file the collection configuration is expect to be in. */
75 static final public String CONFIG_FILE = "etc" + File.separator + "collect.cfg";
76 static final public String GLI_ARCHIVE = "GLI.jar";
77 static final public String GLI_EXTENSION = ".col";
78
79 /** Definition of an important directory name, in this case the images directory for the collection. */
80 static final public String IMAGES_DIR = "images" + File.separator;
81 /** Definition of an important directory name, in this case the import directory for the collection. */
82 static final public String IMPORT_DIR = "import" + File.separator;
83 /** Definition of an important directory name, in this case the backup import directory for the collection. */
84 static final public String IMPORT_BAK_DIR = "import.bak" + File.separator;
85 /** Definition of an important directory name, in this case the macros directory for the collection. */
86 static final public String MACROS_DIR = "macros" + File.separator;
87 /** Definition of an important directory name, in this case the location of the expected collection metadata sets.. */
88 static final public String META_DIR = "metadata" + File.separator; // Col. Copy
89 /** The default name of the perl executable under unix. */
90 static final public String PERL_EXECUTABLE_UNIX = "perl";
91 /** The default name of the perl executable under windows. */
92 static final public String PERL_EXECUTABLE_WINDOWS = "Perl.exe";
93 /** The name of the Gatherer. */
94 static final public String PROGRAM_NAME = "Greenstone Librarian Interface";
95 /** The current version of the Gatherer. */
96 static final public String PROGRAM_VERSION = "v2.60";
97 static final public String WORKSPACE_TREE = "Workspace";
98
99
100 /**
101 * Delete a file or directory
102 * It turns out that in Java you have to make sure a directory is empty before you delete it (much like unix I suppose),
103 * and so just like unix I'll have to set up a recursive delete function.
104 *
105 * @param file The <strong>File</strong> you want to delete.
106 * @return A <i>boolean</i> which is <i>true</i> if the file specified was successfully deleted, <i>false</i> otherwise.
107 */
108 static public boolean delete(File file)
109 {
110 // Nothing to do if it doesn't exist
111 if (!file.exists()) {
112 return true;
113 }
114
115 // If file is a directory, we have to recursively delete its contents first
116 if (file.isDirectory()) {
117 File files[] = file.listFiles();
118 for (int i = 0; i < files.length; i++) {
119 if (delete(files[i]) == false) {
120 System.err.println("Error: Could not delete folder " + file);
121 return false;
122 }
123 }
124 }
125
126 // Delete file
127 if (file.delete() == false) {
128 System.err.println("Error: Could not delete file " + file);
129 return false;
130 }
131
132 return true;
133 }
134
135
136 static public boolean delete(String filename) {
137 return delete(new File(filename));
138 }
139
140
141 /** Convert a long, detailing the length of a file in bytes, into a nice human readable string using b, kb, Mb and Gb. */
142 static final public String BYTE_SUFFIX = " b";
143 static final public long GIGABYTE = 1024000000l;
144 static final public String GIGABYTE_SUFFIX = " Gb";
145 static final public long KILOBYTE = 1024l;
146 static final public String KILOBYTE_SUFFIX = " kb";
147 static final public long MEGABYTE = 1024000l;
148 static final public String MEGABYTE_SUFFIX = " mb";
149 static final public String formatFileLength(long length) {
150 StringBuffer result = new StringBuffer("");
151 float number = 0f;
152 String suffix = null;
153 // Determine the floating point number and the suffix (radix) used.
154 if(length >= GIGABYTE) {
155 number = (float) length / (float) GIGABYTE;
156 suffix = GIGABYTE_SUFFIX;
157 }
158 else if(length >= MEGABYTE) {
159 number = (float) length / (float) MEGABYTE;
160 suffix = MEGABYTE_SUFFIX;
161 }
162 else if(length >= KILOBYTE) {
163 number = (float) length / (float) KILOBYTE;
164 suffix = KILOBYTE_SUFFIX;
165 }
166 else {
167 // Don't need to do anything fancy if the file is smaller than a kilobyte
168 return length + BYTE_SUFFIX;
169 }
170 // 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.
171 String number_str = Float.toString(number);
172 char number_char[] = number_str.toCharArray();
173 int pos = 0;
174 // Print the characters up to the '.'
175 while(number_char != null && pos < number_char.length && number_char[pos] != '.') {
176 result.append(number_char[pos]);
177 pos++;
178 }
179 if(pos < number_char.length) {
180 // Print the '.' and at most two characters after it
181 result.append(number_char[pos]);
182 pos++;
183 for(int i = 0; i < 2 && pos < number_char.length; i++, pos++) {
184 result.append(number_char[pos]);
185 }
186 // Search through the remaining string for 'E'
187 while(pos < number_char.length && number_char[pos] != 'E') {
188 pos++;
189 }
190 // If we still have string then we found an E. Copy the remaining string.
191 while(pos < number_char.length) {
192 result.append(number_char[pos]);
193 pos++;
194 }
195 }
196 // Add suffix
197 result.append(suffix);
198 // Done
199 return result.toString();
200 }
201
202 /** This method formats a given string, using HTML markup, so its width does not exceed the given width and its appearance if justified.
203 * @param text The <strong>String</strong> requiring formatting.
204 * @param width The maximum width per line as an <i>int</i>.
205 * @return A <strong>String</strong> formatted so as to have no line longer than the specified width.
206 * 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.
207 */
208 static public String formatHTMLWidth(String text, int width) {
209 if(text == null) {
210 return "Error";
211 }
212 HTMLStringTokenizer html = new HTMLStringTokenizer(text);
213 int current_width = 0;
214 int threshold = width / 2;
215 Stack lines = new Stack();
216 String line = "";
217 while(html.hasMoreTokens()) {
218 String token = html.nextToken();
219 while(token != null) {
220 if(html.isTag()) {
221 // Insert smart HTML tag code here.
222 token = null;
223 }
224 else {
225 // If the token is bigger than two thirds width, before we've even started break it down.
226 if(current_width + 1 + token.length() > width && token.length() > threshold) {
227 if(width == current_width) {
228 lines.push(line);
229 line = token;
230 current_width = token.length();
231 }
232 else {
233 String prefix = token.substring(0, width - 1 - current_width);
234 token = token.substring(prefix.length());
235 if(current_width == 0) {
236 line = line + prefix;
237 }
238 else {
239 line = line + " " + prefix;
240 }
241 lines.push(line);
242 line = "";
243 current_width = 0;
244 }
245 }
246 // If adding the next token would push us over the maximum line width.
247 else if(current_width + 1 + token.length() > width) {
248 lines.push(line);
249 line = token;
250 current_width = token.length();
251 token = null;
252 }
253 // Otherwise we should be able to just add the token, give or take.
254 else {
255 if(current_width == 0) {
256 line = line + token;
257 current_width = token.length();
258 }
259 else {
260 // Special case for standard punctuation which may exist after a tag like so:
261 // My name is <scratchy>Slim Shady</scratchy>. <-- Annoying punctuation.
262 if(token.equals(".") || token.equals(",") || token.equals("!") || token.equals("?")) {
263 line = line + token;
264 current_width = current_width + 1;
265 }
266 else {
267 line = line + " " + token;
268 current_width = current_width + 1 + token.length();
269 }
270 }
271 token = null;
272 }
273 }
274 }
275 }
276 String result = line;
277 while(!lines.empty()) {
278 result = (String)lines.pop() + "<BR>" + result;
279 }
280 // Replace ' ' with "&nbsp;"
281 boolean tag = false;
282 int pos = 0;
283 while(pos < result.length()) {
284 if(result.charAt(pos) == '<') {
285 tag = true;
286 }
287 else if(result.charAt(pos) == '>') {
288 tag = false;
289 }
290 else if(result.charAt(pos) == ' ' && !tag) {
291 String prefix = result.substring(0, pos);
292 String suffix = result.substring(pos + 1);
293 result = prefix + "&nbsp;" + suffix;
294 }
295 pos++;
296 }
297 result = "<HTML>" + result + "</HTML>";
298 return result;
299 }
300
301
302 static public String getDateString() {
303 Calendar current = Calendar.getInstance();
304 String day_name = null;
305 switch(current.get(Calendar.DAY_OF_WEEK)) {
306 case Calendar.MONDAY: day_name = "Dates.Mon"; break;
307 case Calendar.TUESDAY: day_name = "Dates.Tue"; break;
308 case Calendar.WEDNESDAY: day_name = "Dates.Wed"; break;
309 case Calendar.THURSDAY: day_name = "Dates.Thu"; break;
310 case Calendar.FRIDAY: day_name = "Dates.Fri"; break;
311 case Calendar.SATURDAY: day_name = "Dates.Sat"; break;
312 case Calendar.SUNDAY: day_name = "Dates.Sun"; break;
313 default: day_name = "";
314 }
315 String month_name = null;
316 switch(current.get(Calendar.MONTH)) {
317 case Calendar.JANUARY: month_name = "Dates.Jan"; break;
318 case Calendar.FEBRUARY: month_name = "Dates.Feb"; break;
319 case Calendar.MARCH: month_name = "Dates.Mar"; break;
320 case Calendar.APRIL: month_name = "Dates.Apr"; break;
321 case Calendar.MAY: month_name = "Dates.May"; break;
322 case Calendar.JUNE: month_name = "Dates.Jun"; break;
323 case Calendar.JULY: month_name = "Dates.Jul"; break;
324 case Calendar.AUGUST: month_name = "Dates.Aug"; break;
325 case Calendar.SEPTEMBER: month_name = "Dates.Sep"; break;
326 case Calendar.OCTOBER: month_name = "Dates.Oct"; break;
327 case Calendar.NOVEMBER: month_name = "Dates.Nov"; break;
328 case Calendar.DECEMBER: month_name = "Dates.Dec"; break;
329 default: month_name = "";
330 }
331 int day = current.get(Calendar.DAY_OF_MONTH);
332 int hour = current.get(Calendar.HOUR_OF_DAY);
333 int minute = current.get(Calendar.MINUTE);
334 int second = current.get(Calendar.SECOND);
335 int year = current.get(Calendar.YEAR);
336
337 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);
338 }
339
340
341 /** Determine this machines name.
342 * @return The name as a <strong>String</strong>.
343 */
344 static public String getMachineName() {
345 try {
346 return InetAddress.getLocalHost().getHostName();
347 }
348 catch(UnknownHostException ex) {
349 }
350 return "Unknown Machine";
351 }
352
353
354 static public String getSitesDir(String gsdl3_path) {
355 return gsdl3_path + "sites" + File.separator;
356
357 }
358
359
360 /** returns the path to the greenstone version of wget */
361 static public String getWGetPath(String gsdl_path)
362 {
363 if (isWindows()) {
364 return gsdl_path + "bin" + File.separator + "windows" + File.separator + "wget.exe";
365 }
366 else if (isMac()) {
367 return gsdl_path + "bin" + File.separator + "darwin" + File.separator + "wget";
368 }
369 else {
370 return gsdl_path + "bin" + File.separator + "linux" + File.separator + "wget";
371 }
372 }
373
374
375 /** Method to determine if the host system is MacOS based.
376 * @return a boolean which is true if the platform is MacOS, false otherwise
377 */
378 public static boolean isMac() {
379 Properties props = System.getProperties();
380 String os_name = props.getProperty("os.name","");
381 if(os_name.startsWith("Mac OS")) {
382 return true;
383 }
384 return false;
385 }
386
387
388 /** Method to determine if the host system is Microsoft Windows based.
389 * @return A <i>boolean</i> which is <i>true</i> if the platform is Windows, <i>false</i> otherwise.
390 */
391 public static boolean isWindows() {
392 Properties props = System.getProperties();
393 String os_name = props.getProperty("os.name","");
394 if(os_name.startsWith("Windows")) {
395 return true;
396 }
397 return false;
398 }
399
400 public static boolean isWindows9x() {
401 Properties props = System.getProperties();
402 String os_name = props.getProperty("os.name","");
403 if(os_name.startsWith("Windows") && os_name.indexOf("9") != -1) {
404 return true;
405 }
406 return false;
407 }
408 /** Takes a string and a desired length and pads out the string to the length by adding spaces to the left.
409 * @param str The target <strong>String</strong> that needs to be padded.
410 * @param length The desired length of the string as an <i>int</i>.
411 * @return A <strong>String</strong> made from appending space characters with the string until it has a length equal to length.
412 */
413 static private String pad(String str_raw, int length, char fill, boolean end) {
414 StringBuffer str = new StringBuffer(str_raw);
415 while(str.length() < length) {
416 if(end) {
417 str.insert(0, fill);
418 }
419 else {
420 str.append(fill);
421 }
422 }
423 return str.toString();
424 }
425
426
427 static public StringBuffer readXMLStream(InputStream input_stream)
428 {
429 StringBuffer xml = new StringBuffer("");
430
431 try {
432 InputStreamReader isr = new InputStreamReader(input_stream, "UTF-8");
433 BufferedReader buffered_in = new BufferedReader(isr);
434
435 String line = "";
436 boolean xml_content = false;
437 while((line = buffered_in.readLine()) != null) {
438 if(xml_content) {
439 xml.append(line);
440 xml.append("\n");
441 }
442 else if(line.trim().startsWith("<?xml")) {
443 xml_content = true;
444 xml.append(line);
445 xml.append("\n");
446 }
447 }
448 buffered_in = null;
449 }
450 catch (Exception error) {
451 System.err.println("Failed when trying to parse XML stream");
452 error.printStackTrace();
453 }
454
455 return xml;
456 }
457
458
459 /** I think this works a bit better on Unicode strings. */
460 static public String stripNL(String raw_string)
461 {
462 String stripped_string = new String();
463 for (int i = 0; i < raw_string.length(); i++) {
464 char raw_character = raw_string.charAt(i);
465 if (raw_character != '\n' && raw_character != '\t') {
466 stripped_string = stripped_string + raw_character;
467 }
468 }
469 return stripped_string;
470 }
471}
Note: See TracBrowser for help on using the repository browser.