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: 2008-08-27 16:47:58 -0700 (Wed, 27 Aug 2008) $'
10
 * '$Revision: 4327 $'
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.HashMap;
36
import java.util.Hashtable;
37
import java.util.Properties;
38
import java.util.Stack;
39
import java.util.Vector;
40
import java.util.regex.PatternSyntaxException;
41

    
42
import org.apache.log4j.Logger;
43

    
44
import com.oreilly.servlet.multipart.FilePart;
45

    
46
import edu.ucsb.nceas.dbadapter.AbstractDatabase;
47
import edu.ucsb.nceas.metacat.DBSAXHandler;
48
import edu.ucsb.nceas.metacat.MetaCatServlet;
49
import edu.ucsb.nceas.metacat.service.PropertyService;
50
import edu.ucsb.nceas.metacat.service.SkinPropertyService;
51
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
52
import edu.ucsb.nceas.utilities.FileUtil;
53

    
54
/**
55
 * A suite of utility classes for the metadata catalog server
56
 */
57
public class MetaCatUtil
58
{
59

    
60
    public static AbstractDatabase dbAdapter;
61

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

    
71
    static {
72
    	// Determine our db adapter class and create an instance of that class
73
        try {
74
            dbAdapter = (AbstractDatabase) createObject(PropertyService.getProperty("database.adapter"));
75
        } catch (Exception e) {
76
            System.err.println("Error in MetaCatUtil static block:"
77
                    + e.getMessage());
78
            e.printStackTrace();
79
        }
80

    
81
        try {
82
        	separator = PropertyService.getProperty("document.accNumSeparator").charAt(0);
83
        } catch (PropertyNotFoundException pnfe) {
84
        	logMetacat.error("Could not retrieve account number separator. " 
85
        			+ "Separator set to '.' : " + pnfe.getMessage());
86
        }
87
    }
88
    
89
    /**
90
     * Instantiate a class using the name of the class at runtime
91
     *
92
     * @param className the fully qualified name of the class to instantiate
93
     */
94
    public static Object createObject(String className) throws Exception
95
    {
96

    
97
        Object object = null;
98
        try {
99
            Class classDefinition = Class.forName(className);
100
            object = classDefinition.newInstance();
101
        } catch (InstantiationException e) {
102
            throw e;
103
        } catch (IllegalAccessException e) {
104
            throw e;
105
        } catch (ClassNotFoundException e) {
106
            throw e;
107
        }
108
        return object;
109
    }
110

    
111
    /**
112
     * Utility method to parse the query part of a URL into parameters. This
113
     * method assumes the format of the query par tof the url is an ampersand
114
     * separated list of name/value pairs, with equal signs separating the name
115
     * from the value (e.g., name=tom&zip=99801 ). Returns a has of the name
116
     * value pairs, hashed on name.
117
     */
118
    public static Hashtable parseQuery(String query)
119
            throws MalformedURLException
120
    {
121
        String[][] params = new String[200][2];
122
        Hashtable parameters = new Hashtable();
123

    
124
        String temp = "";
125
        boolean ampflag = true;
126
        boolean poundflag = false;
127
        int arrcount = 0;
128

    
129
        if (query != null) {
130
            for (int i = 0; i < query.length(); i++) {
131

    
132
                // go throught the remainder of the query one character at a
133
                // time.
134
                if (query.charAt(i) == '=') {
135
                    // if the current char is a # then the preceding should be
136
                    // a name
137
                    if (!poundflag && ampflag) {
138
                        params[arrcount][0] = temp.trim();
139
                        temp = "";
140
                    } else {
141
                        //if there are two #s or &s in a row throw an
142
                        // exception.
143
                        throw new MalformedURLException(
144
                                "metacatURL: Two parameter names "
145
                                        + "not allowed in sequence");
146
                    }
147
                    poundflag = true;
148
                    ampflag = false;
149
                } else if (query.charAt(i) == '&' || i == query.length() - 1) {
150
                    //the text preceding the & should be the param value.
151
                    if (i == query.length() - 1) {
152
                        //if at the end of the string grab the last value and
153
                        // append it.
154
                        if (query.charAt(i) != '=') {
155
                            //ignore an extra & on the end of the string
156
                            temp += query.charAt(i);
157
                        }
158
                    }
159

    
160
                    if (!ampflag && poundflag) {
161
                        params[arrcount][1] = temp.trim();
162
                        parameters
163
                                .put(params[arrcount][0], params[arrcount][1]);
164
                        temp = "";
165
                        arrcount++; //increment the array to the next row.
166
                    } else {
167
                        //if there are two =s or &s in a row through an
168
                        // exception
169
                        throw new MalformedURLException(
170
                                "metacatURL: Two parameter values "
171
                                        + "not allowed in sequence");
172
                    }
173
                    poundflag = false;
174
                    ampflag = true;
175
                } else {
176
                    //get the next character in the string
177
                    temp += query.charAt(i);
178
                }
179
            }
180
        }
181
        return parameters;
182
    }
183
  
184
    public static Vector<String> getOptionList(String optiontext)
185
    {
186
        Vector<String> optionsVector = new Vector<String>();
187
        if (optiontext.indexOf(",") == -1) {
188
            optionsVector.addElement(optiontext);
189
            return optionsVector;
190
        }
191

    
192
        while (optiontext.indexOf(",") != -1) {
193
            String s = optiontext.substring(0, optiontext.indexOf(","));
194
            optionsVector.addElement(s.trim());
195
            optiontext = optiontext.substring(optiontext.indexOf(",") + 1,
196
                    optiontext.length());
197
            if (optiontext.indexOf(",") == -1) { //catch the last list entry
198
                optionsVector.addElement(optiontext.trim());
199
            }
200
        }
201
        return optionsVector;
202
    }
203

    
204
    /** Normalizes a string read from DB. So it will be compatible to HTML */
205
    public static String normalize(String s)
206
    {
207
        StringBuffer str = new StringBuffer();
208

    
209
             int len = (s != null) ? s.length() : 0;
210
             for (int i = 0; i < len; i++) {
211
                 char ch = s.charAt(i);
212
                 switch (ch) {
213
                     case '<': {
214
                         str.append("&lt;");
215
                         break;
216
                     }
217
                     case '>': {
218
                         str.append("&gt;");
219
                         break;
220
                     }
221
                     case '&': {
222
                         /*
223
                          * patch provided by Johnoel Ancheta from U of Hawaii
224
                          */
225
                         // check if & is for a character reference &#xnnnn;
226
                         if (i + 1 < len - 1 && s.charAt(i + 1) == '#') {
227
                             str.append("&#");
228
                             i += 2;
229

    
230
                             ch = s.charAt(i);
231
                             while (i < len && ch != ';') {
232
                                 str.append(ch);
233
                                 i++;
234
                                 ch = s.charAt(i);
235
                             }
236
                             str.append(';');
237
                         } else 
238
                         // check if & is in front of amp; 
239
                         // (we dont yet check for other HTML 4.0 Character entities) 
240
                         if (i + 4 < len  && s.charAt(i + 1) == 'a' 
241
                        	 && s.charAt(i + 2) == 'm' 
242
                        		 && s.charAt(i + 3) == 'p' 
243
                        			 && s.charAt(i + 4) == ';'){
244
                             str.append("&amp;");
245
                             i += 4;                        	 
246
                         }
247
                         else  if (i + 3 < len && s.charAt(i + 1) == 'l' 
248
                        	 && s.charAt(i + 2) == 't' 
249
                        		 && s.charAt(i + 3) == ';' ){
250
                    	  // check if & is in front of it; 
251
                             str.append("&lt;");
252
                             i += 3;                        	 
253
                         } 
254
                         else  if (i + 3 < len && s.charAt(i + 1) == 'g' 
255
                        	 && s.charAt(i + 2) == 't' 
256
                        		 && s.charAt(i + 3) == ';' ){
257
                    	  // check if & is in front of gt; 
258
                           // (we dont yet check for other HTML 4.0 Character entities) 
259
                             str.append("&gt;");
260
                             i += 3;                        	 
261
                         } 
262
                         else  if (i + 5 < len && s.charAt(i + 1) == 'q' 
263
                        	 && s.charAt(i + 2) == 'u' 
264
                        		 && s.charAt(i + 3) == 'o' 
265
                        	 && s.charAt(i + 4) == 't'
266
                        	 && s.charAt(i + 5) == ';')
267
                             {
268
                    	   // check if & is in front of quot; 
269
                           // (we dont yet check for other HTML 4.0 Character entities) 
270
                             str.append("&quot;");
271
                             i += 5;                        	 
272
                         } 
273
                         else  if (i + 5 < len && s.charAt(i + 1) == 'a' 
274
                        	 && s.charAt(i + 2) == 'p' 
275
                        		 && s.charAt(i + 3) == 'o' 
276
                        	 && s.charAt(i + 4) == 's'
277
                        	 && s.charAt(i + 5) == ';')
278
                             {
279
                    	   // check if & is in front of apostrophe; 
280
                           // (we dont yet check for other HTML 4.0 Character entities) 
281
                             str.append("&apos;");
282
                             i += 5;                        	 
283
                         } 
284
                         else{
285
                             str.append("&amp;");
286
                         }
287
                         /////////
288
                         break;
289
                     }
290
                     case '"':
291
                    	 str.append("&quot;");
292
                         break;
293
                     case '\'':
294
                    	 str.append("&apos;");
295
                         break;
296
                    default: {
297
                         if ( (ch<128) && (ch>31) ) {
298
                             str.append(ch);
299
                         }
300
                         else if (ch<32) {
301
                             if (ch == 10) { // new line
302
                                 str.append(ch);
303
                             }
304
                             if (ch == 13) { // carriage return
305
                                 str.append(ch);
306
                             }
307
                             if (ch == 9) {  // tab
308
                                 str.append(ch);
309
                             }
310
                             // otherwise skip
311
                         }
312
                         else {
313
                        	 //Don't transfer special character to numeric entity
314
                             /*str.append("&#");
315
                             str.append(Integer.toString(ch));
316
                             str.append(';');*/
317
                             str.append(ch);
318
                         }
319
                     }
320
                 }
321
             }
322
             return str.toString();
323
    }
324

    
325
    /**
326
     * Get docid from online/url string
327
     */
328
    public static String getDocIdWithRevFromOnlineURL(String url)
329
    {
330
        String docid = null;
331
        String DOCID = "docid";
332
        boolean find = false;
333
        char limited = '&';
334
        int count = 0; //keep track how many & was found
335
        Vector list = new Vector();// keep index number for &
336
        if (url == null) {
337
            logMetacat.info("url is null and null will be returned");
338
            return docid;
339
        }
340
        // the first element in list is 0
341
        list.add(new Integer(0));
342
        for (int i = 0; i < url.length(); i++) {
343
            if (url.charAt(i) == limited) {
344
                // count plus 1
345
                count++;
346
                list.add(new Integer(i));
347
                // get substring beween two &
348
                String str = url.substring(
349
                        ((Integer) list.elementAt(count - 1)).intValue(), i);
350
                logMetacat.info("substring between two & is: " + str);
351
                //if the subString contains docid, we got it
352
                if (str.indexOf(DOCID) != -1) {
353
                    //get index of '="
354
                    int start = getIndexForGivenChar(str, '=') + 1;
355
                    int end = str.length();
356
                    docid = str.substring(start, end);
357
                    find = true;
358
                }//if
359
            }//if
360
        }//for
361
        //if not find, we need check the subtring between the index of last &
362
        // and
363
        // the end of string
364
        if (!find) {
365
            logMetacat.info("Checking the last substring");
366
            String str = url.substring(((Integer) list.elementAt(count))
367
                    .intValue() + 1, url.length());
368
            logMetacat.info("Last substring is: " + str);
369
            if (str.indexOf(DOCID) != -1) {
370
                //get index of '="
371
                int start = getIndexForGivenChar(str, '=') + 1;
372
                int end = str.length();
373
                docid = str.substring(start, end);
374
                find = true;
375
            }//if
376
        }//if
377
        logMetacat.info("The docid from online url is:" + docid);
378
        return docid.trim();
379
    }
380

    
381

    
382
    /**
383
     * Eocgorid identifier will look like: ecogrid://knb/tao.1.1
384
     * The AccessionNumber tao.1.1 will be returned. If the given doesn't
385
     * contains ecogrid, null will be returned.
386
     * @param identifier String
387
     * @return String
388
     */
389
    public static String getAccessionNumberFromEcogridIdentifier(String identifier)
390
    {
391
      String accessionNumber = null;
392
      if (identifier != null && identifier.startsWith(DBSAXHandler.ECOGRID))
393
      {
394
        // find the last "/" in identifier
395
        int indexOfLastSlash = identifier.lastIndexOf("/");
396
        int start = indexOfLastSlash+1;
397
        int end   = identifier.length();
398
        accessionNumber = identifier.substring(start, end);
399
      }
400
      logMetacat.warn("The accession number from url is " +
401
                                 accessionNumber);
402
      return accessionNumber;
403
    }
404

    
405
    private static int getIndexForGivenChar(String str, char character)
406
    {
407
        int index = -1;
408
        // make sure str is not null
409
        if (str == null) {
410
            logMetacat.info(
411
                    "The given str is null and -1 will be returned");
412
            return index;
413
        }
414
        // got though the string
415
        for (int i = 0; i < str.length(); i++) {
416
            // find the first one then break the loop
417
            if (str.charAt(i) == character) {
418
                index = i;
419
                break;
420
            }//if
421
        }//for
422
        logMetacat.info("the index for char " + character + " is: "
423
                + index);
424
        return index;
425
    }
426

    
427
    /**
428
     * Utility method to get docid from a given string
429
     *
430
     * @param string, the given string should be these two format: 1) str1.str2
431
     *            in this case docid= str1.str2 2) str1.str2.str3, in this case
432
     *            docid =str1.str2
433
     * @param the sperator char
434
     */
435
    public static String getDocIdFromString(String str)
436
    {
437
        String docId = null;
438
        if (str == null) {
439
            logMetacat.info(
440
                    "The given str is null and null will be returned"
441
                            + " in getDocIdfromString");
442
            return docId;
443
        } //make sure docid is not null
444
        int dotNumber = 0;//count how many dots in given string
445
        int indexOfLastDot = 0;
446

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

    
454
        //The string formatt is wrong, because it has more than two or less
455
        // than
456
        //one seperator
457
        if (dotNumber > 2 || dotNumber < 1) {
458
            docId = null;
459
        } else if (dotNumber == 2) //the case for str1.str2.str3
460
        {
461
            docId = str.substring(0, indexOfLastDot);
462
        } else if (dotNumber == 1) //the case for str1.str2
463
        {
464
            docId = str;
465
        }
466

    
467
        return docId;
468
    }//getDocIdFromString
469

    
470
    /**
471
     * Utility method to get version number from a given string
472
     *
473
     * @param string, the given string should be these two format: 1)
474
     *            str1.str2(no version) version =-1; 2) str1.str2.str3, in this
475
     *            case version = str3; 3) other, vresion =-2
476
     */
477
    public static int getVersionFromString(String str)
478
            throws NumberFormatException
479
    {
480
        int version = -1;
481
        String versionString = null;
482
        int dotNumber = 0;//count how many dots in given string
483
        int indexOfLastDot = 0;
484

    
485
        for (int i = 0; i < str.length(); i++) {
486
            if (str.charAt(i) == separator) {
487
                dotNumber++;//count how many dots
488
                indexOfLastDot = i;//keep the last dot postion
489
            }
490
        }//for
491

    
492
        //The string formatt is wrong, because it has more than two or less
493
        // than
494
        //one seperator
495
        if (dotNumber > 2 || dotNumber < 1) {
496
            version = -2;
497
        } else if (dotNumber == 2 && (indexOfLastDot != (str.length() - 1)))
498
        //the case for str1.str2.str3
499
        {
500
            versionString = str.substring((indexOfLastDot + 1), str.length());
501
            version = Integer.parseInt(versionString);
502
        } else if (dotNumber == 1) //the case for str1.str2
503
        {
504
            version = -1;
505
        }
506

    
507
        return version;
508
    }//getVersionFromString
509

    
510
    /**
511
     * Utility method to get version string from a given string
512
     *
513
     * @param string, the given string should be these two format: 1)
514
     *            str1.str2(no version) version=null; 2) str1.str2.str3, in
515
     *            this case version = str3; 3) other, vresion =null;
516
     */
517
    public static String getRevisionStringFromString(String str)
518
            throws NumberFormatException
519
    {
520
        // String to store the version
521
        String versionString = null;
522
        int dotNumber = 0;//count how many dots in given string
523
        int indexOfLastDot = 0;
524

    
525
        for (int i = 0; i < str.length(); i++) {
526
            if (str.charAt(i) == separator) {
527
                dotNumber++;//count how many dots
528
                indexOfLastDot = i;//keep the last dot postion
529
            }
530
        }//for
531

    
532
        //The string formatt is wrong, because it has more than two or less
533
        // than
534
        //one seperator
535
        if (dotNumber > 2 || dotNumber < 1) {
536
            versionString = null;
537
        } else if (dotNumber == 2 && (indexOfLastDot != (str.length() - 1))) {
538
            //the case for str1.str2.str3
539
            // indexOfLastDot != (str.length() -1) means get rid of str1.str2.
540
            versionString = str.substring((indexOfLastDot + 1), str.length());
541
        } else if (dotNumber == 1) //the case for str1.str2 or str1.str2.
542
        {
543
            versionString = null;
544
        }
545

    
546
        return versionString;
547
    }//getVersionFromString
548

    
549
    /**
550
     * This method will get docid from an AccessionNumber. There is no
551
     * assumption the accessnumber will be str1.str2.str3. It can be more. So
552
     * we think the docid will be get rid of last part
553
     */
554
    public static String getDocIdFromAccessionNumber(String accessionNumber)
555
    {
556
        String docid = null;
557
        if (accessionNumber == null) { return docid; }
558
        int indexOfLastSeperator = accessionNumber.lastIndexOf(separator);
559
        docid = accessionNumber.substring(0, indexOfLastSeperator);
560
        logMetacat.info("after parsing accessionnumber, docid is "
561
                + docid);
562
        return docid;
563
    }
564

    
565
    /**
566
     * This method will get inline data id without the revision number.
567
     * So if inlineData.1.2 is passed as input, inlineData.2 is returned.
568
     */
569
    public static String getInlineDataIdWithoutRev(String accessionNumber)
570
    {
571
        String docid = null;
572
        if (accessionNumber == null) { return docid; }
573
        int indexOfLastSeperator = accessionNumber.lastIndexOf(separator);
574
        String version = accessionNumber.substring(indexOfLastSeperator,
575
                                                   accessionNumber.length());
576
        accessionNumber = accessionNumber.substring(0, indexOfLastSeperator);
577
        indexOfLastSeperator = accessionNumber.lastIndexOf(separator);
578
        docid = accessionNumber.substring(0, indexOfLastSeperator) + version;
579
        logMetacat.info("after parsing accessionnumber, docid is "
580
                                 + docid);
581

    
582
        return docid;
583
    }
584

    
585
    /**
586
     * This method will call both getDocIdFromString and
587
     * getDocIdFromAccessionNumber. So first, if the string looks str1.str2,
588
     * the docid will be str1.str2. If the string is str1.str2.str3, the docid
589
     * will be str1.str2. If the string is str1.str2.str3.str4 or more, the
590
     * docid will be str1.str2.str3. If the string look like str1, null will be
591
     * returned
592
     *
593
     */
594
    public static String getSmartDocId(String str)
595
    {
596
        String docid = null;
597
        //call geDocIdFromString first.
598
        docid = getDocIdFromString(str);
599
        // If docid is null, try to call getDocIdFromAccessionNumber
600
        // it will handle the seperator more than2
601
        if (docid == null) {
602
            docid = getDocIdFromAccessionNumber(str);
603
        }
604
        logMetacat.info("The docid get from smart docid getor is "
605
                + docid);
606
        return docid;
607
    }
608

    
609
    /**
610
     * This method will get revision from an AccessionNumber. There is no
611
     * assumption the accessnumber will be str1.str2.str3. It can be more. So
612
     * we think the docid will be get rid of last part
613
     */
614
    public static int getRevisionFromAccessionNumber(String accessionNumber)
615
            throws NumberFormatException
616
    {
617
        String rev = null;
618
        int revNumber = -1;
619
        if (accessionNumber == null) { return revNumber; }
620
        int indexOfLastSeperator = accessionNumber.lastIndexOf(separator);
621
        rev = accessionNumber.substring(indexOfLastSeperator + 1,
622
                accessionNumber.length());
623
        revNumber = Integer.parseInt(rev);
624
        logMetacat.info("after parsing accessionnumber, rev is "
625
                + revNumber);
626
        return revNumber;
627
    }
628

    
629
    /**
630
     * Method to get the name of local replication server
631
     */
632
    public static String getLocalReplicationServerName()
633
    {
634
        String replicationServerName = null;
635
        // String serverHost = null;
636
        // serverHost = getProperty("server");
637
        // append "context/servlet/replication" to the host name
638
        try {
639
        replicationServerName = 
640
        	SystemUtil.getContextURL() + "/servlet/replication";
641
        } catch (PropertyNotFoundException pnfe) {
642
        	logMetacat.error("Could not get local replication server name " 
643
        			+ "because property could not be found: " + pnfe.getMessage());
644
        }
645
        return replicationServerName;
646

    
647
    }
648

    
649
    /**
650
     * Method to get docidwithrev from eml2 inline data id The eml inline data
651
     * id would look like eml.200.2.3
652
     */
653
    public static String getDocIdWithoutRevFromInlineDataID(String inlineDataID)
654
    {
655
        String docidWithoutRev = null;
656
        if (inlineDataID == null) { return docidWithoutRev; }
657
        char charSeperator = separator;
658
        int targetNumberOfSeperator = 2;// we want to know his index
659
        int numberOfSeperator = 0;
660
        for (int i = 0; i < inlineDataID.length(); i++) {
661
            // meet seperator, increase number of seperator
662
            if (inlineDataID.charAt(i) == charSeperator) {
663
                numberOfSeperator++;
664
            }
665
            // if number of seperator reach the target one, record the index(i)
666
            // and get substring and terminate the loop
667
            if (numberOfSeperator == targetNumberOfSeperator) {
668
                docidWithoutRev = inlineDataID.substring(0, i);
669
                break;
670
            }
671
        }
672

    
673
        logMetacat.info("Docid without rev from inlinedata id: "
674
                + docidWithoutRev);
675
        return docidWithoutRev;
676

    
677
    }
678

    
679
    /**
680
     * Revise stack change a stack to opposite order
681
     */
682
    public static Stack reviseStack(Stack stack)
683
    {
684
        Stack result = new Stack();
685
        // make sure the parameter is correct
686
        if (stack == null || stack.isEmpty()) {
687
            result = stack;
688
            return result;
689
        }
690

    
691
        while (!stack.isEmpty()) {
692
            Object obj = stack.pop();
693
            result.push(obj);
694
        }
695
        return result;
696
    }
697

    
698
    /** A method to replace whitespace in url */
699
    public static String replaceWhiteSpaceForURL(String urlHasWhiteSpace)
700
    {
701
        StringBuffer newUrl = new StringBuffer();
702
        String whiteSpaceReplace = "%20";
703
        if (urlHasWhiteSpace == null || urlHasWhiteSpace.trim().equals("")) { return null; }
704

    
705
        for (int i = 0; i < urlHasWhiteSpace.length(); i++) {
706
            char ch = urlHasWhiteSpace.charAt(i);
707
            if (!Character.isWhitespace(ch)) {
708
                newUrl.append(ch);
709
            } else {
710
                //it is white sapce, replace it by %20
711
                newUrl = newUrl.append(whiteSpaceReplace);
712
            }
713

    
714
        }//for
715
        logMetacat.info("The new string without space is:"
716
                + newUrl.toString());
717
        return newUrl.toString();
718

    
719
    }// replaceWhiteSpaceForUR
720

    
721
    /**
722
	 * Writes debug information into a file. In metacat.properties, if property
723
	 * application.writeDebugToFile is set to true, the debug information will be written to
724
	 * debug file, which value is the property application.debugOutputFile in
725
	 * metacat.properties.
726
	 * 
727
	 */
728
	public static void writeDebugToFile(String debugInfo) {
729
		String debug = "false";
730
		try {
731
			debug = PropertyService.getProperty("application.writeDebugToFile");
732
			if (debug != null && debug.equalsIgnoreCase("true")) {
733
				File outputFile = 
734
					new File(PropertyService.getProperty("application.debugOutputFile"));
735
				FileOutputStream fos = new FileOutputStream(outputFile, true);
736
				PrintWriter pw = new PrintWriter(fos);
737
				pw.println(debugInfo);
738
				pw.flush();
739
				pw.close();
740
				fos.close();
741
			}
742
		} catch (PropertyNotFoundException pnfe) {
743
			// only log debug to file warning once
744
			if (!debugErrorDisplayed) {
745
				logMetacat.warn("Could not get debug property.  Write debug to " 
746
						+ "file is set to false: " + pnfe.getMessage());
747
				debugErrorDisplayed = true;
748
			}
749
		} catch (Exception io) {
750
			logMetacat.warn("Error in MetacatUtil.writeDebugToFile "
751
					+ io.getMessage());
752
		}
753
	}
754
    
755
   /**
756
	 * Writes debug information into a file in delimitered format
757
	 * 
758
	 * @param debugInfo
759
	 *            the debug information
760
	 * @param newLine
761
	 *            append the debug info to a line or not
762
	 */
763
	public static void writeDebugToDelimiteredFile(String debugInfo, boolean newLine) {
764
		String debug = "false";
765
		try {
766
			debug = PropertyService.getProperty("application.writeDebugToFile");
767
			if (debug != null && debug.equalsIgnoreCase("true")) {
768
				File outputFile = new File(PropertyService
769
						.getProperty("application.delimiteredOutputFile"));
770
				FileOutputStream fos = new FileOutputStream(outputFile, true);
771
				PrintWriter pw = new PrintWriter(fos);
772
				if (newLine) {
773
					pw.println(debugInfo);
774
				} else {
775
					pw.print(debugInfo);
776
				}
777
				pw.flush();
778
				pw.close();
779
				fos.close();
780
			}
781
		} catch (PropertyNotFoundException pnfe) {
782
			// only log debug to file warning once
783
			if (!debugErrorDisplayed) {
784
				logMetacat.warn("Could not get delimited debug property. Write debug to " 
785
						+ "file is set to false: " + pnfe.getMessage());
786
				debugErrorDisplayed = true;
787
			}
788
		} catch (Exception io) {
789
			logMetacat.warn("Eorr in writeDebugToDelimiteredFile "
790
					+ io.getMessage());
791
		}
792
	}
793

    
794
		/**
795
		 * Write the uploaded file to disk for temporary storage before moving
796
		 * it to its final Metacat location.
797
		 * 
798
		 * @param filePart
799
		 *            the FilePart object containing the file form element
800
		 * @param fileName
801
		 *            the name of the file to be written to disk
802
		 * @return tempFilePath a String containing location of temporary file
803
		 */
804
    public static String writeTempFile (FilePart filePart, String fileName) {
805
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
806
        String tempFilePath = null;
807
        String tempDirPath = null;
808
        try {
809
        	tempDirPath = PropertyService.getProperty("temp-dir");
810
        } catch (PropertyNotFoundException pnfe) {
811
        	logMetacat.warn("Temp property not found.  An attempt will be made " 
812
        			+ "to use system temp directory: " + pnfe.getMessage());
813
        }
814
        long fileSize;
815
        File tempFile;
816
        File tempDir;
817

    
818
        if ((fileName == null) || fileName.equals("")) {
819
            return tempFilePath;
820
        }
821
				
822
        // the tempfilepath token isn't set, use Java default
823
		if (tempDirPath == null) {
824
			String javaTempDir = System.getProperty("java.io.tempdir");
825
			if (javaTempDir == null) {
826
				// no paths set, use unix default
827
				tempDirPath = "/tmp";
828
			} else {
829
				tempDirPath = javaTempDir;
830
			}
831
		}
832

    
833
        tempDir = new File(tempDirPath);
834

    
835
        // Create the temporary directory if it doesn't exist
836
        try {
837
            if (!tempDir.exists()) {
838
                tempDir.mkdirs();
839
            }
840
        } catch (SecurityException e) {
841
            logMetacat.error("Can't create directory: " + tempDir.getPath() +
842
                             ". Error: " + e.getMessage());
843
        }
844
        try {
845
            tempFile = new File(tempDirPath, fileName);
846
            fileSize = filePart.writeTo(tempFile);
847
            tempFilePath = tempDirPath + File.separator + fileName;
848

    
849
            if (fileSize == 0) {
850
                logMetacat.error("Uploaded file '" + fileName + "'is empty!");
851
            }
852
        } catch (IOException e) {
853
            logMetacat.error("IO exception which writing temporary file: " +
854
                             tempFilePath + " " + e.getMessage());
855
        }
856

    
857
        logMetacat.info("Temporary file is: " + tempFilePath);
858

    
859
        return tempFilePath;
860
    }
861

    
862
    /**
863
	 * 
864
	 * Copy a file between two locations specified as strings. Fails if either
865
	 * path cannot be created. Based on the public domain FileCopy class in
866
	 * _Java in a Nutshell_.
867
	 * 
868
	 * @param sourceName
869
	 *            the source file to read from disk
870
	 * @param destName
871
	 *            the destination file on disk
872
	 */
873
    public static void copyFile(String sourceName, String destName) throws IOException {
874
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
875

    
876
        File sourceFile = new File(sourceName);
877
        File destFile = new File(destName);
878
        FileInputStream source = null;
879
        FileOutputStream dest = null;
880
        byte[] buffer;
881
        int bytesRead;
882

    
883
        try {
884
            if (!sourceFile.exists() || !sourceFile.isFile()) {
885
                logMetacat.error("File copy: no such source" +
886
                                 " file: " + sourceName);
887
            }
888
            if (!sourceFile.canRead()) {
889
                logMetacat.error("File copy: source file " +
890
                                 "is unreadable: " + sourceName);
891
            }
892

    
893
            if (destFile.exists()) {
894
                if (destFile.isFile()) {
895
                    if (!destFile.canWrite()) {
896
                        logMetacat.error("File copy: destination " +
897
                                         "file is unwriteable: " + destFile);
898
                    }
899
                } else {
900
                    logMetacat.error("File copy: destination file " +
901
                                     "is not a file: " + destFile);
902
                }
903
            } else {
904
                File parentDir = parent(destFile);
905

    
906
                if (!parentDir.exists())
907
                {
908
                    logMetacat.error("File copy: destination diretory " +
909
                                     " doesn't exist: " + destName);
910
                }
911
                if (!parentDir.canWrite()) {
912
                    logMetacat.error("File copy: destination directory " +
913
                                     " is unwritable: " + destName);
914
                }
915
            }
916

    
917
            // Verbose error checking done, copy the file object
918
            source = new FileInputStream(sourceFile);
919
            dest = new FileOutputStream(destFile);
920
            buffer = new byte[1024];
921

    
922
            while (true) {
923
                bytesRead = source.read(buffer);
924
                if (bytesRead == -1) {
925
                    break;
926
                }
927
                dest.write(buffer, 0, bytesRead);
928
            }
929
        }
930
        finally {
931
            if (source != null) {
932
                try { source.close(); } catch (IOException e) { ; }
933
            }
934
            if (dest != null) {
935
                try { dest.close(); } catch (IOException e) { ; }
936
            }
937
        }
938
    }
939

    
940
    private static File parent(File f) {
941
        String dirname = f.getParent();
942
        if (dirname == null) {
943
            if (f.isAbsolute()) return new File(File.separator);
944
            else return new File(System.getProperty("user.dir"));
945
        }
946
        return new File(dirname);
947
    }
948

    
949
	/**
950
	 * Reports whether metacat is fully configured.
951
	 * 
952
	 * @return a boolean that is true if all sections are configured and 
953
	 * false otherwise
954
	 */
955
	public static boolean isMetacatConfigured() {
956
		boolean metacatConfigured = false;
957
		try {
958
			metacatConfigured = PropertyService.arePropertiesConfigured()
959
//					&& OrganizationUtil.areOrganizationsConfigured() 
960
					&& LDAPUtil.isLDAPConfigured()
961
					&& SkinUtil.areSkinsConfigured()
962
					&& DatabaseUtil.isDatabaseConfigured()
963
					&& GeoserverUtil.isGeoserverConfigured();
964
		} catch (UtilException ue) {
965
			logMetacat.error("Could not determine if metacat is configured: "
966
					+ ue.getMessage());
967
		}
968

    
969
		return metacatConfigured;
970
	}
971
		
972
	/**
973
	 * Reports whether the metacat configuration utility should be run.  
974
	 * Returns false if  
975
	 *   -- dev.runConfiguration=false and
976
	 *   -- backup properties file exists
977
	 * Note that dev.runConfiguration should only be set to false when
978
	 * reinstalling the same version of the application in developement.
979
	 * 
980
	 * @return a boolean that is false if dev.runConfiguration is false and 
981
	 * the backup properties file exists.  
982
	 */
983
	public static boolean bypassConfiguration() {
984
		
985
		// we use the bypassConfiguration() method in Property service
986
		// to determine if bypass is necessary.  if it is, we call the 
987
		// similar method in SkinPropertyService.  Both of these calls
988
		// make sure backup properties get persisted to active properties.
989
		boolean bypass = PropertyService.bypassConfiguration();
990
		if (bypass) {
991
			SkinPropertyService.bypassConfiguration();
992
		}
993
		
994
		return bypass;
995
	}
996
		
997
}
(4-4/11)