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: daigle $'
9
 *     '$Date: 2008-08-29 10:20:19 -0700 (Fri, 29 Aug 2008) $'
10
 * '$Revision: 4335 $'
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.Stack;
37
import java.util.Vector;
38

    
39
import org.apache.log4j.Logger;
40

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

    
43
import edu.ucsb.nceas.dbadapter.AbstractDatabase;
44
import edu.ucsb.nceas.metacat.DBSAXHandler;
45
import edu.ucsb.nceas.metacat.MetaCatServlet;
46
import edu.ucsb.nceas.metacat.service.PropertyService;
47
import edu.ucsb.nceas.metacat.service.SkinPropertyService;
48
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
49
import edu.ucsb.nceas.utilities.FileUtil;
50

    
51
/**
52
 * A suite of utility classes for the metadata catalog server
53
 */
54
public class MetaCatUtil
55
{
56

    
57
    public static AbstractDatabase dbAdapter;
58

    
59
    public static Vector pathsForIndexing;
60
    
61
    private static boolean debug = true;
62
    
63
    private static boolean debugErrorDisplayed = false;
64
    
65
    private static Logger logMetacat = Logger.getLogger(MetaCatUtil.class);
66
    private static char separator = '.';
67

    
68
    static {
69
        try {
70
        	separator = PropertyService.getProperty("document.accNumSeparator").charAt(0);
71
        } catch (PropertyNotFoundException pnfe) {
72
        	logMetacat.error("Could not retrieve account number separator. " 
73
        			+ "Separator set to '.' : " + pnfe.getMessage());
74
        }
75
    }
76

    
77
    /**
78
     * Utility method to parse the query part of a URL into parameters. This
79
     * method assumes the format of the query par tof the url is an ampersand
80
     * separated list of name/value pairs, with equal signs separating the name
81
     * from the value (e.g., name=tom&zip=99801 ). Returns a has of the name
82
     * value pairs, hashed on name.
83
     */
84
    public static Hashtable parseQuery(String query)
85
            throws MalformedURLException
86
    {
87
        String[][] params = new String[200][2];
88
        Hashtable parameters = new Hashtable();
89

    
90
        String temp = "";
91
        boolean ampflag = true;
92
        boolean poundflag = false;
93
        int arrcount = 0;
94

    
95
        if (query != null) {
96
            for (int i = 0; i < query.length(); i++) {
97

    
98
                // go throught the remainder of the query one character at a
99
                // time.
100
                if (query.charAt(i) == '=') {
101
                    // if the current char is a # then the preceding should be
102
                    // a name
103
                    if (!poundflag && ampflag) {
104
                        params[arrcount][0] = temp.trim();
105
                        temp = "";
106
                    } else {
107
                        //if there are two #s or &s in a row throw an
108
                        // exception.
109
                        throw new MalformedURLException(
110
                                "metacatURL: Two parameter names "
111
                                        + "not allowed in sequence");
112
                    }
113
                    poundflag = true;
114
                    ampflag = false;
115
                } else if (query.charAt(i) == '&' || i == query.length() - 1) {
116
                    //the text preceding the & should be the param value.
117
                    if (i == query.length() - 1) {
118
                        //if at the end of the string grab the last value and
119
                        // append it.
120
                        if (query.charAt(i) != '=') {
121
                            //ignore an extra & on the end of the string
122
                            temp += query.charAt(i);
123
                        }
124
                    }
125

    
126
                    if (!ampflag && poundflag) {
127
                        params[arrcount][1] = temp.trim();
128
                        parameters
129
                                .put(params[arrcount][0], params[arrcount][1]);
130
                        temp = "";
131
                        arrcount++; //increment the array to the next row.
132
                    } else {
133
                        //if there are two =s or &s in a row through an
134
                        // exception
135
                        throw new MalformedURLException(
136
                                "metacatURL: Two parameter values "
137
                                        + "not allowed in sequence");
138
                    }
139
                    poundflag = false;
140
                    ampflag = true;
141
                } else {
142
                    //get the next character in the string
143
                    temp += query.charAt(i);
144
                }
145
            }
146
        }
147
        return parameters;
148
    }
149
  
150
    public static Vector<String> getOptionList(String optiontext)
151
    {
152
        Vector<String> optionsVector = new Vector<String>();
153
        if (optiontext.indexOf(",") == -1) {
154
            optionsVector.addElement(optiontext);
155
            return optionsVector;
156
        }
157

    
158
        while (optiontext.indexOf(",") != -1) {
159
            String s = optiontext.substring(0, optiontext.indexOf(","));
160
            optionsVector.addElement(s.trim());
161
            optiontext = optiontext.substring(optiontext.indexOf(",") + 1,
162
                    optiontext.length());
163
            if (optiontext.indexOf(",") == -1) { //catch the last list entry
164
                optionsVector.addElement(optiontext.trim());
165
            }
166
        }
167
        return optionsVector;
168
    }
169

    
170
    /** Normalizes a string read from DB. So it will be compatible to HTML */
171
    public static String normalize(String s)
172
    {
173
        StringBuffer str = new StringBuffer();
174

    
175
             int len = (s != null) ? s.length() : 0;
176
             for (int i = 0; i < len; i++) {
177
                 char ch = s.charAt(i);
178
                 switch (ch) {
179
                     case '<': {
180
                         str.append("&lt;");
181
                         break;
182
                     }
183
                     case '>': {
184
                         str.append("&gt;");
185
                         break;
186
                     }
187
                     case '&': {
188
                         /*
189
                          * patch provided by Johnoel Ancheta from U of Hawaii
190
                          */
191
                         // check if & is for a character reference &#xnnnn;
192
                         if (i + 1 < len - 1 && s.charAt(i + 1) == '#') {
193
                             str.append("&#");
194
                             i += 2;
195

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

    
291
    /**
292
     * Get docid from online/url string
293
     */
294
    public static String getDocIdWithRevFromOnlineURL(String url)
295
    {
296
        String docid = null;
297
        String DOCID = "docid";
298
        boolean find = false;
299
        char limited = '&';
300
        int count = 0; //keep track how many & was found
301
        Vector list = new Vector();// keep index number for &
302
        if (url == null) {
303
            logMetacat.info("url is null and null will be returned");
304
            return docid;
305
        }
306
        // the first element in list is 0
307
        list.add(new Integer(0));
308
        for (int i = 0; i < url.length(); i++) {
309
            if (url.charAt(i) == limited) {
310
                // count plus 1
311
                count++;
312
                list.add(new Integer(i));
313
                // get substring beween two &
314
                String str = url.substring(
315
                        ((Integer) list.elementAt(count - 1)).intValue(), i);
316
                logMetacat.info("substring between two & is: " + str);
317
                //if the subString contains docid, we got it
318
                if (str.indexOf(DOCID) != -1) {
319
                    //get index of '="
320
                    int start = getIndexForGivenChar(str, '=') + 1;
321
                    int end = str.length();
322
                    docid = str.substring(start, end);
323
                    find = true;
324
                }//if
325
            }//if
326
        }//for
327
        //if not find, we need check the subtring between the index of last &
328
        // and
329
        // the end of string
330
        if (!find) {
331
            logMetacat.info("Checking the last substring");
332
            String str = url.substring(((Integer) list.elementAt(count))
333
                    .intValue() + 1, url.length());
334
            logMetacat.info("Last substring is: " + str);
335
            if (str.indexOf(DOCID) != -1) {
336
                //get index of '="
337
                int start = getIndexForGivenChar(str, '=') + 1;
338
                int end = str.length();
339
                docid = str.substring(start, end);
340
                find = true;
341
            }//if
342
        }//if
343
        logMetacat.info("The docid from online url is:" + docid);
344
        return docid.trim();
345
    }
346

    
347

    
348
    /**
349
     * Eocgorid identifier will look like: ecogrid://knb/tao.1.1
350
     * The AccessionNumber tao.1.1 will be returned. If the given doesn't
351
     * contains ecogrid, null will be returned.
352
     * @param identifier String
353
     * @return String
354
     */
355
    public static String getAccessionNumberFromEcogridIdentifier(String identifier)
356
    {
357
      String accessionNumber = null;
358
      if (identifier != null && identifier.startsWith(DBSAXHandler.ECOGRID))
359
      {
360
        // find the last "/" in identifier
361
        int indexOfLastSlash = identifier.lastIndexOf("/");
362
        int start = indexOfLastSlash+1;
363
        int end   = identifier.length();
364
        accessionNumber = identifier.substring(start, end);
365
      }
366
      logMetacat.warn("The accession number from url is " +
367
                                 accessionNumber);
368
      return accessionNumber;
369
    }
370

    
371
    private static int getIndexForGivenChar(String str, char character)
372
    {
373
        int index = -1;
374
        // make sure str is not null
375
        if (str == null) {
376
            logMetacat.info(
377
                    "The given str is null and -1 will be returned");
378
            return index;
379
        }
380
        // got though the string
381
        for (int i = 0; i < str.length(); i++) {
382
            // find the first one then break the loop
383
            if (str.charAt(i) == character) {
384
                index = i;
385
                break;
386
            }//if
387
        }//for
388
        logMetacat.info("the index for char " + character + " is: "
389
                + index);
390
        return index;
391
    }
392

    
393
    /**
394
     * Utility method to get docid from a given string
395
     *
396
     * @param string, the given string should be these two format: 1) str1.str2
397
     *            in this case docid= str1.str2 2) str1.str2.str3, in this case
398
     *            docid =str1.str2
399
     * @param the sperator char
400
     */
401
    public static String getDocIdFromString(String str)
402
    {
403
        String docId = null;
404
        if (str == null) {
405
            logMetacat.info(
406
                    "The given str is null and null will be returned"
407
                            + " in getDocIdfromString");
408
            return docId;
409
        } //make sure docid is not null
410
        int dotNumber = 0;//count how many dots in given string
411
        int indexOfLastDot = 0;
412

    
413
        for (int i = 0; i < str.length(); i++) {
414
            if (str.charAt(i) == separator) {
415
                dotNumber++;//count how many dots
416
                indexOfLastDot = i;//keep the last dot postion
417
            }
418
        }//for
419

    
420
        //The string formatt is wrong, because it has more than two or less
421
        // than
422
        //one seperator
423
        if (dotNumber > 2 || dotNumber < 1) {
424
            docId = null;
425
        } else if (dotNumber == 2) //the case for str1.str2.str3
426
        {
427
            docId = str.substring(0, indexOfLastDot);
428
        } else if (dotNumber == 1) //the case for str1.str2
429
        {
430
            docId = str;
431
        }
432

    
433
        return docId;
434
    }//getDocIdFromString
435

    
436
    /**
437
     * Utility method to get version number from a given string
438
     *
439
     * @param string, the given string should be these two format: 1)
440
     *            str1.str2(no version) version =-1; 2) str1.str2.str3, in this
441
     *            case version = str3; 3) other, vresion =-2
442
     */
443
    public static int getVersionFromString(String str)
444
            throws NumberFormatException
445
    {
446
        int version = -1;
447
        String versionString = null;
448
        int dotNumber = 0;//count how many dots in given string
449
        int indexOfLastDot = 0;
450

    
451
        for (int i = 0; i < str.length(); i++) {
452
            if (str.charAt(i) == separator) {
453
                dotNumber++;//count how many dots
454
                indexOfLastDot = i;//keep the last dot postion
455
            }
456
        }//for
457

    
458
        //The string formatt is wrong, because it has more than two or less
459
        // than
460
        //one seperator
461
        if (dotNumber > 2 || dotNumber < 1) {
462
            version = -2;
463
        } else if (dotNumber == 2 && (indexOfLastDot != (str.length() - 1)))
464
        //the case for str1.str2.str3
465
        {
466
            versionString = str.substring((indexOfLastDot + 1), str.length());
467
            version = Integer.parseInt(versionString);
468
        } else if (dotNumber == 1) //the case for str1.str2
469
        {
470
            version = -1;
471
        }
472

    
473
        return version;
474
    }//getVersionFromString
475

    
476
    /**
477
     * Utility method to get version string from a given string
478
     *
479
     * @param string, the given string should be these two format: 1)
480
     *            str1.str2(no version) version=null; 2) str1.str2.str3, in
481
     *            this case version = str3; 3) other, vresion =null;
482
     */
483
    public static String getRevisionStringFromString(String str)
484
            throws NumberFormatException
485
    {
486
        // String to store the version
487
        String versionString = null;
488
        int dotNumber = 0;//count how many dots in given string
489
        int indexOfLastDot = 0;
490

    
491
        for (int i = 0; i < str.length(); i++) {
492
            if (str.charAt(i) == separator) {
493
                dotNumber++;//count how many dots
494
                indexOfLastDot = i;//keep the last dot postion
495
            }
496
        }//for
497

    
498
        //The string formatt is wrong, because it has more than two or less
499
        // than
500
        //one seperator
501
        if (dotNumber > 2 || dotNumber < 1) {
502
            versionString = null;
503
        } else if (dotNumber == 2 && (indexOfLastDot != (str.length() - 1))) {
504
            //the case for str1.str2.str3
505
            // indexOfLastDot != (str.length() -1) means get rid of str1.str2.
506
            versionString = str.substring((indexOfLastDot + 1), str.length());
507
        } else if (dotNumber == 1) //the case for str1.str2 or str1.str2.
508
        {
509
            versionString = null;
510
        }
511

    
512
        return versionString;
513
    }//getVersionFromString
514

    
515
    /**
516
     * This method will get docid from an AccessionNumber. There is no
517
     * assumption the accessnumber will be str1.str2.str3. It can be more. So
518
     * we think the docid will be get rid of last part
519
     */
520
    public static String getDocIdFromAccessionNumber(String accessionNumber)
521
    {
522
        String docid = null;
523
        if (accessionNumber == null) { return docid; }
524
        int indexOfLastSeperator = accessionNumber.lastIndexOf(separator);
525
        docid = accessionNumber.substring(0, indexOfLastSeperator);
526
        logMetacat.info("after parsing accessionnumber, docid is "
527
                + docid);
528
        return docid;
529
    }
530

    
531
    /**
532
     * This method will get inline data id without the revision number.
533
     * So if inlineData.1.2 is passed as input, inlineData.2 is returned.
534
     */
535
    public static String getInlineDataIdWithoutRev(String accessionNumber)
536
    {
537
        String docid = null;
538
        if (accessionNumber == null) { return docid; }
539
        int indexOfLastSeperator = accessionNumber.lastIndexOf(separator);
540
        String version = accessionNumber.substring(indexOfLastSeperator,
541
                                                   accessionNumber.length());
542
        accessionNumber = accessionNumber.substring(0, indexOfLastSeperator);
543
        indexOfLastSeperator = accessionNumber.lastIndexOf(separator);
544
        docid = accessionNumber.substring(0, indexOfLastSeperator) + version;
545
        logMetacat.info("after parsing accessionnumber, docid is "
546
                                 + docid);
547

    
548
        return docid;
549
    }
550

    
551
    /**
552
     * This method will call both getDocIdFromString and
553
     * getDocIdFromAccessionNumber. So first, if the string looks str1.str2,
554
     * the docid will be str1.str2. If the string is str1.str2.str3, the docid
555
     * will be str1.str2. If the string is str1.str2.str3.str4 or more, the
556
     * docid will be str1.str2.str3. If the string look like str1, null will be
557
     * returned
558
     *
559
     */
560
    public static String getSmartDocId(String str)
561
    {
562
        String docid = null;
563
        //call geDocIdFromString first.
564
        docid = getDocIdFromString(str);
565
        // If docid is null, try to call getDocIdFromAccessionNumber
566
        // it will handle the seperator more than2
567
        if (docid == null) {
568
            docid = getDocIdFromAccessionNumber(str);
569
        }
570
        logMetacat.info("The docid get from smart docid getor is "
571
                + docid);
572
        return docid;
573
    }
574

    
575
    /**
576
     * This method will get revision from an AccessionNumber. There is no
577
     * assumption the accessnumber will be str1.str2.str3. It can be more. So
578
     * we think the docid will be get rid of last part
579
     */
580
    public static int getRevisionFromAccessionNumber(String accessionNumber)
581
            throws NumberFormatException
582
    {
583
        String rev = null;
584
        int revNumber = -1;
585
        if (accessionNumber == null) { return revNumber; }
586
        int indexOfLastSeperator = accessionNumber.lastIndexOf(separator);
587
        rev = accessionNumber.substring(indexOfLastSeperator + 1,
588
                accessionNumber.length());
589
        revNumber = Integer.parseInt(rev);
590
        logMetacat.info("after parsing accessionnumber, rev is "
591
                + revNumber);
592
        return revNumber;
593
    }
594

    
595
    /**
596
     * Method to get the name of local replication server
597
     */
598
    public static String getLocalReplicationServerName()
599
    {
600
        String replicationServerName = null;
601
        // String serverHost = null;
602
        // serverHost = getProperty("server");
603
        // append "context/servlet/replication" to the host name
604
        try {
605
        replicationServerName = 
606
        	SystemUtil.getContextURL() + "/servlet/replication";
607
        } catch (PropertyNotFoundException pnfe) {
608
        	logMetacat.error("Could not get local replication server name " 
609
        			+ "because property could not be found: " + pnfe.getMessage());
610
        }
611
        return replicationServerName;
612

    
613
    }
614

    
615
    /**
616
     * Method to get docidwithrev from eml2 inline data id The eml inline data
617
     * id would look like eml.200.2.3
618
     */
619
    public static String getDocIdWithoutRevFromInlineDataID(String inlineDataID)
620
    {
621
        String docidWithoutRev = null;
622
        if (inlineDataID == null) { return docidWithoutRev; }
623
        char charSeperator = separator;
624
        int targetNumberOfSeperator = 2;// we want to know his index
625
        int numberOfSeperator = 0;
626
        for (int i = 0; i < inlineDataID.length(); i++) {
627
            // meet seperator, increase number of seperator
628
            if (inlineDataID.charAt(i) == charSeperator) {
629
                numberOfSeperator++;
630
            }
631
            // if number of seperator reach the target one, record the index(i)
632
            // and get substring and terminate the loop
633
            if (numberOfSeperator == targetNumberOfSeperator) {
634
                docidWithoutRev = inlineDataID.substring(0, i);
635
                break;
636
            }
637
        }
638

    
639
        logMetacat.info("Docid without rev from inlinedata id: "
640
                + docidWithoutRev);
641
        return docidWithoutRev;
642

    
643
    }
644

    
645
    /**
646
     * Revise stack change a stack to opposite order
647
     */
648
    public static Stack reviseStack(Stack stack)
649
    {
650
        Stack result = new Stack();
651
        // make sure the parameter is correct
652
        if (stack == null || stack.isEmpty()) {
653
            result = stack;
654
            return result;
655
        }
656

    
657
        while (!stack.isEmpty()) {
658
            Object obj = stack.pop();
659
            result.push(obj);
660
        }
661
        return result;
662
    }
663

    
664
    /** A method to replace whitespace in url */
665
    public static String replaceWhiteSpaceForURL(String urlHasWhiteSpace)
666
    {
667
        StringBuffer newUrl = new StringBuffer();
668
        String whiteSpaceReplace = "%20";
669
        if (urlHasWhiteSpace == null || urlHasWhiteSpace.trim().equals("")) { return null; }
670

    
671
        for (int i = 0; i < urlHasWhiteSpace.length(); i++) {
672
            char ch = urlHasWhiteSpace.charAt(i);
673
            if (!Character.isWhitespace(ch)) {
674
                newUrl.append(ch);
675
            } else {
676
                //it is white sapce, replace it by %20
677
                newUrl = newUrl.append(whiteSpaceReplace);
678
            }
679

    
680
        }//for
681
        logMetacat.info("The new string without space is:"
682
                + newUrl.toString());
683
        return newUrl.toString();
684

    
685
    }// replaceWhiteSpaceForUR
686

    
687
    /**
688
	 * Writes debug information into a file. In metacat.properties, if property
689
	 * application.writeDebugToFile is set to true, the debug information will be written to
690
	 * debug file, which value is the property application.debugOutputFile in
691
	 * metacat.properties.
692
	 * 
693
	 */
694
	public static void writeDebugToFile(String debugInfo) {
695
		String debug = "false";
696
		try {
697
			debug = PropertyService.getProperty("application.writeDebugToFile");
698
			if (debug != null && debug.equalsIgnoreCase("true")) {
699
				File outputFile = 
700
					new File(PropertyService.getProperty("application.debugOutputFile"));
701
				FileOutputStream fos = new FileOutputStream(outputFile, true);
702
				PrintWriter pw = new PrintWriter(fos);
703
				pw.println(debugInfo);
704
				pw.flush();
705
				pw.close();
706
				fos.close();
707
			}
708
		} catch (PropertyNotFoundException pnfe) {
709
			// only log debug to file warning once
710
			if (!debugErrorDisplayed) {
711
				logMetacat.warn("Could not get debug property.  Write debug to " 
712
						+ "file is set to false: " + pnfe.getMessage());
713
				debugErrorDisplayed = true;
714
			}
715
		} catch (Exception io) {
716
			logMetacat.warn("Error in MetacatUtil.writeDebugToFile "
717
					+ io.getMessage());
718
		}
719
	}
720
    
721
   /**
722
	 * Writes debug information into a file in delimitered format
723
	 * 
724
	 * @param debugInfo
725
	 *            the debug information
726
	 * @param newLine
727
	 *            append the debug info to a line or not
728
	 */
729
	public static void writeDebugToDelimiteredFile(String debugInfo, boolean newLine) {
730
		String debug = "false";
731
		try {
732
			debug = PropertyService.getProperty("application.writeDebugToFile");
733
			if (debug != null && debug.equalsIgnoreCase("true")) {
734
				File outputFile = new File(PropertyService
735
						.getProperty("application.delimiteredOutputFile"));
736
				FileOutputStream fos = new FileOutputStream(outputFile, true);
737
				PrintWriter pw = new PrintWriter(fos);
738
				if (newLine) {
739
					pw.println(debugInfo);
740
				} else {
741
					pw.print(debugInfo);
742
				}
743
				pw.flush();
744
				pw.close();
745
				fos.close();
746
			}
747
		} catch (PropertyNotFoundException pnfe) {
748
			// only log debug to file warning once
749
			if (!debugErrorDisplayed) {
750
				logMetacat.warn("Could not get delimited debug property. Write debug to " 
751
						+ "file is set to false: " + pnfe.getMessage());
752
				debugErrorDisplayed = true;
753
			}
754
		} catch (Exception io) {
755
			logMetacat.warn("Eorr in writeDebugToDelimiteredFile "
756
					+ io.getMessage());
757
		}
758
	}
759

    
760
		/**
761
		 * Write the uploaded file to disk for temporary storage before moving
762
		 * it to its final Metacat location.
763
		 * 
764
		 * @param filePart
765
		 *            the FilePart object containing the file form element
766
		 * @param fileName
767
		 *            the name of the file to be written to disk
768
		 * @return tempFilePath a String containing location of temporary file
769
		 */
770
    public static String writeTempFile (FilePart filePart, String fileName) {
771
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
772
        String tempFilePath = null;
773
        String tempDirPath = null;
774
        try {
775
        	tempDirPath = PropertyService.getProperty("temp-dir");
776
        } catch (PropertyNotFoundException pnfe) {
777
        	logMetacat.warn("Temp property not found.  An attempt will be made " 
778
        			+ "to use system temp directory: " + pnfe.getMessage());
779
        }
780
        long fileSize;
781
        File tempFile;
782
        File tempDir;
783

    
784
        if ((fileName == null) || fileName.equals("")) {
785
            return tempFilePath;
786
        }
787
				
788
        // the tempfilepath token isn't set, use Java default
789
		if (tempDirPath == null) {
790
			String javaTempDir = System.getProperty("java.io.tempdir");
791
			if (javaTempDir == null) {
792
				// no paths set, use unix default
793
				tempDirPath = "/tmp";
794
			} else {
795
				tempDirPath = javaTempDir;
796
			}
797
		}
798

    
799
        tempDir = new File(tempDirPath);
800

    
801
        // Create the temporary directory if it doesn't exist
802
        try {
803
            if (!tempDir.exists()) {
804
                tempDir.mkdirs();
805
            }
806
        } catch (SecurityException e) {
807
            logMetacat.error("Can't create directory: " + tempDir.getPath() +
808
                             ". Error: " + e.getMessage());
809
        }
810
        try {
811
            tempFile = new File(tempDirPath, fileName);
812
            fileSize = filePart.writeTo(tempFile);
813
            tempFilePath = tempDirPath + File.separator + fileName;
814

    
815
            if (fileSize == 0) {
816
                logMetacat.error("Uploaded file '" + fileName + "'is empty!");
817
            }
818
        } catch (IOException e) {
819
            logMetacat.error("IO exception which writing temporary file: " +
820
                             tempFilePath + " " + e.getMessage());
821
        }
822

    
823
        logMetacat.info("Temporary file is: " + tempFilePath);
824

    
825
        return tempFilePath;
826
    }
827

    
828
    /**
829
	 * 
830
	 * Copy a file between two locations specified as strings. Fails if either
831
	 * path cannot be created. Based on the public domain FileCopy class in
832
	 * _Java in a Nutshell_.
833
	 * 
834
	 * @param sourceName
835
	 *            the source file to read from disk
836
	 * @param destName
837
	 *            the destination file on disk
838
	 */
839
    public static void copyFile(String sourceName, String destName) throws IOException {
840
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
841

    
842
        File sourceFile = new File(sourceName);
843
        File destFile = new File(destName);
844
        FileInputStream source = null;
845
        FileOutputStream dest = null;
846
        byte[] buffer;
847
        int bytesRead;
848

    
849
        try {
850
            if (!sourceFile.exists() || !sourceFile.isFile()) {
851
                logMetacat.error("File copy: no such source" +
852
                                 " file: " + sourceName);
853
            }
854
            if (!sourceFile.canRead()) {
855
                logMetacat.error("File copy: source file " +
856
                                 "is unreadable: " + sourceName);
857
            }
858

    
859
            if (destFile.exists()) {
860
                if (destFile.isFile()) {
861
                    if (!destFile.canWrite()) {
862
                        logMetacat.error("File copy: destination " +
863
                                         "file is unwriteable: " + destFile);
864
                    }
865
                } else {
866
                    logMetacat.error("File copy: destination file " +
867
                                     "is not a file: " + destFile);
868
                }
869
            } else {
870
                File parentDir = parent(destFile);
871

    
872
                if (!parentDir.exists())
873
                {
874
                    logMetacat.error("File copy: destination diretory " +
875
                                     " doesn't exist: " + destName);
876
                }
877
                if (!parentDir.canWrite()) {
878
                    logMetacat.error("File copy: destination directory " +
879
                                     " is unwritable: " + destName);
880
                }
881
            }
882

    
883
            // Verbose error checking done, copy the file object
884
            source = new FileInputStream(sourceFile);
885
            dest = new FileOutputStream(destFile);
886
            buffer = new byte[1024];
887

    
888
            while (true) {
889
                bytesRead = source.read(buffer);
890
                if (bytesRead == -1) {
891
                    break;
892
                }
893
                dest.write(buffer, 0, bytesRead);
894
            }
895
        }
896
        finally {
897
            if (source != null) {
898
                try { source.close(); } catch (IOException e) { ; }
899
            }
900
            if (dest != null) {
901
                try { dest.close(); } catch (IOException e) { ; }
902
            }
903
        }
904
    }
905

    
906
    private static File parent(File f) {
907
        String dirname = f.getParent();
908
        if (dirname == null) {
909
            if (f.isAbsolute()) return new File(File.separator);
910
            else return new File(System.getProperty("user.dir"));
911
        }
912
        return new File(dirname);
913
    }
914

    
915
	/**
916
	 * Reports whether metacat is fully configured.
917
	 * 
918
	 * @return a boolean that is true if all sections are configured and 
919
	 * false otherwise
920
	 */
921
	public static boolean isMetacatConfigured() {
922
		boolean metacatConfigured = false;
923
		try {
924
			metacatConfigured = PropertyService.arePropertiesConfigured()
925
//					&& OrganizationUtil.areOrganizationsConfigured() 
926
					&& LDAPUtil.isLDAPConfigured()
927
					&& SkinUtil.areSkinsConfigured()
928
					&& DatabaseUtil.isDatabaseConfigured()
929
					&& GeoserverUtil.isGeoserverConfigured();
930
		} catch (UtilException ue) {
931
			logMetacat.error("Could not determine if metacat is configured: "
932
					+ ue.getMessage());
933
		}
934

    
935
		return metacatConfigured;
936
	}
937
		
938
	/**
939
	 * Reports whether the metacat configuration utility should be run.  
940
	 * Returns false if  
941
	 *   -- dev.runConfiguration=false and
942
	 *   -- backup properties file exists
943
	 * Note that dev.runConfiguration should only be set to false when
944
	 * reinstalling the same version of the application in developement.
945
	 * 
946
	 * @return a boolean that is false if dev.runConfiguration is false and 
947
	 * the backup properties file exists.  
948
	 */
949
	public static boolean bypassConfiguration() {
950
		
951
		// we use the bypassConfiguration() method in Property service
952
		// to determine if bypass is necessary.  if it is, we call the 
953
		// similar method in SkinPropertyService.  Both of these calls
954
		// make sure backup properties get persisted to active properties.
955
		boolean bypass = PropertyService.bypassConfiguration();
956
		if (bypass) {
957
			SkinPropertyService.bypassConfiguration();
958
		}
959
		
960
		return bypass;
961
	}
962
		
963
}
(4-4/11)