KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > util > Util


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core.util;
12
13 import java.io.*;
14 import java.net.URI JavaDoc;
15 import java.util.*;
16 import java.util.zip.ZipEntry JavaDoc;
17 import java.util.zip.ZipFile JavaDoc;
18
19 import org.eclipse.core.filesystem.EFS;
20 import org.eclipse.core.filesystem.IFileStore;
21 import org.eclipse.core.resources.*;
22 import org.eclipse.core.runtime.*;
23 import org.eclipse.core.runtime.content.IContentType;
24 import org.eclipse.core.runtime.preferences.IScopeContext;
25 import org.eclipse.core.runtime.preferences.InstanceScope;
26 import org.eclipse.jdt.core.*;
27 import org.eclipse.jdt.core.compiler.CharOperation;
28 import org.eclipse.jdt.core.dom.ASTNode;
29 import org.eclipse.jdt.core.dom.ArrayType;
30 import org.eclipse.jdt.core.dom.ParameterizedType;
31 import org.eclipse.jdt.core.dom.PrimitiveType;
32 import org.eclipse.jdt.core.dom.QualifiedType;
33 import org.eclipse.jdt.core.dom.SimpleType;
34 import org.eclipse.jdt.core.dom.Type;
35 import org.eclipse.jdt.core.dom.WildcardType;
36 import org.eclipse.jdt.core.util.IClassFileAttribute;
37 import org.eclipse.jdt.core.util.IClassFileReader;
38 import org.eclipse.jdt.core.util.ICodeAttribute;
39 import org.eclipse.jdt.core.util.IFieldInfo;
40 import org.eclipse.jdt.core.util.IMethodInfo;
41 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
42 import org.eclipse.jdt.internal.compiler.ast.Argument;
43 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
44 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
45 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
46 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
47 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
48 import org.eclipse.jdt.internal.core.JavaElement;
49 import org.eclipse.jdt.internal.core.JavaModelManager;
50 import org.eclipse.jdt.internal.core.PackageFragmentRoot;
51 import org.eclipse.jface.text.BadLocationException;
52 import org.eclipse.text.edits.MalformedTreeException;
53 import org.eclipse.text.edits.TextEdit;
54
55 /**
56  * Provides convenient utility methods to other types in this package.
57  */

58 public class Util {
59
60     public interface Comparable {
61         /**
62          * Returns 0 if this and c are equal, >0 if this is greater than c,
63          * or <0 if this is less than c.
64          */

65         int compareTo(Comparable JavaDoc c);
66     }
67
68     public interface Comparer {
69         /**
70          * Returns 0 if a and b are equal, >0 if a is greater than b,
71          * or <0 if a is less than b.
72          */

73         int compare(Object JavaDoc a, Object JavaDoc b);
74     }
75     private static final String JavaDoc ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
76

77     private static final String JavaDoc EMPTY_ARGUMENT = " "; //$NON-NLS-1$
78

79     private static char[][] JAVA_LIKE_EXTENSIONS;
80     public static boolean ENABLE_JAVA_LIKE_EXTENSIONS = true;
81
82     private static final char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
83
private static final char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
84
private static final char[] CHAR = "char".toCharArray(); //$NON-NLS-1$
85
private static final char[] DOUBLE = "double".toCharArray(); //$NON-NLS-1$
86
private static final char[] FLOAT = "float".toCharArray(); //$NON-NLS-1$
87
private static final char[] INT = "int".toCharArray(); //$NON-NLS-1$
88
private static final char[] LONG = "long".toCharArray(); //$NON-NLS-1$
89
private static final char[] SHORT = "short".toCharArray(); //$NON-NLS-1$
90
private static final char[] VOID = "void".toCharArray(); //$NON-NLS-1$
91
private static final char[] INIT = "<init>".toCharArray(); //$NON-NLS-1$
92

93     private Util() {
94         // cannot be instantiated
95
}
96     
97     /**
98      * Returns a new array adding the second array at the end of first array.
99      * It answers null if the first and second are null.
100      * If the first array is null or if it is empty, then a new array is created with second.
101      * If the second array is null, then the first array is returned.
102      * <br>
103      * <br>
104      * For example:
105      * <ol>
106      * <li><pre>
107      * first = null
108      * second = "a"
109      * => result = {"a"}
110      * </pre>
111      * <li><pre>
112      * first = {"a"}
113      * second = null
114      * => result = {"a"}
115      * </pre>
116      * </li>
117      * <li><pre>
118      * first = {"a"}
119      * second = {"b"}
120      * => result = {"a", "b"}
121      * </pre>
122      * </li>
123      * </ol>
124      *
125      * @param first the first array to concatenate
126      * @param second the array to add at the end of the first array
127      * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
128      */

129     public static final String JavaDoc[] arrayConcat(String JavaDoc[] first, String JavaDoc second) {
130         if (second == null)
131             return first;
132         if (first == null)
133             return new String JavaDoc[] {second};
134
135         int length = first.length;
136         if (first.length == 0) {
137             return new String JavaDoc[] {second};
138         }
139         
140         String JavaDoc[] result = new String JavaDoc[length + 1];
141         System.arraycopy(first, 0, result, 0, length);
142         result[length] = second;
143         return result;
144     }
145
146     /**
147      * Checks the type signature in String sig,
148      * starting at start and ending before end (end is not included).
149      * Returns the index of the character immediately after the signature if valid,
150      * or -1 if not valid.
151      */

152     private static int checkTypeSignature(String JavaDoc sig, int start, int end, boolean allowVoid) {
153         if (start >= end) return -1;
154         int i = start;
155         char c = sig.charAt(i++);
156         int nestingDepth = 0;
157         while (c == '[') {
158             ++nestingDepth;
159             if (i >= end) return -1;
160             c = sig.charAt(i++);
161         }
162         switch (c) {
163             case 'B':
164             case 'C':
165             case 'D':
166             case 'F':
167             case 'I':
168             case 'J':
169             case 'S':
170             case 'Z':
171                 break;
172             case 'V':
173                 if (!allowVoid) return -1;
174                 // array of void is not allowed
175
if (nestingDepth != 0) return -1;
176                 break;
177             case 'L':
178                 int semicolon = sig.indexOf(';', i);
179                 // Must have at least one character between L and ;
180
if (semicolon <= i || semicolon >= end) return -1;
181                 i = semicolon + 1;
182                 break;
183             default:
184                 return -1;
185         }
186         return i;
187     }
188     
189     /**
190      * Combines two hash codes to make a new one.
191      */

192     public static int combineHashCodes(int hashCode1, int hashCode2) {
193         return hashCode1 * 17 + hashCode2;
194     }
195     
196     /**
197      * Compares two byte arrays.
198      * Returns <0 if a byte in a is less than the corresponding byte in b, or if a is shorter, or if a is null.
199      * Returns >0 if a byte in a is greater than the corresponding byte in b, or if a is longer, or if b is null.
200      * Returns 0 if they are equal or both null.
201      */

202     public static int compare(byte[] a, byte[] b) {
203         if (a == b)
204             return 0;
205         if (a == null)
206             return -1;
207         if (b == null)
208             return 1;
209         int len = Math.min(a.length, b.length);
210         for (int i = 0; i < len; ++i) {
211             int diff = a[i] - b[i];
212             if (diff != 0)
213                 return diff;
214         }
215         if (a.length > len)
216             return 1;
217         if (b.length > len)
218             return -1;
219         return 0;
220     }
221     /**
222      * Compares two strings lexicographically.
223      * The comparison is based on the Unicode value of each character in
224      * the strings.
225      *
226      * @return the value <code>0</code> if the str1 is equal to str2;
227      * a value less than <code>0</code> if str1
228      * is lexicographically less than str2;
229      * and a value greater than <code>0</code> if str1 is
230      * lexicographically greater than str2.
231      */

232     public static int compare(char[] str1, char[] str2) {
233         int len1= str1.length;
234         int len2= str2.length;
235         int n= Math.min(len1, len2);
236         int i= 0;
237         while (n-- != 0) {
238             char c1= str1[i];
239             char c2= str2[i++];
240             if (c1 != c2) {
241                 return c1 - c2;
242             }
243         }
244         return len1 - len2;
245     }
246
247     /**
248      * Concatenate two strings with a char in between.
249      * @see #concat(String, String)
250      */

251     public static String JavaDoc concat(String JavaDoc s1, char c, String JavaDoc s2) {
252         if (s1 == null) s1 = "null"; //$NON-NLS-1$
253
if (s2 == null) s2 = "null"; //$NON-NLS-1$
254
int l1 = s1.length();
255         int l2 = s2.length();
256         char[] buf = new char[l1 + 1 + l2];
257         s1.getChars(0, l1, buf, 0);
258         buf[l1] = c;
259         s2.getChars(0, l2, buf, l1 + 1);
260         return new String JavaDoc(buf);
261     }
262     
263     /**
264      * Concatenate two strings.
265      * Much faster than using +, which:
266      * - creates a StringBuffer,
267      * - which is synchronized,
268      * - of default size, so the resulting char array is
269      * often larger than needed.
270      * This implementation creates an extra char array, since the
271      * String constructor copies its argument, but there's no way around this.
272      */

273     public static String JavaDoc concat(String JavaDoc s1, String JavaDoc s2) {
274         if (s1 == null) s1 = "null"; //$NON-NLS-1$
275
if (s2 == null) s2 = "null"; //$NON-NLS-1$
276
int l1 = s1.length();
277         int l2 = s2.length();
278         char[] buf = new char[l1 + l2];
279         s1.getChars(0, l1, buf, 0);
280         s2.getChars(0, l2, buf, l1);
281         return new String JavaDoc(buf);
282     }
283
284     /**
285      * Returns the concatenation of the given array parts using the given separator between each part.
286      * <br>
287      * <br>
288      * For example:<br>
289      * <ol>
290      * <li><pre>
291      * array = {"a", "b"}
292      * separator = '.'
293      * => result = "a.b"
294      * </pre>
295      * </li>
296      * <li><pre>
297      * array = {}
298      * separator = '.'
299      * => result = ""
300      * </pre></li>
301      * </ol>
302      *
303      * @param array the given array
304      * @param separator the given separator
305      * @return the concatenation of the given array parts using the given separator between each part
306      */

307     public static final String JavaDoc concatWith(String JavaDoc[] array, char separator) {
308         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
309         for (int i = 0, length = array.length; i < length; i++) {
310             buffer.append(array[i]);
311             if (i < length - 1)
312                 buffer.append(separator);
313         }
314         return buffer.toString();
315     }
316     
317     /**
318      * Returns the concatenation of the given array parts using the given separator between each
319      * part and appending the given name at the end.
320      * <br>
321      * <br>
322      * For example:<br>
323      * <ol>
324      * <li><pre>
325      * name = "c"
326      * array = { "a", "b" }
327      * separator = '.'
328      * => result = "a.b.c"
329      * </pre>
330      * </li>
331      * <li><pre>
332      * name = null
333      * array = { "a", "b" }
334      * separator = '.'
335      * => result = "a.b"
336      * </pre></li>
337      * <li><pre>
338      * name = " c"
339      * array = null
340      * separator = '.'
341      * => result = "c"
342      * </pre></li>
343      * </ol>
344      *
345      * @param array the given array
346      * @param name the given name
347      * @param separator the given separator
348      * @return the concatenation of the given array parts using the given separator between each
349      * part and appending the given name at the end
350      */

351     public static final String JavaDoc concatWith(
352         String JavaDoc[] array,
353         String JavaDoc name,
354         char separator) {
355         
356         if (array == null || array.length == 0) return name;
357         if (name == null || name.length() == 0) return concatWith(array, separator);
358         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
359         for (int i = 0, length = array.length; i < length; i++) {
360             buffer.append(array[i]);
361             buffer.append(separator);
362         }
363         buffer.append(name);
364         return buffer.toString();
365         
366     }
367     
368     /**
369      * Concatenate three strings.
370      * @see #concat(String, String)
371      */

372     public static String JavaDoc concat(String JavaDoc s1, String JavaDoc s2, String JavaDoc s3) {
373         if (s1 == null) s1 = "null"; //$NON-NLS-1$
374
if (s2 == null) s2 = "null"; //$NON-NLS-1$
375
if (s3 == null) s3 = "null"; //$NON-NLS-1$
376
int l1 = s1.length();
377         int l2 = s2.length();
378         int l3 = s3.length();
379         char[] buf = new char[l1 + l2 + l3];
380         s1.getChars(0, l1, buf, 0);
381         s2.getChars(0, l2, buf, l1);
382         s3.getChars(0, l3, buf, l1 + l2);
383         return new String JavaDoc(buf);
384     }
385         
386     /**
387      * Converts a type signature from the IBinaryType representation to the DC representation.
388      */

389     public static String JavaDoc convertTypeSignature(char[] sig, int start, int length) {
390         return new String JavaDoc(sig, start, length).replace('/', '.');
391     }
392     
393     /*
394      * Returns the default java extension (".java").
395      * To be used when the extension is not known.
396      */

397     public static String JavaDoc defaultJavaExtension() {
398         return SuffixConstants.SUFFIX_STRING_java;
399     }
400
401     /**
402      * Apply the given edit on the given string and return the updated string.
403      * Return the given string if anything wrong happen while applying the edit.
404      *
405      * @param original the given string
406      * @param edit the given edit
407      *
408      * @return the updated string
409      */

410     public final static String JavaDoc editedString(String JavaDoc original, TextEdit edit) {
411         if (edit == null) {
412             return original;
413         }
414         SimpleDocument document = new SimpleDocument(original);
415         try {
416             edit.apply(document, TextEdit.NONE);
417             return document.get();
418         } catch (MalformedTreeException e) {
419             e.printStackTrace();
420         } catch (BadLocationException e) {
421             e.printStackTrace();
422         }
423         return original;
424     }
425
426     /**
427      * Returns true iff str.toLowerCase().endsWith(end.toLowerCase())
428      * implementation is not creating extra strings.
429      */

430     public final static boolean endsWithIgnoreCase(String JavaDoc str, String JavaDoc end) {
431         
432         int strLength = str == null ? 0 : str.length();
433         int endLength = end == null ? 0 : end.length();
434         
435         // return false if the string is smaller than the end.
436
if(endLength > strLength)
437             return false;
438             
439         // return false if any character of the end are
440
// not the same in lower case.
441
for(int i = 1 ; i <= endLength; i++){
442             if(ScannerHelper.toLowerCase(end.charAt(endLength - i)) != ScannerHelper.toLowerCase(str.charAt(strLength - i)))
443                 return false;
444         }
445         
446         return true;
447     }
448
449     /**
450      * Compares two arrays using equals() on the elements.
451      * Neither can be null. Only the first len elements are compared.
452      * Return false if either array is shorter than len.
453      */

454     public static boolean equalArrays(Object JavaDoc[] a, Object JavaDoc[] b, int len) {
455         if (a == b) return true;
456         if (a.length < len || b.length < len) return false;
457         for (int i = 0; i < len; ++i) {
458             if (a[i] == null) {
459                 if (b[i] != null) return false;
460             } else {
461                 if (!a[i].equals(b[i])) return false;
462             }
463         }
464         return true;
465     }
466
467     /**
468      * Compares two arrays using equals() on the elements.
469      * Either or both arrays may be null.
470      * Returns true if both are null.
471      * Returns false if only one is null.
472      * If both are arrays, returns true iff they have the same length and
473      * all elements are equal.
474      */

475     public static boolean equalArraysOrNull(int[] a, int[] b) {
476         if (a == b)
477             return true;
478         if (a == null || b == null)
479             return false;
480         int len = a.length;
481         if (len != b.length)
482             return false;
483         for (int i = 0; i < len; ++i) {
484             if (a[i] != b[i])
485                 return false;
486         }
487         return true;
488     }
489
490     /**
491      * Compares two arrays using equals() on the elements.
492      * Either or both arrays may be null.
493      * Returns true if both are null.
494      * Returns false if only one is null.
495      * If both are arrays, returns true iff they have the same length and
496      * all elements compare true with equals.
497      */

498     public static boolean equalArraysOrNull(Object JavaDoc[] a, Object JavaDoc[] b) {
499         if (a == b) return true;
500         if (a == null || b == null) return false;
501
502         int len = a.length;
503         if (len != b.length) return false;
504         // walk array from end to beginning as this optimizes package name cases
505
// where the first part is always the same (e.g. org.eclipse.jdt)
506
for (int i = len-1; i >= 0; i--) {
507             if (a[i] == null) {
508                 if (b[i] != null) return false;
509             } else {
510                 if (!a[i].equals(b[i])) return false;
511             }
512         }
513         return true;
514     }
515     
516     /**
517      * Compares two arrays using equals() on the elements.
518      * The arrays are first sorted.
519      * Either or both arrays may be null.
520      * Returns true if both are null.
521      * Returns false if only one is null.
522      * If both are arrays, returns true iff they have the same length and
523      * iff, after sorting both arrays, all elements compare true with equals.
524      * The original arrays are left untouched.
525      */

526     public static boolean equalArraysOrNullSortFirst(Comparable JavaDoc[] a, Comparable JavaDoc[] b) {
527         if (a == b) return true;
528         if (a == null || b == null) return false;
529         int len = a.length;
530         if (len != b.length) return false;
531         if (len >= 2) { // only need to sort if more than two items
532
a = sortCopy(a);
533             b = sortCopy(b);
534         }
535         for (int i = 0; i < len; ++i) {
536             if (!a[i].equals(b[i])) return false;
537         }
538         return true;
539     }
540     
541     /**
542      * Compares two String arrays using equals() on the elements.
543      * The arrays are first sorted.
544      * Either or both arrays may be null.
545      * Returns true if both are null.
546      * Returns false if only one is null.
547      * If both are arrays, returns true iff they have the same length and
548      * iff, after sorting both arrays, all elements compare true with equals.
549      * The original arrays are left untouched.
550      */

551     public static boolean equalArraysOrNullSortFirst(String JavaDoc[] a, String JavaDoc[] b) {
552         if (a == b) return true;
553         if (a == null || b == null) return false;
554         int len = a.length;
555         if (len != b.length) return false;
556         if (len >= 2) { // only need to sort if more than two items
557
a = sortCopy(a);
558             b = sortCopy(b);
559         }
560         for (int i = 0; i < len; ++i) {
561             if (!a[i].equals(b[i])) return false;
562         }
563         return true;
564     }
565     
566     /**
567      * Compares two objects using equals().
568      * Either or both array may be null.
569      * Returns true if both are null.
570      * Returns false if only one is null.
571      * Otherwise, return the result of comparing with equals().
572      */

573     public static boolean equalOrNull(Object JavaDoc a, Object JavaDoc b) {
574         if (a == b) {
575             return true;
576         }
577         if (a == null || b == null) {
578             return false;
579         }
580         return a.equals(b);
581     }
582     
583     /*
584      * Returns whether the given file name equals to the given string ignoring the java like extension
585      * of the file name.
586      * Returns false if it is not a java like file name.
587      */

588     public static boolean equalsIgnoreJavaLikeExtension(String JavaDoc fileName, String JavaDoc string) {
589         int fileNameLength = fileName.length();
590         int stringLength = string.length();
591         if (fileNameLength < stringLength) return false;
592         for (int i = 0; i < stringLength; i ++) {
593             if (fileName.charAt(i) != string.charAt(i)) {
594                 return false;
595             }
596         }
597         char[][] javaLikeExtensions = getJavaLikeExtensions();
598         suffixes: for (int i = 0, length = javaLikeExtensions.length; i < length; i++) {
599             char[] suffix = javaLikeExtensions[i];
600             int extensionStart = stringLength+1;
601             if (extensionStart + suffix.length != fileNameLength) continue;
602             if (fileName.charAt(stringLength) != '.') continue;
603             for (int j = extensionStart; j < fileNameLength; j++) {
604                 if (fileName.charAt(j) != suffix[j-extensionStart])
605                     continue suffixes;
606             }
607             return true;
608         }
609         return false;
610     }
611     
612     /**
613      * Given a qualified name, extract the last component.
614      * If the input is not qualified, the same string is answered.
615      */

616     public static String JavaDoc extractLastName(String JavaDoc qualifiedName) {
617         int i = qualifiedName.lastIndexOf('.');
618         if (i == -1) return qualifiedName;
619         return qualifiedName.substring(i+1);
620     }
621     
622     /**
623      * Extracts the parameter types from a method signature.
624      */

625     public static String JavaDoc[] extractParameterTypes(char[] sig) {
626         int count = getParameterCount(sig);
627         String JavaDoc[] result = new String JavaDoc[count];
628         if (count == 0)
629             return result;
630         int i = CharOperation.indexOf('(', sig) + 1;
631         count = 0;
632         int len = sig.length;
633         int start = i;
634         for (;;) {
635             if (i == len)
636                 break;
637             char c = sig[i];
638             if (c == ')')
639                 break;
640             if (c == '[') {
641                 ++i;
642             } else
643                 if (c == 'L') {
644                     i = CharOperation.indexOf(';', sig, i + 1) + 1;
645                     Assert.isTrue(i != 0);
646                     result[count++] = convertTypeSignature(sig, start, i - start);
647                     start = i;
648                 } else {
649                     ++i;
650                     result[count++] = convertTypeSignature(sig, start, i - start);
651                     start = i;
652                 }
653         }
654         return result;
655     }
656
657     /**
658      * Extracts the return type from a method signature.
659      */

660     public static String JavaDoc extractReturnType(String JavaDoc sig) {
661         int i = sig.lastIndexOf(')');
662         Assert.isTrue(i != -1);
663         return sig.substring(i+1);
664     }
665     private static IFile findFirstClassFile(IFolder folder) {
666         try {
667             IResource[] members = folder.members();
668             for (int i = 0, max = members.length; i < max; i++) {
669                 IResource member = members[i];
670                 if (member.getType() == IResource.FOLDER) {
671                     return findFirstClassFile((IFolder)member);
672                 } else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(member.getName())) {
673                     return (IFile) member;
674                 }
675             }
676         } catch (CoreException e) {
677             // ignore
678
}
679         return null;
680     }
681     
682     /**
683      * Finds the first line separator used by the given text.
684      *
685      * @return </code>"\n"</code> or </code>"\r"</code> or </code>"\r\n"</code>,
686      * or <code>null</code> if none found
687      */

688     public static String JavaDoc findLineSeparator(char[] text) {
689         // find the first line separator
690
int length = text.length;
691         if (length > 0) {
692             char nextChar = text[0];
693             for (int i = 0; i < length; i++) {
694                 char currentChar = nextChar;
695                 nextChar = i < length-1 ? text[i+1] : ' ';
696                 switch (currentChar) {
697                     case '\n': return "\n"; //$NON-NLS-1$
698
case '\r': return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
699
}
700             }
701         }
702         // not found
703
return null;
704     }
705     
706     public static IClassFileAttribute getAttribute(IClassFileReader classFileReader, char[] attributeName) {
707         IClassFileAttribute[] attributes = classFileReader.getAttributes();
708         for (int i = 0, max = attributes.length; i < max; i++) {
709             if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
710                 return attributes[i];
711             }
712         }
713         return null;
714     }
715     
716     public static IClassFileAttribute getAttribute(ICodeAttribute codeAttribute, char[] attributeName) {
717         IClassFileAttribute[] attributes = codeAttribute.getAttributes();
718         for (int i = 0, max = attributes.length; i < max; i++) {
719             if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
720                 return attributes[i];
721             }
722         }
723         return null;
724     }
725     
726     public static IClassFileAttribute getAttribute(IFieldInfo fieldInfo, char[] attributeName) {
727         IClassFileAttribute[] attributes = fieldInfo.getAttributes();
728         for (int i = 0, max = attributes.length; i < max; i++) {
729             if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
730                 return attributes[i];
731             }
732         }
733         return null;
734     }
735
736     public static IClassFileAttribute getAttribute(IMethodInfo methodInfo, char[] attributeName) {
737         IClassFileAttribute[] attributes = methodInfo.getAttributes();
738         for (int i = 0, max = attributes.length; i < max; i++) {
739             if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
740                 return attributes[i];
741             }
742         }
743         return null;
744     }
745     
746     /**
747      * Returns the registered Java like extensions.
748      */

749     public static char[][] getJavaLikeExtensions() {
750         if (JAVA_LIKE_EXTENSIONS == null) {
751             // TODO (jerome) reenable once JDT UI supports other file extensions (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=71460)
752
if (!ENABLE_JAVA_LIKE_EXTENSIONS)
753                 JAVA_LIKE_EXTENSIONS = new char[][] {SuffixConstants.EXTENSION_java.toCharArray()};
754             else {
755                 IContentType javaContentType = Platform.getContentTypeManager().getContentType(JavaCore.JAVA_SOURCE_CONTENT_TYPE);
756                 HashSet fileExtensions = new HashSet();
757                 // content types derived from java content type should be included (https://bugs.eclipse.org/bugs/show_bug.cgi?id=121715)
758
IContentType[] contentTypes = Platform.getContentTypeManager().getAllContentTypes();
759                 for (int i = 0, length = contentTypes.length; i < length; i++) {
760                     if (contentTypes[i].isKindOf(javaContentType)) { // note that javaContentType.isKindOf(javaContentType) == true
761
String JavaDoc[] fileExtension = contentTypes[i].getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
762                         for (int j = 0, length2 = fileExtension.length; j < length2; j++) {
763                             fileExtensions.add(fileExtension[j]);
764                         }
765                     }
766                 }
767                 int length = fileExtensions.size();
768                 // note that file extensions contains "java" as it is defined in JDT Core's plugin.xml
769
char[][] extensions = new char[length][];
770                 extensions[0] = SuffixConstants.EXTENSION_java.toCharArray(); // ensure that "java" is first
771
int index = 1;
772                 Iterator iterator = fileExtensions.iterator();
773                 while (iterator.hasNext()) {
774                     String JavaDoc fileExtension = (String JavaDoc) iterator.next();
775                     if (SuffixConstants.EXTENSION_java.equals(fileExtension))
776                         continue;
777                     extensions[index++] = fileExtension.toCharArray();
778                 }
779                 JAVA_LIKE_EXTENSIONS = extensions;
780             }
781         }
782         return JAVA_LIKE_EXTENSIONS;
783     }
784     /**
785      * Get the jdk level of this root.
786      * The value can be:
787      * <ul>
788      * <li>major<<16 + minor : see predefined constants on ClassFileConstants </li>
789      * <li><code>0</null> if the root is a source package fragment root or if a Java model exception occured</li>
790      * </ul>
791      * Returns the jdk level
792      */

793     public static long getJdkLevel(Object JavaDoc targetLibrary) {
794         try {
795             ClassFileReader reader = null;
796             if (targetLibrary instanceof IFolder) {
797                 IFile classFile = findFirstClassFile((IFolder) targetLibrary); // only internal classfolders are allowed
798
if (classFile != null)
799                     reader = Util.newClassFileReader(classFile);
800             } else {
801                 // root is a jar file or a zip file
802
ZipFile JavaDoc jar = null;
803                 try {
804                     IPath path = null;
805                     if (targetLibrary instanceof IResource) {
806                         path = ((IResource)targetLibrary).getFullPath();
807                     } else if (targetLibrary instanceof File JavaDoc){
808                         File JavaDoc f = (File JavaDoc) targetLibrary;
809                         if (!f.isDirectory()) {
810                             path = new Path(((File JavaDoc)targetLibrary).getPath());
811                         }
812                     }
813                     if (path != null) {
814                         jar = JavaModelManager.getJavaModelManager().getZipFile(path);
815                         for (Enumeration e= jar.entries(); e.hasMoreElements();) {
816                             ZipEntry JavaDoc member= (ZipEntry JavaDoc) e.nextElement();
817                             String JavaDoc entryName= member.getName();
818                             if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
819                                 reader = ClassFileReader.read(jar, entryName);
820                                 break;
821                             }
822                         }
823                     }
824                 } catch (CoreException e) {
825                     // ignore
826
} finally {
827                     JavaModelManager.getJavaModelManager().closeZipFile(jar);
828                 }
829             }
830             if (reader != null) {
831                 return reader.getVersion();
832             }
833         } catch (CoreException e) {
834             // ignore
835
} catch(ClassFormatException e) {
836             // ignore
837
} catch(IOException e) {
838             // ignore
839
}
840         return 0;
841     }
842     
843     /**
844      * Returns the substring of the given file name, ending at the start of a
845      * Java like extension. The entire file name is returned if it doesn't end
846      * with a Java like extension.
847      */

848     public static String JavaDoc getNameWithoutJavaLikeExtension(String JavaDoc fileName) {
849         int index = indexOfJavaLikeExtension(fileName);
850         if (index == -1)
851             return fileName;
852         return fileName.substring(0, index);
853     }
854     
855     /**
856      * Returns the line separator found in the given text.
857      * If it is null, or not found return the line delimitor for the given project.
858      * If the project is null, returns the line separator for the workspace.
859      * If still null, return the system line separator.
860      */

861     public static String JavaDoc getLineSeparator(String JavaDoc text, IJavaProject project) {
862         String JavaDoc lineSeparator = null;
863         
864         // line delimiter in given text
865
if (text != null && text.length() != 0) {
866             lineSeparator = findLineSeparator(text.toCharArray());
867             if (lineSeparator != null)
868                 return lineSeparator;
869         }
870         
871         // line delimiter in project preference
872
IScopeContext[] scopeContext;
873         if (project != null) {
874             scopeContext= new IScopeContext[] { new ProjectScope(project.getProject()) };
875             lineSeparator= Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
876             if (lineSeparator != null)
877                 return lineSeparator;
878         }
879         
880         // line delimiter in workspace preference
881
scopeContext= new IScopeContext[] { new InstanceScope() };
882         lineSeparator = Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
883         if (lineSeparator != null)
884             return lineSeparator;
885         
886         // system line delimiter
887
return org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR;
888     }
889     
890     /**
891      * Returns the line separator used by the given buffer.
892      * Uses the given text if none found.
893      *
894      * @return </code>"\n"</code> or </code>"\r"</code> or </code>"\r\n"</code>
895      */

896     private static String JavaDoc getLineSeparator(char[] text, char[] buffer) {
897         // search in this buffer's contents first
898
String JavaDoc lineSeparator = findLineSeparator(buffer);
899         if (lineSeparator == null) {
900             // search in the given text
901
lineSeparator = findLineSeparator(text);
902             if (lineSeparator == null) {
903                 // default to system line separator
904
return getLineSeparator((String JavaDoc) null, (IJavaProject) null);
905             }
906         }
907         return lineSeparator;
908     }
909         
910     /**
911      * Returns the number of parameter types in a method signature.
912      */

913     public static int getParameterCount(char[] sig) {
914         int i = CharOperation.indexOf('(', sig) + 1;
915         Assert.isTrue(i != 0);
916         int count = 0;
917         int len = sig.length;
918         for (;;) {
919             if (i == len)
920                 break;
921             char c = sig[i];
922             if (c == ')')
923                 break;
924             if (c == '[') {
925                 ++i;
926             } else
927                 if (c == 'L') {
928                     ++count;
929                     i = CharOperation.indexOf(';', sig, i + 1) + 1;
930                     Assert.isTrue(i != 0);
931                 } else {
932                     ++count;
933                     ++i;
934                 }
935         }
936         return count;
937     }
938     
939     /**
940      * Put all the arguments in one String.
941      */

942     public static String JavaDoc getProblemArgumentsForMarker(String JavaDoc[] arguments){
943         StringBuffer JavaDoc args = new StringBuffer JavaDoc(10);
944         
945         args.append(arguments.length);
946         args.append(':');
947         
948             
949         for (int j = 0; j < arguments.length; j++) {
950             if(j != 0)
951                 args.append(ARGUMENTS_DELIMITER);
952             
953             if(arguments[j].length() == 0) {
954                 args.append(EMPTY_ARGUMENT);
955             } else {
956                 args.append(arguments[j]);
957             }
958         }
959         
960         return args.toString();
961     }
962     
963     /**
964      * Separate all the arguments of a String made by getProblemArgumentsForMarker
965      */

966     public static String JavaDoc[] getProblemArgumentsFromMarker(String JavaDoc argumentsString){
967         if (argumentsString == null) return null;
968         int index = argumentsString.indexOf(':');
969         if(index == -1)
970             return null;
971         
972         int length = argumentsString.length();
973         int numberOfArg;
974         try{
975             numberOfArg = Integer.parseInt(argumentsString.substring(0 , index));
976         } catch (NumberFormatException JavaDoc e) {
977             return null;
978         }
979         argumentsString = argumentsString.substring(index + 1, length);
980         
981         String JavaDoc[] args = new String JavaDoc[length];
982         int count = 0;
983         
984         StringTokenizer tokenizer = new StringTokenizer(argumentsString, ARGUMENTS_DELIMITER);
985         while(tokenizer.hasMoreTokens()) {
986             String JavaDoc argument = tokenizer.nextToken();
987             if(argument.equals(EMPTY_ARGUMENT))
988                 argument = ""; //$NON-NLS-1$
989
args[count++] = argument;
990         }
991         
992         if(count != numberOfArg)
993             return null;
994         
995         System.arraycopy(args, 0, args = new String JavaDoc[count], 0, count);
996         return args;
997     }
998     
999     /**
1000     * Returns the given file's contents as a byte array.
1001     */

1002    public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException {
1003        InputStream stream= null;
1004        try {
1005            stream = file.getContents(true);
1006        } catch (CoreException e) {
1007            throw new JavaModelException(e);
1008        }
1009        try {
1010            return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1);
1011        } catch (IOException e) {
1012            throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
1013        } finally {
1014            try {
1015                stream.close();
1016            } catch (IOException e) {
1017                // ignore
1018
}
1019        }
1020    }
1021    
1022    /**
1023     * Returns the given file's contents as a character array.
1024     */

1025    public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException {
1026        // Get encoding from file
1027
String JavaDoc encoding;
1028        try {
1029            encoding = file.getCharset();
1030        } catch(CoreException ce) {
1031            // do not use any encoding
1032
encoding = null;
1033        }
1034        return getResourceContentsAsCharArray(file, encoding);
1035    }
1036        
1037    public static char[] getResourceContentsAsCharArray(IFile file, String JavaDoc encoding) throws JavaModelException {
1038        // Get file length
1039
// workaround https://bugs.eclipse.org/bugs/show_bug.cgi?id=130736 by using java.io.File if possible
1040
IPath location = file.getLocation();
1041        long length;
1042        if (location == null) {
1043            // non local file
1044
try {
1045                length = EFS.getStore(file.getLocationURI()).fetchInfo().getLength();
1046            } catch (CoreException e) {
1047                throw new JavaModelException(e);
1048            }
1049        } else {
1050            // local file
1051
length = location.toFile().length();
1052        }
1053        
1054        // Get resource contents
1055
InputStream stream= null;
1056        try {
1057            stream = file.getContents(true);
1058        } catch (CoreException e) {
1059            throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST);
1060        }
1061        try {
1062            return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, (int) length, encoding);
1063        } catch (IOException e) {
1064            throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
1065        } finally {
1066            try {
1067                stream.close();
1068            } catch (IOException e) {
1069                // ignore
1070
}
1071        }
1072    }
1073    
1074    /*
1075     * Returns the signature of the given type.
1076     */

1077    public static String JavaDoc getSignature(Type type) {
1078        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1079        getFullyQualifiedName(type, buffer);
1080        return Signature.createTypeSignature(buffer.toString(), false/*not resolved in source*/);
1081    }
1082    
1083    /*
1084     * Returns the source attachment property for this package fragment root's path
1085     */

1086    public static String JavaDoc getSourceAttachmentProperty(IPath path) throws JavaModelException {
1087        Map rootPathToAttachments = JavaModelManager.getJavaModelManager().rootPathToAttachments;
1088        String JavaDoc property = (String JavaDoc) rootPathToAttachments.get(path);
1089        if (property == null) {
1090            try {
1091                property = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(getSourceAttachmentPropertyName(path));
1092                if (property == null) {
1093                    rootPathToAttachments.put(path, PackageFragmentRoot.NO_SOURCE_ATTACHMENT);
1094                    return null;
1095                }
1096                rootPathToAttachments.put(path, property);
1097                return property;
1098            } catch (CoreException e) {
1099                throw new JavaModelException(e);
1100            }
1101        } else if (property.equals(PackageFragmentRoot.NO_SOURCE_ATTACHMENT)) {
1102            return null;
1103        } else
1104            return property;
1105    }
1106    
1107    private static QualifiedName getSourceAttachmentPropertyName(IPath path) {
1108        return new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + path.toOSString()); //$NON-NLS-1$
1109
}
1110
1111    public static void setSourceAttachmentProperty(IPath path, String JavaDoc property) {
1112        JavaModelManager.getJavaModelManager().rootPathToAttachments.put(path, property);
1113        try {
1114            ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(getSourceAttachmentPropertyName(path), property);
1115        } catch (CoreException e) {
1116            e.printStackTrace();
1117        }
1118    }
1119    
1120    /*
1121     * Returns the declaring type signature of the element represented by the given binding key.
1122     * Returns the signature of the element if it is a type.
1123     *
1124     * @return the declaring type signature
1125     */

1126    public static String JavaDoc getDeclaringTypeSignature(String JavaDoc key) {
1127        KeyToSignature keyToSignature = new KeyToSignature(key, KeyToSignature.DECLARING_TYPE);
1128        keyToSignature.parse();
1129        return keyToSignature.signature.toString();
1130    }
1131    
1132    /*
1133     * Appends to the given buffer the fully qualified name (as it appears in the source) of the given type
1134     */

1135    private static void getFullyQualifiedName(Type type, StringBuffer JavaDoc buffer) {
1136        switch (type.getNodeType()) {
1137            case ASTNode.ARRAY_TYPE:
1138                ArrayType arrayType = (ArrayType) type;
1139                getFullyQualifiedName(arrayType.getElementType(), buffer);
1140                for (int i = 0, length = arrayType.getDimensions(); i < length; i++) {
1141                    buffer.append('[');
1142                    buffer.append(']');
1143                }
1144                break;
1145            case ASTNode.PARAMETERIZED_TYPE:
1146                ParameterizedType parameterizedType = (ParameterizedType) type;
1147                getFullyQualifiedName(parameterizedType.getType(), buffer);
1148                buffer.append('<');
1149                Iterator iterator = parameterizedType.typeArguments().iterator();
1150                boolean isFirst = true;
1151                while (iterator.hasNext()) {
1152                    if (!isFirst)
1153                        buffer.append(',');
1154                    else
1155                        isFirst = false;
1156                    Type typeArgument = (Type) iterator.next();
1157                    getFullyQualifiedName(typeArgument, buffer);
1158                }
1159                buffer.append('>');
1160                break;
1161            case ASTNode.PRIMITIVE_TYPE:
1162                buffer.append(((PrimitiveType) type).getPrimitiveTypeCode().toString());
1163                break;
1164            case ASTNode.QUALIFIED_TYPE:
1165                buffer.append(((QualifiedType) type).getName().getFullyQualifiedName());
1166                break;
1167            case ASTNode.SIMPLE_TYPE:
1168                buffer.append(((SimpleType) type).getName().getFullyQualifiedName());
1169                break;
1170            case ASTNode.WILDCARD_TYPE:
1171                buffer.append('?');
1172                WildcardType wildcardType = (WildcardType) type;
1173                Type bound = wildcardType.getBound();
1174                if (bound == null) return;
1175                if (wildcardType.isUpperBound()) {
1176                    buffer.append(" extends "); //$NON-NLS-1$
1177
} else {
1178                    buffer.append(" super "); //$NON-NLS-1$
1179
}
1180                getFullyQualifiedName(bound, buffer);
1181                break;
1182        }
1183    }
1184
1185    /**
1186     * Returns a trimmed version the simples names returned by Signature.
1187     */

1188    public static String JavaDoc[] getTrimmedSimpleNames(String JavaDoc name) {
1189        String JavaDoc[] result = Signature.getSimpleNames(name);
1190        for (int i = 0, length = result.length; i < length; i++) {
1191            result[i] = result[i].trim();
1192        }
1193        return result;
1194    }
1195    
1196        /*
1197     * Returns the index of the most specific argument paths which is strictly enclosing the path to check
1198     */

1199    public static int indexOfEnclosingPath(IPath checkedPath, IPath[] paths, int pathCount) {
1200
1201        int bestMatch = -1, bestLength = -1;
1202        for (int i = 0; i < pathCount; i++){
1203            if (paths[i].equals(checkedPath)) continue;
1204            if (paths[i].isPrefixOf(checkedPath)) {
1205                int currentLength = paths[i].segmentCount();
1206                if (currentLength > bestLength) {
1207                    bestLength = currentLength;
1208                    bestMatch = i;
1209                }
1210            }
1211        }
1212        return bestMatch;
1213    }
1214    
1215    /*
1216     * Returns the index of the Java like extension of the given file name
1217     * or -1 if it doesn't end with a known Java like extension.
1218     * Note this is the index of the '.' even if it is not considered part of the extension.
1219     */

1220    public static int indexOfJavaLikeExtension(String JavaDoc fileName) {
1221        int fileNameLength = fileName.length();
1222        char[][] javaLikeExtensions = getJavaLikeExtensions();
1223        extensions: for (int i = 0, length = javaLikeExtensions.length; i < length; i++) {
1224            char[] extension = javaLikeExtensions[i];
1225            int extensionLength = extension.length;
1226            int extensionStart = fileNameLength - extensionLength;
1227            int dotIndex = extensionStart - 1;
1228            if (dotIndex < 0) continue;
1229            if (fileName.charAt(dotIndex) != '.') continue;
1230            for (int j = 0; j < extensionLength; j++) {
1231                if (fileName.charAt(extensionStart + j) != extension[j])
1232                    continue extensions;
1233            }
1234            return dotIndex;
1235        }
1236        return -1;
1237    }
1238    
1239    /*
1240     * Returns the index of the first argument paths which is equal to the path to check
1241     */

1242    public static int indexOfMatchingPath(IPath checkedPath, IPath[] paths, int pathCount) {
1243
1244        for (int i = 0; i < pathCount; i++){
1245            if (paths[i].equals(checkedPath)) return i;
1246        }
1247        return -1;
1248    }
1249
1250    /*
1251     * Returns the index of the first argument paths which is strictly nested inside the path to check
1252     */

1253    public static int indexOfNestedPath(IPath checkedPath, IPath[] paths, int pathCount) {
1254
1255        for (int i = 0; i < pathCount; i++){
1256            if (checkedPath.equals(paths[i])) continue;
1257            if (checkedPath.isPrefixOf(paths[i])) return i;
1258        }
1259        return -1;
1260    }
1261    /**
1262     * Returns whether the local file system supports accessing and modifying
1263     * the given attribute.
1264     */

1265    protected static boolean isAttributeSupported(int attribute) {
1266        return (EFS.getLocalFileSystem().attributes() & attribute) != 0;
1267    }
1268    
1269    /**
1270     * Returns whether the given resource is read-only or not.
1271     * @param resource
1272     * @return <code>true</code> if the resource is read-only, <code>false</code> if it is not or
1273     * if the file system does not support the read-only attribute.
1274     */

1275    public static boolean isReadOnly(IResource resource) {
1276        if (isReadOnlySupported()) {
1277            ResourceAttributes resourceAttributes = resource.getResourceAttributes();
1278            if (resourceAttributes == null) return false; // not supported on this platform for this resource
1279
return resourceAttributes.isReadOnly();
1280        }
1281        return false;
1282    }
1283
1284    /**
1285     * Returns whether the local file system supports accessing and modifying
1286     * the read only flag.
1287     */

1288    public static boolean isReadOnlySupported() {
1289        return isAttributeSupported(EFS.ATTRIBUTE_READ_ONLY);
1290    }
1291
1292    /*
1293     * Returns whether the given java element is exluded from its root's classpath.
1294     * It doesn't check whether the root itself is on the classpath or not
1295     */

1296    public static final boolean isExcluded(IJavaElement element) {
1297        int elementType = element.getElementType();
1298        switch (elementType) {
1299            case IJavaElement.JAVA_MODEL:
1300            case IJavaElement.JAVA_PROJECT:
1301            case IJavaElement.PACKAGE_FRAGMENT_ROOT:
1302                return false;
1303
1304            case IJavaElement.PACKAGE_FRAGMENT:
1305                PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
1306                IResource resource = element.getResource();
1307                return resource != null && isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars());
1308                
1309            case IJavaElement.COMPILATION_UNIT:
1310                root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
1311                resource = element.getResource();
1312                if (resource == null)
1313                    return false;
1314                if (isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars()))
1315                    return true;
1316                return isExcluded(element.getParent());
1317                
1318            default:
1319                IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
1320                return cu != null && isExcluded(cu);
1321        }
1322    }
1323    /*
1324     * Returns whether the given resource path matches one of the inclusion/exclusion
1325     * patterns.
1326     * NOTE: should not be asked directly using pkg root pathes
1327     * @see IClasspathEntry#getInclusionPatterns
1328     * @see IClasspathEntry#getExclusionPatterns
1329     */

1330    public final static boolean isExcluded(IPath resourcePath, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean isFolderPath) {
1331        if (inclusionPatterns == null && exclusionPatterns == null) return false;
1332        return org.eclipse.jdt.internal.compiler.util.Util.isExcluded(resourcePath.toString().toCharArray(), inclusionPatterns, exclusionPatterns, isFolderPath);
1333    }
1334
1335    /*
1336     * Returns whether the given resource matches one of the exclusion patterns.
1337     * NOTE: should not be asked directly using pkg root pathes
1338     * @see IClasspathEntry#getExclusionPatterns
1339     */

1340    public final static boolean isExcluded(IResource resource, char[][] inclusionPatterns, char[][] exclusionPatterns) {
1341        IPath path = resource.getFullPath();
1342        // ensure that folders are only excluded if all of their children are excluded
1343
int resourceType = resource.getType();
1344        return isExcluded(path, inclusionPatterns, exclusionPatterns, resourceType == IResource.FOLDER || resourceType == IResource.PROJECT);
1345    }
1346
1347
1348    /**
1349     * Validate the given .class file name.
1350     * A .class file name must obey the following rules:
1351     * <ul>
1352     * <li> it must not be null
1353     * <li> it must include the <code>".class"</code> suffix
1354     * <li> its prefix must be a valid identifier
1355     * </ul>
1356     * </p>
1357     * @param name the name of a .class file
1358     * @param sourceLevel the source level
1359     * @param complianceLevel the compliance level
1360     * @return a status object with code <code>IStatus.OK</code> if
1361     * the given name is valid as a .class file name, otherwise a status
1362     * object indicating what is wrong with the name
1363     */

1364    public static boolean isValidClassFileName(String JavaDoc name, String JavaDoc sourceLevel, String JavaDoc complianceLevel) {
1365        return JavaConventions.validateClassFileName(name, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
1366    }
1367
1368
1369    /**
1370     * Validate the given compilation unit name.
1371     * A compilation unit name must obey the following rules:
1372     * <ul>
1373     * <li> it must not be null
1374     * <li> it must include the <code>".java"</code> suffix
1375     * <li> its prefix must be a valid identifier
1376     * </ul>
1377     * </p>
1378     * @param name the name of a compilation unit
1379     * @param sourceLevel the source level
1380     * @param complianceLevel the compliance level
1381     * @return a status object with code <code>IStatus.OK</code> if
1382     * the given name is valid as a compilation unit name, otherwise a status
1383     * object indicating what is wrong with the name
1384     */

1385    public static boolean isValidCompilationUnitName(String JavaDoc name, String JavaDoc sourceLevel, String JavaDoc complianceLevel) {
1386        return JavaConventions.validateCompilationUnitName(name, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
1387    }
1388
1389    /**
1390     * Returns true if the given folder name is valid for a package,
1391     * false if it is not.
1392     * @param folderName the name of the folder
1393     * @param sourceLevel the source level
1394     * @param complianceLevel the compliance level
1395     */

1396    public static boolean isValidFolderNameForPackage(String JavaDoc folderName, String JavaDoc sourceLevel, String JavaDoc complianceLevel) {
1397        return JavaConventions.validateIdentifier(folderName, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
1398    }
1399
1400    /**
1401     * Returns true if the given method signature is valid,
1402     * false if it is not.
1403     */

1404    public static boolean isValidMethodSignature(String JavaDoc sig) {
1405        int len = sig.length();
1406        if (len == 0) return false;
1407        int i = 0;
1408        char c = sig.charAt(i++);
1409        if (c != '(') return false;
1410        if (i >= len) return false;
1411        while (sig.charAt(i) != ')') {
1412            // Void is not allowed as a parameter type.
1413
i = checkTypeSignature(sig, i, len, false);
1414            if (i == -1) return false;
1415            if (i >= len) return false;
1416        }
1417        ++i;
1418        i = checkTypeSignature(sig, i, len, true);
1419        return i == len;
1420    }
1421    
1422    /**
1423     * Returns true if the given type signature is valid,
1424     * false if it is not.
1425     */

1426    public static boolean isValidTypeSignature(String JavaDoc sig, boolean allowVoid) {
1427        int len = sig.length();
1428        return checkTypeSignature(sig, 0, len, allowVoid) == len;
1429    }
1430    
1431    /*
1432     * Returns the simple name of a local type from the given binary type name.
1433     * The last '$' is at lastDollar. The last character of the type name is at end-1.
1434     */

1435    public static String JavaDoc localTypeName(String JavaDoc binaryTypeName, int lastDollar, int end) {
1436        if (lastDollar > 0 && binaryTypeName.charAt(lastDollar-1) == '$')
1437            // local name starts with a dollar sign
1438
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=103466)
1439
return binaryTypeName;
1440        int nameStart = lastDollar+1;
1441        while (nameStart < end && Character.isDigit(binaryTypeName.charAt(nameStart)))
1442            nameStart++;
1443        return binaryTypeName.substring(nameStart, end);
1444    }
1445
1446    /*
1447     * Add a log entry
1448     */

1449    public static void log(Throwable JavaDoc e, String JavaDoc message) {
1450        Throwable JavaDoc nestedException;
1451        if (e instanceof JavaModelException
1452                && (nestedException = ((JavaModelException)e).getException()) != null) {
1453            e = nestedException;
1454        }
1455        IStatus status= new Status(
1456            IStatus.ERROR,
1457            JavaCore.PLUGIN_ID,
1458            IStatus.ERROR,
1459            message,
1460            e);
1461        JavaCore.getPlugin().getLog().log(status);
1462    }
1463    
1464    public static ClassFileReader newClassFileReader(IResource resource) throws CoreException, ClassFormatException, IOException {
1465        InputStream in = null;
1466        try {
1467            in = ((IFile) resource).getContents(true);
1468            return ClassFileReader.read(in, resource.getFullPath().toString());
1469        } finally {
1470            if (in != null)
1471                in.close();
1472        }
1473    }
1474
1475    /**
1476     * Normalizes the cariage returns in the given text.
1477     * They are all changed to use the given buffer's line separator.
1478     */

1479    public static char[] normalizeCRs(char[] text, char[] buffer) {
1480        CharArrayBuffer result = new CharArrayBuffer();
1481        int lineStart = 0;
1482        int length = text.length;
1483        if (length == 0) return text;
1484        String JavaDoc lineSeparator = getLineSeparator(text, buffer);
1485        char nextChar = text[0];
1486        for (int i = 0; i < length; i++) {
1487            char currentChar = nextChar;
1488            nextChar = i < length-1 ? text[i+1] : ' ';
1489            switch (currentChar) {
1490                case '\n':
1491                    int lineLength = i-lineStart;
1492                    char[] line = new char[lineLength];
1493                    System.arraycopy(text, lineStart, line, 0, lineLength);
1494                    result.append(line);
1495                    result.append(lineSeparator);
1496                    lineStart = i+1;
1497                    break;
1498                case '\r':
1499                    lineLength = i-lineStart;
1500                    if (lineLength >= 0) {
1501                        line = new char[lineLength];
1502                        System.arraycopy(text, lineStart, line, 0, lineLength);
1503                        result.append(line);
1504                        result.append(lineSeparator);
1505                        if (nextChar == '\n') {
1506                            nextChar = ' ';
1507                            lineStart = i+2;
1508                        } else {
1509                            // when line separator are mixed in the same file
1510
// \r might not be followed by a \n. If not, we should increment
1511
// lineStart by one and not by two.
1512
lineStart = i+1;
1513                        }
1514                    } else {
1515                        // when line separator are mixed in the same file
1516
// we need to prevent NegativeArraySizeException
1517
lineStart = i+1;
1518                    }
1519                    break;
1520            }
1521        }
1522        char[] lastLine;
1523        if (lineStart > 0) {
1524            int lastLineLength = length-lineStart;
1525            if (lastLineLength > 0) {
1526                lastLine = new char[lastLineLength];
1527                System.arraycopy(text, lineStart, lastLine, 0, lastLineLength);
1528                result.append(lastLine);
1529            }
1530            return result.getContents();
1531        }
1532        return text;
1533    }
1534
1535    /**
1536     * Normalizes the cariage returns in the given text.
1537     * They are all changed to use given buffer's line sepatator.
1538     */

1539    public static String JavaDoc normalizeCRs(String JavaDoc text, String JavaDoc buffer) {
1540        return new String JavaDoc(normalizeCRs(text.toCharArray(), buffer.toCharArray()));
1541    }
1542
1543    /**
1544     * Converts the given relative path into a package name.
1545     * Returns null if the path is not a valid package name.
1546     * @param pkgPath the package path
1547     * @param sourceLevel the source level
1548     * @param complianceLevel the compliance level
1549     */

1550    public static String JavaDoc packageName(IPath pkgPath, String JavaDoc sourceLevel, String JavaDoc complianceLevel) {
1551        StringBuffer JavaDoc pkgName = new StringBuffer JavaDoc(IPackageFragment.DEFAULT_PACKAGE_NAME);
1552        for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
1553            String JavaDoc segment = pkgPath.segment(j);
1554            if (!isValidFolderNameForPackage(segment, sourceLevel, complianceLevel)) {
1555                return null;
1556            }
1557            pkgName.append(segment);
1558            if (j < pkgPath.segmentCount() - 1) {
1559                pkgName.append("." ); //$NON-NLS-1$
1560
}
1561        }
1562        return pkgName.toString();
1563    }
1564
1565    /**
1566     * Returns the length of the common prefix between s1 and s2.
1567     */

1568    public static int prefixLength(char[] s1, char[] s2) {
1569        int len= 0;
1570        int max= Math.min(s1.length, s2.length);
1571        for (int i= 0; i < max && s1[i] == s2[i]; ++i)
1572            ++len;
1573        return len;
1574    }
1575    /**
1576     * Returns the length of the common prefix between s1 and s2.
1577     */

1578    public static int prefixLength(String JavaDoc s1, String JavaDoc s2) {
1579        int len= 0;
1580        int max= Math.min(s1.length(), s2.length());
1581        for (int i= 0; i < max && s1.charAt(i) == s2.charAt(i); ++i)
1582            ++len;
1583        return len;
1584    }
1585    private static void quickSort(char[][] list, int left, int right) {
1586        int original_left= left;
1587        int original_right= right;
1588        char[] mid= list[left + (right - left) / 2];
1589        do {
1590            while (compare(list[left], mid) < 0) {
1591                left++;
1592            }
1593            while (compare(mid, list[right]) < 0) {
1594                right--;
1595            }
1596            if (left <= right) {
1597                char[] tmp= list[left];
1598                list[left]= list[right];
1599                list[right]= tmp;
1600                left++;
1601                right--;
1602            }
1603        } while (left <= right);
1604        if (original_left < right) {
1605            quickSort(list, original_left, right);
1606        }
1607        if (left < original_right) {
1608            quickSort(list, left, original_right);
1609        }
1610    }
1611
1612    /**
1613     * Sort the comparable objects in the given collection.
1614     */

1615    private static void quickSort(Comparable JavaDoc[] sortedCollection, int left, int right) {
1616        int original_left = left;
1617        int original_right = right;
1618        Comparable JavaDoc mid = sortedCollection[ left + (right - left) / 2];
1619        do {
1620            while (sortedCollection[left].compareTo(mid) < 0) {
1621                left++;
1622            }
1623            while (mid.compareTo(sortedCollection[right]) < 0) {
1624                right--;
1625            }
1626            if (left <= right) {
1627                Comparable JavaDoc tmp = sortedCollection[left];
1628                sortedCollection[left] = sortedCollection[right];
1629                sortedCollection[right] = tmp;
1630                left++;
1631                right--;
1632            }
1633        } while (left <= right);
1634        if (original_left < right) {
1635            quickSort(sortedCollection, original_left, right);
1636        }
1637        if (left < original_right) {
1638            quickSort(sortedCollection, left, original_right);
1639        }
1640    }
1641    private static void quickSort(int[] list, int left, int right) {
1642        int original_left= left;
1643        int original_right= right;
1644        int mid= list[left + (right - left) / 2];
1645        do {
1646            while (list[left] < mid) {
1647                left++;
1648            }
1649            while (mid < list[right]) {
1650                right--;
1651            }
1652            if (left <= right) {
1653                int tmp= list[left];
1654                list[left]= list[right];
1655                list[right]= tmp;
1656                left++;
1657                right--;
1658            }
1659        } while (left <= right);
1660        if (original_left < right) {
1661            quickSort(list, original_left, right);
1662        }
1663        if (left < original_right) {
1664            quickSort(list, left, original_right);
1665        }
1666    }
1667
1668    /**
1669     * Sort the objects in the given collection using the given comparer.
1670     */

1671    private static void quickSort(Object JavaDoc[] sortedCollection, int left, int right, Comparer comparer) {
1672        int original_left = left;
1673        int original_right = right;
1674        Object JavaDoc mid = sortedCollection[ left + (right - left) / 2];
1675        do {
1676            while (comparer.compare(sortedCollection[left], mid) < 0) {
1677                left++;
1678            }
1679            while (comparer.compare(mid, sortedCollection[right]) < 0) {
1680                right--;
1681            }
1682            if (left <= right) {
1683                Object JavaDoc tmp = sortedCollection[left];
1684                sortedCollection[left] = sortedCollection[right];
1685                sortedCollection[right] = tmp;
1686                left++;
1687                right--;
1688            }
1689        } while (left <= right);
1690        if (original_left < right) {
1691            quickSort(sortedCollection, original_left, right, comparer);
1692        }
1693        if (left < original_right) {
1694            quickSort(sortedCollection, left, original_right, comparer);
1695        }
1696    }
1697
1698    /**
1699     * Sort the strings in the given collection.
1700     */

1701    private static void quickSort(String JavaDoc[] sortedCollection, int left, int right) {
1702        int original_left = left;
1703        int original_right = right;
1704        String JavaDoc mid = sortedCollection[ left + (right - left) / 2];
1705        do {
1706            while (sortedCollection[left].compareTo(mid) < 0) {
1707                left++;
1708            }
1709            while (mid.compareTo(sortedCollection[right]) < 0) {
1710                right--;
1711            }
1712            if (left <= right) {
1713                String JavaDoc tmp = sortedCollection[left];
1714                sortedCollection[left] = sortedCollection[right];
1715                sortedCollection[right] = tmp;
1716                left++;
1717                right--;
1718            }
1719        } while (left <= right);
1720        if (original_left < right) {
1721            quickSort(sortedCollection, original_left, right);
1722        }
1723        if (left < original_right) {
1724            quickSort(sortedCollection, left, original_right);
1725        }
1726    }
1727
1728    /**
1729     * Returns the toString() of the given full path minus the first given number of segments.
1730     * The returned string is always a relative path (it has no leading slash)
1731     */

1732    public static String JavaDoc relativePath(IPath fullPath, int skipSegmentCount) {
1733        boolean hasTrailingSeparator = fullPath.hasTrailingSeparator();
1734        String JavaDoc[] segments = fullPath.segments();
1735        
1736        // compute length
1737
int length = 0;
1738        int max = segments.length;
1739        if (max > skipSegmentCount) {
1740            for (int i1 = skipSegmentCount; i1 < max; i1++) {
1741                length += segments[i1].length();
1742            }
1743            //add the separator lengths
1744
length += max - skipSegmentCount - 1;
1745        }
1746        if (hasTrailingSeparator)
1747            length++;
1748
1749        char[] result = new char[length];
1750        int offset = 0;
1751        int len = segments.length - 1;
1752        if (len >= skipSegmentCount) {
1753            //append all but the last segment, with separators
1754
for (int i = skipSegmentCount; i < len; i++) {
1755                int size = segments[i].length();
1756                segments[i].getChars(0, size, result, offset);
1757                offset += size;
1758                result[offset++] = '/';
1759            }
1760            //append the last segment
1761
int size = segments[len].length();
1762            segments[len].getChars(0, size, result, offset);
1763            offset += size;
1764        }
1765        if (hasTrailingSeparator)
1766            result[offset++] = '/';
1767        return new String JavaDoc(result);
1768    }
1769    
1770    /*
1771     * Resets the list of Java-like extensions after a change in content-type.
1772     */

1773    public static void resetJavaLikeExtensions() {
1774        JAVA_LIKE_EXTENSIONS = null;
1775    }
1776    
1777    /**
1778     * Return a new array which is the split of the given string using the given divider. The given end
1779     * is exclusive and the given start is inclusive.
1780     * <br>
1781     * <br>
1782     * For example:
1783     * <ol>
1784     * <li><pre>
1785     * divider = 'b'
1786     * string = "abbaba"
1787     * start = 2
1788     * end = 5
1789     * result => { "", "a", "" }
1790     * </pre>
1791     * </li>
1792     * </ol>
1793     *
1794     * @param divider the given divider
1795     * @param string the given string
1796     * @param start the given starting index
1797     * @param end the given ending index
1798     * @return a new array which is the split of the given string using the given divider
1799     * @throws ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
1800     */

1801    public static final String JavaDoc[] splitOn(
1802        char divider,
1803        String JavaDoc string,
1804        int start,
1805        int end) {
1806        int length = string == null ? 0 : string.length();
1807        if (length == 0 || start > end)
1808            return CharOperation.NO_STRINGS;
1809
1810        int wordCount = 1;
1811        for (int i = start; i < end; i++)
1812            if (string.charAt(i) == divider)
1813                wordCount++;
1814        String JavaDoc[] split = new String JavaDoc[wordCount];
1815        int last = start, currentWord = 0;
1816        for (int i = start; i < end; i++) {
1817            if (string.charAt(i) == divider) {
1818                split[currentWord++] = string.substring(last, i);
1819                last = i + 1;
1820            }
1821        }
1822        split[currentWord] = string.substring(last, end);
1823        return split;
1824    }
1825    /**
1826     * Sets or unsets the given resource as read-only in the file system.
1827     * It's a no-op if the file system does not support the read-only attribute.
1828     *
1829     * @param resource The resource to set as read-only
1830     * @param readOnly <code>true</code> to set it to read-only,
1831     * <code>false</code> to unset
1832     */

1833    public static void setReadOnly(IResource resource, boolean readOnly) {
1834        if (isReadOnlySupported()) {
1835            ResourceAttributes resourceAttributes = resource.getResourceAttributes();
1836            if (resourceAttributes == null) return; // not supported on this platform for this resource
1837
resourceAttributes.setReadOnly(readOnly);
1838            try {
1839                resource.setResourceAttributes(resourceAttributes);
1840            } catch (CoreException e) {
1841                // ignore
1842
}
1843        }
1844    }
1845    public static void sort(char[][] list) {
1846        if (list.length > 1)
1847            quickSort(list, 0, list.length - 1);
1848    }
1849
1850    /**
1851     * Sorts an array of Comparable objects in place.
1852     */

1853    public static void sort(Comparable JavaDoc[] objects) {
1854        if (objects.length > 1)
1855            quickSort(objects, 0, objects.length - 1);
1856    }
1857    public static void sort(int[] list) {
1858        if (list.length > 1)
1859            quickSort(list, 0, list.length - 1);
1860    }
1861
1862    /**
1863     * Sorts an array of objects in place.
1864     * The given comparer compares pairs of items.
1865     */

1866    public static void sort(Object JavaDoc[] objects, Comparer comparer) {
1867        if (objects.length > 1)
1868            quickSort(objects, 0, objects.length - 1, comparer);
1869    }
1870
1871    /**
1872     * Sorts an array of strings in place using quicksort.
1873     */

1874    public static void sort(String JavaDoc[] strings) {
1875        if (strings.length > 1)
1876            quickSort(strings, 0, strings.length - 1);
1877    }
1878
1879    /**
1880     * Sorts an array of Comparable objects, returning a new array
1881     * with the sorted items. The original array is left untouched.
1882     */

1883    public static Comparable JavaDoc[] sortCopy(Comparable JavaDoc[] objects) {
1884        int len = objects.length;
1885        Comparable JavaDoc[] copy = new Comparable JavaDoc[len];
1886        System.arraycopy(objects, 0, copy, 0, len);
1887        sort(copy);
1888        return copy;
1889    }
1890
1891    /**
1892     * Sorts an array of Java elements based on their toStringWithAncestors(),
1893     * returning a new array with the sorted items.
1894     * The original array is left untouched.
1895     */

1896    public static IJavaElement[] sortCopy(IJavaElement[] elements) {
1897        int len = elements.length;
1898        IJavaElement[] copy = new IJavaElement[len];
1899        System.arraycopy(elements, 0, copy, 0, len);
1900        sort(copy, new Comparer() {
1901            public int compare(Object JavaDoc a, Object JavaDoc b) {
1902                return ((JavaElement) a).toStringWithAncestors().compareTo(((JavaElement) b).toStringWithAncestors());
1903            }
1904        });
1905        return copy;
1906    }
1907    
1908    /**
1909     * Sorts an array of Strings, returning a new array
1910     * with the sorted items. The original array is left untouched.
1911     */

1912    public static Object JavaDoc[] sortCopy(Object JavaDoc[] objects, Comparer comparer) {
1913        int len = objects.length;
1914        Object JavaDoc[] copy = new Object JavaDoc[len];
1915        System.arraycopy(objects, 0, copy, 0, len);
1916        sort(copy, comparer);
1917        return copy;
1918    }
1919
1920    /**
1921     * Sorts an array of Strings, returning a new array
1922     * with the sorted items. The original array is left untouched.
1923     */

1924    public static String JavaDoc[] sortCopy(String JavaDoc[] objects) {
1925        int len = objects.length;
1926        String JavaDoc[] copy = new String JavaDoc[len];
1927        System.arraycopy(objects, 0, copy, 0, len);
1928        sort(copy);
1929        return copy;
1930    }
1931
1932    /*
1933     * Returns whether the given compound name starts with the given prefix.
1934     * Returns true if the n first elements of the prefix are equals and the last element of the
1935     * prefix is a prefix of the corresponding element in the compound name.
1936     */

1937    public static boolean startsWithIgnoreCase(String JavaDoc[] compoundName, String JavaDoc[] prefix, boolean partialMatch) {
1938        int prefixLength = prefix.length;
1939        int nameLength = compoundName.length;
1940        if (prefixLength > nameLength) return false;
1941        for (int i = 0; i < prefixLength - 1; i++) {
1942            if (!compoundName[i].equalsIgnoreCase(prefix[i]))
1943                return false;
1944        }
1945        return (partialMatch || prefixLength == nameLength) && compoundName[prefixLength-1].toLowerCase().startsWith(prefix[prefixLength-1].toLowerCase());
1946    }
1947
1948    /*
1949     * Returns whether the given compound name matches the given pattern.
1950     */

1951    public static boolean matchesWithIgnoreCase(String JavaDoc[] compoundName, String JavaDoc pattern) {
1952        if (pattern.equals("*")) return true; //$NON-NLS-1$
1953
int nameLength = compoundName.length;
1954        if (pattern.length() == 0) return nameLength == 0;
1955        if (nameLength == 0) return false;
1956        int length = nameLength-1;
1957        for (int i=0; i<nameLength; i++) {
1958            length += compoundName[i].length();
1959        }
1960        char[] compoundChars = new char[length];
1961        int pos = 0;
1962        for (int i=0; i<nameLength; i++) {
1963            if (pos > 0) compoundChars[pos++] = '.';
1964            char[] array = compoundName[i].toCharArray();
1965            int size = array.length;
1966            System.arraycopy(array, 0, compoundChars, pos, size);
1967            pos += size;
1968        }
1969        return CharOperation.match(pattern.toCharArray(), compoundChars, false);
1970    }
1971
1972    /**
1973     * Converts a String[] to char[][].
1974     */

1975    public static char[][] toCharArrays(String JavaDoc[] a) {
1976        int len = a.length;
1977        if (len == 0) return CharOperation.NO_CHAR_CHAR;
1978        char[][] result = new char[len][];
1979        for (int i = 0; i < len; ++i) {
1980            result[i] = a[i].toCharArray();
1981        }
1982        return result;
1983    }
1984
1985    /**
1986     * Converts a String to char[][], where segments are separate by '.'.
1987     */

1988    public static char[][] toCompoundChars(String JavaDoc s) {
1989        int len = s.length();
1990        if (len == 0) {
1991            return CharOperation.NO_CHAR_CHAR;
1992        }
1993        int segCount = 1;
1994        for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) {
1995            ++segCount;
1996        }
1997        char[][] segs = new char[segCount][];
1998        int start = 0;
1999        for (int i = 0; i < segCount; ++i) {
2000            int dot = s.indexOf('.', start);
2001            int end = (dot == -1 ? s.length() : dot);
2002            segs[i] = new char[end - start];
2003            s.getChars(start, end, segs[i], 0);
2004            start = end + 1;
2005        }
2006        return segs;
2007    }
2008    /*
2009     * Converts the given URI to a local file. Use the existing file if the uri is on the local file system.
2010     * Otherwise fetch it.
2011     * Returns null if unable to fetch it.
2012     */

2013    public static File JavaDoc toLocalFile(URI JavaDoc uri, IProgressMonitor monitor) throws CoreException {
2014        IFileStore fileStore = EFS.getStore(uri);
2015        File JavaDoc localFile = fileStore.toLocalFile(EFS.NONE, monitor);
2016        if (localFile ==null)
2017            // non local file system
2018
localFile= fileStore.toLocalFile(EFS.CACHE, monitor);
2019        return localFile;
2020    }
2021    /**
2022     * Converts a char[][] to String, where segments are separated by '.'.
2023     */

2024    public static String JavaDoc toString(char[][] c) {
2025        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
2026        for (int i = 0, max = c.length; i < max; ++i) {
2027            if (i != 0) sb.append('.');
2028            sb.append(c[i]);
2029        }
2030        return sb.toString();
2031    }
2032
2033    /**
2034     * Converts a char[][] and a char[] to String, where segments are separated by '.'.
2035     */

2036    public static String JavaDoc toString(char[][] c, char[] d) {
2037        if (c == null) return new String JavaDoc(d);
2038        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
2039        for (int i = 0, max = c.length; i < max; ++i) {
2040            sb.append(c[i]);
2041            sb.append('.');
2042        }
2043        sb.append(d);
2044        return sb.toString();
2045    }
2046    
2047    /*
2048     * Converts a char[][] to String[].
2049     */

2050    public static String JavaDoc[] toStrings(char[][] a) {
2051        int len = a.length;
2052        String JavaDoc[] result = new String JavaDoc[len];
2053        for (int i = 0; i < len; ++i) {
2054            result[i] = new String JavaDoc(a[i]);
2055        }
2056        return result;
2057    }
2058    private static void appendArrayTypeSignature(char[] string, int start, StringBuffer JavaDoc buffer, boolean compact) {
2059        int length = string.length;
2060        // need a minimum 2 char
2061
if (start >= length - 1) {
2062            throw new IllegalArgumentException JavaDoc();
2063        }
2064        char c = string[start];
2065        if (c != Signature.C_ARRAY) {
2066            throw new IllegalArgumentException JavaDoc();
2067        }
2068        
2069        int index = start;
2070        c = string[++index];
2071        while(c == Signature.C_ARRAY) {
2072            // need a minimum 2 char
2073
if (index >= length - 1) {
2074                throw new IllegalArgumentException JavaDoc();
2075            }
2076            c = string[++index];
2077        }
2078        
2079        appendTypeSignature(string, index, buffer, compact);
2080        
2081        for(int i = 0, dims = index - start; i < dims; i++) {
2082            buffer.append('[').append(']');
2083        }
2084    }
2085    private static void appendClassTypeSignature(char[] string, int start, StringBuffer JavaDoc buffer, boolean compact) {
2086        char c = string[start];
2087        if (c != Signature.C_RESOLVED) {
2088            return;
2089        }
2090        int p = start + 1;
2091        int checkpoint = buffer.length();
2092        while (true) {
2093            c = string[p];
2094            switch(c) {
2095                case Signature.C_SEMICOLON :
2096                    // all done
2097
return;
2098                case Signature.C_DOT :
2099                case '/' :
2100                    // erase package prefix
2101
if (compact) {
2102                        buffer.setLength(checkpoint);
2103                    } else {
2104                        buffer.append('.');
2105                    }
2106                    break;
2107                 case Signature.C_DOLLAR :
2108                    /**
2109                     * Convert '$' in resolved type signatures into '.'.
2110                     * NOTE: This assumes that the type signature is an inner type
2111                     * signature. This is true in most cases, but someone can define a
2112                     * non-inner type name containing a '$'.
2113                     */

2114                    buffer.append('.');
2115                    break;
2116                 default :
2117                    buffer.append(c);
2118            }
2119            p++;
2120        }
2121    }
2122    static void appendTypeSignature(char[] string, int start, StringBuffer JavaDoc buffer, boolean compact) {
2123        char c = string[start];
2124        switch (c) {
2125            case Signature.C_ARRAY :
2126                appendArrayTypeSignature(string, start, buffer, compact);
2127                break;
2128            case Signature.C_RESOLVED :
2129                appendClassTypeSignature(string, start, buffer, compact);
2130                break;
2131            case Signature.C_TYPE_VARIABLE :
2132                int e = Util.scanTypeVariableSignature(string, start);
2133                buffer.append(string, start + 1, e - start - 1);
2134                break;
2135            case Signature.C_BOOLEAN :
2136                buffer.append(BOOLEAN);
2137                break;
2138            case Signature.C_BYTE :
2139                buffer.append(BYTE);
2140                break;
2141            case Signature.C_CHAR :
2142                buffer.append(CHAR);
2143                break;
2144            case Signature.C_DOUBLE :
2145                buffer.append(DOUBLE);
2146                break;
2147            case Signature.C_FLOAT :
2148                buffer.append(FLOAT);
2149                break;
2150            case Signature.C_INT :
2151                buffer.append(INT);
2152                break;
2153            case Signature.C_LONG :
2154                buffer.append(LONG);
2155                break;
2156            case Signature.C_SHORT :
2157                buffer.append(SHORT);
2158                break;
2159            case Signature.C_VOID :
2160                buffer.append(VOID);
2161                break;
2162        }
2163    }
2164    public static String JavaDoc toString(char[] declaringClass, char[] methodName, char[] methodSignature, boolean includeReturnType, boolean compact) {
2165        final boolean isConstructor = CharOperation.equals(methodName, INIT);
2166        int firstParen = CharOperation.indexOf(Signature.C_PARAM_START, methodSignature);
2167        if (firstParen == -1) {
2168            return ""; //$NON-NLS-1$
2169
}
2170        
2171        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(methodSignature.length + 10);
2172        
2173        // decode declaring class name
2174
// it can be either an array signature or a type signature
2175
if (declaringClass.length > 0) {
2176            char[] declaringClassSignature = null;
2177            if (declaringClass[0] == Signature.C_ARRAY) {
2178                CharOperation.replace(declaringClass, '/', '.');
2179                declaringClassSignature = Signature.toCharArray(declaringClass);
2180            } else {
2181                CharOperation.replace(declaringClass, '/', '.');
2182                declaringClassSignature = declaringClass;
2183            }
2184            int lastIndexOfSlash = CharOperation.lastIndexOf('.', declaringClassSignature);
2185            if (compact && lastIndexOfSlash != -1) {
2186                buffer.append(declaringClassSignature, lastIndexOfSlash + 1, declaringClassSignature.length - lastIndexOfSlash - 1);
2187            } else {
2188                buffer.append(declaringClassSignature);
2189            }
2190        }
2191
2192        // selector
2193
if (!isConstructor) {
2194            buffer.append('.');
2195            if (methodName != null) {
2196                buffer.append(methodName);
2197            }
2198        }
2199        
2200        // parameters
2201
buffer.append('(');
2202        char[][] pts = Signature.getParameterTypes(methodSignature);
2203        for (int i = 0, max = pts.length; i < max; i++) {
2204            appendTypeSignature(pts[i], 0 , buffer, compact);
2205            if (i != pts.length - 1) {
2206                buffer.append(',');
2207                buffer.append(' ');
2208            }
2209        }
2210        buffer.append(')');
2211        
2212        if (!isConstructor) {
2213            buffer.append(" : "); //$NON-NLS-1$
2214
// return type
2215
if (includeReturnType) {
2216                char[] rts = Signature.getReturnType(methodSignature);
2217                appendTypeSignature(rts, 0 , buffer, compact);
2218            }
2219        }
2220        return String.valueOf(buffer);
2221    }
2222    /*
2223     * Returns the unresolved type parameter signatures of the given method
2224     * e.g. {"QString;", "[int", "[[Qjava.util.Vector;"}
2225     */

2226    public static String JavaDoc[] typeParameterSignatures(AbstractMethodDeclaration method) {
2227        Argument[] args = method.arguments;
2228        if (args != null) {
2229            int length = args.length;
2230            String JavaDoc[] signatures = new String JavaDoc[length];
2231            for (int i = 0; i < args.length; i++) {
2232                Argument arg = args[i];
2233                signatures[i] = typeSignature(arg.type);
2234            }
2235            return signatures;
2236        }
2237        return CharOperation.NO_STRINGS;
2238    }
2239
2240    /*
2241     * Returns the unresolved type signature of the given type reference,
2242     * e.g. "QString;", "[int", "[[Qjava.util.Vector;"
2243     */

2244    public static String JavaDoc typeSignature(TypeReference type) {
2245        char[][] compoundName = type.getParameterizedTypeName();
2246        char[] typeName =CharOperation.concatWith(compoundName, '.');
2247        String JavaDoc signature = Signature.createTypeSignature(typeName, false/*don't resolve*/);
2248        return signature;
2249    }
2250
2251    /**
2252     * Asserts that the given method signature is valid.
2253     */

2254    public static void validateMethodSignature(String JavaDoc sig) {
2255        Assert.isTrue(isValidMethodSignature(sig));
2256    }
2257
2258    /**
2259     * Asserts that the given type signature is valid.
2260     */

2261    public static void validateTypeSignature(String JavaDoc sig, boolean allowVoid) {
2262        Assert.isTrue(isValidTypeSignature(sig, allowVoid));
2263    }
2264    public static void verbose(String JavaDoc log) {
2265        verbose(log, System.out);
2266    }
2267    public static synchronized void verbose(String JavaDoc log, PrintStream printStream) {
2268        int start = 0;
2269        do {
2270            int end = log.indexOf('\n', start);
2271            printStream.print(Thread.currentThread());
2272            printStream.print(" "); //$NON-NLS-1$
2273
printStream.print(log.substring(start, end == -1 ? log.length() : end+1));
2274            start = end+1;
2275        } while (start != 0);
2276        printStream.println();
2277    }
2278
2279    /**
2280     * Returns true if the given name ends with one of the known java like extension.
2281     * (implementation is not creating extra strings)
2282     */

2283    public final static boolean isJavaLikeFileName(String JavaDoc name) {
2284        if (name == null) return false;
2285        return indexOfJavaLikeExtension(name) != -1;
2286    }
2287
2288    /**
2289     * Returns true if the given name ends with one of the known java like extension.
2290     * (implementation is not creating extra strings)
2291     */

2292    public final static boolean isJavaLikeFileName(char[] fileName) {
2293        if (fileName == null) return false;
2294        int fileNameLength = fileName.length;
2295        char[][] javaLikeExtensions = getJavaLikeExtensions();
2296        extensions: for (int i = 0, length = javaLikeExtensions.length; i < length; i++) {
2297            char[] extension = javaLikeExtensions[i];
2298            int extensionLength = extension.length;
2299            int extensionStart = fileNameLength - extensionLength;
2300            if (extensionStart-1 < 0) continue;
2301            if (fileName[extensionStart-1] != '.') continue;
2302            for (int j = 0; j < extensionLength; j++) {
2303                if (fileName[extensionStart + j] != extension[j])
2304                    continue extensions;
2305            }
2306            return true;
2307        }
2308        return false;
2309    }
2310
2311    /**
2312     * Scans the given string for a type signature starting at the given index
2313     * and returns the index of the last character.
2314     * <pre>
2315     * TypeSignature:
2316     * | BaseTypeSignature
2317     * | ArrayTypeSignature
2318     * | ClassTypeSignature
2319     * | TypeVariableSignature
2320     * </pre>
2321     *
2322     * @param string the signature string
2323     * @param start the 0-based character index of the first character
2324     * @return the 0-based character index of the last character
2325     * @exception IllegalArgumentException if this is not a type signature
2326     */

2327    public static int scanTypeSignature(char[] string, int start) {
2328        // need a minimum 1 char
2329
if (start >= string.length) {
2330            throw new IllegalArgumentException JavaDoc();
2331        }
2332        char c = string[start];
2333        switch (c) {
2334            case Signature.C_ARRAY :
2335                return scanArrayTypeSignature(string, start);
2336            case Signature.C_RESOLVED :
2337            case Signature.C_UNRESOLVED :
2338                return scanClassTypeSignature(string, start);
2339            case Signature.C_TYPE_VARIABLE :
2340                return scanTypeVariableSignature(string, start);
2341            case Signature.C_BOOLEAN :
2342            case Signature.C_BYTE :
2343            case Signature.C_CHAR :
2344            case Signature.C_DOUBLE :
2345            case Signature.C_FLOAT :
2346            case Signature.C_INT :
2347            case Signature.C_LONG :
2348            case Signature.C_SHORT :
2349            case Signature.C_VOID :
2350                return scanBaseTypeSignature(string, start);
2351            case Signature.C_CAPTURE :
2352                return scanCaptureTypeSignature(string, start);
2353            case Signature.C_EXTENDS:
2354            case Signature.C_SUPER:
2355            case Signature.C_STAR:
2356                return scanTypeBoundSignature(string, start);
2357            default :
2358                throw new IllegalArgumentException JavaDoc();
2359        }
2360    }
2361
2362    /**
2363     * Scans the given string for a base type signature starting at the given index
2364     * and returns the index of the last character.
2365     * <pre>
2366     * BaseTypeSignature:
2367     * <b>B</b> | <b>C</b> | <b>D</b> | <b>F</b> | <b>I</b>
2368     * | <b>J</b> | <b>S</b> | <b>V</b> | <b>Z</b>
2369     * </pre>
2370     * Note that although the base type "V" is only allowed in method return types,
2371     * there is no syntactic ambiguity. This method will accept them anywhere
2372     * without complaint.
2373     *
2374     * @param string the signature string
2375     * @param start the 0-based character index of the first character
2376     * @return the 0-based character index of the last character
2377     * @exception IllegalArgumentException if this is not a base type signature
2378     */

2379    public static int scanBaseTypeSignature(char[] string, int start) {
2380        // need a minimum 1 char
2381
if (start >= string.length) {
2382            throw new IllegalArgumentException JavaDoc();
2383        }
2384        char c = string[start];
2385        if ("BCDFIJSVZ".indexOf(c) >= 0) { //$NON-NLS-1$
2386
return start;
2387        } else {
2388            throw new IllegalArgumentException JavaDoc();
2389        }
2390    }
2391
2392    /**
2393     * Scans the given string for an array type signature starting at the given
2394     * index and returns the index of the last character.
2395     * <pre>
2396     * ArrayTypeSignature:
2397     * <b>[</b> TypeSignature
2398     * </pre>
2399     *
2400     * @param string the signature string
2401     * @param start the 0-based character index of the first character
2402     * @return the 0-based character index of the last character
2403     * @exception IllegalArgumentException if this is not an array type signature
2404     */

2405    public static int scanArrayTypeSignature(char[] string, int start) {
2406        int length = string.length;
2407        // need a minimum 2 char
2408
if (start >= length - 1) {
2409            throw new IllegalArgumentException JavaDoc();
2410        }
2411        char c = string[start];
2412        if (c != Signature.C_ARRAY) {
2413            throw new IllegalArgumentException JavaDoc();
2414        }
2415        
2416        c = string[++start];
2417        while(c == Signature.C_ARRAY) {
2418            // need a minimum 2 char
2419
if (start >= length - 1) {
2420                throw new IllegalArgumentException JavaDoc();
2421            }
2422            c = string[++start];
2423        }
2424        return scanTypeSignature(string, start);
2425    }
2426    
2427    /**
2428     * Scans the given string for a capture of a wildcard type signature starting at the given
2429     * index and returns the index of the last character.
2430     * <pre>
2431     * CaptureTypeSignature:
2432     * <b>!</b> TypeBoundSignature
2433     * </pre>
2434     *
2435     * @param string the signature string
2436     * @param start the 0-based character index of the first character
2437     * @return the 0-based character index of the last character
2438     * @exception IllegalArgumentException if this is not a capture type signature
2439     */

2440    public static int scanCaptureTypeSignature(char[] string, int start) {
2441        // need a minimum 2 char
2442
if (start >= string.length - 1) {
2443            throw new IllegalArgumentException JavaDoc();
2444        }
2445        char c = string[start];
2446        if (c != Signature.C_CAPTURE) {
2447            throw new IllegalArgumentException JavaDoc();
2448        }
2449        return scanTypeBoundSignature(string, start + 1);
2450    }
2451
2452    /**
2453     * Scans the given string for a type variable signature starting at the given
2454     * index and returns the index of the last character.
2455     * <pre>
2456     * TypeVariableSignature:
2457     * <b>T</b> Identifier <b>;</b>
2458     * </pre>
2459     *
2460     * @param string the signature string
2461     * @param start the 0-based character index of the first character
2462     * @return the 0-based character index of the last character
2463     * @exception IllegalArgumentException if this is not a type variable signature
2464     */

2465    public static int scanTypeVariableSignature(char[] string, int start) {
2466        // need a minimum 3 chars "Tx;"
2467
if (start >= string.length - 2) {
2468            throw new IllegalArgumentException JavaDoc();
2469        }
2470        // must start in "T"
2471
char c = string[start];
2472        if (c != Signature.C_TYPE_VARIABLE) {
2473            throw new IllegalArgumentException JavaDoc();
2474        }
2475        int id = scanIdentifier(string, start + 1);
2476        c = string[id + 1];
2477        if (c == Signature.C_SEMICOLON) {
2478            return id + 1;
2479        } else {
2480            throw new IllegalArgumentException JavaDoc();
2481        }
2482    }
2483
2484    /**
2485     * Scans the given string for an identifier starting at the given
2486     * index and returns the index of the last character.
2487     * Stop characters are: ";", ":", "&lt;", "&gt;", "/", ".".
2488     *
2489     * @param string the signature string
2490     * @param start the 0-based character index of the first character
2491     * @return the 0-based character index of the last character
2492     * @exception IllegalArgumentException if this is not an identifier
2493     */

2494    public static int scanIdentifier(char[] string, int start) {
2495        // need a minimum 1 char
2496
if (start >= string.length) {
2497            throw new IllegalArgumentException JavaDoc();
2498        }
2499        int p = start;
2500        while (true) {
2501            char c = string[p];
2502            if (c == '<' || c == '>' || c == ':' || c == ';' || c == '.' || c == '/') {
2503                return p - 1;
2504            }
2505            p++;
2506            if (p == string.length) {
2507                return p - 1;
2508            }
2509        }
2510    }
2511
2512    /**
2513     * Scans the given string for a class type signature starting at the given
2514     * index and returns the index of the last character.
2515     * <pre>
2516     * ClassTypeSignature:
2517     * { <b>L</b> | <b>Q</b> } Identifier
2518     * { { <b>/</b> | <b>.</b> Identifier [ <b>&lt;</b> TypeArgumentSignature* <b>&gt;</b> ] }
2519     * <b>;</b>
2520     * </pre>
2521     * Note that although all "/"-identifiers most come before "."-identifiers,
2522     * there is no syntactic ambiguity. This method will accept them without
2523     * complaint.
2524     *
2525     * @param string the signature string
2526     * @param start the 0-based character index of the first character
2527     * @return the 0-based character index of the last character
2528     * @exception IllegalArgumentException if this is not a class type signature
2529     */

2530    public static int scanClassTypeSignature(char[] string, int start) {
2531        // need a minimum 3 chars "Lx;"
2532
if (start >= string.length - 2) {
2533            throw new IllegalArgumentException JavaDoc();
2534        }
2535        // must start in "L" or "Q"
2536
char c = string[start];
2537        if (c != Signature.C_RESOLVED && c != Signature.C_UNRESOLVED) {
2538            return -1;
2539        }
2540        int p = start + 1;
2541        while (true) {
2542            if (p >= string.length) {
2543                throw new IllegalArgumentException JavaDoc();
2544            }
2545            c = string[p];
2546            if (c == Signature.C_SEMICOLON) {
2547                // all done
2548
return p;
2549            } else if (c == Signature.C_GENERIC_START) {
2550                int e = scanTypeArgumentSignatures(string, p);
2551                p = e;
2552            } else if (c == Signature.C_DOT || c == '/') {
2553                int id = scanIdentifier(string, p + 1);
2554                p = id;
2555            }
2556            p++;
2557        }
2558    }
2559
2560    /**
2561     * Scans the given string for a type bound signature starting at the given
2562     * index and returns the index of the last character.
2563     * <pre>
2564     * TypeBoundSignature:
2565     * <b>[-+]</b> TypeSignature <b>;</b>
2566     * <b>*</b></b>
2567     * </pre>
2568     *
2569     * @param string the signature string
2570     * @param start the 0-based character index of the first character
2571     * @return the 0-based character index of the last character
2572     * @exception IllegalArgumentException if this is not a type variable signature
2573     */

2574    public static int scanTypeBoundSignature(char[] string, int start) {
2575        // need a minimum 1 char for wildcard
2576
if (start >= string.length) {
2577            throw new IllegalArgumentException JavaDoc();
2578        }
2579        char c = string[start];
2580        switch (c) {
2581            case Signature.C_STAR :
2582                return start;
2583            case Signature.C_SUPER :
2584            case Signature.C_EXTENDS :
2585                // need a minimum 3 chars "+[I"
2586
if (start >= string.length - 2) {
2587                    throw new IllegalArgumentException JavaDoc();
2588                }
2589                break;
2590            default :
2591                // must start in "+/-"
2592
throw new IllegalArgumentException JavaDoc();
2593                
2594        }
2595        c = string[++start];
2596        switch (c) {
2597            case Signature.C_CAPTURE :
2598                return scanCaptureTypeSignature(string, start);
2599            case Signature.C_SUPER :
2600            case Signature.C_EXTENDS :
2601                return scanTypeBoundSignature(string, start);
2602            case Signature.C_RESOLVED :
2603            case Signature.C_UNRESOLVED :
2604                return scanClassTypeSignature(string, start);
2605            case Signature.C_TYPE_VARIABLE :
2606                return scanTypeVariableSignature(string, start);
2607            case Signature.C_ARRAY :
2608                return scanArrayTypeSignature(string, start);
2609            case Signature.C_STAR:
2610                return start;
2611            default:
2612                throw new IllegalArgumentException JavaDoc();
2613        }
2614    }
2615    
2616    /**
2617     * Scans the given string for a list of type argument signatures starting at
2618     * the given index and returns the index of the last character.
2619     * <pre>
2620     * TypeArgumentSignatures:
2621     * <b>&lt;</b> TypeArgumentSignature* <b>&gt;</b>
2622     * </pre>
2623     * Note that although there is supposed to be at least one type argument, there
2624     * is no syntactic ambiguity if there are none. This method will accept zero
2625     * type argument signatures without complaint.
2626     *
2627     * @param string the signature string
2628     * @param start the 0-based character index of the first character
2629     * @return the 0-based character index of the last character
2630     * @exception IllegalArgumentException if this is not a list of type arguments
2631     * signatures
2632     */

2633    public static int scanTypeArgumentSignatures(char[] string, int start) {
2634        // need a minimum 2 char "<>"
2635
if (start >= string.length - 1) {
2636            throw new IllegalArgumentException JavaDoc();
2637        }
2638        char c = string[start];
2639        if (c != Signature.C_GENERIC_START) {
2640            throw new IllegalArgumentException JavaDoc();
2641        }
2642        int p = start + 1;
2643        while (true) {
2644            if (p >= string.length) {
2645                throw new IllegalArgumentException JavaDoc();
2646            }
2647            c = string[p];
2648            if (c == Signature.C_GENERIC_END) {
2649                return p;
2650            }
2651            int e = scanTypeArgumentSignature(string, p);
2652            p = e + 1;
2653        }
2654    }
2655
2656    /**
2657     * Scans the given string for a type argument signature starting at the given
2658     * index and returns the index of the last character.
2659     * <pre>
2660     * TypeArgumentSignature:
2661     * <b>&#42;</b>
2662     * | <b>+</b> TypeSignature
2663     * | <b>-</b> TypeSignature
2664     * | TypeSignature
2665     * </pre>
2666     * Note that although base types are not allowed in type arguments, there is
2667     * no syntactic ambiguity. This method will accept them without complaint.
2668     *
2669     * @param string the signature string
2670     * @param start the 0-based character index of the first character
2671     * @return the 0-based character index of the last character
2672     * @exception IllegalArgumentException if this is not a type argument signature
2673     */

2674    public static int scanTypeArgumentSignature(char[] string, int start) {
2675        // need a minimum 1 char
2676
if (start >= string.length) {
2677            throw new IllegalArgumentException JavaDoc();
2678        }
2679        char c = string[start];
2680        switch (c) {
2681            case Signature.C_STAR :
2682                return start;
2683            case Signature.C_EXTENDS :
2684            case Signature.C_SUPER :
2685                return scanTypeBoundSignature(string, start);
2686            default :
2687                return scanTypeSignature(string, start);
2688        }
2689    }
2690
2691    /**
2692     * Get all type arguments from an array of signatures.
2693     *
2694     * Example:
2695     * For following type X<Y<Z>,V<W>,U>.A<B> signatures is:
2696     * [
2697     * ['L','X','<','L','Y','<','L','Z',';'>',';','L','V','<','L','W',';'>',';','L','U',';',>',';'],
2698     * ['L','A','<','L','B',';','>',';']
2699     * ]
2700     * @see #splitTypeLevelsSignature(String)
2701     * Then, this method returns:
2702     * [
2703     * [
2704     * ['L','Y','<','L','Z',';'>',';'],
2705     * ['L','V','<','L','W',';'>',';'],
2706     * ['L','U',';']
2707     * ],
2708     * [
2709     * ['L','B',';']
2710     * ]
2711     * ]
2712     *
2713     * @param typeSignatures Array of signatures (one per each type levels)
2714     * @throws IllegalArgumentException If one of provided signature is malformed
2715     * @return char[][][] Array of type arguments for each signature
2716     */

2717    public final static char[][][] getAllTypeArguments(char[][] typeSignatures) {
2718        if (typeSignatures == null) return null;
2719        int length = typeSignatures.length;
2720        char[][][] typeArguments = new char[length][][];
2721        for (int i=0; i<length; i++){
2722            typeArguments[i] = Signature.getTypeArguments(typeSignatures[i]);
2723        }
2724        return typeArguments;
2725    }
2726    /**
2727     * Split signatures of all levels from a type unique key.
2728     *
2729     * Example:
2730     * For following type X<Y<Z>,V<W>,U>.A<B>, unique key is:
2731     * "LX<LY<LZ;>;LV<LW;>;LU;>.LA<LB;>;"
2732     *
2733     * The return splitted signatures array is:
2734     * [
2735     * ['L','X','<','L','Y','<','L','Z',';'>',';','L','V','<','L','W',';'>',';','L','U','>',';'],
2736     * ['L','A','<','L','B',';','>',';']
2737     *
2738     * @param typeSignature ParameterizedSourceType type signature
2739     * @return char[][] Array of signatures for each level of given unique key
2740     */

2741    public final static char[][] splitTypeLevelsSignature(String JavaDoc typeSignature) {
2742        // In case of IJavaElement signature, replace '$' by '.'
2743
char[] source = Signature.removeCapture(typeSignature.toCharArray());
2744        CharOperation.replace(source, '$', '.');
2745
2746        // Init counters and arrays
2747
char[][] signatures = new char[10][];
2748        int signaturesCount = 0;
2749// int[] lengthes = new int [10];
2750
int typeArgsCount = 0;
2751        int paramOpening = 0;
2752        
2753        // Scan each signature character
2754
for (int idx=0, ln = source.length; idx < ln; idx++) {
2755            switch (source[idx]) {
2756                case '>':
2757                    paramOpening--;
2758                    if (paramOpening == 0) {
2759                        if (signaturesCount == signatures.length) {
2760                            System.arraycopy(signatures, 0, signatures = new char[signaturesCount+10][], 0, signaturesCount);
2761                        }
2762                        typeArgsCount = 0;
2763                    }
2764                    break;
2765                case '<':
2766                    paramOpening++;
2767                    if (paramOpening == 1) {
2768                        typeArgsCount = 1;
2769                    }
2770                    break;
2771                case '*':
2772                case ';':
2773                    if (paramOpening == 1) typeArgsCount++;
2774                    break;
2775                case '.':
2776                    if (paramOpening == 0) {
2777                        if (signaturesCount == signatures.length) {
2778                            System.arraycopy(signatures, 0, signatures = new char[signaturesCount+10][], 0, signaturesCount);
2779                        }
2780                        signatures[signaturesCount] = new char[idx+1];
2781                        System.arraycopy(source, 0, signatures[signaturesCount], 0, idx);
2782                        signatures[signaturesCount][idx] = Signature.C_SEMICOLON;
2783                        signaturesCount++;
2784                    }
2785                    break;
2786                case '/':
2787                    source[idx] = '.';
2788                    break;
2789            }
2790        }
2791
2792        // Resize signatures array
2793
char[][] typeSignatures = new char[signaturesCount+1][];
2794        typeSignatures[0] = source;
2795        for (int i=1, j=signaturesCount-1; i<=signaturesCount; i++, j--){
2796            typeSignatures[i] = signatures[j];
2797        }
2798        return typeSignatures;
2799    }
2800    
2801    /*
2802     * Can throw IllegalArgumentException or ArrayIndexOutOfBoundsException
2803     */

2804    public static String JavaDoc toAnchor(char[] methodSignature, String JavaDoc methodName, boolean isVarArgs) {
2805        try {
2806            return new String JavaDoc(toAnchor(methodSignature, methodName.toCharArray(), isVarArgs));
2807        } catch(IllegalArgumentException JavaDoc e) {
2808            return null;
2809        }
2810    }
2811    private static char[] toAnchor(char[] methodSignature, char[] methodName, boolean isVargArgs) {
2812        int firstParen = CharOperation.indexOf(Signature.C_PARAM_START, methodSignature);
2813        if (firstParen == -1) {
2814            throw new IllegalArgumentException JavaDoc();
2815        }
2816        
2817        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(methodSignature.length + 10);
2818
2819        // selector
2820
if (methodName != null) {
2821            buffer.append(methodName);
2822        }
2823        
2824        // parameters
2825
buffer.append('(');
2826        char[][] pts = Signature.getParameterTypes(methodSignature);
2827        for (int i = 0, max = pts.length; i < max; i++) {
2828            if (i == max - 1) {
2829                appendTypeSignatureForAnchor(pts[i], 0 , buffer, isVargArgs);
2830            } else {
2831                appendTypeSignatureForAnchor(pts[i], 0 , buffer, false);
2832            }
2833            if (i != pts.length - 1) {
2834                buffer.append(',');
2835                buffer.append(' ');
2836            }
2837        }
2838        buffer.append(')');
2839        char[] result = new char[buffer.length()];
2840        buffer.getChars(0, buffer.length(), result, 0);
2841        return result;
2842    }
2843
2844    private static int appendTypeSignatureForAnchor(char[] string, int start, StringBuffer JavaDoc buffer, boolean isVarArgs) {
2845        // need a minimum 1 char
2846
if (start >= string.length) {
2847            throw new IllegalArgumentException JavaDoc();
2848        }
2849        char c = string[start];
2850        if (isVarArgs) {
2851            switch (c) {
2852                case Signature.C_ARRAY :
2853                    return appendArrayTypeSignatureForAnchor(string, start, buffer, true);
2854                case Signature.C_RESOLVED :
2855                case Signature.C_TYPE_VARIABLE :
2856                case Signature.C_BOOLEAN :
2857                case Signature.C_BYTE :
2858                case Signature.C_CHAR :
2859                case Signature.C_DOUBLE :
2860                case Signature.C_FLOAT :
2861                case Signature.C_INT :
2862                case Signature.C_LONG :
2863                case Signature.C_SHORT :
2864                case Signature.C_VOID :
2865                case Signature.C_STAR:
2866                case Signature.C_EXTENDS:
2867                case Signature.C_SUPER:
2868                case Signature.C_CAPTURE:
2869                default:
2870                    throw new IllegalArgumentException JavaDoc(); // a var args is an array type
2871
}
2872        } else {
2873            switch (c) {
2874                case Signature.C_ARRAY :
2875                    return appendArrayTypeSignatureForAnchor(string, start, buffer, false);
2876                case Signature.C_RESOLVED :
2877                    return appendClassTypeSignatureForAnchor(string, start, buffer);
2878                case Signature.C_TYPE_VARIABLE :
2879                    int e = Util.scanTypeVariableSignature(string, start);
2880                    buffer.append(string, start + 1, e - start - 1);
2881                    return e;
2882                case Signature.C_BOOLEAN :
2883                    buffer.append(BOOLEAN);
2884                    return start;
2885                case Signature.C_BYTE :
2886                    buffer.append(BYTE);
2887                    return start;
2888                case Signature.C_CHAR :
2889                    buffer.append(CHAR);
2890                    return start;
2891                case Signature.C_DOUBLE :
2892                    buffer.append(DOUBLE);
2893                    return start;
2894                case Signature.C_FLOAT :
2895                    buffer.append(FLOAT);
2896                    return start;
2897                case Signature.C_INT :
2898                    buffer.append(INT);
2899                    return start;
2900                case Signature.C_LONG :
2901                    buffer.append(LONG);
2902                    return start;
2903                case Signature.C_SHORT :
2904                    buffer.append(SHORT);
2905                    return start;
2906                case Signature.C_VOID :
2907                    buffer.append(VOID);
2908                    return start;
2909                case Signature.C_CAPTURE :
2910                    return appendCaptureTypeSignatureForAnchor(string, start, buffer);
2911                case Signature.C_STAR:
2912                case Signature.C_EXTENDS:
2913                case Signature.C_SUPER:
2914                    return appendTypeArgumentSignatureForAnchor(string, start, buffer);
2915                default :
2916                    throw new IllegalArgumentException JavaDoc();
2917            }
2918        }
2919    }
2920    private static int appendTypeArgumentSignatureForAnchor(char[] string, int start, StringBuffer JavaDoc buffer) {
2921        // need a minimum 1 char
2922
if (start >= string.length) {
2923            throw new IllegalArgumentException JavaDoc();
2924        }
2925        char c = string[start];
2926        switch(c) {
2927            case Signature.C_STAR :
2928                return start;
2929            case Signature.C_EXTENDS :
2930                return appendTypeSignatureForAnchor(string, start + 1, buffer, false);
2931            case Signature.C_SUPER :
2932                return appendTypeSignatureForAnchor(string, start + 1, buffer, false);
2933            default :
2934                return appendTypeSignatureForAnchor(string, start, buffer, false);
2935        }
2936    }
2937    private static int appendCaptureTypeSignatureForAnchor(char[] string, int start, StringBuffer JavaDoc buffer) {
2938        // need a minimum 2 char
2939
if (start >= string.length - 1) {
2940            throw new IllegalArgumentException JavaDoc();
2941        }
2942        char c = string[start];
2943        if (c != Signature.C_CAPTURE) {
2944            throw new IllegalArgumentException JavaDoc();
2945        }
2946        return appendTypeArgumentSignatureForAnchor(string, start + 1, buffer);
2947    }
2948    private static int appendArrayTypeSignatureForAnchor(char[] string, int start, StringBuffer JavaDoc buffer, boolean isVarArgs) {
2949        int length = string.length;
2950        // need a minimum 2 char
2951
if (start >= length - 1) {
2952            throw new IllegalArgumentException JavaDoc();
2953        }
2954        char c = string[start];
2955        if (c != Signature.C_ARRAY) {
2956            throw new IllegalArgumentException JavaDoc();
2957        }
2958        
2959        int index = start;
2960        c = string[++index];
2961        while(c == Signature.C_ARRAY) {
2962            // need a minimum 2 char
2963
if (index >= length - 1) {
2964                throw new IllegalArgumentException JavaDoc();
2965            }
2966            c = string[++index];
2967        }
2968        
2969        int e = appendTypeSignatureForAnchor(string, index, buffer, false);
2970        
2971        for(int i = 1, dims = index - start; i < dims; i++) {
2972            buffer.append('[').append(']');
2973        }
2974        
2975        if (isVarArgs) {
2976            buffer.append('.').append('.').append('.');
2977        } else {
2978            buffer.append('[').append(']');
2979        }
2980        return e;
2981    }
2982    private static int appendClassTypeSignatureForAnchor(char[] string, int start, StringBuffer JavaDoc buffer) {
2983        // need a minimum 3 chars "Lx;"
2984
if (start >= string.length - 2) {
2985            throw new IllegalArgumentException JavaDoc();
2986        }
2987        // must start in "L" or "Q"
2988
char c = string[start];
2989        if (c != Signature.C_RESOLVED && c != Signature.C_UNRESOLVED) {
2990            throw new IllegalArgumentException JavaDoc();
2991        }
2992        int p = start + 1;
2993        while (true) {
2994            if (p >= string.length) {
2995                throw new IllegalArgumentException JavaDoc();
2996            }
2997            c = string[p];
2998            switch(c) {
2999                case Signature.C_SEMICOLON :
3000                    // all done
3001
return p;
3002                case Signature.C_GENERIC_START :
3003                    int e = scanGenericEnd(string, p + 1);
3004                    // once we hit type arguments there are no more package prefixes
3005
p = e;
3006                    break;
3007                case Signature.C_DOT :
3008                    buffer.append('.');
3009                    break;
3010                 case '/' :
3011                    buffer.append('/');
3012                    break;
3013                 case Signature.C_DOLLAR :
3014                    // once we hit "$" there are no more package prefixes
3015
/**
3016                     * Convert '$' in resolved type signatures into '.'.
3017                     * NOTE: This assumes that the type signature is an inner type
3018                     * signature. This is true in most cases, but someone can define a
3019                     * non-inner type name containing a '$'.
3020                     */

3021                    buffer.append('.');
3022                    break;
3023                 default :
3024                    buffer.append(c);
3025            }
3026            p++;
3027        }
3028    }
3029    private static int scanGenericEnd(char[] string, int start) {
3030        if (string[start] == Signature.C_GENERIC_END) {
3031            return start;
3032        }
3033        int length = string.length;
3034        int balance = 1;
3035        start++;
3036        while (start <= length) {
3037            switch(string[start]) {
3038                case Signature.C_GENERIC_END :
3039                    balance--;
3040                    if (balance == 0) {
3041                        return start;
3042                    }
3043                    break;
3044                case Signature.C_GENERIC_START :
3045                    balance++;
3046                    break;
3047            }
3048            start++;
3049        }
3050        return start;
3051    }
3052}
3053
Popular Tags