Project

General

Profile

Download (19 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

    
10
package eu.etaxonomy.cdm.common;
11

    
12
import java.io.BufferedReader;
13
import java.io.File;
14
import java.io.IOException;
15
import java.io.InputStream;
16
import java.io.InputStreamReader;
17
import java.lang.annotation.Annotation;
18
import java.lang.reflect.Field;
19
import java.lang.reflect.Modifier;
20
import java.net.HttpURLConnection;
21
import java.net.MalformedURLException;
22
import java.net.URI;
23
import java.net.URISyntaxException;
24
import java.net.URL;
25
import java.util.ArrayList;
26
import java.util.HashMap;
27
import java.util.Map;
28
import java.util.regex.Matcher;
29
import java.util.regex.Pattern;
30

    
31
import org.apache.commons.lang.StringUtils;
32
import org.apache.log4j.Logger;
33

    
34
/**
35
 * Util class for consistent access to and creation of per instance application configuration files.
36
 *
37
 * @author a.mueller
38
 * @author a.kohlbecker
39
 */
40
public class CdmUtils {
41

    
42
    private static final Logger logger = Logger.getLogger(CdmUtils.class);
43

    
44
    // ============= TODO externalize into CdmFileUtils class ? ========== //
45

    
46
    private static final String USER_HOME = System.getProperty("user.home");
47

    
48
    /**
49
     * The per user cdm folder name: ".cdmLibrary"
50
     */
51
    private static final String CDM_FOLDER_NAME = ".cdmLibrary";
52

    
53
    /**
54
     * The per user cdm folder "~/.cdmLibrary"
55
     */
56
    public final static File PER_USER_CDM_FOLDER = new File(USER_HOME + File.separator + CDM_FOLDER_NAME );
57

    
58
    /**
59
     * suggested sub folder for web app related data and configurations.
60
     * Each webapp instance should use a dedicated subfolder or file
61
     * which is named by the data source bean id.
62
     */
63
    public static final String SUBFOLDER_WEBAPP = "remote-webapp";
64

    
65
    static final String MUST_EXIST_FILE = "MUST-EXIST.txt";
66

    
67
    //folder separator
68
    static String folderSeparator;
69

    
70
    public static File getCdmHomeDir() {
71
        return new File(PER_USER_CDM_FOLDER + File.separator);
72
    }
73

    
74
	/**
75
	 * Returns specified the sub folder of  {@link #CDM_FOLDER_NAME}.
76
	 * If the sub folder does not exist it will be created.
77
	 *
78
	 * @param subFolderName
79
	 * @return the sub folder or null in case the folder did not exist ant the attempt to create it has failed.
80
	 *
81
	 * @see {@link #SUBFOLDER_WEBAPP}
82
	 */
83
	public static File getCdmHomeSubDir(String subFolderName) {
84

    
85
		File parentFolder = getCdmHomeDir();
86
        return ensureSubfolderExists(parentFolder, subFolderName);
87
	}
88

    
89
	/**
90
     * Returns a instance specific folder folder in  {@link #CDM_FOLDER_NAME}/<code>subFolderName</code>
91
     * Non existing folders will be created.
92
     *
93
     * @param subFolderName
94
     *      The name of a subfolded. In most cases this will be {@link #SUBFOLDER_WEBAPP}
95
     * @param instanceName
96
     *      The name of the application instance. The name should be related to the data source id.
97
     * @return the sub folder or null in case the folder did not exist ant the attempt to create it has failed.
98
     *
99
     * @see {@link #SUBFOLDER_WEBAPP}
100
     */
101
    public static File getCdmInstanceSubDir(String subFolderName, String instanceName) {
102

    
103
        File subfolder = ensureSubfolderExists(getCdmHomeDir(), subFolderName);
104
        return ensureSubfolderExists(subfolder, instanceName);
105
    }
106

    
107
    /**
108
     * @param subFolderName
109
     * @param parentFolder
110
     * @return
111
     */
112
    private static File ensureSubfolderExists(File parentFolder, String subFolderName) {
113
        File folder = new File(parentFolder, subFolderName);
114
		// if the directory does not exist, create it
115
		if (!folder.exists()) {
116
			if (!folder.mkdir()) {
117
				// TODO throw some Exception
118
				return null;
119
			}
120
		}
121
		return folder;
122
    }
123

    
124
	// ============= END of CdmFileUtils ========== //
125

    
126
    /**
127
     * Returns the an InputStream for a read-only source
128
     * @param resourceFileName the resources path within the classpath(!)
129
     * @return
130
     * @throws IOException
131
     */
132
    public static InputStream getReadableResourceStream(String resourceFileName)
133
            throws IOException{
134
        InputStream urlStream = CdmUtils.class.getResourceAsStream("/"+ resourceFileName);
135
        return urlStream;
136
    }
137

    
138
    /**
139
     * Returns the an InputStream for a read-only source
140
     * @param resourceFileName the resources path within the classpath(!)
141
     * @return
142
     * @throws IOException
143
     */
144
    public static InputStreamReader getUtf8ResourceReader(String resourceFileName)
145
            throws IOException{
146
        InputStream urlStream = CdmUtils.class.getResourceAsStream("/"+ resourceFileName);
147
        InputStreamReader inputStreamReader = new InputStreamReader(urlStream, "UTF8");
148
        return inputStreamReader;
149
    }
150

    
151

    
152
    /**
153
     * @return
154
     */
155
    static public String getFolderSeperator(){
156
        if (folderSeparator == null){
157
            URL url = CdmUtils.class.getResource("/"+ MUST_EXIST_FILE);
158
            if ( url != null && ! urlIsJarOrBundle(url) ){
159
                folderSeparator =  File.separator;
160
            }else{
161
                folderSeparator = "/";
162
            }
163
        }
164
        return folderSeparator;
165
    }
166

    
167

    
168
    /**
169
     * @param url
170
     * @return
171
     */
172
    static private boolean urlIsJarOrBundle(URL url){
173
        return url.getProtocol().startsWith("jar") || url.getProtocol().startsWith("bundleresource");
174
    }
175

    
176
    /**
177
     * Returns the file name for the file in which 'clazz' is to be found (helps finding according libraries)
178
     * @param clazz
179
     * @return
180
     */
181
    static public String findLibrary(Class<?> clazz){
182
        String result = null;
183
        if (clazz != null){
184
            String fullPackageName = clazz.getCanonicalName();
185
            fullPackageName = fullPackageName.replace(".", "/");
186
            URL url = CdmUtils.class.getResource("/" + fullPackageName + ".class" );
187
            if (url != null){
188
                result = url.getFile();
189
            }else{
190
                result = "";
191
            }
192
            logger.debug("LibraryURL for " + clazz.getCanonicalName() + " : " + result);
193
        }
194
        return result;
195
    }
196

    
197
    static public String testMe(){
198
        String message = "This is a test";
199
        System.out.println(message);
200
        return message;
201
    }
202

    
203
    static public String readInputLine(String inputQuestion){
204
        try {
205

    
206
            System.out.print(inputQuestion);
207
            BufferedReader in = new BufferedReader( new java.io.InputStreamReader( System.in ));
208
            String input;
209
            input = in.readLine();
210
            return input;
211
        } catch (IOException e) {
212
            logger.warn("IOExeption");
213
            return null;
214
        }
215
    }
216

    
217

    
218
    /**
219
     * Returns the trimmed value string if value is not <code>null</code>.
220
     * Returns the empty string if value is <code>null</code>.
221
     * @param value
222
     * @return
223
     */
224
    static public String NzTrim(String value){
225
        return (value == null ? "" : value);
226
    }
227

    
228

    
229
    /**
230
     * Returns value if value is not <code>null</code>. Returns empty string if value is <code>null</code>.
231
     * @param value
232
     * @return
233
     */
234
    static public String Nz(String value){
235
        return (value == null ? "" : value);
236
    }
237

    
238
    /**
239
     * Returns value if value is not <code>null</code>. Returns defaultValue if value is <code>null</code>.
240
     * @param value
241
     * @return
242
     */
243
    static public String Nz(String value, String defaultValue){
244
        return (value == null ? defaultValue : value);
245
    }
246

    
247
    /**
248
     * Returns value if value is not <code>null</code>. Returns 0 if value is <code>null</code>.
249
     * @param value
250
     * @return
251
     */
252
    static public Integer Nz(Integer value){
253
        return (value == null ? 0 : value);
254
    }
255

    
256
    /**
257
     * Returns value if value is not <code>null</code>. Returns 0 if value is <code>null</code>.
258
     * @param value
259
     * @return
260
     */
261
    static public Long Nz(Long value){
262
        return (value == null ? 0 : value);
263
    }
264

    
265
    /**
266
     * Returns str if str is not the empty String (''). Returns null if str is empty.
267
     * @param str
268
     * @return
269
     */
270
    static public String Ne(String str){
271
        return ("".equals(str)? null : str);
272
    }
273

    
274
    /**
275
     * Returns str if str.trim() is not empty. Returns null otherwise.
276
     * @param str
277
     * @return
278
     */
279
    static public String Nb(String str){
280
        return (str == null || str.trim().equals("")? null : str);
281
    }
282

    
283

    
284
    /**
285
     * Concatenates an array of strings using the defined separator.<BR>
286
     * <code>Null</code> values are interpreted as empty strings.<BR>
287
     * If all strings are <code>null</code> then <code>null</code> is returned.
288
     * @param strings
289
     * @param seperator
290
     * @return String
291
     */
292
    static public String concat(CharSequence separator, String... strings){
293
        String result = "";
294
        boolean allNull = true;
295
        for (String string : strings){
296
            if (string != null){
297
                if (result.length() > 0 && string.length() > 0){
298
                    result += separator;
299
                }
300
                result += string;
301
                allNull = false;
302
            }
303
        }
304
        //if all strings are null result should be null, not ""
305
        if (allNull){
306
            return null;
307
        }else {
308
            return result;
309
        }
310
    }
311

    
312
    /**
313
     * Concatenates two strings, using the defined seperator.<BR>
314
     * <code>Null</code> values are interpreted as empty Strings.<BR>
315
     * If both strings are <code>null</code> then <code>null</code> is returned.
316
     * @see #concat(CharSequence, String[])
317
     * @param seperator
318
     * @param string1
319
     * @param string2
320
     * @return String
321
     */
322
    static public String concat(CharSequence separator, String string1, String string2){
323
        String[] strings = {string1, string2};
324
        return concat(separator, strings);
325
    }
326

    
327

    
328
	/**
329
	 * Returns <code>preferred</code> if not blank, else returns <code>alternative</code>.
330
	 * If reverse is <code>true</code> computation is
331
	 * the other way round (<code>alternative</code> if not blank, otherwise <code>preferred</code>).
332
	 * @param preferred first string
333
	 * @param alternative second string
334
	 * @param reverse reverse flag
335
	 * @param nzTrim if <code>true</code> the result is trimmed and <code>null</code> values are replaced by empty string.
336
	 * @return the preferred string
337
	 */
338
	static public String getPreferredNonEmptyString(String preferred, String alternative, boolean reverse, boolean nzTrim){
339
		String result;
340
		if (! reverse){
341
			result = StringUtils.isBlank(preferred) ? alternative : preferred;
342
		}else{
343
			result = StringUtils.isBlank(alternative) ? preferred : alternative;
344
		}
345
		if (nzTrim){
346
			result = Nz(result).trim();
347
		}
348
		return result;
349
	}
350

    
351

    
352
    /** Returns a version of the input where all contiguous
353
     * whitespace characters are replaced with a single
354
     * space. Line terminators are treated like whitespace.
355
     *
356
     * @param inputStr
357
     * @return
358
     */
359
    public static CharSequence removeDuplicateWhitespace(CharSequence inputStr) {
360

    
361
        String patternStr = "\\s+";
362
        String replaceStr = " ";
363
        Pattern pattern = Pattern.compile(patternStr);
364
        Matcher matcher = pattern.matcher(inputStr);
365
        return matcher.replaceAll(replaceStr);
366
    }
367

    
368

    
369
    /** Builds a list of strings by splitting an input string
370
     * with delimiters whitespace, comma, or semicolon
371
     * @param value
372
     * @return
373
     */
374
    public static ArrayList<String> buildList(String value) {
375

    
376
        ArrayList<String> resultList = new ArrayList<String>();
377
        for (String tag : value.split("[\\s,;]+")) {
378
            resultList.add(tag);
379
        }
380
        return resultList;
381
    }
382

    
383

    
384
    static public boolean urlExists(String strUrl, boolean withWarning){
385
        try {
386
             HttpURLConnection.setFollowRedirects(false);
387
              // note : you may also need
388
              //        HttpURLConnection.setInstanceFollowRedirects(false)
389
              HttpURLConnection con =
390
                 (HttpURLConnection) new URL(strUrl).openConnection();
391
              con.setRequestMethod("HEAD");
392
              return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
393
        } catch (MalformedURLException e) {
394
            if (withWarning) {
395
                logger.warn(e);
396
            }
397
        } catch (IOException e) {
398
            //
399
        };
400
        return false;
401
    }
402

    
403
    static public URI string2Uri(String string) {
404
        URI uri = null;
405
        try {
406
            uri = new URI(string);
407
            logger.debug("uri: " + uri.toString());
408
        } catch (URISyntaxException ex) {
409
            logger.error("Problem converting string " + string + " to URI " + uri);
410
            return null;
411
        }
412
        return uri;
413
    }
414

    
415
    static public boolean isNumeric(String string){
416
        if (string == null){
417
            return false;
418
        }
419
        try {
420
            Double.valueOf(string);
421
            return true;
422
        } catch (NumberFormatException e) {
423
            return false;
424
        }
425

    
426
    }
427

    
428
    /**
429
     * Returns <code>true</code> if the passed string starts with an upper case letter.
430
     * <code>false</code> otherwise. The later includes <code>null</code> and empty strings.
431
     * @param string
432
     * @return
433
     */
434
    static public boolean isCapital(String string){
435
        if (isBlank(string)){
436
            return false;
437
        }else{
438
            Character firstChar = string.charAt(0);
439
            if (firstChar.equals(Character.toUpperCase(firstChar))){
440
                return true;
441
            }else{
442
                return false;
443
            }
444
        }
445

    
446
    }
447

    
448
    /**
449
     * Returns true if string is null, "" or string.trim() is ""
450
     * @see isNotEmpty(String string)
451
     * @param string
452
     * @return
453
     */
454
    static public boolean isBlank(String string){
455
        if (string == null){
456
            return true;
457
        }
458
        if ("".equals(string.trim())){
459
            return true;
460
        }
461
        return false;
462
    }
463

    
464
    /**
465
     * Returns <code>false</code> if string is null, "" or string.trim() is ""
466
     * @see isNotEmpty(String string)
467
     * @param string
468
     * @return
469
     */
470
    static public boolean isNotBlank(String string){
471
        return ! isBlank(string);
472
    }
473

    
474
    /**
475
     * @see #isBlank(String)
476
     * @deprecated use {@link #isBlank(String)} instead
477
     * @param string
478
     * @return
479
     */
480
    @Deprecated
481
    static public boolean isEmpty(String string){
482
        return isBlank(string);
483
    }
484

    
485
    static public boolean areBlank(String ... strings){
486
        for (String string : strings){
487
            if (! isBlank(string)){
488
                return false;
489
            }
490
        }
491
        return true;
492
    }
493

    
494
    /**
495
     * Tests if two objects are equal or both null. Otherwise returns false
496
     * @param obj1
497
     * @param obj2
498
     * @return
499
     */
500
    public static boolean nullSafeEqual(Object obj1, Object obj2) {
501
        if (obj1 == null && obj2 == null){
502
            return true;
503
        }
504
        if (obj1 == null && obj2 != null){
505
            return false;
506
        }
507
        return (obj1.equals(obj2));
508
    }
509

    
510

    
511
    /**
512
     * Compares 2 strings with defined values for <code>null</code>
513
     * @param str1
514
     * @param str2
515
     * @return
516
     */
517
    public static int nullSafeCompareTo(String str1, String str2) {
518
        if (str1 == null){
519
            return str2 == null ? 0 : -1;
520
        }else if (str2 == null){
521
            return 1;
522
        }else{
523
            return (str1.compareTo(str2));
524
        }
525
    }
526

    
527
    /**
528
     * Returns false if string is null, "" or string.trim() is ""
529
     * Else true.
530
     * @see isBlank(String string)
531
     * @see #isNotBlank(String)
532
     * @deprecated use {@link #isNotBlank(String)} instead
533
     * @param string
534
     * @return
535
     */
536
    @Deprecated
537
    static public boolean isNotEmpty(String string){
538
        return isNotBlank(string);
539
    }
540

    
541

    
542
    /**
543
     * Computes all fields recursively
544
     * @param clazz
545
     * @return
546
     */
547
    public static Map<String, Field> getAllFields(Class clazz, Class highestClass, boolean includeStatic, boolean includeTransient, boolean makeAccessible, boolean includeHighestClass) {
548
        Map<String, Field> result = new HashMap<String, Field>();
549
        if ( highestClass.isAssignableFrom(clazz) && (clazz != highestClass || includeHighestClass)){
550
            //exclude static
551
            for (Field field: clazz.getDeclaredFields()){
552
                if (includeStatic || ! Modifier.isStatic(field.getModifiers())){
553
                    if (includeTransient || ! isTransient(field)){
554
                        field.setAccessible(makeAccessible);
555
                        result.put(field.getName(), field);
556
                    }
557
                }
558
            }
559

    
560
            //include superclass fields
561
            Class superclass = clazz.getSuperclass();
562
            if (superclass != null){
563
                result.putAll(getAllFields(superclass, highestClass, includeStatic, includeTransient, makeAccessible, includeHighestClass));
564
            }
565
        }
566
        return result;
567
    }
568

    
569

    
570
    /**
571
     * Returns true, if field has an annotation of type javax.persistence.Annotation
572
     * @param field
573
     * @return
574
     */
575
    protected static boolean isTransient(Field field) {
576
        for (Annotation annotation : field.getAnnotations()){
577
            //if (Transient.class.isAssignableFrom(annotation.annotationType())){
578
            if (annotation.annotationType().getSimpleName().equals("Transient")){
579
                return true;
580
            }
581
        }
582
        return false;
583
    }
584

    
585
    /**
586
     * Trims the string and if the string ends with a dot removes it.
587
     * @param string
588
     * @return
589
     */
590
    public static String removeTrailingDot(String string){
591
        if (string == null){
592
            return null;
593
        }
594
        if (string.trim().endsWith(".")){
595
            return string.substring(0, string.length() -1);
596
        }
597
        return string;
598
    }
599

    
600
    /**
601
     * Returns surrounding brackets "(",")". Trim the string if necessary.
602
     * @param text
603
     * @return
604
     */
605
    public static String removeBrackets(String text) {
606
        if (text == null){
607
            return null;
608
        }
609
        text = text.trim();
610
        if (text.matches("^\\(.*\\)$")){
611
            text = text.substring(1, text.length() -1);
612
        }
613
        return text;
614
    }
615

    
616
    /**
617
     * Compares 2 strings. If they are not empty and equal returns <code>true</code>
618
     * otherwise false.
619
     *
620
     * @param str1
621
     * @param str2
622
     * @return compare result as boolean
623
     */
624
    public static boolean nonEmptyEquals(String str1, String str2) {
625
        return (isNotBlank(str1) && str1.equals(str2));
626
    }
627

    
628
    /**
629
     * Compares if str1 and str2 is equal when ignoring whitespaces.
630
     * Returns <code>true</code> if both or <code>null</code> or
631
     * whitespace ignore equal.
632
     * @param str1
633
     * @param str2
634
     * @return
635
     */
636
    public static boolean equalsIgnoreWS(String str1, String str2) {
637
        if (str1 == null){
638
            return str2 == null;
639
        }else if (str2 == null){
640
            return false;
641
        }else{
642
            return str1.replaceAll("\\s", "").equals(str2.replaceAll("\\s", ""));
643
        }
644
    }
645

    
646
}
(3-3/21)