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: walbridge $'
9
 *     '$Date: 2007-09-11 15:36:35 -0700 (Tue, 11 Sep 2007) $'
10
 * '$Revision: 3420 $'
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;
28

    
29
import java.io.File;
30
import java.io.FileInputStream;
31
import java.io.FileOutputStream;
32
import java.io.FileWriter;
33
import java.io.IOException;
34
import java.io.PrintWriter;
35
import java.io.StringReader;
36
import java.net.MalformedURLException;
37
import java.net.URL;
38
import java.text.SimpleDateFormat;
39
import java.util.HashMap;
40
import java.util.Hashtable;
41
import java.util.Stack;
42
import java.util.Vector;
43
import java.util.regex.PatternSyntaxException;
44

    
45
import org.apache.log4j.Logger;
46

    
47
import com.oreilly.servlet.multipart.FilePart;
48

    
49
import edu.ucsb.nceas.dbadapter.AbstractDatabase;
50
import edu.ucsb.nceas.utilities.Options;
51

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

    
58
    public static AbstractDatabase dbAdapter;
59

    
60
    public static Vector pathsForIndexing;
61
    
62
    public static HashMap skinconfigs = new HashMap();
63

    
64
    private static edu.ucsb.nceas.utilities.Options options = null;
65

    
66
    private static boolean debug = true;
67
    
68
    private static String[] administrators;
69
    
70
    private static String[] moderators;
71

    
72
    private static String[] allowedSubmitters;
73

    
74
    private static String[] deniedSubmitters;
75
    
76
    private static Logger logMetacat = Logger.getLogger(MetaCatUtil.class);
77

    
78
    static {
79
    	// Determine our db adapter class and create an instance of that class
80
        try {
81
            dbAdapter = (AbstractDatabase) createObject(getOption("dbAdapter"));
82
        } catch (Exception e) {
83
            System.err.println("Error in MetaCatUtil static block:"
84
                    + e.getMessage());
85
            e.printStackTrace();
86
        }
87

    
88
        // read administrator and moderator lists from metacat.properties
89
        getUserAccessControlLists();
90
    }
91
    
92
    /**
93
     * Instantiate a class using the name of the class at runtime
94
     *
95
     * @param className the fully qualified name of the class to instantiate
96
     */
97
    public static Object createObject(String className) throws Exception
98
    {
99

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

    
114
    /**
115
     * Utility method to get an option value from the properties file
116
     *
117
     * @param optionName the name of the option requested
118
     * @return the String value for the option, or null if not set
119
     */
120
    public static String getOption(String optionName)
121
    {
122
        if (options == null) {
123
            options = edu.ucsb.nceas.utilities.Options.getInstance();
124
        }
125
        if (options == null) {
126
            Logger logMetacat = Logger.getLogger(MetaCatUtil.class);
127
        	logMetacat.info("options is null");
128
        }
129
        String value = options.getOption(optionName);
130
        return value;
131
    }
132
    
133
    /**
134
     * Utility method to set an option value from the properties file
135
     *
136
     * @param optionName the name of the option requested
137
     */
138
    public static void setOption(String optionName, String newValue)
139
    {
140
        if (options == null) {
141
            options = edu.ucsb.nceas.utilities.Options.getInstance();
142
        }
143
        options.setOption(optionName, newValue);
144
        
145
    }
146

    
147
    /** Utility method to convert a file handle into a URL */
148
    public static URL fileToURL(File file)
149
    {
150
        String path = file.getAbsolutePath();
151
        String fSep = System.getProperty("file.separator");
152
        if (fSep != null && fSep.length() == 1)
153
                path = path.replace(fSep.charAt(0), '/');
154
        if (path.length() > 0 && path.charAt(0) != '/') path = '/' + path;
155
        try {
156
            return new URL("file", null, path);
157
        } catch (java.net.MalformedURLException e) {
158
            /*
159
             * According to the spec this could only happen if the file
160
             */
161
            throw new Error("unexpected MalformedURLException");
162
        }
163
    }
164

    
165
    /**
166
     * Utility method to parse the query part of a URL into parameters. This
167
     * method assumes the format of the query par tof the url is an ampersand
168
     * separated list of name/value pairs, with equal signs separating the name
169
     * from the value (e.g., name=tom&zip=99801 ). Returns a has of the name
170
     * value pairs, hashed on name.
171
     */
172
    public static Hashtable parseQuery(String query)
173
            throws MalformedURLException
174
    {
175
        String[][] params = new String[200][2];
176
        Hashtable parameters = new Hashtable();
177

    
178
        String temp = "";
179
        boolean ampflag = true;
180
        boolean poundflag = false;
181
        int arrcount = 0;
182

    
183
        if (query != null) {
184
            for (int i = 0; i < query.length(); i++) {
185

    
186
                // go throught the remainder of the query one character at a
187
                // time.
188
                if (query.charAt(i) == '=') {
189
                    // if the current char is a # then the preceding should be
190
                    // a name
191
                    if (!poundflag && ampflag) {
192
                        params[arrcount][0] = temp.trim();
193
                        temp = "";
194
                    } else {
195
                        //if there are two #s or &s in a row throw an
196
                        // exception.
197
                        throw new MalformedURLException(
198
                                "metacatURL: Two parameter names "
199
                                        + "not allowed in sequence");
200
                    }
201
                    poundflag = true;
202
                    ampflag = false;
203
                } else if (query.charAt(i) == '&' || i == query.length() - 1) {
204
                    //the text preceding the & should be the param value.
205
                    if (i == query.length() - 1) {
206
                        //if at the end of the string grab the last value and
207
                        // append it.
208
                        if (query.charAt(i) != '=') {
209
                            //ignore an extra & on the end of the string
210
                            temp += query.charAt(i);
211
                        }
212
                    }
213

    
214
                    if (!ampflag && poundflag) {
215
                        params[arrcount][1] = temp.trim();
216
                        parameters
217
                                .put(params[arrcount][0], params[arrcount][1]);
218
                        temp = "";
219
                        arrcount++; //increment the array to the next row.
220
                    } else {
221
                        //if there are two =s or &s in a row through an
222
                        // exception
223
                        throw new MalformedURLException(
224
                                "metacatURL: Two parameter values "
225
                                        + "not allowed in sequence");
226
                    }
227
                    poundflag = false;
228
                    ampflag = true;
229
                } else {
230
                    //get the next character in the string
231
                    temp += query.charAt(i);
232
                }
233
            }
234
        }
235
        return parameters;
236
    }
237
  
238
    public static Vector getOptionList(String optiontext)
239
    {
240
        Vector optionsVector = new Vector();
241
        if (optiontext.indexOf(",") == -1) {
242
            optionsVector.addElement(optiontext);
243
            return optionsVector;
244
        }
245

    
246
        while (optiontext.indexOf(",") != -1) {
247
            String s = optiontext.substring(0, optiontext.indexOf(","));
248
            optionsVector.addElement(s.trim());
249
            optiontext = optiontext.substring(optiontext.indexOf(",") + 1,
250
                    optiontext.length());
251
            if (optiontext.indexOf(",") == -1) { //catch the last list entry
252
                optionsVector.addElement(optiontext.trim());
253
            }
254
        }
255
        return optionsVector;
256
    }
257

    
258
    /** Normalizes the given string. Taken from configXML.java */
259
    public static String normalize(String s)
260
    {
261
        StringBuffer str = new StringBuffer();
262

    
263
             int len = (s != null) ? s.length() : 0;
264
             for (int i = 0; i < len; i++) {
265
                 char ch = s.charAt(i);
266
                 switch (ch) {
267
                     case '<': {
268
                         str.append("&lt;");
269
                         break;
270
                     }
271
                     case '>': {
272
                         str.append("&gt;");
273
                         break;
274
                     }
275
                     case '&': {
276
                         /*
277
                          * patch provided by Johnoel Ancheta from U of Hawaii
278
                          */
279
                         // check if & is for a character reference &#xnnnn;
280
                         if (i + 1 < len - 1 && s.charAt(i + 1) == '#') {
281
                             str.append("&#");
282
                             i += 2;
283

    
284
                             ch = s.charAt(i);
285
                             while (i < len && ch != ';') {
286
                                 str.append(ch);
287
                                 i++;
288
                                 ch = s.charAt(i);
289
                             }
290
                             str.append(';');
291
                         } else 
292
                         // check if & is in front of amp; 
293
                         // (we dont yet check for other HTML 4.0 Character entities) 
294
                         if (i + 4 < len -1 && s.charAt(i + 1) == 'a' 
295
                        	 && s.charAt(i + 2) == 'm' 
296
                        		 && s.charAt(i + 3) == 'p' 
297
                        			 && s.charAt(i + 4) == ';'){
298
                             str.append("&amp;");
299
                             i += 4;                        	 
300
                         } else
301
                             str.append("&amp;");
302
                         /////////
303
                         break;
304
                     }
305
                     case '"':
306
                    	 str.append("&quot;");
307
                         break;
308
                    default: {
309
                         if ( (ch<128) && (ch>31) ) {
310
                             str.append(ch);
311
                         }
312
                         else if (ch<32) {
313
                             if (ch == 10) { // new line
314
                                 str.append(ch);
315
                             }
316
                             if (ch == 13) { // carriage return
317
                                 str.append(ch);
318
                             }
319
                             if (ch == 9) {  // tab
320
                                 str.append(ch);
321
                             }
322
                             // otherwise skip
323
                         }
324
                         else {
325
                             str.append("&#");
326
                             str.append(Integer.toString(ch));
327
                             str.append(';');
328
                         }
329
                     }
330
                 }
331
             }
332
             return str.toString();
333
    }
334

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

    
391

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

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

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

    
457
        //assume that seperator is one charactor string
458
        char seperator = getOption("accNumSeparator").charAt(0);
459

    
460
        for (int i = 0; i < str.length(); i++) {
461
            if (str.charAt(i) == seperator) {
462
                dotNumber++;//count how many dots
463
                indexOfLastDot = i;//keep the last dot postion
464
            }
465
        }//for
466

    
467
        //The string formatt is wrong, because it has more than two or less
468
        // than
469
        //one seperator
470
        if (dotNumber > 2 || dotNumber < 1) {
471
            docId = null;
472
        } else if (dotNumber == 2) //the case for str1.str2.str3
473
        {
474
            docId = str.substring(0, indexOfLastDot);
475
        } else if (dotNumber == 1) //the case for str1.str2
476
        {
477
            docId = str;
478
        }
479

    
480
        return docId;
481
    }//getDocIdFromString
482

    
483
    /**
484
     * Utility method to get version number from a given string
485
     *
486
     * @param string, the given string should be these two format: 1)
487
     *            str1.str2(no version) version =-1; 2) str1.str2.str3, in this
488
     *            case version = str3; 3) other, vresion =-2
489
     */
490
    public static int getVersionFromString(String str)
491
            throws NumberFormatException
492
    {
493
        int version = -1;
494
        String versionString = null;
495
        int dotNumber = 0;//count how many dots in given string
496
        int indexOfLastDot = 0;
497

    
498
        //assume that seperator is one charactor string
499
        char seperator = getOption("accNumSeparator").charAt(0);
500

    
501
        for (int i = 0; i < str.length(); i++) {
502
            if (str.charAt(i) == seperator) {
503
                dotNumber++;//count how many dots
504
                indexOfLastDot = i;//keep the last dot postion
505
            }
506
        }//for
507

    
508
        //The string formatt is wrong, because it has more than two or less
509
        // than
510
        //one seperator
511
        if (dotNumber > 2 || dotNumber < 1) {
512
            version = -2;
513
        } else if (dotNumber == 2 && (indexOfLastDot != (str.length() - 1)))
514
        //the case for str1.str2.str3
515
        {
516
            versionString = str.substring((indexOfLastDot + 1), str.length());
517
            version = Integer.parseInt(versionString);
518
        } else if (dotNumber == 1) //the case for str1.str2
519
        {
520
            version = -1;
521
        }
522

    
523
        return version;
524
    }//getVersionFromString
525

    
526
    /**
527
     * Utility method to get version string from a given string
528
     *
529
     * @param string, the given string should be these two format: 1)
530
     *            str1.str2(no version) version=null; 2) str1.str2.str3, in
531
     *            this case version = str3; 3) other, vresion =null;
532
     */
533
    public static String getRevisionStringFromString(String str)
534
            throws NumberFormatException
535
    {
536
        // String to store the version
537
        String versionString = null;
538
        int dotNumber = 0;//count how many dots in given string
539
        int indexOfLastDot = 0;
540

    
541
        //assume that seperator is one charactor string
542
        char seperator = getOption("accNumSeparator").charAt(0);
543

    
544
        for (int i = 0; i < str.length(); i++) {
545
            if (str.charAt(i) == seperator) {
546
                dotNumber++;//count how many dots
547
                indexOfLastDot = i;//keep the last dot postion
548
            }
549
        }//for
550

    
551
        //The string formatt is wrong, because it has more than two or less
552
        // than
553
        //one seperator
554
        if (dotNumber > 2 || dotNumber < 1) {
555
            versionString = null;
556
        } else if (dotNumber == 2 && (indexOfLastDot != (str.length() - 1))) {
557
            //the case for str1.str2.str3
558
            // indexOfLastDot != (str.length() -1) means get rid of str1.str2.
559
            versionString = str.substring((indexOfLastDot + 1), str.length());
560
        } else if (dotNumber == 1) //the case for str1.str2 or str1.str2.
561
        {
562
            versionString = null;
563
        }
564

    
565
        return versionString;
566
    }//getVersionFromString
567

    
568
    /**
569
     * This method will get docid from an AccessionNumber. There is no
570
     * assumption the accessnumber will be str1.str2.str3. It can be more. So
571
     * we think the docid will be get rid of last part
572
     */
573
    public static String getDocIdFromAccessionNumber(String accessionNumber)
574
    {
575
        String docid = null;
576
        if (accessionNumber == null) { return docid; }
577
        String seperator = getOption("accNumSeparator");
578
        int indexOfLastSeperator = accessionNumber.lastIndexOf(seperator);
579
        docid = accessionNumber.substring(0, indexOfLastSeperator);
580
        logMetacat.info("after parsing accessionnumber, docid is "
581
                + docid);
582
        return docid;
583
    }
584

    
585
    /**
586
     * This method will get inline data id without the revision number.
587
     * So if inlineData.1.2 is passed as input, inlineData.2 is returned.
588
     */
589
    public static String getInlineDataIdWithoutRev(String accessionNumber)
590
    {
591
        String docid = null;
592
        if (accessionNumber == null) { return docid; }
593
        String seperator = getOption("accNumSeparator");
594
        int indexOfLastSeperator = accessionNumber.lastIndexOf(seperator);
595
        String version = accessionNumber.substring(indexOfLastSeperator,
596
                                                   accessionNumber.length());
597
        accessionNumber = accessionNumber.substring(0, indexOfLastSeperator);
598
        indexOfLastSeperator = accessionNumber.lastIndexOf(seperator);
599
        docid = accessionNumber.substring(0, indexOfLastSeperator) + version;
600
        logMetacat.info("after parsing accessionnumber, docid is "
601
                                 + docid);
602

    
603
        return docid;
604
    }
605

    
606
    /**
607
     * This method will call both getDocIdFromString and
608
     * getDocIdFromAccessionNumber. So first, if the string looks str1.str2,
609
     * the docid will be str1.str2. If the string is str1.str2.str3, the docid
610
     * will be str1.str2. If the string is str1.str2.str3.str4 or more, the
611
     * docid will be str1.str2.str3. If the string look like str1, null will be
612
     * returned
613
     *
614
     */
615
    public static String getSmartDocId(String str)
616
    {
617
        String docid = null;
618
        //call geDocIdFromString first.
619
        docid = getDocIdFromString(str);
620
        // If docid is null, try to call getDocIdFromAccessionNumber
621
        // it will handle the seperator more than2
622
        if (docid == null) {
623
            docid = getDocIdFromAccessionNumber(str);
624
        }
625
        logMetacat.info("The docid get from smart docid getor is "
626
                + docid);
627
        return docid;
628
    }
629

    
630
    /**
631
     * This method will get revision from an AccessionNumber. There is no
632
     * assumption the accessnumber will be str1.str2.str3. It can be more. So
633
     * we think the docid will be get rid of last part
634
     */
635
    public static int getRevisionFromAccessionNumber(String accessionNumber)
636
            throws NumberFormatException
637
    {
638
        String rev = null;
639
        int revNumber = -1;
640
        if (accessionNumber == null) { return revNumber; }
641
        String seperator = getOption("accNumSeparator");
642
        int indexOfLastSeperator = accessionNumber.lastIndexOf(seperator);
643
        rev = accessionNumber.substring(indexOfLastSeperator + 1,
644
                accessionNumber.length());
645
        revNumber = Integer.parseInt(rev);
646
        logMetacat.info("after parsing accessionnumber, rev is "
647
                + revNumber);
648
        return revNumber;
649
    }
650

    
651
    /**
652
     * Method to get the name of local replication server
653
     */
654
    public static String getLocalReplicationServerName()
655
    {
656
        String replicationServerName = null;
657
        String serverHost = null;
658
        serverHost = getOption("server");
659
        // append "context/servelet/replication" to the host name
660
        replicationServerName = serverHost.trim() + getOption("replicationpath").trim();
661
        return replicationServerName;
662

    
663
    }
664

    
665
    /**
666
     * Method to get docidwithrev from eml2 inline data id The eml inline data
667
     * id would look like eml.200.2.3
668
     */
669
    public static String getDocIdWithoutRevFromInlineDataID(String inlineDataID)
670
    {
671
        String docidWithoutRev = null;
672
        if (inlineDataID == null) { return docidWithoutRev; }
673
        String seperator = MetaCatUtil.getOption("accNumSeparator");
674
        char charSeperator = seperator.charAt(0);
675
        int targetNumberOfSeperator = 2;// we want to know his index
676
        int numberOfSeperator = 0;
677
        for (int i = 0; i < inlineDataID.length(); i++) {
678
            // meet seperator, increase number of seperator
679
            if (inlineDataID.charAt(i) == charSeperator) {
680
                numberOfSeperator++;
681
            }
682
            // if number of seperator reach the target one, record the index(i)
683
            // and get substring and terminate the loop
684
            if (numberOfSeperator == targetNumberOfSeperator) {
685
                docidWithoutRev = inlineDataID.substring(0, i);
686
                break;
687
            }
688
        }
689

    
690
        logMetacat.info("Docid without rev from inlinedata id: "
691
                + docidWithoutRev);
692
        return docidWithoutRev;
693

    
694
    }
695

    
696
    /**
697
     * Revise stack change a stack to opposite order
698
     */
699
    public static Stack reviseStack(Stack stack)
700
    {
701
        Stack result = new Stack();
702
        // make sure the parameter is correct
703
        if (stack == null || stack.isEmpty()) {
704
            result = stack;
705
            return result;
706
        }
707

    
708
        while (!stack.isEmpty()) {
709
            Object obj = stack.pop();
710
            result.push(obj);
711
        }
712
        return result;
713
    }
714

    
715
    /** A method to replace whitespace in url */
716
    public static String replaceWhiteSpaceForURL(String urlHasWhiteSpace)
717
    {
718
        StringBuffer newUrl = new StringBuffer();
719
        String whiteSpaceReplace = "%20";
720
        if (urlHasWhiteSpace == null || urlHasWhiteSpace.trim().equals("")) { return null; }
721

    
722
        for (int i = 0; i < urlHasWhiteSpace.length(); i++) {
723
            char ch = urlHasWhiteSpace.charAt(i);
724
            if (!Character.isWhitespace(ch)) {
725
                newUrl.append(ch);
726
            } else {
727
                //it is white sapce, replace it by %20
728
                newUrl = newUrl.append(whiteSpaceReplace);
729
            }
730

    
731
        }//for
732
        logMetacat.info("The new string without space is:"
733
                + newUrl.toString());
734
        return newUrl.toString();
735

    
736
    }// replaceWhiteSpaceForUR
737

    
738
    /** 
739
     * A method to read administrators and moderators list from the metacat.properties 
740
     **/
741
    public static void getUserAccessControlLists(){
742
    	administrators = getListFromOption("administrators");
743
    	moderators = getListFromOption("moderators");
744
    	allowedSubmitters = getListFromOption("allowedSubmitters");
745
    	deniedSubmitters = getListFromOption("deniedSubmitters");
746
    }
747

    
748
    /** 
749
     * A method to read value of a given option from the metacat.properties 
750
     * into specified String array
751
     **/
752
    private static String[] getListFromOption(String optionName){
753
    	String[] list = null;
754
    	String listString = MetaCatUtil.getOption(optionName);
755
      
756
        try {
757
            if ( listString != null && !listString.trim().equals("")) {
758
            	list = listString.split(":");
759
            } else {
760
            	list = null;
761
            }
762
            
763
        } catch (PatternSyntaxException pse) {
764
        	list = null;
765
            logMetacat.error("Error in MetacatServlet.init: "
766
                + pse.getMessage());
767
        }
768
        return list;
769
    }
770
    
771
    /** 
772
     * A method to check if the specified user is part of the moderators list 
773
     **/
774
    private static boolean onList(String list[], String username, String[] groups){
775

    
776
    	if(list == null){
777
    		return false;
778
    	}
779

    
780
    	// Check that the user is authenticated as an administrator account
781
        for (int i = 0; i < list.length; i++) {
782
            // check the given admin dn is a group dn...
783
        	if(groups != null && list[i].startsWith("cn=")){
784
            	// is a group dn
785
        		for (int j = 0; j < groups.length; j++) {
786
        			if (groups[j].equals(list[i])) {
787
                		return true;
788
                	}	
789
        		}   		
790
            } else { 
791
            	// is a user dn
792
            	if (username != null && username.equals(list[i])) {
793
    	    		return true;
794
            	}	
795
            }
796
        }
797
        return false;
798
    }
799

    
800
    /** 
801
     * A method to check if the specified user is part of the administrators list 
802
     **/
803
    public static boolean isAdministrator(String username, String[] groups){
804
    	return (onList(administrators, username, groups));
805
    }
806
    
807
    /** 
808
     * A method to check if the specified user is part of the moderators list 
809
     **/
810
    public static boolean isModerator(String username, String[] groups){
811
    	return (onList(moderators, username, groups));
812
    }
813

    
814
    /** 
815
     * A method to check if the specified user is part of the moderators list 
816
     **/
817
    public static boolean isAllowedSubmitter(String username, String[] groups){
818
    	if(allowedSubmitters != null){
819
    		return (onList(allowedSubmitters, username, groups));
820
    	} else {
821
    		// no allowedSubmitters list specified - 
822
    		// hence everyone should be allowed
823
    		return true;
824
    	}
825
   }
826

    
827
    /** 
828
     * A method to check if the specified user is part of the moderators list 
829
     **/
830
    public static boolean isDeniedSubmitter(String username, String[] groups){
831
		return (onList(deniedSubmitters, username, groups));
832
    }
833
    
834
    /** 
835
     * A method to check if the specified user can insert the document 
836
     **/
837
    public static boolean canInsertOrUpdate(String username, String[] groups){
838
    	return (isAllowedSubmitter(username, groups) 
839
    			&& !isDeniedSubmitter(username, groups));
840
    }
841
    
842
    /**
843
     * Writes debug information into a file. In metacat.properties, if property writeDebugToFile is
844
     * set to true, the debug information will be written to debug file, which value is the property
845
     * debugOutputFile in metacat.properties.
846
     *
847
     */
848
    public static void writeDebugToFile(String debugInfo)
849
    {
850
    	String debug = MetaCatUtil.getOption("writeDebugToFile");
851
    	if (debug != null && debug.equalsIgnoreCase("true"))
852
    	{
853
    		 try
854
    		 {
855
    			 File outputFile = new File(MetaCatUtil.getOption("debugOutputFile"));   			 
856
    			 FileOutputStream fos = new FileOutputStream(outputFile, true);
857
                 PrintWriter pw = new PrintWriter(fos);
858
                 pw.println(debugInfo);
859
                 pw.flush();
860
                 pw.close();
861
    			 fos.close();
862
    			 
863
    		 }
864
    		 catch(Exception io)
865
    		 {
866
    			logMetacat.warn("Eorr in MetacatUtil.writeDebugToFile "+io.getMessage()) ;
867
    		 }
868
    	}
869
    	
870
    }
871
    
872
   /**
873
    *  Writes debug information into a file in delimitered format
874
    * @param debugInfo   the debug information
875
    * @param newLine    append the debug info to a line or not
876
    */
877
    public static void writeDebugToDelimiteredFile(String debugInfo, boolean newLine)
878
    {
879
    	String debug = MetaCatUtil.getOption("writeDebugToFile");
880
    	if (debug != null && debug.equalsIgnoreCase("true"))
881
    	{
882
    		 try
883
    		 {
884
    			 File outputFile = new File(MetaCatUtil.getOption("delimiteredOutputFile"));   			 
885
    			 FileOutputStream fos = new FileOutputStream(outputFile, true);
886
                 PrintWriter pw = new PrintWriter(fos);
887
                 if (newLine)
888
                 {
889
                     pw.println(debugInfo);
890
                 }
891
                 else
892
                 {
893
                	 pw.print(debugInfo);
894
                 }
895
                 pw.flush();
896
                 pw.close();
897
    			 fos.close();
898
    			 
899
    		 }
900
    		 catch(Exception io)
901
    		 {
902
    			logMetacat.warn("Eorr in writeDebugToDelimiteredFile "+io.getMessage()) ;
903
    		 }
904
    	}
905
    	
906
    }
907

    
908
		/**
909
     * Write the uploaded file to disk for temporary storage before moving it 
910
     * to its final Metacat location.
911
     *
912
     * @param  filePart          the FilePart object containing the file form element
913
     * @param  fileName          the name of the file to be written to disk
914
     * @return tempFilePath      a String containing location of temporary file
915
     */
916
    public static String writeTempFile (FilePart filePart, String fileName) {
917
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
918
        String tempFilePath = null;
919
        String tempDirPath = getOption("temp-dir");
920
        long fileSize;
921
        File tempFile;
922
        File tempDir;
923

    
924
        if ((fileName == null) || fileName.equals("")) {
925
            return tempFilePath;
926
        }
927
				
928
        // the tempfilepath token isn't set, use Java default
929
        if (tempDirPath == null) {
930
						String javaTempDir = System.getProperty("java.io.tempdir");
931
						if (javaTempDir == null) {
932
							  // no paths set, use unix default
933
								tempDirPath = "/tmp";
934
						} else {
935
								tempDirPath = javaTempDir;
936
						}
937
        }
938

    
939
        tempDir = new File(tempDirPath);
940

    
941
        // Create the temporary directory if it doesn't exist
942
        try {
943
            if (!tempDir.exists()) {
944
                tempDir.mkdirs();
945
            }
946
        } catch (SecurityException e) {
947
            logMetacat.error("Can't create directory: " + tempDir.getPath() +
948
                             ". Error: " + e.getMessage());
949
        }
950
        try {
951
            tempFile = new File(tempDirPath, fileName);
952
            fileSize = filePart.writeTo(tempFile);
953
            tempFilePath = tempDirPath + File.separator + fileName;
954

    
955
            if (fileSize == 0) {
956
                logMetacat.error("Uploaded file '" + fileName + "'is empty!");
957
            }
958
        } catch (IOException e) {
959
            logMetacat.error("IO exception which writing temporary file: " +
960
                             tempFilePath + " " + e.getMessage());
961
        }
962

    
963
        logMetacat.info("Temporary file is: " + tempFilePath);
964

    
965
        return tempFilePath;
966
    }
967
		
968
		/**
969
		 *
970
		 * Copy a file between two locations specified as strings.  Fails
971
     * if either path cannot be created. Based on the public domain
972
     * FileCopy class in _Java in a Nutshell_.
973
     *
974
		 * @param sourceName		the source file to read from disk
975
     * @param destName  		the destination file on disk
976
     */
977
    public static void copyFile(String sourceName, String destName) throws IOException {
978
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
979

    
980
        File sourceFile = new File(sourceName);
981
        File destFile = new File(destName);
982
        FileInputStream source = null;
983
        FileOutputStream dest = null;
984
        byte[] buffer;
985
        int bytesRead;
986

    
987
        try {
988
            if (!sourceFile.exists() || !sourceFile.isFile()) {
989
                logMetacat.error("File copy: no such source" +
990
                                 " file: " + sourceName);
991
            }
992
            if (!sourceFile.canRead()) {
993
                logMetacat.error("File copy: source file " +
994
                                 "is unreadable: " + sourceName);
995
            }
996

    
997
            if (destFile.exists()) {
998
                if (destFile.isFile()) {
999
                    if (!destFile.canWrite()) {
1000
                        logMetacat.error("File copy: destination " +
1001
                                         "file is unwriteable: " + destFile);
1002
                    }
1003
                } else {
1004
                    logMetacat.error("File copy: destination file " +
1005
                                     "is not a file: " + destFile);
1006
                }
1007
            } else {
1008
                File parentDir = parent(destFile);
1009

    
1010
                if (!parentDir.exists())
1011
                {
1012
                    logMetacat.error("File copy: destination diretory " +
1013
                                     " doesn't exist: " + destName);
1014
                }
1015
                if (!parentDir.canWrite()) {
1016
                    logMetacat.error("File copy: destination directory " +
1017
                                     " is unwritable: " + destName);
1018
                }
1019
            }
1020

    
1021
            // Verbose error checking done, copy the file object
1022
            source = new FileInputStream(sourceFile);
1023
            dest = new FileOutputStream(destFile);
1024
            buffer = new byte[1024];
1025

    
1026
            while (true) {
1027
                bytesRead = source.read(buffer);
1028
                if (bytesRead == -1) {
1029
                    break;
1030
                }
1031
                dest.write(buffer, 0, bytesRead);
1032
            }
1033
        }
1034
        finally {
1035
            if (source != null) {
1036
                try { source.close(); } catch (IOException e) { ; }
1037
            }
1038
            if (dest != null) {
1039
                try { dest.close(); } catch (IOException e) { ; }
1040
            }
1041
        }
1042
    }
1043

    
1044
    private static File parent(File f) {
1045
        String dirname = f.getParent();
1046
        if (dirname == null) {
1047
            if (f.isAbsolute()) return new File(File.separator);
1048
            else return new File(System.getProperty("user.dir"));
1049
        }
1050
        return new File(dirname);
1051
    }
1052

    
1053
}
(45-45/66)