source: other-projects/FileTransfer-WebSocketPair/testGXTWithGreenstone/src/org/greenstone/gatherer/util/Utility.java@ 33053

Last change on this file since 33053 was 33053, checked in by ak19, 5 years ago

I still had some stuff of Nathan Kelly's (FileTransfer-WebSocketPair) sitting on my USB. Had already commited the Themes folder at the time, 2 years back. Not sure if he wanted this additional folder commited. But I didn't want to delete it and decided it will be better off on SVN. When we use his project, if we find we didn't need this test folder, we can remove it from svn then.

File size: 21.2 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
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 */
37
38package org.greenstone.gatherer.util;
39
40
41// Don't even think about adding import java.awt.* here!
42// The functions in this class should not use any graphical classes. Put your function somewhere else buster!
43import java.io.Closeable;
44import java.io.*;
45import java.net.*;
46import java.util.*;
47// Don't even think about adding import javax.swing.* here!
48// The functions in this class should not use any graphical classes. Put your function somewhere else buster!
49import org.greenstone.gatherer.Dictionary;
50// Don't even think about adding import org.greenstone.gatherer.Gatherer in here!
51// The functions in this class should be independent of the Gatherer class. Put your function somewhere else buster!
52
53
54/** To provide a library of common methods, in a static context, for use in the Gatherer.
55 * @author John Thompson, Greenstone Digital Library, University of Waikato
56 * @version 2.3b
57 */
58public class Utility
59{
60 /** Definition of an important directory name, in this case the file the collection configuration is expect to be in. */
61 static final public String CONFIG_FILE = "etc" + File.separator + "collect.cfg";
62 static final public String CONFIG_GS3_FILE = "etc" + File.separator + "collectionConfig.xml";
63 static final public String COLLECT_CFG = "collect.cfg";
64 static final public String COLLECT_BAK = "collect.bak";
65 static final public String COLLECTION_CONFIG_XML = "collectionConfig.xml";
66 static final public String COLLECTION_CONFIG_BAK = "collectionConfig.bak";
67 static final public String GS3MODE_ARGUMENT = "-gs3mode";
68 static final public String BUILD_CFG = "build.cfg";
69 static final public String BUILD_CONFIG_XML = "buildConfig.xml";
70
71 /** The default name of the perl executable under unix. */
72 static final public String PERL_EXECUTABLE_UNIX = "perl";
73 /** The default name of the perl executable under windows. */
74 static final public String PERL_EXECUTABLE_WINDOWS = "Perl.exe";
75
76
77 /**
78 * Reads in a text file and returns the contents as a String
79 */
80 static public String readFile(File file) {
81 BufferedReader fin = null;
82 StringBuffer contents = new StringBuffer();
83
84 try {
85 fin = new BufferedReader(new FileReader(file));
86 String line = null;
87 while((line = fin.readLine()) != null) {
88 contents.append(line);
89 contents.append("\n");
90 }
91 } catch(IOException e) {
92 System.err.println("*** Could not read in file: " + file.toString());
93 System.err.println("*** Exception occurred: " + e.getMessage());
94 } finally {
95 closeResource(fin);
96 }
97
98 return contents.toString();
99 }
100
101 /**
102 * Delete a file or directory
103 * @param file The <strong>File</strong> you want to delete.
104 * @return A <i>boolean</i> which is <i>true</i> if the file specified was successfully deleted, <i>false</i> otherwise.
105 */
106 static public boolean delete(File file)
107 {
108 // Nothing to do if it doesn't exist
109 if (!file.exists()) {
110 return true;
111 }
112
113 return deleteInternal(file);
114 }
115
116
117 /** Convenience function. */
118 static public boolean delete(String filename)
119 {
120 return delete(new File(filename));
121 }
122
123
124 /** In Java you have to make sure a directory is empty before you delete it, so recursively delete. */
125 static private boolean deleteInternal(File file)
126 {
127 // If file is a directory, we have to recursively delete its contents first
128 if (file.isDirectory()) {
129 File files[] = file.listFiles();
130 for (int i = 0; i < files.length; i++) {
131 if (deleteInternal(files[i]) == false) {
132 System.err.println("Error: Could not delete folder " + file);
133 return false;
134 }
135 }
136 }
137
138 // Delete file
139 if (file.delete() == false) {
140 System.err.println("Error: Could not delete file " + file);
141 return false;
142 }
143
144 return true;
145 }
146
147
148 /** Convert a long, detailing the length of a file in bytes, into a nice human readable string using b, kb, Mb and Gb. */
149 static final public String BYTE_SUFFIX = " b";
150 static final public long GIGABYTE = 1024000000l;
151 static final public String GIGABYTE_SUFFIX = " Gb";
152 static final public long KILOBYTE = 1024l;
153 static final public String KILOBYTE_SUFFIX = " kb";
154 static final public long MEGABYTE = 1024000l;
155 static final public String MEGABYTE_SUFFIX = " Mb";
156 static final public String formatFileLength(long length) {
157 StringBuffer result = new StringBuffer("");
158 float number = 0f;
159 String suffix = null;
160 // Determine the floating point number and the suffix (radix) used.
161 if(length >= GIGABYTE) {
162 number = (float) length / (float) GIGABYTE;
163 suffix = GIGABYTE_SUFFIX;
164 }
165 else if(length >= MEGABYTE) {
166 number = (float) length / (float) MEGABYTE;
167 suffix = MEGABYTE_SUFFIX;
168 }
169 else if(length >= KILOBYTE) {
170 number = (float) length / (float) KILOBYTE;
171 suffix = KILOBYTE_SUFFIX;
172 }
173 else {
174 // Don't need to do anything fancy if the file is smaller than a kilobyte
175 return length + BYTE_SUFFIX;
176 }
177 // 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.
178 String number_str = Float.toString(number);
179 char number_char[] = number_str.toCharArray();
180 int pos = 0;
181 // Print the characters up to the '.'
182 while(number_char != null && pos < number_char.length && number_char[pos] != '.') {
183 result.append(number_char[pos]);
184 pos++;
185 }
186 if(pos < number_char.length) {
187 // Print the '.' and at most two characters after it
188 result.append(number_char[pos]);
189 pos++;
190 for(int i = 0; i < 2 && pos < number_char.length; i++, pos++) {
191 result.append(number_char[pos]);
192 }
193 // Search through the remaining string for 'E'
194 while(pos < number_char.length && number_char[pos] != 'E') {
195 pos++;
196 }
197 // If we still have string then we found an E. Copy the remaining string.
198 while(pos < number_char.length) {
199 result.append(number_char[pos]);
200 pos++;
201 }
202 }
203 // Add suffix
204 result.append(suffix);
205 // Done
206 return result.toString();
207 }
208
209 /** This method formats a given string, using HTML markup, so its width does not exceed the given width and its appearance if justified.
210 * @param text The <strong>String</strong> requiring formatting.
211 * @param width The maximum width per line as an <i>int</i>.
212 * @return A <strong>String</strong> formatted so as to have no line longer than the specified width.
213 * 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.
214 */
215 static public String formatHTMLWidth(String text, int width) {
216 if(text == null) {
217 return "Error";
218 }
219 HTMLStringTokenizer html = new HTMLStringTokenizer(text);
220 int current_width = 0;
221 int threshold = width / 2;
222 Stack lines = new Stack();
223 String line = "";
224 while(html.hasMoreTokens()) {
225 String token = html.nextToken();
226 while(token != null) {
227 if(html.isTag()) {
228 // Insert smart HTML tag code here.
229 token = null;
230 }
231 else {
232 // If the token is bigger than two thirds width, before we've even started break it down.
233 if(current_width + 1 + token.length() > width && token.length() > threshold) {
234 if(width == current_width) {
235 lines.push(line);
236 line = token;
237 current_width = token.length();
238 }
239 else {
240 String prefix = token.substring(0, width - 1 - current_width);
241 token = token.substring(prefix.length());
242 if(current_width == 0) {
243 line = line + prefix;
244 }
245 else {
246 line = line + " " + prefix;
247 }
248 lines.push(line);
249 line = "";
250 current_width = 0;
251 }
252 }
253 // If adding the next token would push us over the maximum line width.
254 else if(current_width + 1 + token.length() > width) {
255 lines.push(line);
256 line = token;
257 current_width = token.length();
258 token = null;
259 }
260 // Otherwise we should be able to just add the token, give or take.
261 else {
262 if(current_width == 0) {
263 line = line + token;
264 current_width = token.length();
265 }
266 else {
267 // Special case for standard punctuation which may exist after a tag like so:
268 // My name is <scratchy>Slim Shady</scratchy>. <-- Annoying punctuation.
269 if(token.equals(".") || token.equals(",") || token.equals("!") || token.equals("?")) {
270 line = line + token;
271 current_width = current_width + 1;
272 }
273 else {
274 line = line + " " + token;
275 current_width = current_width + 1 + token.length();
276 }
277 }
278 token = null;
279 }
280 }
281 }
282 }
283 String result = line;
284 while(!lines.empty()) {
285 result = (String)lines.pop() + "<BR>" + result;
286 }
287 // Replace ' ' with "&nbsp;"
288 boolean tag = false;
289 int pos = 0;
290 while(pos < result.length()) {
291 if(result.charAt(pos) == '<') {
292 tag = true;
293 }
294 else if(result.charAt(pos) == '>') {
295 tag = false;
296 }
297 else if(result.charAt(pos) == ' ' && !tag) {
298 String prefix = result.substring(0, pos);
299 String suffix = result.substring(pos + 1);
300 result = prefix + "&nbsp;" + suffix;
301 }
302 pos++;
303 }
304 result = "<HTML>" + result + "</HTML>";
305 return result;
306 }
307
308
309 static public String getDateString() {
310 Calendar current = Calendar.getInstance();
311 String day_name = null;
312 switch(current.get(Calendar.DAY_OF_WEEK)) {
313 case Calendar.MONDAY: day_name = "Dates.Mon"; break;
314 case Calendar.TUESDAY: day_name = "Dates.Tue"; break;
315 case Calendar.WEDNESDAY: day_name = "Dates.Wed"; break;
316 case Calendar.THURSDAY: day_name = "Dates.Thu"; break;
317 case Calendar.FRIDAY: day_name = "Dates.Fri"; break;
318 case Calendar.SATURDAY: day_name = "Dates.Sat"; break;
319 case Calendar.SUNDAY: day_name = "Dates.Sun"; break;
320 default: day_name = "";
321 }
322 String month_name = null;
323 switch(current.get(Calendar.MONTH)) {
324 case Calendar.JANUARY: month_name = "Dates.Jan"; break;
325 case Calendar.FEBRUARY: month_name = "Dates.Feb"; break;
326 case Calendar.MARCH: month_name = "Dates.Mar"; break;
327 case Calendar.APRIL: month_name = "Dates.Apr"; break;
328 case Calendar.MAY: month_name = "Dates.May"; break;
329 case Calendar.JUNE: month_name = "Dates.Jun"; break;
330 case Calendar.JULY: month_name = "Dates.Jul"; break;
331 case Calendar.AUGUST: month_name = "Dates.Aug"; break;
332 case Calendar.SEPTEMBER: month_name = "Dates.Sep"; break;
333 case Calendar.OCTOBER: month_name = "Dates.Oct"; break;
334 case Calendar.NOVEMBER: month_name = "Dates.Nov"; break;
335 case Calendar.DECEMBER: month_name = "Dates.Dec"; break;
336 default: month_name = "";
337 }
338 int day = current.get(Calendar.DAY_OF_MONTH);
339 int hour = current.get(Calendar.HOUR_OF_DAY);
340 int minute = current.get(Calendar.MINUTE);
341 int second = current.get(Calendar.SECOND);
342 int year = current.get(Calendar.YEAR);
343
344 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);
345 }
346
347
348 /** Determine this machines name.
349 * @return The name as a <strong>String</strong>.
350 */
351 static public String getMachineName() {
352 try {
353 return InetAddress.getLocalHost().getHostName();
354 }
355 catch(UnknownHostException ex) {
356 }
357 return "Unknown Machine";
358 }
359
360
361 static public String getSitesDir(String gsdl3_path) {
362 return gsdl3_path + "sites" + File.separator;
363
364 }
365
366 /** @return the OSdir foldername: windows, linux or darwin */
367 public static String getOSdirName() {
368 if(Utility.isWindows()) {
369 return "windows";
370 }
371 if(Utility.isMac()) {
372 return "darwin";
373 }
374 return "linux"; // else assume it's a linux machine, OSdirname = linux
375 }
376
377
378 /** Method to determine if the host system is MacOS based.
379 * @return a boolean which is true if the platform is MacOS, false otherwise
380 */
381 public static boolean isMac() {
382 Properties props = System.getProperties();
383 String os_name = props.getProperty("os.name","");
384 if(os_name.startsWith("Mac OS")) {
385 return true;
386 }
387 return false;
388 }
389
390
391 /** Method to determine if the host system is Microsoft Windows based.
392 * @return A <i>boolean</i> which is <i>true</i> if the platform is Windows, <i>false</i> otherwise.
393 */
394 public static boolean isWindows() {
395 Properties props = System.getProperties();
396 String os_name = props.getProperty("os.name","");
397 if(os_name.startsWith("Windows")) {
398 return true;
399 }
400 return false;
401 }
402
403 public static boolean isWindows9x() {
404 Properties props = System.getProperties();
405 String os_name = props.getProperty("os.name","");
406 if(os_name.startsWith("Windows") && os_name.indexOf("9") != -1) {
407 return true;
408 }
409 return false;
410 }
411 /** Takes a string and a desired length and pads out the string to the length by adding spaces to the left.
412 * @param str The target <strong>String</strong> that needs to be padded.
413 * @param length The desired length of the string as an <i>int</i>.
414 * @return A <strong>String</strong> made from appending space characters with the string until it has a length equal to length.
415 */
416 static private String pad(String str_raw, int length, char fill, boolean end) {
417 StringBuffer str = new StringBuffer(str_raw);
418 while(str.length() < length) {
419 if(end) {
420 str.insert(0, fill);
421 }
422 else {
423 str.append(fill);
424 }
425 }
426 return str.toString();
427 }
428
429
430 /** Builds the cache dir by appending the user path and 'cache'.
431 * @return a File representing the path to the private file cache within the current collection.
432 */
433 public static File getCacheDir() {
434 return new File(getGLIUserFolder(), StaticStrings.CACHE_FOLDER);
435 }
436
437 /** Method which constructs the log directory given a certain collection.
438 * @param col_dir The location of the collection directory as a <strong>String</strong>.
439 * @return The location of the given collections log directory, also as a <strong>String</strong>.
440 */
441 public static String getLogDir(String col_dir) {
442 if(col_dir != null) {
443 return col_dir + LOG_DIR;
444 }
445 else {
446 return getGLIUserFolder().getAbsolutePath() + File.separator + LOG_DIR;
447 }
448 }
449
450 static final private String APPLICATION_DATA_FOLDER = "Application Data";
451 static final private String UNIX_GLI_CONFIG_FOLDER = ".gli";
452 static final private String USER_HOME_PROPERTY = "user.home";
453 static final private String WIN_GLI_CONFIG_FOLDER = "Greenstone" + File.separator + "GLI";
454 /** Definition of an important directory name, in this case the log directory for the collection. */
455 static final public String LOG_DIR = "log" + File.separator;
456
457 static public File getGLIUserFolder()
458 {
459 if (Utility.isWindows()) {
460 return new File(System.getProperty(USER_HOME_PROPERTY) + File.separator + APPLICATION_DATA_FOLDER + File.separator + WIN_GLI_CONFIG_FOLDER + File.separator);
461 }
462 else {
463 return new File(System.getProperty(USER_HOME_PROPERTY) + File.separator + UNIX_GLI_CONFIG_FOLDER + File.separator);
464 }
465 }
466
467 static private HashMap plugin_map = null;
468
469 static private void setUpPluginNameMap() {
470 plugin_map = new HashMap();
471 plugin_map.put("GAPlug", "GreenstoneXMLPlugin");
472 plugin_map.put("RecPlug", "DirectoryPlugin");
473 plugin_map.put("ArcPlug","ArchivesInfPlugin");
474 plugin_map.put("TEXTPlug","TextPlugin");
475 plugin_map.put("XMLPlug","ReadXMLFile");
476 plugin_map.put("EMAILPlug","EmailPlugin");
477 plugin_map.put("SRCPlug","SourceCodePlugin");
478 plugin_map.put("NULPlug","NulPlugin");
479 plugin_map.put("W3ImgPlug","HTMLImagePlugin");
480 plugin_map.put("PagedImgPlug","PagedImagePlugin");
481 plugin_map.put("METSPlug", "GreenstoneMETSPlugin");
482 plugin_map.put("DBPlug", "DatabasePlugin");
483 plugin_map.put("PPTPlug", "PowerPointPlugin");
484 plugin_map.put("PSPlug", "PostScriptPlugin");
485 }
486
487 static public String ensureNewPluginName(String plugin) {
488 if (plugin.endsWith("Plugin")) return plugin;
489 if (plugin_map == null) {
490 setUpPluginNameMap();
491 }
492 String new_name = (String)plugin_map.get(plugin);
493 if (new_name != null) return new_name;
494 new_name = plugin.replaceAll("Plug", "Plugin");
495 return new_name;
496 }
497
498
499 /** Write out a property line--a (property, value) pair--to the gsdl(3)site.cfg file.
500 * If the file already contains the line as-is, it is not re-written.
501 * If the file doesn't contain the line, it is appended.
502 * If the file contained a different value for the property, the line is corrected
503 * and the file is written out.
504 * If the propertyValue parameter is null, the property line is removed from the file.
505 * Not using the Properties class, as we want to keep the file's contents in the
506 * same order and preserve all the comments in as they're meant to help the user.
507 * Return the old value for the property, if it existed, else "".
508 */
509 public static String updatePropertyConfigFile(
510 String filename, String propertyName, String propertyValue)
511 {
512 File propFile = new File(filename);
513 String oldValue = "";
514 if(!propFile.exists()) {
515 System.err.println("*** Unable to update property " + propertyName + " in file "
516 + filename + " to\n" + propertyValue + ". File does not (yet) exist.\n");
517 return oldValue;
518 }
519 BufferedReader fin = null;
520 BufferedWriter fout = null;
521 StringBuffer contents = new StringBuffer();
522 String insertLine = null;
523 if(propertyValue != null) {
524 insertLine = propertyName+"\t"+propertyValue+"\n"; // new line after every propertyLine
525 }
526 boolean found = false;
527 try {
528 fin = new BufferedReader(new FileReader(filename));
529 String line = "";
530 while((line = fin.readLine()) != null) {
531 line = line.trim(); // remove any preceding (surrounding) whitespace
532 if(line.startsWith(propertyName)) { // won't match comment
533 found = true;
534 // store the previous value for the property
535 oldValue = line;
536 oldValue = oldValue.substring(propertyName.length());
537 oldValue = oldValue.trim();
538
539 if(propertyValue != null) { // line should be removed if propertyValue == null
540 if(line.equals(insertLine)) { // file is already correct, nothing to do
541 fin.close();
542 fin = null;
543 break;
544 } else {
545 contents.append(insertLine);
546 }
547 }
548 } else { // any other line
549 contents.append(line);
550 contents.append("\n"); // ensures the required new line at end of file
551 }
552 }
553
554 if(fin != null) { // need to write something out to the file
555 fin.close();
556 fin = null;
557
558 // if collecthome/property wasn't already specified in the file, append it
559 // but only if we have a value to write out to the file
560 if(!found && propertyValue != null) {
561 fout = new BufferedWriter(new FileWriter(filename, true)); // append mode
562 fout.write(insertLine, 0, insertLine.length());
563 } else {
564 fout = new BufferedWriter(new FileWriter(filename)); // hopefully this will overwrite
565 fout.write(contents.toString(), 0, contents.length());
566 }
567
568 fout.close();
569 fout = null;
570
571 } // else the file is fine
572 } catch(IOException e) {
573 System.err.println("*** Could not update file: " + filename);
574 System.err.println("with the " + propertyName + " property set to " + propertyValue);
575 System.err.println("Exception occurred: " + e.getMessage());
576 } finally {
577 closeResource(fin);
578 closeResource(fout);
579
580 }
581 return oldValue;
582 }
583
584 // For safely closing streams/handles/resources.
585 // For examples of use look in the Input- and OutputStreamGobbler classes.
586 // http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
587 // http://stackoverflow.com/questions/481446/throws-exception-in-finally-blocks
588 public static void closeResource(Closeable resourceHandle) {
589 try {
590 if(resourceHandle != null) {
591 resourceHandle.close();
592 resourceHandle = null;
593 }
594 } catch(Exception e) {
595 System.err.println("Exception closing resource: " + e.getMessage());
596 e.printStackTrace();
597 resourceHandle = null;
598 }
599 }
600
601 public static void closeProcess(Process prcs) {
602 if( prcs != null ) {
603 closeResource(prcs.getErrorStream());
604 closeResource(prcs.getOutputStream());
605 closeResource(prcs.getInputStream());
606 prcs.destroy();
607 }
608 }
609}
Note: See TracBrowser for help on using the repository browser.