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: leinfelder $'
9
 *     '$Date: 2013-06-21 21:44:12 -0700 (Fri, 21 Jun 2013) $'
10
 * '$Revision: 7823 $'
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 File writeTempUploadFile (FilePart filePart, String fileName) throws IOException {
404
        File tempFile = 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 tempDir;
414

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

    
430
        tempDir = new File(tempDirPath);
431

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

    
442
		//tempFile = new File(tempDirPath, fileName);
443
		tempFile = File.createTempFile("upload", ".tmp", tempDir);
444
		fileSize = filePart.writeTo(tempFile);
445

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

    
450
        logMetacat.debug("Temporary file is: " + tempFile.getAbsolutePath());
451

    
452
        return tempFile;
453
    }
454

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

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

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

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

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

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

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

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