1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core.util;
13 import java.io.BufferedInputStream;
14 import java.io.DataInput;
15 import java.io.EOFException;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19 import java.io.PrintStream;
20 import java.io.UTFDataFormatException;
21 import java.util.Locale;
22 import java.util.MissingResourceException;
23 import java.util.ResourceBundle;
24 import java.util.StringTokenizer;
26 import net.sourceforge.phpdt.core.IJavaElement;
27 import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
28 import net.sourceforge.phpdt.core.IPackageFragment;
29 import net.sourceforge.phpdt.core.JavaCore;
30 import net.sourceforge.phpdt.core.JavaModelException;
31 import net.sourceforge.phpdt.core.Signature;
32 import net.sourceforge.phpdt.core.compiler.CharOperation;
33 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
35 //import net.sourceforge.phpdt.internal.corext.Assert;
36 import org.eclipse.core.runtime.Assert;
37 //import net.sourceforge.phpdt.internal.core.PackageFragmentRoot;
38 import net.sourceforge.phpdt.internal.core.util.PHPFileUtil;
40 import org.eclipse.core.resources.IFile;
41 //import org.eclipse.core.resources.IFolder;
42 import org.eclipse.core.resources.IResource;
43 import org.eclipse.core.runtime.CoreException;
44 import org.eclipse.core.runtime.IPath;
45 import org.eclipse.core.runtime.IStatus;
46 import org.eclipse.core.runtime.Status;
47 //import org.eclipse.jface.text.BadLocationException;
48 //import org.eclipse.text.edits.MalformedTreeException;
49 //import org.eclipse.text.edits.TextEdit;
52 * Provides convenient utility methods to other types in this package.
56 public interface Comparable {
58 * Returns 0 if this and c are equal, >0 if this is greater than c, or
59 * <0 if this is less than c.
61 int compareTo(Comparable c);
64 public interface Comparer {
66 * Returns 0 if a and b are equal, >0 if a is greater than b, or <0 if a
69 int compare(Object a, Object b);
72 private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
74 /* Bundle containing messages */
75 protected static ResourceBundle bundle;
77 private final static String bundleName = "net.sourceforge.phpdt.internal.core.util.messages"; //$NON-NLS-1$
79 private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
81 private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$
83 public static final String[] fgEmptyStringArray = new String[0];
85 private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
92 // cannot be instantiated
96 * Lookup the message with the given ID in this catalog
98 public static String bind(String id) {
99 return bind(id, (String[]) null);
103 * Lookup the message with the given ID in this catalog and bind its
104 * substitution locations with the given string.
106 public static String bind(String id, String binding) {
107 return bind(id, new String[] { binding });
111 * Lookup the message with the given ID in this catalog and bind its
112 * substitution locations with the given strings.
114 public static String bind(String id, String binding1, String binding2) {
115 return bind(id, new String[] { binding1, binding2 });
119 * Lookup the message with the given ID in this catalog and bind its
120 * substitution locations with the given string values.
122 public static String bind(String id, String[] bindings) {
124 return "No message available"; //$NON-NLS-1$
125 String message = null;
127 message = bundle.getString(id);
128 } catch (MissingResourceException e) {
129 // If we got an exception looking for the message, fail gracefully
131 // the id we were looking for. In most cases this is
132 // semi-informative so is not too bad.
133 return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
135 // for compatibility with MessageFormat which eliminates double quotes
136 // in original message
137 char[] messageWithNoDoubleQuotes = CharOperation.replace(message
138 .toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
140 if (bindings == null)
141 return new String(messageWithNoDoubleQuotes);
143 int length = messageWithNoDoubleQuotes.length;
146 StringBuffer output = null;
148 if ((end = CharOperation.indexOf('{', messageWithNoDoubleQuotes,
151 output = new StringBuffer(length + bindings.length * 20);
152 output.append(messageWithNoDoubleQuotes, start, end - start);
153 if ((start = CharOperation.indexOf('}',
154 messageWithNoDoubleQuotes, end + 1)) > -1) {
156 String argId = new String(messageWithNoDoubleQuotes,
157 end + 1, start - end - 1);
159 index = Integer.parseInt(argId);
160 output.append(bindings[index]);
161 } catch (NumberFormatException nfe) { // could be nested
164 boolean done = false;
165 if (!id.equals(argId)) {
166 String argMessage = null;
168 argMessage = bundle.getString(argId);
169 output.append(argMessage);
171 } catch (MissingResourceException e) {
172 // unable to bind argument, ignore (will leave
177 output.append(messageWithNoDoubleQuotes, end + 1,
179 } catch (ArrayIndexOutOfBoundsException e) {
181 .append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
185 output.append(messageWithNoDoubleQuotes, end, length);
190 return new String(messageWithNoDoubleQuotes);
191 output.append(messageWithNoDoubleQuotes, start, length - start);
195 return output.toString();
199 * Checks the type signature in String sig, starting at start and ending
200 * before end (end is not included). Returns the index of the character
201 * immediately after the signature if valid, or -1 if not valid.
203 private static int checkTypeSignature(String sig, int start, int end,
208 char c = sig.charAt(i++);
209 int nestingDepth = 0;
229 // array of void is not allowed
230 if (nestingDepth != 0)
234 int semicolon = sig.indexOf(';', i);
235 // Must have at least one character between L and ;
236 if (semicolon <= i || semicolon >= end)
247 * Combines two hash codes to make a new one.
249 public static int combineHashCodes(int hashCode1, int hashCode2) {
250 return hashCode1 * 17 + hashCode2;
254 * Compares two byte arrays. Returns <0 if a byte in a is less than the
255 * corresponding byte in b, or if a is shorter, or if a is null. Returns >0
256 * if a byte in a is greater than the corresponding byte in b, or if a is
257 * longer, or if b is null. Returns 0 if they are equal or both null.
259 public static int compare(byte[] a, byte[] b) {
266 int len = Math.min(a.length, b.length);
267 for (int i = 0; i < len; ++i) {
268 int diff = a[i] - b[i];
280 * Compares two strings lexicographically. The comparison is based on the
281 * Unicode value of each character in the strings.
283 * @return the value <code>0</code> if the str1 is equal to str2; a value
284 * less than <code>0</code> if str1 is lexicographically less than
285 * str2; and a value greater than <code>0</code> if str1 is
286 * lexicographically greater than str2.
288 public static int compare(char[] str1, char[] str2) {
289 int len1 = str1.length;
290 int len2 = str2.length;
291 int n = Math.min(len1, len2);
304 * Concatenate two strings with a char in between.
306 * @see #concat(String, String)
308 public static String concat(String s1, char c, String s2) {
310 s1 = "null"; //$NON-NLS-1$
312 s2 = "null"; //$NON-NLS-1$
313 int l1 = s1.length();
314 int l2 = s2.length();
315 char[] buf = new char[l1 + 1 + l2];
316 s1.getChars(0, l1, buf, 0);
318 s2.getChars(0, l2, buf, l1 + 1);
319 return new String(buf);
323 * Concatenate two strings. Much faster than using +, which: - creates a
324 * StringBuffer, - which is synchronized, - of default size, so the
325 * resulting char array is often larger than needed. This implementation
326 * creates an extra char array, since the String constructor copies its
327 * argument, but there's no way around this.
329 public static String concat(String s1, String s2) {
331 s1 = "null"; //$NON-NLS-1$
333 s2 = "null"; //$NON-NLS-1$
334 int l1 = s1.length();
335 int l2 = s2.length();
336 char[] buf = new char[l1 + l2];
337 s1.getChars(0, l1, buf, 0);
338 s2.getChars(0, l2, buf, l1);
339 return new String(buf);
343 * Concatenate three strings.
345 * @see #concat(String, String)
347 public static String concat(String s1, String s2, String s3) {
349 s1 = "null"; //$NON-NLS-1$
351 s2 = "null"; //$NON-NLS-1$
353 s3 = "null"; //$NON-NLS-1$
354 int l1 = s1.length();
355 int l2 = s2.length();
356 int l3 = s3.length();
357 char[] buf = new char[l1 + l2 + l3];
358 s1.getChars(0, l1, buf, 0);
359 s2.getChars(0, l2, buf, l1);
360 s3.getChars(0, l3, buf, l1 + l2);
361 return new String(buf);
365 * Converts a type signature from the IBinaryType representation to the DC
368 public static String convertTypeSignature(char[] sig) {
369 return new String(sig).replace('/', '.');
373 * Apply the given edit on the given string and return the updated string.
374 * Return the given string if anything wrong happen while applying the edit.
381 * @return the updated string
383 // public final static String editedString(String original, TextEdit edit) {
384 // if (edit == null) {
387 // SimpleDocument document = new SimpleDocument(original);
389 // edit.apply(document, TextEdit.NONE);
390 // return document.get();
391 // } catch (MalformedTreeException e) {
392 // e.printStackTrace();
393 // } catch (BadLocationException e) {
394 // e.printStackTrace();
400 * Returns true iff str.toLowerCase().endsWith(end.toLowerCase())
401 * implementation is not creating extra strings.
403 public final static boolean endsWithIgnoreCase(String str, String end) {
405 int strLength = str == null ? 0 : str.length();
406 int endLength = end == null ? 0 : end.length();
408 // return false if the string is smaller than the end.
409 if (endLength > strLength)
412 // return false if any character of the end are
413 // not the same in lower case.
414 for (int i = 1; i <= endLength; i++) {
415 if (Character.toLowerCase(end.charAt(endLength - i)) != Character
416 .toLowerCase(str.charAt(strLength - i)))
424 * Compares two arrays using equals() on the elements. Either or both arrays
425 * may be null. Returns true if both are null. Returns false if only one is
426 * null. If both are arrays, returns true iff they have the same length and
427 * all elements are equal.
429 public static boolean equalArraysOrNull(int[] a, int[] b) {
432 if (a == null || b == null)
437 for (int i = 0; i < len; ++i) {
445 * Compares two arrays using equals() on the elements. Either or both arrays
446 * may be null. Returns true if both are null. Returns false if only one is
447 * null. If both are arrays, returns true iff they have the same length and
448 * all elements compare true with equals.
450 public static boolean equalArraysOrNull(Object[] a, Object[] b) {
453 if (a == null || b == null)
459 for (int i = 0; i < len; ++i) {
464 if (!a[i].equals(b[i]))
472 * Compares two arrays using equals() on the elements. The arrays are first
473 * sorted. Either or both arrays may be null. Returns true if both are null.
474 * Returns false if only one is null. If both are arrays, returns true iff
475 * they have the same length and iff, after sorting both arrays, all
476 * elements compare true with equals. The original arrays are left
479 public static boolean equalArraysOrNullSortFirst(Comparable[] a,
483 if (a == null || b == null)
488 if (len >= 2) { // only need to sort if more than two items
492 for (int i = 0; i < len; ++i) {
493 if (!a[i].equals(b[i]))
500 * Compares two String arrays using equals() on the elements. The arrays are
501 * first sorted. Either or both arrays may be null. Returns true if both are
502 * null. Returns false if only one is null. If both are arrays, returns true
503 * iff they have the same length and iff, after sorting both arrays, all
504 * elements compare true with equals. The original arrays are left
507 public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) {
510 if (a == null || b == null)
515 if (len >= 2) { // only need to sort if more than two items
519 for (int i = 0; i < len; ++i) {
520 if (!a[i].equals(b[i]))
527 * Compares two objects using equals(). Either or both array may be null.
528 * Returns true if both are null. Returns false if only one is null.
529 * Otherwise, return the result of comparing with equals().
531 public static boolean equalOrNull(Object a, Object b) {
535 if (a == null || b == null) {
542 * Given a qualified name, extract the last component. If the input is not
543 * qualified, the same string is answered.
545 public static String extractLastName(String qualifiedName) {
546 int i = qualifiedName.lastIndexOf('.');
548 return qualifiedName;
549 return qualifiedName.substring(i + 1);
553 * Extracts the parameter types from a method signature.
555 public static String[] extractParameterTypes(char[] sig) {
556 int count = getParameterCount(sig);
557 String[] result = new String[count];
560 int i = CharOperation.indexOf('(', sig) + 1;
562 int len = sig.length;
572 } else if (c == 'L') {
573 i = CharOperation.indexOf(';', sig, i + 1) + 1;
574 Assert.isTrue(i != 0);
575 result[count++] = convertTypeSignature(CharOperation.subarray(
580 result[count++] = convertTypeSignature(CharOperation.subarray(
589 * Extracts the return type from a method signature.
591 public static String extractReturnType(String sig) {
592 int i = sig.lastIndexOf(')');
593 Assert.isTrue(i != -1);
594 return sig.substring(i + 1);
597 // private static IFile findFirstClassFile(IFolder folder) {
599 // IResource[] members = folder.members();
600 // for (int i = 0, max = members.length; i < max; i++) {
601 // IResource member = members[i];
602 // if (member.getType() == IResource.FOLDER) {
603 // return findFirstClassFile((IFolder) member);
605 // // (net.sourceforge.phpdt.internal.compiler.util.Util.isClassFileName(member.getName()))
607 // // return (IFile) member;
610 // } catch (CoreException e) {
617 * Finds the first line separator used by the given text.
619 * @return</code> "\n"</code> or</code> "\r"</code> or</code> "\r\n"</code>,
620 * or <code>null</code> if none found
622 public static String findLineSeparator(char[] text) {
623 // find the first line separator
624 int length = text.length;
626 char nextChar = text[0];
627 for (int i = 0; i < length; i++) {
628 char currentChar = nextChar;
629 nextChar = i < length - 1 ? text[i + 1] : ' ';
630 switch (currentChar) {
632 return "\n"; //$NON-NLS-1$
634 return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
642 // public static IClassFileAttribute getAttribute(IClassFileReader
643 // classFileReader, char[] attributeName) {
644 // IClassFileAttribute[] attributes = classFileReader.getAttributes();
645 // for (int i = 0, max = attributes.length; i < max; i++) {
646 // if (CharOperation.equals(attributes[i].getAttributeName(),
648 // return attributes[i];
654 // public static IClassFileAttribute getAttribute(ICodeAttribute
655 // codeAttribute, char[] attributeName) {
656 // IClassFileAttribute[] attributes = codeAttribute.getAttributes();
657 // for (int i = 0, max = attributes.length; i < max; i++) {
658 // if (CharOperation.equals(attributes[i].getAttributeName(),
660 // return attributes[i];
666 // public static IClassFileAttribute getAttribute(IFieldInfo fieldInfo,
667 // char[] attributeName) {
668 // IClassFileAttribute[] attributes = fieldInfo.getAttributes();
669 // for (int i = 0, max = attributes.length; i < max; i++) {
670 // if (CharOperation.equals(attributes[i].getAttributeName(),
672 // return attributes[i];
678 // public static IClassFileAttribute getAttribute(IMethodInfo methodInfo,
679 // char[] attributeName) {
680 // IClassFileAttribute[] attributes = methodInfo.getAttributes();
681 // for (int i = 0, max = attributes.length; i < max; i++) {
682 // if (CharOperation.equals(attributes[i].getAttributeName(),
684 // return attributes[i];
690 * Get the jdk level of this root. The value can be:
692 * <li>major < <16 + minor : see predefined constants on ClassFileConstants</li>
693 * <li><code>0</null> if the root is a source package fragment root or if a Java model exception occured</li>
695 * Returns the jdk level
697 // public static long getJdkLevel(Object targetLibrary) {
699 // ClassFileReader reader = null;
700 // if (targetLibrary instanceof IFolder) {
701 // IFile classFile = findFirstClassFile((IFolder) targetLibrary); // only
702 // internal classfolders are allowed
703 // if (classFile != null) {
704 // byte[] bytes = Util.getResourceContentsAsByteArray(classFile);
705 // IPath location = classFile.getLocation();
706 // reader = new ClassFileReader(bytes, location == null ? null :
707 // location.toString().toCharArray());
710 // // root is a jar file or a zip file
711 // ZipFile jar = null;
713 // IPath path = null;
714 // if (targetLibrary instanceof IResource) {
715 // path = ((IResource)targetLibrary).getLocation();
716 // } else if (targetLibrary instanceof File){
717 // File f = (File) targetLibrary;
718 // if (!f.isDirectory()) {
719 // path = new Path(((File)targetLibrary).getPath());
722 // if (path != null) {
723 // jar = JavaModelManager.getJavaModelManager().getZipFile(path);
724 // for (Enumeration e= jar.entries(); e.hasMoreElements();) {
725 // ZipEntry member= (ZipEntry) e.nextElement();
726 // String entryName= member.getName();
728 // (net.sourceforge.phpdt.internal.compiler.util.Util.isClassFileName(entryName))
730 // reader = ClassFileReader.read(jar, entryName);
735 // } catch (CoreException e) {
738 // JavaModelManager.getJavaModelManager().closeZipFile(jar);
741 // if (reader != null) {
742 // return reader.getVersion();
744 // } catch(JavaModelException e) {
746 // } catch(ClassFormatException e) {
748 // } catch(IOException e) {
754 * Returns the line separator used by the given buffer. Uses the given text
757 * @return</code> "\n"</code> or</code> "\r"</code> or</code> "\r\n"</code>
759 private static String getLineSeparator(char[] text, char[] buffer) {
760 // search in this buffer's contents first
761 String lineSeparator = findLineSeparator(buffer);
762 if (lineSeparator == null) {
763 // search in the given text
764 lineSeparator = findLineSeparator(text);
765 if (lineSeparator == null) {
766 // default to system line separator
767 return net.sourceforge.phpdt.internal.compiler.util.Util.LINE_SEPARATOR;
770 return lineSeparator;
774 * Returns the number of parameter types in a method signature.
776 public static int getParameterCount(char[] sig) {
777 int i = CharOperation.indexOf('(', sig) + 1;
778 Assert.isTrue(i != 0);
780 int len = sig.length;
789 } else if (c == 'L') {
791 i = CharOperation.indexOf(';', sig, i + 1) + 1;
792 Assert.isTrue(i != 0);
802 * Put all the arguments in one String.
804 public static String getProblemArgumentsForMarker(String[] arguments) {
805 StringBuffer args = new StringBuffer(10);
807 args.append(arguments.length);
810 for (int j = 0; j < arguments.length; j++) {
812 args.append(ARGUMENTS_DELIMITER);
814 if (arguments[j].length() == 0) {
815 args.append(EMPTY_ARGUMENT);
817 args.append(arguments[j]);
821 return args.toString();
825 * Separate all the arguments of a String made by
826 * getProblemArgumentsForMarker
828 public static String[] getProblemArgumentsFromMarker(String argumentsString) {
829 if (argumentsString == null)
831 int index = argumentsString.indexOf(':');
835 int length = argumentsString.length();
838 numberOfArg = Integer.parseInt(argumentsString.substring(0, index));
839 } catch (NumberFormatException e) {
842 argumentsString = argumentsString.substring(index + 1, length);
844 String[] args = new String[length];
847 StringTokenizer tokenizer = new StringTokenizer(argumentsString,
848 ARGUMENTS_DELIMITER);
849 while (tokenizer.hasMoreTokens()) {
850 String argument = tokenizer.nextToken();
851 if (argument.equals(EMPTY_ARGUMENT))
852 argument = ""; //$NON-NLS-1$
853 args[count++] = argument;
856 if (count != numberOfArg)
859 System.arraycopy(args, 0, args = new String[count], 0, count);
864 * Returns the given file's contents as a byte array.
866 public static byte[] getResourceContentsAsByteArray(IFile file)
867 throws JavaModelException {
868 InputStream stream = null;
870 stream = new BufferedInputStream(file.getContents(true));
871 } catch (CoreException e) {
872 throw new JavaModelException(e);
875 return net.sourceforge.phpdt.internal.compiler.util.Util
876 .getInputStreamAsByteArray(stream, -1);
877 } catch (IOException e) {
878 throw new JavaModelException(e,
879 IJavaModelStatusConstants.IO_EXCEPTION);
883 } catch (IOException e) {
890 * Returns the given file's contents as a character array.
892 public static char[] getResourceContentsAsCharArray(IFile file)
893 throws JavaModelException {
894 // Get encoding from file
895 String encoding = null;
897 encoding = file.getCharset();
898 } catch (CoreException ce) {
899 // do not use any encoding
901 return getResourceContentsAsCharArray(file, encoding);
904 public static char[] getResourceContentsAsCharArray(IFile file,
905 String encoding) throws JavaModelException {
906 // Get resource contents
907 InputStream stream = null;
909 stream = new BufferedInputStream(file.getContents(true));
910 } catch (CoreException e) {
911 throw new JavaModelException(e,
912 IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST);
915 return net.sourceforge.phpdt.internal.compiler.util.Util
916 .getInputStreamAsCharArray(stream, -1, encoding);
917 } catch (IOException e) {
918 throw new JavaModelException(e,
919 IJavaModelStatusConstants.IO_EXCEPTION);
923 } catch (IOException e) {
930 * Returns a trimmed version the simples names returned by Signature.
932 public static String[] getTrimmedSimpleNames(String name) {
933 String[] result = Signature.getSimpleNames(name);
936 for (int i = 0, length = result.length; i < length; i++) {
937 result[i] = result[i].trim();
943 * Returns the index of the most specific argument paths which is strictly
944 * enclosing the path to check
946 public static int indexOfEnclosingPath(IPath checkedPath, IPath[] paths,
949 int bestMatch = -1, bestLength = -1;
950 for (int i = 0; i < pathCount; i++) {
951 if (paths[i].equals(checkedPath))
953 if (paths[i].isPrefixOf(checkedPath)) {
954 int currentLength = paths[i].segmentCount();
955 if (currentLength > bestLength) {
956 bestLength = currentLength;
965 * Returns the index of the first argument paths which is equal to the path
968 public static int indexOfMatchingPath(IPath checkedPath, IPath[] paths,
971 for (int i = 0; i < pathCount; i++) {
972 if (paths[i].equals(checkedPath))
979 * Returns the index of the first argument paths which is strictly nested
980 * inside the path to check
982 public static int indexOfNestedPath(IPath checkedPath, IPath[] paths,
985 for (int i = 0; i < pathCount; i++) {
986 if (checkedPath.equals(paths[i]))
988 if (checkedPath.isPrefixOf(paths[i]))
995 * Returns whether the given java element is exluded from its root's
996 * classpath. It doesn't check whether the root itself is on the classpath
999 public static final boolean isExcluded(IJavaElement element) {
1000 int elementType = element.getElementType();
1001 //PackageFragmentRoot root = null;
1002 //IResource resource = null;
1003 switch (elementType) {
1004 case IJavaElement.JAVA_MODEL:
1005 case IJavaElement.JAVA_PROJECT:
1006 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
1009 // case IJavaElement.PACKAGE_FRAGMENT:
1010 // PackageFragmentRoot root =
1011 // (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
1012 // IResource resource = element.getResource();
1013 // return resource != null && isExcluded(resource,
1014 // root.fullInclusionPatternChars(),
1015 // root.fullExclusionPatternChars());
1017 case IJavaElement.COMPILATION_UNIT:
1018 // root = (PackageFragmentRoot) element
1019 // .getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
1020 //resource = element.getResource();
1021 // if (resource != null && isExcluded(resource,
1022 // root.fullInclusionPatternChars(),
1023 // root.fullExclusionPatternChars()))
1025 return isExcluded(element.getParent());
1028 IJavaElement cu = element
1029 .getAncestor(IJavaElement.COMPILATION_UNIT);
1030 return cu != null && isExcluded(cu);
1035 * Returns whether the given resource path matches one of the
1036 * inclusion/exclusion patterns. NOTE: should not be asked directly using
1039 * @see IClasspathEntry#getInclusionPatterns
1040 * @see IClasspathEntry#getExclusionPatterns
1042 public final static boolean isExcluded(IPath resourcePath,
1043 char[][] inclusionPatterns, char[][] exclusionPatterns,
1044 boolean isFolderPath) {
1045 if (inclusionPatterns == null && exclusionPatterns == null)
1047 char[] path = resourcePath.toString().toCharArray();
1049 inclusionCheck: if (inclusionPatterns != null) {
1050 for (int i = 0, length = inclusionPatterns.length; i < length; i++) {
1051 char[] pattern = inclusionPatterns[i];
1052 char[] folderPattern = pattern;
1054 int lastSlash = CharOperation.lastIndexOf('/', pattern);
1055 if (lastSlash != -1 && lastSlash != pattern.length - 1) { // trailing
1063 // http://ant.apache.org/manual/dirtasks.html)
1064 int star = CharOperation.indexOf('*', pattern,
1066 if ((star == -1 || star >= pattern.length - 1 || pattern[star + 1] != '*')) {
1067 folderPattern = CharOperation.subarray(pattern, 0,
1072 if (CharOperation.pathMatch(folderPattern, path, true, '/')) {
1073 break inclusionCheck;
1076 return true; // never included
1079 path = CharOperation.concat(path, new char[] { '*' }, '/');
1081 exclusionCheck: if (exclusionPatterns != null) {
1082 for (int i = 0, length = exclusionPatterns.length; i < length; i++) {
1083 if (CharOperation.pathMatch(exclusionPatterns[i], path, true,
1092 public final static boolean isExcluded(IResource resource,
1093 char[][] exclusionPatterns) {
1094 IPath path = resource.getFullPath();
1095 // ensure that folders are only excluded if all of their children are
1097 return isExcluded(path, null, exclusionPatterns,
1098 resource.getType() == IResource.FOLDER);
1102 * Returns whether the given resource matches one of the exclusion patterns.
1103 * NOTE: should not be asked directly using pkg root pathes
1105 * @see IClasspathEntry#getExclusionPatterns
1107 public final static boolean isExcluded(IResource resource,
1108 char[][] inclusionPatterns, char[][] exclusionPatterns) {
1109 IPath path = resource.getFullPath();
1110 // ensure that folders are only excluded if all of their children are
1112 return isExcluded(path, inclusionPatterns, exclusionPatterns, resource
1113 .getType() == IResource.FOLDER);
1117 * Validate the given .class file name. A .class file name must obey the
1120 * <li>it must not be null
1121 * <li>it must include the <code>".class"</code> suffix
1122 * <li>its prefix must be a valid identifier
1127 * the name of a .class file
1128 * @return a status object with code <code>IStatus.OK</code> if the given
1129 * name is valid as a .class file name, otherwise a status object
1130 * indicating what is wrong with the name
1132 // public static boolean isValidClassFileName(String name) {
1133 // return JavaConventions.validateClassFileName(name).getSeverity() !=
1137 * Validate the given compilation unit name. A compilation unit name must
1138 * obey the following rules:
1140 * <li>it must not be null
1141 * <li>it must include the <code>".java"</code> suffix
1142 * <li>its prefix must be a valid identifier
1147 * the name of a compilation unit
1148 * @return a status object with code <code>IStatus.OK</code> if the given
1149 * name is valid as a compilation unit name, otherwise a status
1150 * object indicating what is wrong with the name
1152 public static boolean isValidCompilationUnitName(String name) {
1153 return PHPFileUtil.isPHPFileName(name);
1155 // JavaConventions.validateCompilationUnitName(name).getSeverity() !=
1160 * Returns true if the given folder name is valid for a package, false if it
1163 public static boolean isValidFolderNameForPackage(String folderName) {
1164 // return JavaConventions.validateIdentifier(folderName).getSeverity()
1165 // != IStatus.ERROR;
1170 * Returns true if the given method signature is valid, false if it is not.
1172 public static boolean isValidMethodSignature(String sig) {
1173 int len = sig.length();
1177 char c = sig.charAt(i++);
1182 while (sig.charAt(i) != ')') {
1183 // Void is not allowed as a parameter type.
1184 i = checkTypeSignature(sig, i, len, false);
1191 i = checkTypeSignature(sig, i, len, true);
1196 * Returns true if the given type signature is valid, false if it is not.
1198 public static boolean isValidTypeSignature(String sig, boolean allowVoid) {
1199 int len = sig.length();
1200 return checkTypeSignature(sig, 0, len, allowVoid) == len;
1206 public static void log(Throwable e, String message) {
1207 Throwable nestedException;
1208 if (e instanceof JavaModelException
1209 && (nestedException = ((JavaModelException) e).getException()) != null) {
1210 e = nestedException;
1212 IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID,
1213 IStatus.ERROR, message, e);
1214 JavaCore.getPlugin().getLog().log(status);
1218 * Normalizes the cariage returns in the given text. They are all changed to
1219 * use the given buffer's line separator.
1221 public static char[] normalizeCRs(char[] text, char[] buffer) {
1222 CharArrayBuffer result = new CharArrayBuffer();
1224 int length = text.length;
1227 String lineSeparator = getLineSeparator(text, buffer);
1228 char nextChar = text[0];
1229 for (int i = 0; i < length; i++) {
1230 char currentChar = nextChar;
1231 nextChar = i < length - 1 ? text[i + 1] : ' ';
1232 switch (currentChar) {
1234 int lineLength = i - lineStart;
1235 char[] line = new char[lineLength];
1236 System.arraycopy(text, lineStart, line, 0, lineLength);
1237 result.append(line);
1238 result.append(lineSeparator);
1242 lineLength = i - lineStart;
1243 if (lineLength >= 0) {
1244 line = new char[lineLength];
1245 System.arraycopy(text, lineStart, line, 0, lineLength);
1246 result.append(line);
1247 result.append(lineSeparator);
1248 if (nextChar == '\n') {
1252 // when line separator are mixed in the same file
1253 // \r might not be followed by a \n. If not, we should
1255 // lineStart by one and not by two.
1259 // when line separator are mixed in the same file
1260 // we need to prevent NegativeArraySizeException
1267 if (lineStart > 0) {
1268 int lastLineLength = length - lineStart;
1269 if (lastLineLength > 0) {
1270 lastLine = new char[lastLineLength];
1271 System.arraycopy(text, lineStart, lastLine, 0, lastLineLength);
1272 result.append(lastLine);
1274 return result.getContents();
1280 * Normalizes the cariage returns in the given text. They are all changed to
1281 * use given buffer's line sepatator.
1283 public static String normalizeCRs(String text, String buffer) {
1285 normalizeCRs(text.toCharArray(), buffer.toCharArray()));
1289 * Converts the given relative path into a package name. Returns null if the
1290 * path is not a valid package name.
1292 public static String packageName(IPath pkgPath) {
1293 StringBuffer pkgName = new StringBuffer(
1294 IPackageFragment.DEFAULT_PACKAGE_NAME);
1295 for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
1296 String segment = pkgPath.segment(j);
1297 // if (!isValidFolderNameForPackage(segment)) {
1300 pkgName.append(segment);
1301 if (j < pkgPath.segmentCount() - 1) {
1302 pkgName.append("."); //$NON-NLS-1$
1305 return pkgName.toString();
1309 * Returns the length of the common prefix between s1 and s2.
1311 public static int prefixLength(char[] s1, char[] s2) {
1313 int max = Math.min(s1.length, s2.length);
1314 for (int i = 0; i < max && s1[i] == s2[i]; ++i)
1320 * Returns the length of the common prefix between s1 and s2.
1322 public static int prefixLength(String s1, String s2) {
1324 int max = Math.min(s1.length(), s2.length());
1325 for (int i = 0; i < max && s1.charAt(i) == s2.charAt(i); ++i)
1330 private static void quickSort(char[][] list, int left, int right) {
1331 int original_left = left;
1332 int original_right = right;
1333 char[] mid = list[(left + right) / 2];
1335 while (compare(list[left], mid) < 0) {
1338 while (compare(mid, list[right]) < 0) {
1341 if (left <= right) {
1342 char[] tmp = list[left];
1343 list[left] = list[right];
1348 } while (left <= right);
1349 if (original_left < right) {
1350 quickSort(list, original_left, right);
1352 if (left < original_right) {
1353 quickSort(list, left, original_right);
1358 * Sort the comparable objects in the given collection.
1360 private static void quickSort(Comparable[] sortedCollection, int left,
1362 int original_left = left;
1363 int original_right = right;
1364 Comparable mid = sortedCollection[(left + right) / 2];
1366 while (sortedCollection[left].compareTo(mid) < 0) {
1369 while (mid.compareTo(sortedCollection[right]) < 0) {
1372 if (left <= right) {
1373 Comparable tmp = sortedCollection[left];
1374 sortedCollection[left] = sortedCollection[right];
1375 sortedCollection[right] = tmp;
1379 } while (left <= right);
1380 if (original_left < right) {
1381 quickSort(sortedCollection, original_left, right);
1383 if (left < original_right) {
1384 quickSort(sortedCollection, left, original_right);
1388 private static void quickSort(int[] list, int left, int right) {
1389 int original_left = left;
1390 int original_right = right;
1391 int mid = list[(left + right) / 2];
1393 while (list[left] < mid) {
1396 while (mid < list[right]) {
1399 if (left <= right) {
1400 int tmp = list[left];
1401 list[left] = list[right];
1406 } while (left <= right);
1407 if (original_left < right) {
1408 quickSort(list, original_left, right);
1410 if (left < original_right) {
1411 quickSort(list, left, original_right);
1416 * Sort the objects in the given collection using the given comparer.
1418 private static void quickSort(Object[] sortedCollection, int left,
1419 int right, Comparer comparer) {
1420 int original_left = left;
1421 int original_right = right;
1422 Object mid = sortedCollection[(left + right) / 2];
1424 while (comparer.compare(sortedCollection[left], mid) < 0) {
1427 while (comparer.compare(mid, sortedCollection[right]) < 0) {
1430 if (left <= right) {
1431 Object tmp = sortedCollection[left];
1432 sortedCollection[left] = sortedCollection[right];
1433 sortedCollection[right] = tmp;
1437 } while (left <= right);
1438 if (original_left < right) {
1439 quickSort(sortedCollection, original_left, right, comparer);
1441 if (left < original_right) {
1442 quickSort(sortedCollection, left, original_right, comparer);
1447 * Sort the objects in the given collection using the given sort order.
1449 private static void quickSort(Object[] sortedCollection, int left,
1450 int right, int[] sortOrder) {
1451 int original_left = left;
1452 int original_right = right;
1453 int mid = sortOrder[(left + right) / 2];
1455 while (sortOrder[left] < mid) {
1458 while (mid < sortOrder[right]) {
1461 if (left <= right) {
1462 Object tmp = sortedCollection[left];
1463 sortedCollection[left] = sortedCollection[right];
1464 sortedCollection[right] = tmp;
1465 int tmp2 = sortOrder[left];
1466 sortOrder[left] = sortOrder[right];
1467 sortOrder[right] = tmp2;
1471 } while (left <= right);
1472 if (original_left < right) {
1473 quickSort(sortedCollection, original_left, right, sortOrder);
1475 if (left < original_right) {
1476 quickSort(sortedCollection, left, original_right, sortOrder);
1481 * Sort the strings in the given collection.
1483 private static void quickSort(String[] sortedCollection, int left, int right) {
1484 int original_left = left;
1485 int original_right = right;
1486 String mid = sortedCollection[(left + right) / 2];
1488 while (sortedCollection[left].compareTo(mid) < 0) {
1491 while (mid.compareTo(sortedCollection[right]) < 0) {
1494 if (left <= right) {
1495 String tmp = sortedCollection[left];
1496 sortedCollection[left] = sortedCollection[right];
1497 sortedCollection[right] = tmp;
1501 } while (left <= right);
1502 if (original_left < right) {
1503 quickSort(sortedCollection, original_left, right);
1505 if (left < original_right) {
1506 quickSort(sortedCollection, left, original_right);
1511 * Sort the strings in the given collection in reverse alphabetical order.
1513 private static void quickSortReverse(String[] sortedCollection, int left,
1515 int original_left = left;
1516 int original_right = right;
1517 String mid = sortedCollection[(left + right) / 2];
1519 while (sortedCollection[left].compareTo(mid) > 0) {
1522 while (mid.compareTo(sortedCollection[right]) > 0) {
1525 if (left <= right) {
1526 String tmp = sortedCollection[left];
1527 sortedCollection[left] = sortedCollection[right];
1528 sortedCollection[right] = tmp;
1532 } while (left <= right);
1533 if (original_left < right) {
1534 quickSortReverse(sortedCollection, original_left, right);
1536 if (left < original_right) {
1537 quickSortReverse(sortedCollection, left, original_right);
1542 * Reads in a string from the specified data input stream. The string has
1543 * been encoded using a modified UTF-8 format.
1545 * The first two bytes are read as if by <code>readUnsignedShort</code>.
1546 * This value gives the number of following bytes that are in the encoded
1547 * string, not the length of the resulting string. The following bytes are
1548 * then interpreted as bytes encoding characters in the UTF-8 format and are
1549 * converted into characters.
1551 * This method blocks until all the bytes are read, the end of the stream is
1552 * detected, or an exception is thrown.
1555 * a data input stream.
1556 * @return a Unicode string.
1557 * @exception EOFException
1558 * if the input stream reaches the end before all the bytes.
1559 * @exception IOException
1560 * if an I/O error occurs.
1561 * @exception UTFDataFormatException
1562 * if the bytes do not represent a valid UTF-8 encoding of a
1564 * @see java.io.DataInputStream#readUnsignedShort()
1566 public final static char[] readUTF(DataInput in) throws IOException {
1567 int utflen = in.readUnsignedShort();
1568 char str[] = new char[utflen];
1571 while (count < utflen) {
1572 int c = in.readUnsignedByte();
1585 str[strlen++] = (char) c;
1589 // 110x xxxx 10xx xxxx
1592 throw new UTFDataFormatException();
1593 char2 = in.readUnsignedByte();
1594 if ((char2 & 0xC0) != 0x80)
1595 throw new UTFDataFormatException();
1596 str[strlen++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
1599 // 1110 xxxx 10xx xxxx 10xx xxxx
1602 throw new UTFDataFormatException();
1603 char2 = in.readUnsignedByte();
1604 char3 = in.readUnsignedByte();
1605 if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
1606 throw new UTFDataFormatException();
1607 str[strlen++] = (char) (((c & 0x0F) << 12)
1608 | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
1611 // 10xx xxxx, 1111 xxxx
1612 throw new UTFDataFormatException();
1615 if (strlen < utflen) {
1616 System.arraycopy(str, 0, str = new char[strlen], 0, strlen);
1622 * Creates a NLS catalog for the given locale.
1624 public static void relocalize() {
1626 bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
1627 } catch (MissingResourceException e) {
1629 .println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
1634 public static void sort(char[][] list) {
1635 if (list.length > 1)
1636 quickSort(list, 0, list.length - 1);
1640 * Sorts an array of Comparable objects in place.
1642 public static void sort(Comparable[] objects) {
1643 if (objects.length > 1)
1644 quickSort(objects, 0, objects.length - 1);
1647 public static void sort(int[] list) {
1648 if (list.length > 1)
1649 quickSort(list, 0, list.length - 1);
1653 * Sorts an array of objects in place. The given comparer compares pairs of
1656 public static void sort(Object[] objects, Comparer comparer) {
1657 if (objects.length > 1)
1658 quickSort(objects, 0, objects.length - 1, comparer);
1662 * Sorts an array of objects in place, using the sort order given for each
1665 public static void sort(Object[] objects, int[] sortOrder) {
1666 if (objects.length > 1)
1667 quickSort(objects, 0, objects.length - 1, sortOrder);
1671 * Sorts an array of strings in place using quicksort.
1673 public static void sort(String[] strings) {
1674 if (strings.length > 1)
1675 quickSort(strings, 0, strings.length - 1);
1679 * Sorts an array of Comparable objects, returning a new array with the
1680 * sorted items. The original array is left untouched.
1682 public static Comparable[] sortCopy(Comparable[] objects) {
1683 int len = objects.length;
1684 Comparable[] copy = new Comparable[len];
1685 System.arraycopy(objects, 0, copy, 0, len);
1691 * Sorts an array of Strings, returning a new array with the sorted items.
1692 * The original array is left untouched.
1694 public static Object[] sortCopy(Object[] objects, Comparer comparer) {
1695 int len = objects.length;
1696 Object[] copy = new Object[len];
1697 System.arraycopy(objects, 0, copy, 0, len);
1698 sort(copy, comparer);
1703 * Sorts an array of Strings, returning a new array with the sorted items.
1704 * The original array is left untouched.
1706 public static String[] sortCopy(String[] objects) {
1707 int len = objects.length;
1708 String[] copy = new String[len];
1709 System.arraycopy(objects, 0, copy, 0, len);
1715 * Sorts an array of strings in place using quicksort in reverse
1716 * alphabetical order.
1718 public static void sortReverseOrder(String[] strings) {
1719 if (strings.length > 1)
1720 quickSortReverse(strings, 0, strings.length - 1);
1724 * Converts a String[] to char[][].
1726 public static char[][] toCharArrays(String[] a) {
1728 char[][] result = new char[len][];
1729 for (int i = 0; i < len; ++i) {
1730 result[i] = toChars(a[i]);
1736 * Converts a String to char[].
1738 public static char[] toChars(String s) {
1739 int len = s.length();
1740 char[] chars = new char[len];
1741 s.getChars(0, len, chars, 0);
1746 * Converts a String to char[][], where segments are separate by '.'.
1748 public static char[][] toCompoundChars(String s) {
1749 int len = s.length();
1751 return CharOperation.NO_CHAR_CHAR;
1754 for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) {
1757 char[][] segs = new char[segCount][];
1759 for (int i = 0; i < segCount; ++i) {
1760 int dot = s.indexOf('.', start);
1761 int end = (dot == -1 ? s.length() : dot);
1762 segs[i] = new char[end - start];
1763 s.getChars(start, end, segs[i], 0);
1770 * Converts a char[] to String.
1772 public static String toString(char[] c) {
1773 return new String(c);
1777 * Converts a char[][] to String, where segments are separated by '.'.
1779 public static String toString(char[][] c) {
1780 StringBuffer sb = new StringBuffer();
1781 for (int i = 0, max = c.length; i < max; ++i) {
1786 return sb.toString();
1790 * Converts a char[][] and a char[] to String, where segments are separated
1793 public static String toString(char[][] c, char[] d) {
1795 return new String(d);
1796 StringBuffer sb = new StringBuffer();
1797 for (int i = 0, max = c.length; i < max; ++i) {
1802 return sb.toString();
1806 * Returns the unresolved type parameter signatures of the given method e.g.
1807 * {"QString;", "[int", "[[Qjava.util.Vector;"}
1809 // public static String[] typeParameterSignatures(AbstractMethodDeclaration
1811 // Argument[] args = method.arguments;
1812 // if (args != null) {
1813 // int length = args.length;
1814 // String[] signatures = new String[length];
1815 // for (int i = 0; i < args.length; i++) {
1816 // Argument arg = args[i];
1817 // signatures[i] = typeSignature(arg.type);
1819 // return signatures;
1821 // return new String[0];
1824 * Returns the unresolved type signature of the given type reference, e.g.
1825 * "QString;", "[int", "[[Qjava.util.Vector;"
1827 // public static String typeSignature(TypeReference type) {
1828 // char[][] compoundName = type.getTypeName();
1829 // char[] typeName =CharOperation.concatWith(compoundName, '.');
1830 // String signature = Signature.createTypeSignature(typeName, false/*don't
1832 // int dimensions = type.dimensions();
1833 // if (dimensions > 0) {
1834 // signature = Signature.createArraySignature(signature, dimensions);
1836 // return signature;
1839 * Returns the unresolved type signature of the given type reference, e.g.
1840 * "QString;", "[int", "[[Qjava.util.Vector;"
1842 public static String typeSignature(TypeReference type) {
1843 char[][] compoundName = type.getTypeName();
1844 char[] typeName = CharOperation.concatWith(compoundName, '.');
1845 String signature = Signature
1846 .createTypeSignature(typeName, false/* don't resolve */);
1847 int dimensions = type.dimensions();
1848 if (dimensions > 0) {
1849 signature = Signature.createArraySignature(signature, dimensions);
1855 * Asserts that the given method signature is valid.
1857 public static void validateMethodSignature(String sig) {
1858 Assert.isTrue(isValidMethodSignature(sig));
1862 * Asserts that the given type signature is valid.
1864 public static void validateTypeSignature(String sig, boolean allowVoid) {
1865 Assert.isTrue(isValidTypeSignature(sig, allowVoid));
1868 public static void verbose(String log) {
1869 verbose(log, System.out);
1872 public static synchronized void verbose(String log, PrintStream printStream) {
1875 int end = log.indexOf('\n', start);
1876 printStream.print(Thread.currentThread());
1877 printStream.print(" "); //$NON-NLS-1$
1878 printStream.print(log.substring(start, end == -1 ? log.length()
1881 } while (start != 0);
1882 printStream.println();
1886 * Writes a string to the given output stream using UTF-8 encoding in a
1887 * machine-independent manner.
1889 * First, two bytes are written to the output stream as if by the
1890 * <code>writeShort</code> method giving the number of bytes to follow.
1891 * This value is the number of bytes actually written out, not the length of
1892 * the string. Following the length, each character of the string is output,
1893 * in sequence, using the UTF-8 encoding for the character.
1896 * a string to be written.
1897 * @return the number of bytes written to the stream.
1898 * @exception IOException
1899 * if an I/O error occurs.
1902 public static int writeUTF(OutputStream out, char[] str) throws IOException {
1903 int strlen = str.length;
1905 for (int i = 0; i < strlen; i++) {
1907 if ((c >= 0x0001) && (c <= 0x007F)) {
1909 } else if (c > 0x07FF) {
1916 throw new UTFDataFormatException();
1917 out.write((utflen >>> 8) & 0xFF);
1918 out.write((utflen >>> 0) & 0xFF);
1919 if (strlen == utflen) {
1920 for (int i = 0; i < strlen; i++)
1923 for (int i = 0; i < strlen; i++) {
1925 if ((c >= 0x0001) && (c <= 0x007F)) {
1927 } else if (c > 0x07FF) {
1928 out.write(0xE0 | ((c >> 12) & 0x0F));
1929 out.write(0x80 | ((c >> 6) & 0x3F));
1930 out.write(0x80 | ((c >> 0) & 0x3F));
1932 out.write(0xC0 | ((c >> 6) & 0x1F));
1933 out.write(0x80 | ((c >> 0) & 0x3F));
1937 return utflen + 2; // the number of bytes written to the stream