PageRenderTime 242ms CodeModel.GetById 104ms app.highlight 115ms RepoModel.GetById 12ms app.codeStats 0ms

/bundles/plugins-trunk/XML/sidekick/ecmascript/parser/Util.java

#
Java | 699 lines | 388 code | 96 blank | 215 comment | 140 complexity | 6db5ff0d3d272584dcae12618fd43bd7 MD5 | raw file
  1/*
  2 Copyright (c) 2004-2005, The Dojo Foundation
  3 All Rights Reserved.
  4
  5 Licensed under the Academic Free License version 2.1 or above OR the
  6 modified BSD license. For more information on Dojo licensing, see:
  7
  8 http://dojotoolkit.org/community/licensing.shtml <http://dojotoolkit.org/community/licensing.shtml>
  9
 10 Code donated to the Dojo Foundation by AOL LLC under the terms of
 11 the Dojo CCLA (http://dojotoolkit.org/ccla.txt).
 12
 13 */
 14package sidekick.ecmascript.parser;
 15
 16import java.util.*;
 17import java.util.logging.Level;
 18import java.io.*;
 19import java.text.*;
 20
 21import java.nio.*;
 22import java.nio.channels.*;
 23import java.nio.charset.*;
 24
 25
 26/**
 27 * Collection of useful static utility methods.
 28 *
 29 *
 30 * @since JDK 1.4
 31 */
 32public class Util extends Object {
 33
 34    /**
 35     * Converts milliseconds to some more human readable representation.
 36     *
 37     * @param millis
 38     *            An amount of elapsed milliseconds
 39     * @return A human readable time string
 40     */
 41    static public final String millisToNice(long millis) {
 42        long seconds = millis / 1000;
 43        long sec = (seconds % 3600) % 60;
 44        long min = (seconds % 3600) / 60;
 45        long hour = seconds / 3600;
 46        StringBuffer strbuf = new StringBuffer(60);
 47        strbuf.append(" [ ");
 48        if (hour > 0L) {
 49            strbuf.append(hour + " h ");
 50        }
 51        if (min > 0L) {
 52            strbuf.append(min + " min ");
 53        }
 54
 55        if (sec > 0L) {
 56            strbuf.append(sec + " sec ");
 57        }
 58
 59        strbuf.append((millis % 1000) + " millis");
 60        strbuf.append(" ]");
 61        return strbuf.toString();
 62    }
 63
 64    /**
 65     * Creates an array of strings from a string of comma-separated string
 66     * tokens.
 67     *
 68     * @param aString
 69     *            string containing tokens separated by ","
 70     * @return array containing string tokens, can be null if string empty
 71     */
 72    static public final String[] tokenizeCommaSepString(String aString) {
 73        if (aString == null) {
 74            return null;
 75        }
 76        StringTokenizer tokenizer = new StringTokenizer(aString, ",");
 77        String[] result = null;
 78
 79        int n = tokenizer.countTokens();
 80
 81        if (n > 0) {
 82            result = new String[n];
 83
 84            int i = 0;
 85            while (tokenizer.hasMoreTokens()) {
 86                result[i] = tokenizer.nextToken().trim();
 87                i++;
 88            }
 89        }
 90        return result;
 91    }
 92
 93    /**
 94     * Finds the common prefix of two specified strings.
 95     *
 96     * @param str1
 97     *            first string
 98     * @param str2
 99     *            second string
100     * @return string which is a common prefix of the two strings, can be empty
101     *         string, is never null
102     */
103    static public final String commonPrefix(String str1, String str2) {
104        boolean done = false;
105        StringBuffer buffer = new StringBuffer();
106
107        int i = 0;
108        int n1 = str1.length();
109        int n2 = str2.length();
110
111        while (!done) {
112            char c = str1.charAt(i);
113
114            if (c == str2.charAt(i)) {
115                buffer.append(c);
116                i++;
117                if ((i == n1) || (i == n2)) {
118                    done = true;
119                }
120            } else {
121                done = true;
122            }
123        }
124
125        return buffer.toString();
126    }
127
128    /**
129     * Finds the common path prefix of two specified paths. Paths have to be
130     * canonical
131     *
132     * @param path1
133     *            first path
134     * @param path2
135     *            second path
136     * @return string which is a non-empty common path prefix of the two paths,
137     *         or null if they don't have a non-empty common prefix
138     */
139    static public final String commonPathPrefix(String path1, String path2) {
140        boolean done = false;
141        StringBuffer buffer = new StringBuffer();
142
143        StringTokenizer st1 = new StringTokenizer(path1, File.separator, true);
144        StringTokenizer st2 = new StringTokenizer(path2, File.separator, true);
145
146        done = (!(st1.hasMoreTokens() && st2.hasMoreTokens()));
147
148        while (!done) {
149            String p1 = st1.nextToken();
150            String p2 = st2.nextToken();
151
152            if (p1.equals(p2)) {
153                buffer.append(p1);
154                done = (!(st1.hasMoreTokens() && st2.hasMoreTokens()));
155            } else {
156                done = true;
157            }
158        }
159
160        return buffer.length() > 0 ? buffer.toString() : null;
161    }
162
163    static private final ByteBuffer copyBuffer = ByteBuffer
164            .allocateDirect(16 * 1024);
165
166    /**
167     * Does a fast file copy from specified source to specified destination.
168     * Uses nio API introduced in jdk 1.4.
169     *
170     * @param srcFilename
171     *            file name of source file
172     * @param dstFilename
173     *            file name of copy
174     * @exception IOException
175     *                if an I/O error occurs
176     */
177    static public final void copyFile(String srcFilename, String dstFilename)
178            throws IOException {
179        FileInputStream fis = null;
180        FileOutputStream fos = null;
181        FileChannel ifc = null;
182        FileChannel ofc = null;
183
184        Util.copyBuffer.clear();
185
186        try {
187            // Open the file and then get a channel from the stream
188            fis = new FileInputStream(srcFilename);
189            ifc = fis.getChannel();
190            fos = new FileOutputStream(dstFilename);
191            ofc = fos.getChannel();
192
193            int sz = (int) ifc.size();
194
195            int n = 0;
196            while (n < sz) {
197                if (ifc.read(Util.copyBuffer) < 0) {
198                    break;
199                }
200                Util.copyBuffer.flip();
201                n += ofc.write(Util.copyBuffer);
202                Util.copyBuffer.compact();
203            }
204
205        } finally {
206            try {
207                if (ifc != null) {
208                    ifc.close();
209                } else if (fis != null) {
210                    fis.close();
211                }
212            } catch (IOException exc) {
213            }
214
215            try {
216                if (ofc != null) {
217                    ofc.close();
218                } else if (fos != null) {
219                    fos.close();
220                }
221            } catch (IOException exc) {
222            }
223        }
224
225        // FileInputStream fis = null;
226        // FileOutputStream fos = null;
227        // FileChannel ifc = null;
228        // FileChannel ofc = null;
229
230        // try {
231        // fis = new FileInputStream(srcFilename);
232        // ifc = fis.getChannel();
233        // fos = new FileOutputStream(dstFilename);
234        // ofc = fos.getChannel();
235
236        // int sz = (int)ifc.size();
237        // ifc.transferTo(0, sz, ofc);
238        // } finally {
239        // try {
240        // if(ifc != null){
241        // ifc.close();
242        // } else if(fis != null){
243        // fis.close();
244        // }
245        // } catch(IOException exc){
246        // }
247
248        // try {
249        // if(ofc != null){
250        // ofc.close();
251        // } else if(fos != null){
252        // fos.close();
253        // }
254        // } catch(IOException exc){
255        // }
256        // }
257    }
258
259    static private final DateFormat dateFormat = DateFormat
260            .getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
261
262    /**
263     * Creates a string representing a date stamp of the current system date and
264     * system time. Returned string is suitable to be used in a filename.
265     *
266     * @return string with date/time stamp
267     */
268    static public final String getDateStamp() {
269        String dateStamp = dateFormat.format(new Date());
270        dateStamp = dateStamp.replace(' ', '_');
271        dateStamp = dateStamp.replace(',', '_');
272        dateStamp = dateStamp.replace('/', '-');
273        dateStamp = dateStamp.replace(':', '-');
274
275        return dateStamp;
276    }
277
278    /**
279     * Returns <code>true</code> if specified string is a valid identifier for
280     * java or javascript.
281     *
282     * @param candidate
283     *            potential identifier
284     * @return <code>true</code> if it is in fact an identifier
285     */
286    static public final boolean isJavaIdentifier(String candidate) {
287        if ((candidate == null) || (candidate.length() == 0)) {
288            return false;
289        }
290
291        char c = candidate.charAt(0);
292
293        if (!Character.isJavaIdentifierStart(c)) {
294            return false;
295        }
296
297        int n = candidate.length();
298
299        for (int i = 1; i < n; i++) {
300            c = candidate.charAt(i);
301
302            if (!Character.isJavaIdentifierPart(c)) {
303                return false;
304            }
305        }
306
307        return true;
308    }
309
310    /**
311     * Returns <code>true</code> if specified string is a valid composite
312     * reference where each part is a valid identifier for java or javascript.
313     *
314     * @param candidate
315     *            potential identifier
316     * @return <code>true</code> if it is in fact a valid composite reference
317     */
318    static public final boolean isValidCompositeReference(String candidate) {
319        if ((candidate == null) || (candidate.length() == 0)) {
320            return false;
321        }
322
323        char c = candidate.charAt(0);
324
325        if (!Character.isJavaIdentifierStart(c)) {
326            return false;
327        }
328
329        int n = candidate.length();
330
331        for (int i = 1; i < n; i++) {
332            c = candidate.charAt(i);
333
334            if (!(Character.isJavaIdentifierPart(c) || (c == '.'))) {
335                return false;
336            }
337        }
338
339        if (c == '.') {
340            return false;
341        }
342
343        return true;
344    }
345
346    /**
347     * Returns <code>true</code> if specified string is whitespace
348     *
349     * @param candidate
350     *            potential whitespace
351     * @return <code>true</code> if it is in fact whitespace
352     */
353    static public final boolean isWhitespace(String candidate) {
354        int n = candidate.length();
355
356        for (int i = 0; i < n; i++) {
357            char c = candidate.charAt(i);
358
359            if (!Character.isWhitespace(c)) {
360                return false;
361            }
362        }
363
364        return true;
365    }
366
367    /**
368     * Returns <code>true</code> if specified string is a mixed case string
369     * with case mixing happening in the middle of the string (starting with
370     * uppercase char and continuing with all lowercase chars does count).
371     *
372     * @param candidate
373     *            potential mixed case
374     * @return <code>true</code> if it is in fact mixed case
375     */
376    static public final boolean isLikelyIdentifier(String candidate) {
377        int n = candidate.length();
378
379        if (n < 3) {
380            return false;
381        }
382
383        boolean hasLower = false;
384        boolean hasUpper = false;
385        boolean hasUnderscore = false;
386        int nUpper = Character.isUpperCase(candidate.charAt(0)) ? 1 : 0;
387
388        for (int i = 1; i < n; i++) {
389            char c = candidate.charAt(i);
390
391            if (Character.isLowerCase(c)) {
392                hasLower = true;
393            } else if (Character.isUpperCase(c)) {
394                hasUpper = true;
395                nUpper++;
396            } else if (c == '_') {
397                hasUnderscore = true;
398            }
399        }
400
401        return (hasLower && hasUpper) || hasUnderscore
402                || (nUpper == candidate.length());
403    }
404
405    /**
406     * Replaces occurences of substring <code>sub</code> with string
407     * <code>with</code> in specified string.
408     *
409     * @param s
410     *            string for replacement
411     * @param sub
412     *            substring to replace
413     * @param with
414     *            substring to take its place
415     * @return new string with replacements done
416     */
417    static public String replaceString(String s, String sub, String with) {
418        int c = 0;
419        int i = s.indexOf(sub, c);
420        if (i == -1) {
421            return s;
422        }
423
424        StringBuffer buf = new StringBuffer(s.length() + with.length());
425
426        do {
427            buf.append(s.substring(c, i));
428            buf.append(with);
429            c = i + sub.length();
430        } while ((i = s.indexOf(sub, c)) != -1);
431
432        if (c < s.length()) {
433            buf.append(s.substring(c, s.length()));
434        }
435
436        return buf.toString();
437    }
438
439    /**
440     * Replaces occurences of substring <code>sub</code> with string
441     * <code>with</code> in specified string but only if substring is
442     * delimited by non-alphanumeric characters.
443     *
444     * @param s
445     *            string for replacement
446     * @param sub
447     *            substring to replace
448     * @param with
449     *            substring to take its place
450     * @return new string with replacements done
451     */
452    static public String replaceSeparatedString(String s, String sub,
453            String with) {
454        int c = 0;
455        int i = s.indexOf(sub, c);
456        if (i == -1) {
457            return s;
458        }
459
460        StringBuffer buf = new StringBuffer(s.length() + with.length());
461
462        int n = s.length();
463
464        do {
465            buf.append(s.substring(c, i));
466            int beginChar = i > 0 ? s.charAt(i - 1) : -1;
467            int m = i + sub.length();
468            int endChar = m < n ? s.charAt(m) : -1;
469
470            if (((beginChar == -1) || (!Character
471                    .isJavaIdentifierStart((char) beginChar)))
472                    && ((endChar == -1) || (!Character
473                            .isJavaIdentifierPart((char) endChar)))) {
474                buf.append(with);
475            } else {
476                buf.append(sub);
477            }
478            c = i + sub.length();
479        } while ((i = s.indexOf(sub, c)) != -1);
480
481        if (c < s.length()) {
482            buf.append(s.substring(c, s.length()));
483        }
484
485        return buf.toString();
486    }
487
488    /**
489     * Tests if specified string ends with the specified suffix.
490     *
491     * @param aString
492     *            string to test
493     * @param aSuffix
494     *            suffix.
495     * @return <code>true</code> if the ends in suffix
496     */
497    static public boolean endsWith(String aString, String aSuffix) {
498        if (aString == null) {
499            return aSuffix == null;
500        }
501
502        if (aString.equals("")) {
503            return (aSuffix != null) && aSuffix.equals("");
504        }
505
506        int index = aString.lastIndexOf(aSuffix);
507
508        return index == aString.length() - aSuffix.length();
509    }
510
511    /**
512     * Returns <code>true</code> if the specified filename has wildcard
513     * characters in it, i.e. the name contains either "*" or "?" characters.
514     *
515     * @param filename
516     *            filename
517     * @return <code>true</code> if has wildcard characters
518     */
519    static public boolean hasWildcards(String filename) {
520        return (filename.indexOf('*') != -1) || (filename.indexOf('?') != -1);
521    }
522
523    /**
524     * Transforms a user wildcard into a java.util.regex.Pattern pattern string.
525     *
526     * @param wildcard
527     *            wildcard string
528     * @return pattern string
529     */
530    static public String wildCard2Pattern(String wildcard) {
531        int n = wildcard.length();
532        StringBuffer regexPatternBuffer = new StringBuffer(n);
533
534        for (int i = 0; i < n; i++) {
535            char c = wildcard.charAt(i);
536            if (c == '*') {
537                regexPatternBuffer.append(".*");
538            } else if (c == '?') {
539                regexPatternBuffer.append('.');
540            } else if (c == '.') {
541                regexPatternBuffer.append("\\.");
542            } else if (c == '$') {
543                regexPatternBuffer.append("\\$");
544            } else {
545                regexPatternBuffer.append(c);
546            }
547        }
548
549        return regexPatternBuffer.toString();
550    }
551
552    /**
553     * Resolves the specified url path to a file on the local file system. Uses
554     * the specified web root and web map aliases to complete the resolution.
555     *
556     * @param urlPath
557     *            a url path
558     * @param webroot
559     *            directory path on local file system of the web root
560     * @param webmaps
561     *            web map aliases
562     * @return a local File instance
563     */
564    static public File resolveWebURL(String urlPath, String webroot, Map webmaps) {
565        File result = null;
566
567        Iterator iter = webmaps.keySet().iterator();
568
569        while (iter.hasNext()) {
570            String key = (String) iter.next();
571
572            if (urlPath.startsWith(key)) {
573                result = new File(((String) webmaps.get(key))
574                        + urlPath.substring(key.length()));
575                break;
576            }
577        }
578
579        if (result == null) {
580            result = new File(webroot + urlPath);
581        }
582
583        return result;
584    }
585
586    /**
587     * Reads an input stream completely into memory and returns a CharBuffer
588     * instance with the contents.
589     *
590     * @param inputStream
591     *            an input stream
592     * @param decoder
593     *            charset decoder
594     * @return CharBuffer instance with the contents
595     * @exception IOException
596     *                if reading from inputStream throws IOException
597     */
598    static public CharBuffer readBytes(InputStream inputStream,
599            CharsetDecoder decoder) throws IOException {
600        byte[] buffer = new byte[1024];
601        int b = inputStream.read();
602        int i = 0;
603
604        while (b != -1) {
605            if (i == buffer.length) {
606                byte[] grow = new byte[buffer.length * 2];
607                System.arraycopy(buffer, 0, grow, 0, buffer.length);
608                buffer = grow;
609            }
610            buffer[i++] = (byte) b;
611            b = inputStream.read();
612        }
613
614        return decoder.decode(ByteBuffer.wrap(buffer, 0, i));
615    }
616
617    /**
618     * Escapes a plain text string for html. Doesn't look into those funny
619     * characters like euro symbol, copyright symbol etc.
620     *
621     * @param plainString
622     *            plain text string
623     * @return html-escaped string
624     */
625    static public String escape2Html(String plainString) {
626        if (plainString == null) {
627            return null;
628        }
629
630        StringBuffer sb = new StringBuffer();
631        int n = plainString.length();
632
633        int spaceState = 0;
634        int nlState = 0;
635
636        for (int i = 0; i < n; i++) {
637            char c = plainString.charAt(i);
638
639            if (c == ' ') {
640                if (nlState > 0) {
641                    if (nlState == 1) {
642                        sb.append('\n');
643                    } else {
644                        sb.append("<p>");
645                    }
646                }
647                nlState = 0;
648                if (spaceState == 0) {
649                    spaceState = 1;
650                    sb.append(c);
651                } else if (spaceState == 1) {
652                    spaceState = 0;
653                    sb.append("&nbsp;");
654                }
655            } else if (c == '\n') {
656                if (nlState == 0) {
657                    nlState = 1;
658                } else if (nlState == 1) {
659                    nlState = 2;
660                }
661            } else {
662                if (nlState > 0) {
663                    if (nlState == 1) {
664                        sb.append('\n');
665                    } else {
666                        sb.append("<p>");
667                    }
668                }
669                nlState = 0;
670                spaceState = 0;
671                switch (c) {
672                case '<':
673                    sb.append("&lt;");
674                    break;
675                case '>':
676                    sb.append("&gt;");
677                    break;
678                case '&':
679                    sb.append("&amp;");
680                    break;
681                case '"':
682                    sb.append("&quot;");
683                    break;
684                case '\'':
685                    sb.append("&#039;");
686                    break;
687                case '\n':
688                    sb.append("<br>");
689                    break;
690                default:
691                    sb.append(c);
692                    break;
693                }
694            }
695        }
696
697        return sb.toString();
698    }
699}