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-07-24 13:52:51 -0700 (Thu, 24 Jul 2008) $'
10
 * '$Revision: 4159 $'
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 HashMap skinconfigs = new HashMap();
65

    
66
    private static boolean debug = true;
67
    
68
    private static boolean debugErrorDisplayed = false;
69
    
70
    private static Logger logMetacat = Logger.getLogger(MetaCatUtil.class);
71
    private static char separator = '.';
72

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

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

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

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

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

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

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

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

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

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

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

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

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

    
383

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

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

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

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

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

    
469
        return docId;
470
    }//getDocIdFromString
471

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

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

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

    
509
        return version;
510
    }//getVersionFromString
511

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

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

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

    
548
        return versionString;
549
    }//getVersionFromString
550

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

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

    
584
        return docid;
585
    }
586

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

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

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

    
649
    }
650

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

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

    
679
    }
680

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

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

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

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

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

    
721
    }// replaceWhiteSpaceForUR
722

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

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

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

    
835
        tempDir = new File(tempDirPath);
836

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

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

    
859
        logMetacat.info("Temporary file is: " + tempFilePath);
860

    
861
        return tempFilePath;
862
    }
863

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

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

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

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

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

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

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

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

    
951
    // TODO MCD remove skins config stuff from here and move into PropertyService
952
    
953
    /**
954
     * Adds the Properties and skin to the list of skin configurations.
955
     * @param skinName String qformat
956
     * @param skinProperties Properties instance
957
     */
958
    public static void addSkinConfig(String skinName, Properties skinProperties) {
959
        skinconfigs.put(skinName, skinProperties);
960
    }
961

    
962
    /**
963
     * Return the Properties for a given skin name.
964
     * @param skinName String qformat
965
     * @return Properties, or null if none exist for the skin.
966
     */
967
    public static Properties getSkinConfig(String skinName) {
968
        Properties                      result;
969
        
970
        result = (Properties) skinconfigs.get(skinName);
971
        return(result);
972
    }
973
    
974
    /**
975
     * Returns true if Properties exist for a given skin name, false otherwise.
976
     * @param skinName String qformat
977
     * @return boolean
978
     */
979
    public static boolean hasSkinConfig(String skinName) {
980
        boolean                     result;
981
        
982
        result = skinconfigs.containsKey(skinName);
983
        return(result);
984
    }
985

    
986
	/**
987
	 * Reports whether metacat is fully configured.
988
	 * 
989
	 * @return a boolean that is true if all sections are configured and 
990
	 * false otherwise
991
	 */
992
	public static boolean isMetacatConfigured() {
993
		boolean metacatConfigured = false;
994
		try {
995
			metacatConfigured = PropertyService.arePropertiesConfigured()
996
					&& OrganizationUtil.areOrganizationsConfigured() 
997
					&& LDAPUtil.isLDAPConfigured()
998
					&& SkinUtil.areSkinsConfigured()
999
					&& DatabaseUtil.isDatabaseConfigured();
1000
		} catch (UtilException ue) {
1001
			logMetacat.error("Could not determine if metacat is configured: "
1002
					+ ue.getMessage());
1003
		}
1004

    
1005
		return metacatConfigured;
1006
	}
1007
		
1008
	/**
1009
	 * Reports whether the metacat configuration utility should be run.  
1010
	 * Returns false if  
1011
	 *   -- dev.runConfiguration=false and
1012
	 *   -- backup properties file exists
1013
	 * Note that dev.runConfiguration should only be set to false when
1014
	 * reinstalling the same version of the application in developement.
1015
	 * 
1016
	 * @return a boolean that is false if dev.runConfiguration is false and 
1017
	 * the backup properties file exists.  
1018
	 */
1019
	public static boolean bypassConfiguration() {
1020
		
1021
		// we use the bypassConfiguration() method in Property service
1022
		// to determine if bypass is necessary.  if it is, we call the 
1023
		// similar method in SkinPropertyService.  Both of these calls
1024
		// make sure backup properties get persisted to active properties.
1025
		boolean bypass = PropertyService.bypassConfiguration();
1026
		if (bypass) {
1027
			SkinPropertyService.bypassConfiguration();
1028
		}
1029
		
1030
		return bypass;
1031
	}
1032
		
1033
}
(3-3/10)