Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements utility methods for a metadata catalog
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones, Jivka Bojilova
7
 *
8
 *   '$Author: berkley $'
9
 *     '$Date: 2010-09-14 13:28:12 -0700 (Tue, 14 Sep 2010) $'
10
 * '$Revision: 5545 $'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26

    
27
package edu.ucsb.nceas.metacat.util;
28

    
29
import java.io.File;
30
import java.io.FileInputStream;
31
import java.io.FileOutputStream;
32
import java.io.IOException;
33
import java.io.PrintWriter;
34
import java.net.MalformedURLException;
35
import java.util.Hashtable;
36
import java.util.Vector;
37

    
38
import org.apache.log4j.Logger;
39

    
40
import com.oreilly.servlet.multipart.FilePart;
41

    
42
import edu.ucsb.nceas.dbadapter.AbstractDatabase;
43
import edu.ucsb.nceas.metacat.properties.PropertyService;
44
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
45
import edu.ucsb.nceas.utilities.FileUtil;
46

    
47
/**
48
 * A suite of utility classes for the metadata catalog server
49
 */
50
public class MetacatUtil
51
{
52

    
53
    public static final String XMLFORMAT = "xml";	
54
    public static AbstractDatabase dbAdapter;
55
    
56
    private static boolean debugErrorDisplayed = false;
57
    
58
    private static Logger logMetacat = Logger.getLogger(MetacatUtil.class);
59

    
60
    /**
61
     * Utility method to parse the query part of a URL into parameters. This
62
     * method assumes the format of the query part of the url is an ampersand
63
     * separated list of name/value pairs, with equal signs separating the name
64
     * from the value (e.g., name=tom&zip=99801 ). Returns a has of the name
65
     * value pairs, hashed on name.
66
     */
67
    public static Hashtable<String,String> parseQuery(String query)
68
            throws MalformedURLException
69
    {
70
        String[][] params = new String[200][2];
71
        Hashtable<String,String> parameters = new Hashtable<String,String>();
72

    
73
        String temp = "";
74
        boolean ampflag = true;
75
        boolean poundflag = false;
76
        int arrcount = 0;
77

    
78
        if (query != null) {
79
            for (int i = 0; i < query.length(); i++) {
80

    
81
                // go throught the remainder of the query one character at a
82
                // time.
83
                if (query.charAt(i) == '=') {
84
                    // if the current char is a # then the preceding should be
85
                    // a name
86
                    if (!poundflag && ampflag) {
87
                        params[arrcount][0] = temp.trim();
88
                        temp = "";
89
                    } else {
90
                        //if there are two #s or &s in a row throw an
91
                        // exception.
92
                        throw new MalformedURLException(
93
                                "metacatURL: Two parameter names "
94
                                        + "not allowed in sequence");
95
                    }
96
                    poundflag = true;
97
                    ampflag = false;
98
                } else if (query.charAt(i) == '&' || i == query.length() - 1) {
99
                    //the text preceding the & should be the param value.
100
                    if (i == query.length() - 1) {
101
                        //if at the end of the string grab the last value and
102
                        // append it.
103
                        if (query.charAt(i) != '=') {
104
                            //ignore an extra & on the end of the string
105
                            temp += query.charAt(i);
106
                        }
107
                    }
108

    
109
                    if (!ampflag && poundflag) {
110
                        params[arrcount][1] = temp.trim();
111
                        parameters
112
                                .put(params[arrcount][0], params[arrcount][1]);
113
                        temp = "";
114
                        arrcount++; //increment the array to the next row.
115
                    } else {
116
                        //if there are two =s or &s in a row through an
117
                        // exception
118
                        throw new MalformedURLException(
119
                                "metacatURL: Two parameter values "
120
                                        + "not allowed in sequence");
121
                    }
122
                    poundflag = false;
123
                    ampflag = true;
124
                } else {
125
                    //get the next character in the string
126
                    temp += query.charAt(i);
127
                }
128
            }
129
        }
130
        return parameters;
131
    }
132
  
133
    public static Vector<String> getOptionList(String optiontext)
134
    {
135
        Vector<String> optionsVector = new Vector<String>();
136
        if (optiontext.indexOf(",") == -1) {
137
            optionsVector.addElement(optiontext);
138
            return optionsVector;
139
        }
140

    
141
        while (optiontext.indexOf(",") != -1) {
142
            String s = optiontext.substring(0, optiontext.indexOf(","));
143
            optionsVector.addElement(s.trim());
144
            optiontext = optiontext.substring(optiontext.indexOf(",") + 1,
145
                    optiontext.length());
146
            if (optiontext.indexOf(",") == -1) { //catch the last list entry
147
                optionsVector.addElement(optiontext.trim());
148
            }
149
        }
150
        return optionsVector;
151
    }
152

    
153
    /** Normalizes a string read from DB. So it will be compatible to HTML */
154
    public static String normalize(String s)
155
    {
156
        StringBuffer str = new StringBuffer();
157

    
158
             int len = (s != null) ? s.length() : 0;
159
             for (int i = 0; i < len; i++) {
160
                 char ch = s.charAt(i);
161
                 switch (ch) {
162
                     case '<': {
163
                         str.append("&lt;");
164
                         break;
165
                     }
166
                     case '>': {
167
                         str.append("&gt;");
168
                         break;
169
                     }
170
                     case '&': {
171
                         /*
172
                          * patch provided by Johnoel Ancheta from U of Hawaii
173
                          */
174
                         // check if & is for a character reference &#xnnnn;
175
                         if (i + 1 < len - 1 && s.charAt(i + 1) == '#') {
176
                             str.append("&#");
177
                             i += 2;
178

    
179
                             ch = s.charAt(i);
180
                             while (i < len && ch != ';') {
181
                                 str.append(ch);
182
                                 i++;
183
                                 ch = s.charAt(i);
184
                             }
185
                             str.append(';');
186
                         } else 
187
                         // check if & is in front of amp; 
188
                         // (we dont yet check for other HTML 4.0 Character entities) 
189
                         if (i + 4 < len  && s.charAt(i + 1) == 'a' 
190
                        	 && s.charAt(i + 2) == 'm' 
191
                        		 && s.charAt(i + 3) == 'p' 
192
                        			 && s.charAt(i + 4) == ';'){
193
                             str.append("&amp;");
194
                             i += 4;                        	 
195
                         }
196
                         else  if (i + 3 < len && s.charAt(i + 1) == 'l' 
197
                        	 && s.charAt(i + 2) == 't' 
198
                        		 && s.charAt(i + 3) == ';' ){
199
                    	  // check if & is in front of it; 
200
                             str.append("&lt;");
201
                             i += 3;                        	 
202
                         } 
203
                         else  if (i + 3 < len && s.charAt(i + 1) == 'g' 
204
                        	 && s.charAt(i + 2) == 't' 
205
                        		 && s.charAt(i + 3) == ';' ){
206
                    	  // check if & is in front of gt; 
207
                           // (we dont yet check for other HTML 4.0 Character entities) 
208
                             str.append("&gt;");
209
                             i += 3;                        	 
210
                         } 
211
                         else  if (i + 5 < len && s.charAt(i + 1) == 'q' 
212
                        	 && s.charAt(i + 2) == 'u' 
213
                        		 && s.charAt(i + 3) == 'o' 
214
                        	 && s.charAt(i + 4) == 't'
215
                        	 && s.charAt(i + 5) == ';')
216
                             {
217
                    	   // check if & is in front of quot; 
218
                           // (we dont yet check for other HTML 4.0 Character entities) 
219
                             str.append("&quot;");
220
                             i += 5;                        	 
221
                         } 
222
                         else  if (i + 5 < len && s.charAt(i + 1) == 'a' 
223
                        	 && s.charAt(i + 2) == 'p' 
224
                        		 && s.charAt(i + 3) == 'o' 
225
                        	 && s.charAt(i + 4) == 's'
226
                        	 && s.charAt(i + 5) == ';')
227
                             {
228
                    	   // check if & is in front of apostrophe; 
229
                           // (we dont yet check for other HTML 4.0 Character entities) 
230
                             str.append("&apos;");
231
                             i += 5;                        	 
232
                         } 
233
                         else{
234
                             str.append("&amp;");
235
                         }
236
                         /////////
237
                         break;
238
                     }
239
                     case '"':
240
                    	 str.append("&quot;");
241
                         break;
242
                     case '\'':
243
                    	 str.append("&apos;");
244
                         break;
245
                    default: {
246
                         if ( (ch<128) && (ch>31) ) {
247
                             str.append(ch);
248
                         }
249
                         else if (ch<32) {
250
                             if (ch == 10) { // new line
251
                                 str.append(ch);
252
                             }
253
                             if (ch == 13) { // carriage return
254
                                 str.append(ch);
255
                             }
256
                             if (ch == 9) {  // tab
257
                                 str.append(ch);
258
                             }
259
                             // otherwise skip
260
                         }
261
                         else {
262
                        	 //Don't transfer special character to numeric entity
263
                             /*str.append("&#");
264
                             str.append(Integer.toString(ch));
265
                             str.append(';');*/
266
                             str.append(ch);
267
                         }
268
                     }
269
                 }
270
             }
271
             return str.toString();
272
    }
273

    
274
    /**
275
     * Method to get the name of local replication server
276
     */
277
    public static String getLocalReplicationServerName()
278
    {
279
        String replicationServerName = null;
280
        // String serverHost = null;
281
        // serverHost = getProperty("server");
282
        // append "context/servlet/replication" to the host name
283
        try {
284
        replicationServerName = 
285
        	SystemUtil.getSecureServer() 
286
        	+ "/" 
287
			+ PropertyService.getProperty("application.context")
288
			+ "/servlet/replication";
289
        } catch (PropertyNotFoundException pnfe) {
290
        	logMetacat.error("Could not get local replication server name " 
291
        			+ "because property could not be found: " + pnfe.getMessage());
292
        }
293
        return replicationServerName;
294

    
295
    }
296

    
297
    /** A method to replace whitespace in url */
298
    public static String replaceWhiteSpaceForURL(String urlHasWhiteSpace)
299
    {
300
        StringBuffer newUrl = new StringBuffer();
301
        String whiteSpaceReplace = "%20";
302
        if (urlHasWhiteSpace == null || urlHasWhiteSpace.trim().equals("")) { return null; }
303

    
304
        for (int i = 0; i < urlHasWhiteSpace.length(); i++) {
305
            char ch = urlHasWhiteSpace.charAt(i);
306
            if (!Character.isWhitespace(ch)) {
307
                newUrl.append(ch);
308
            } else {
309
                //it is white sapce, replace it by %20
310
                newUrl = newUrl.append(whiteSpaceReplace);
311
            }
312

    
313
        }//for
314
        logMetacat.info("The new string without space is:"
315
                + newUrl.toString());
316
        return newUrl.toString();
317

    
318
    }// replaceWhiteSpaceForUR
319

    
320
    /**
321
	 * Writes debug information into a file. In metacat.properties, if property
322
	 * application.writeDebugToFile is set to true, the debug information will be written to
323
	 * debug file, which value is the property application.debugOutputFile in
324
	 * metacat.properties.
325
	 * 
326
	 */
327
	public static void writeDebugToFile(String debugInfo) {
328
		String debug = "false";
329
		try {
330
			debug = PropertyService.getProperty("application.writeDebugToFile");
331
			if (debug != null && debug.equalsIgnoreCase("true")) {
332
				File outputFile = 
333
					new File(PropertyService.getProperty("application.debugOutputFile"));
334
				FileOutputStream fos = new FileOutputStream(outputFile, true);
335
				PrintWriter pw = new PrintWriter(fos);
336
				pw.println(debugInfo);
337
				pw.flush();
338
				pw.close();
339
				fos.close();
340
			}
341
		} catch (PropertyNotFoundException pnfe) {
342
			// only log debug to file warning once
343
			if (!debugErrorDisplayed) {
344
				logMetacat.warn("Could not get debug property.  Write debug to " 
345
						+ "file is set to false: " + pnfe.getMessage());
346
				debugErrorDisplayed = true;
347
			}
348
		} catch (Exception io) {
349
			logMetacat.warn("Error in MetacatUtil.writeDebugToFile "
350
					+ io.getMessage());
351
		}
352
	}
353
    
354
   /**
355
	 * Writes debug information into a file in delimitered format
356
	 * 
357
	 * @param debugInfo
358
	 *            the debug information
359
	 * @param newLine
360
	 *            append the debug info to a line or not
361
	 */
362
	public static void writeDebugToDelimiteredFile(String debugInfo, boolean newLine) {
363
		String debug = "false";
364
		try {
365
			debug = PropertyService.getProperty("application.writeDebugToFile");
366
			if (debug != null && debug.equalsIgnoreCase("true")) {
367
				File outputFile = new File(PropertyService
368
						.getProperty("application.delimiteredOutputFile"));
369
				FileOutputStream fos = new FileOutputStream(outputFile, true);
370
				PrintWriter pw = new PrintWriter(fos);
371
				if (newLine) {
372
					pw.println(debugInfo);
373
				} else {
374
					pw.print(debugInfo);
375
				}
376
				pw.flush();
377
				pw.close();
378
				fos.close();
379
			}
380
		} catch (PropertyNotFoundException pnfe) {
381
			// only log debug to file warning once
382
			if (!debugErrorDisplayed) {
383
				logMetacat.warn("Could not get delimited debug property. Write debug to " 
384
						+ "file is set to false: " + pnfe.getMessage());
385
				debugErrorDisplayed = true;
386
			}
387
		} catch (Exception io) {
388
			logMetacat.warn("Eorr in writeDebugToDelimiteredFile "
389
					+ io.getMessage());
390
		}
391
	}
392

    
393
	/**
394
	 * Write the uploaded file to disk for temporary storage before moving it to
395
	 * its final Metacat location.
396
	 * 
397
	 * @param filePart
398
	 *            the FilePart object containing the file form element
399
	 * @param fileName
400
	 *            the name of the file to be written to disk
401
	 * @return tempFilePath a String containing location of temporary file
402
	 */
403
    public static String writeTempUploadFile (FilePart filePart, String fileName) throws IOException {
404
        String tempFilePath = null;
405
        String tempDirPath = null;
406
        try {
407
        	tempDirPath = PropertyService.getProperty("application.tempDir") + FileUtil.getFS() + "uploads";
408
        } catch (PropertyNotFoundException pnfe) {
409
        	logMetacat.warn("Temp property not found.  An attempt will be made " 
410
        			+ "to use system temp directory: " + pnfe.getMessage());
411
        }
412
        long fileSize;
413
        File tempFile;
414
        File tempDir;
415

    
416
        if ((fileName == null) || fileName.equals("")) {
417
            return tempFilePath;
418
        }
419
				
420
        // the tempfilepath token isn't set, use Java default
421
		if (tempDirPath == null) {
422
			String javaTempDir = System.getProperty("java.io.tempdir");
423
			if (javaTempDir == null) {
424
				// no paths set, use unix default
425
				tempDirPath = "/tmp";
426
			} else {
427
				tempDirPath = javaTempDir;
428
			}
429
		}
430

    
431
        tempDir = new File(tempDirPath);
432

    
433
		// Create the temporary directory if it doesn't exist
434
		try {
435
			if (!tempDir.exists()) {
436
				tempDir.mkdirs();
437
			}
438
		} catch (SecurityException e) {
439
			throw new IOException("Can't create directory: " + tempDir.getPath() + ". Error: "
440
					+ e.getMessage());
441
		}
442

    
443
		tempFile = new File(tempDirPath, fileName);
444
		fileSize = filePart.writeTo(tempFile);
445
		tempFilePath = tempDirPath + File.separator + fileName;
446

    
447
		if (fileSize == 0) {
448
			logMetacat.warn("Uploaded file '" + fileName + "'is empty!");
449
		}
450

    
451
        logMetacat.debug("Temporary file is: " + tempFilePath);
452

    
453
        return tempFilePath;
454
    }
455

    
456
    /**
457
	 * 
458
	 * Copy a file between two locations specified as strings. Fails if either
459
	 * path cannot be created. Based on the public domain FileCopy class in
460
	 * _Java in a Nutshell_.
461
	 * 
462
	 * @param sourceName
463
	 *            the source file to read from disk
464
	 * @param destName
465
	 *            the destination file on disk
466
	 */
467
    public static void copyFile(String sourceName, String destName) throws IOException {
468

    
469
        File sourceFile = new File(sourceName);
470
        File destFile = new File(destName);
471
        FileInputStream source = null;
472
        FileOutputStream dest = null;
473
        byte[] buffer;
474
        int bytesRead;
475

    
476
        try {
477
            if (!sourceFile.exists() || !sourceFile.isFile()) {
478
                logMetacat.error("File copy: no such source" +
479
                                 " file: " + sourceName);
480
            }
481
            if (!sourceFile.canRead()) {
482
                logMetacat.error("File copy: source file " +
483
                                 "is unreadable: " + sourceName);
484
            }
485

    
486
            if (destFile.exists()) {
487
                if (destFile.isFile()) {
488
                    if (!destFile.canWrite()) {
489
                        logMetacat.error("File copy: destination " +
490
                                         "file is unwriteable: " + destFile);
491
                    }
492
                } else {
493
                    logMetacat.error("File copy: destination file " +
494
                                     "is not a file: " + destFile);
495
                }
496
            } else {
497
                File parentDir = parent(destFile);
498

    
499
                if (!parentDir.exists())
500
                {
501
                    logMetacat.error("File copy: destination diretory " +
502
                                     " doesn't exist: " + destName);
503
                }
504
                if (!parentDir.canWrite()) {
505
                    logMetacat.error("File copy: destination directory " +
506
                                     " is unwritable: " + destName);
507
                }
508
            }
509

    
510
            // Verbose error checking done, copy the file object
511
            source = new FileInputStream(sourceFile);
512
            dest = new FileOutputStream(destFile);
513
            buffer = new byte[1024];
514

    
515
            while (true) {
516
                bytesRead = source.read(buffer);
517
                if (bytesRead == -1) {
518
                    break;
519
                }
520
                dest.write(buffer, 0, bytesRead);
521
            }
522
        }
523
        finally {
524
            if (source != null) {
525
                try { source.close(); } catch (IOException e) { ; }
526
            }
527
            if (dest != null) {
528
                try { dest.close(); } catch (IOException e) { ; }
529
            }
530
        }
531
    }
532

    
533
    private static File parent(File f) {
534
        String dirname = f.getParent();
535
        if (dirname == null) {
536
            if (f.isAbsolute()) return new File(File.separator);
537
            else return new File(System.getProperty("user.dir"));
538
        }
539
        return new File(dirname);
540
    }
541
}
(9-9/15)