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.core.Assert;
34 import net.sourceforge.phpdt.internal.core.PackageFragmentRoot;
35 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
36 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
38 import org.eclipse.core.resources.IFile;
39 import org.eclipse.core.resources.IFolder;
40 import org.eclipse.core.resources.IResource;
41 import org.eclipse.core.runtime.CoreException;
42 import org.eclipse.core.runtime.IPath;
43 import org.eclipse.core.runtime.IStatus;
44 import org.eclipse.core.runtime.Status;
45 import org.eclipse.jface.text.BadLocationException;
46 import org.eclipse.text.edits.MalformedTreeException;
47 import org.eclipse.text.edits.TextEdit;
50 * Provides convenient utility methods to other types in this package.
54 public interface Comparable {
56 * Returns 0 if this and c are equal, >0 if this is greater than c, or <0 if this is less than c.
58 int compareTo(Comparable c);
61 public interface Comparer {
63 * Returns 0 if a and b are equal, >0 if a is greater than b, or <0 if a is less than b.
65 int compare(Object a, Object b);
68 private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
70 /* Bundle containing messages */
71 protected static ResourceBundle bundle;
73 private final static String bundleName = "net.sourceforge.phpdt.internal.core.util.messages"; //$NON-NLS-1$
75 private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
77 private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$
79 public static final String[] fgEmptyStringArray = new String[0];
81 private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
88 // cannot be instantiated
92 * Lookup the message with the given ID in this catalog
94 public static String bind(String id) {
95 return bind(id, (String[]) null);
99 * Lookup the message with the given ID in this catalog and bind its substitution locations with the given string.
101 public static String bind(String id, String binding) {
102 return bind(id, new String[] { binding });
106 * Lookup the message with the given ID in this catalog and bind its substitution locations with the given strings.
108 public static String bind(String id, String binding1, String binding2) {
109 return bind(id, new String[] { binding1, binding2 });
113 * Lookup the message with the given ID in this catalog and bind its substitution locations with the given string values.
115 public static String bind(String id, String[] bindings) {
117 return "No message available"; //$NON-NLS-1$
118 String message = null;
120 message = bundle.getString(id);
121 } catch (MissingResourceException e) {
122 // If we got an exception looking for the message, fail gracefully by just returning
123 // the id we were looking for. In most cases this is semi-informative so is not too bad.
124 return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
126 // for compatibility with MessageFormat which eliminates double quotes in original message
127 char[] messageWithNoDoubleQuotes = CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
129 if (bindings == null)
130 return new String(messageWithNoDoubleQuotes);
132 int length = messageWithNoDoubleQuotes.length;
135 StringBuffer output = null;
137 if ((end = CharOperation.indexOf('{', messageWithNoDoubleQuotes, start)) > -1) {
139 output = new StringBuffer(length + bindings.length * 20);
140 output.append(messageWithNoDoubleQuotes, start, end - start);
141 if ((start = CharOperation.indexOf('}', messageWithNoDoubleQuotes, end + 1)) > -1) {
143 String argId = new String(messageWithNoDoubleQuotes, end + 1, start - end - 1);
145 index = Integer.parseInt(argId);
146 output.append(bindings[index]);
147 } catch (NumberFormatException nfe) { // could be nested message ID {compiler.name}
148 boolean done = false;
149 if (!id.equals(argId)) {
150 String argMessage = null;
152 argMessage = bundle.getString(argId);
153 output.append(argMessage);
155 } catch (MissingResourceException e) {
156 // unable to bind argument, ignore (will leave argument in)
160 output.append(messageWithNoDoubleQuotes, end + 1, start - end);
161 } catch (ArrayIndexOutOfBoundsException e) {
162 output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
166 output.append(messageWithNoDoubleQuotes, end, length);
171 return new String(messageWithNoDoubleQuotes);
172 output.append(messageWithNoDoubleQuotes, start, length - start);
176 return output.toString();
180 * Checks the type signature in String sig, starting at start and ending before end (end is not included). Returns the index of
181 * the character immediately after the signature if valid, or -1 if not valid.
183 private static int checkTypeSignature(String sig, int start, int end, boolean allowVoid) {
187 char c = sig.charAt(i++);
188 int nestingDepth = 0;
208 // array of void is not allowed
209 if (nestingDepth != 0)
213 int semicolon = sig.indexOf(';', i);
214 // Must have at least one character between L and ;
215 if (semicolon <= i || semicolon >= end)
226 * Combines two hash codes to make a new one.
228 public static int combineHashCodes(int hashCode1, int hashCode2) {
229 return hashCode1 * 17 + hashCode2;
233 * Compares two byte arrays. Returns <0 if a byte in a is less than the corresponding byte in b, or if a is shorter, or if a is
234 * null. 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. Returns 0 if
235 * they are equal or both null.
237 public static int compare(byte[] a, byte[] b) {
244 int len = Math.min(a.length, b.length);
245 for (int i = 0; i < len; ++i) {
246 int diff = a[i] - b[i];
258 * Compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings.
260 * @return the value <code>0</code> if the str1 is equal to str2; a value less than <code>0</code> if str1 is
261 * lexicographically less than str2; and a value greater than <code>0</code> if str1 is lexicographically greater than
264 public static int compare(char[] str1, char[] str2) {
265 int len1 = str1.length;
266 int len2 = str2.length;
267 int n = Math.min(len1, len2);
280 * Concatenate two strings with a char in between.
282 * @see #concat(String, String)
284 public static String concat(String s1, char c, String s2) {
286 s1 = "null"; //$NON-NLS-1$
288 s2 = "null"; //$NON-NLS-1$
289 int l1 = s1.length();
290 int l2 = s2.length();
291 char[] buf = new char[l1 + 1 + l2];
292 s1.getChars(0, l1, buf, 0);
294 s2.getChars(0, l2, buf, l1 + 1);
295 return new String(buf);
299 * Concatenate two strings. Much faster than using +, which: - creates a StringBuffer, - which is synchronized, - of default size,
300 * so the resulting char array is often larger than needed. This implementation creates an extra char array, since the String
301 * constructor copies its argument, but there's no way around this.
303 public static String concat(String s1, String s2) {
305 s1 = "null"; //$NON-NLS-1$
307 s2 = "null"; //$NON-NLS-1$
308 int l1 = s1.length();
309 int l2 = s2.length();
310 char[] buf = new char[l1 + l2];
311 s1.getChars(0, l1, buf, 0);
312 s2.getChars(0, l2, buf, l1);
313 return new String(buf);
317 * Concatenate three strings.
319 * @see #concat(String, String)
321 public static String concat(String s1, String s2, String s3) {
323 s1 = "null"; //$NON-NLS-1$
325 s2 = "null"; //$NON-NLS-1$
327 s3 = "null"; //$NON-NLS-1$
328 int l1 = s1.length();
329 int l2 = s2.length();
330 int l3 = s3.length();
331 char[] buf = new char[l1 + l2 + l3];
332 s1.getChars(0, l1, buf, 0);
333 s2.getChars(0, l2, buf, l1);
334 s3.getChars(0, l3, buf, l1 + l2);
335 return new String(buf);
339 * Converts a type signature from the IBinaryType representation to the DC representation.
341 public static String convertTypeSignature(char[] sig) {
342 return new String(sig).replace('/', '.');
346 * Apply the given edit on the given string and return the updated string. Return the given string if anything wrong happen while
354 * @return the updated string
356 public final static String editedString(String original, TextEdit edit) {
360 SimpleDocument document = new SimpleDocument(original);
362 edit.apply(document, TextEdit.NONE);
363 return document.get();
364 } catch (MalformedTreeException e) {
366 } catch (BadLocationException e) {
373 * Returns true iff str.toLowerCase().endsWith(end.toLowerCase()) implementation is not creating extra strings.
375 public final static boolean endsWithIgnoreCase(String str, String end) {
377 int strLength = str == null ? 0 : str.length();
378 int endLength = end == null ? 0 : end.length();
380 // return false if the string is smaller than the end.
381 if (endLength > strLength)
384 // return false if any character of the end are
385 // not the same in lower case.
386 for (int i = 1; i <= endLength; i++) {
387 if (Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i)))
395 * Compares two arrays using equals() on the elements. Either or both arrays may be null. Returns true if both are null. Returns
396 * false if only one is null. If both are arrays, returns true iff they have the same length and all elements are equal.
398 public static boolean equalArraysOrNull(int[] a, int[] b) {
401 if (a == null || b == null)
406 for (int i = 0; i < len; ++i) {
414 * Compares two arrays using equals() on the elements. Either or both arrays may be null. Returns true if both are null. Returns
415 * false if only one is null. If both are arrays, returns true iff they have the same length and all elements compare true with
418 public static boolean equalArraysOrNull(Object[] a, Object[] b) {
421 if (a == null || b == null)
427 for (int i = 0; i < len; ++i) {
432 if (!a[i].equals(b[i]))
440 * Compares two arrays using equals() on the elements. The arrays are first sorted. Either or both arrays may be null. Returns
441 * true if both are null. Returns false if only one is null. If both are arrays, returns true iff they have the same length and
442 * iff, after sorting both arrays, all elements compare true with equals. The original arrays are left untouched.
444 public static boolean equalArraysOrNullSortFirst(Comparable[] a, Comparable[] b) {
447 if (a == null || b == null)
452 if (len >= 2) { // only need to sort if more than two items
456 for (int i = 0; i < len; ++i) {
457 if (!a[i].equals(b[i]))
464 * Compares two String arrays using equals() on the elements. The arrays are first sorted. Either or both arrays may be null.
465 * Returns true if both are null. Returns false if only one is null. If both are arrays, returns true iff they have the same
466 * length and iff, after sorting both arrays, all elements compare true with equals. The original arrays are left untouched.
468 public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) {
471 if (a == null || b == null)
476 if (len >= 2) { // only need to sort if more than two items
480 for (int i = 0; i < len; ++i) {
481 if (!a[i].equals(b[i]))
488 * Compares two objects using equals(). Either or both array may be null. Returns true if both are null. Returns false if only one
489 * is null. Otherwise, return the result of comparing with equals().
491 public static boolean equalOrNull(Object a, Object b) {
495 if (a == null || b == null) {
502 * Given a qualified name, extract the last component. If the input is not qualified, the same string is answered.
504 public static String extractLastName(String qualifiedName) {
505 int i = qualifiedName.lastIndexOf('.');
507 return qualifiedName;
508 return qualifiedName.substring(i + 1);
512 * Extracts the parameter types from a method signature.
514 public static String[] extractParameterTypes(char[] sig) {
515 int count = getParameterCount(sig);
516 String[] result = new String[count];
519 int i = CharOperation.indexOf('(', sig) + 1;
521 int len = sig.length;
531 } else if (c == 'L') {
532 i = CharOperation.indexOf(';', sig, i + 1) + 1;
533 Assert.isTrue(i != 0);
534 result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
538 result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
546 * Extracts the return type from a method signature.
548 public static String extractReturnType(String sig) {
549 int i = sig.lastIndexOf(')');
550 Assert.isTrue(i != -1);
551 return sig.substring(i + 1);
554 private static IFile findFirstClassFile(IFolder folder) {
556 IResource[] members = folder.members();
557 for (int i = 0, max = members.length; i < max; i++) {
558 IResource member = members[i];
559 if (member.getType() == IResource.FOLDER) {
560 return findFirstClassFile((IFolder) member);
561 } else if (net.sourceforge.phpdt.internal.compiler.util.Util.isClassFileName(member.getName())) {
562 return (IFile) member;
565 } catch (CoreException e) {
572 * Finds the first line separator used by the given text.
574 * @return</code> "\n"</code> or</code> "\r"</code> or</code> "\r\n"</code>, or <code>null</code> if none found
576 public static String findLineSeparator(char[] text) {
577 // find the first line separator
578 int length = text.length;
580 char nextChar = text[0];
581 for (int i = 0; i < length; i++) {
582 char currentChar = nextChar;
583 nextChar = i < length - 1 ? text[i + 1] : ' ';
584 switch (currentChar) {
586 return "\n"; //$NON-NLS-1$
588 return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
596 // public static IClassFileAttribute getAttribute(IClassFileReader classFileReader, char[] attributeName) {
597 // IClassFileAttribute[] attributes = classFileReader.getAttributes();
598 // for (int i = 0, max = attributes.length; i < max; i++) {
599 // if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
600 // return attributes[i];
606 // public static IClassFileAttribute getAttribute(ICodeAttribute codeAttribute, char[] attributeName) {
607 // IClassFileAttribute[] attributes = codeAttribute.getAttributes();
608 // for (int i = 0, max = attributes.length; i < max; i++) {
609 // if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
610 // return attributes[i];
616 // public static IClassFileAttribute getAttribute(IFieldInfo fieldInfo, char[] attributeName) {
617 // IClassFileAttribute[] attributes = fieldInfo.getAttributes();
618 // for (int i = 0, max = attributes.length; i < max; i++) {
619 // if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
620 // return attributes[i];
626 // public static IClassFileAttribute getAttribute(IMethodInfo methodInfo, char[] attributeName) {
627 // IClassFileAttribute[] attributes = methodInfo.getAttributes();
628 // for (int i = 0, max = attributes.length; i < max; i++) {
629 // if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
630 // return attributes[i];
636 * Get the jdk level of this root. The value can be:
638 * <li>major < <16 + minor : see predefined constants on ClassFileConstants</li>
639 * <li><code>0</null> if the root is a source package fragment root or if a Java model exception occured</li>
641 * Returns the jdk level
643 // public static long getJdkLevel(Object targetLibrary) {
645 // ClassFileReader reader = null;
646 // if (targetLibrary instanceof IFolder) {
647 // IFile classFile = findFirstClassFile((IFolder) targetLibrary); // only internal classfolders are allowed
648 // if (classFile != null) {
649 // byte[] bytes = Util.getResourceContentsAsByteArray(classFile);
650 // IPath location = classFile.getLocation();
651 // reader = new ClassFileReader(bytes, location == null ? null : location.toString().toCharArray());
654 // // root is a jar file or a zip file
655 // ZipFile jar = null;
657 // IPath path = null;
658 // if (targetLibrary instanceof IResource) {
659 // path = ((IResource)targetLibrary).getLocation();
660 // } else if (targetLibrary instanceof File){
661 // File f = (File) targetLibrary;
662 // if (!f.isDirectory()) {
663 // path = new Path(((File)targetLibrary).getPath());
666 // if (path != null) {
667 // jar = JavaModelManager.getJavaModelManager().getZipFile(path);
668 // for (Enumeration e= jar.entries(); e.hasMoreElements();) {
669 // ZipEntry member= (ZipEntry) e.nextElement();
670 // String entryName= member.getName();
671 // if (net.sourceforge.phpdt.internal.compiler.util.Util.isClassFileName(entryName)) {
672 // reader = ClassFileReader.read(jar, entryName);
677 // } catch (CoreException e) {
680 // JavaModelManager.getJavaModelManager().closeZipFile(jar);
683 // if (reader != null) {
684 // return reader.getVersion();
686 // } catch(JavaModelException e) {
688 // } catch(ClassFormatException e) {
690 // } catch(IOException e) {
696 * Returns the line separator used by the given buffer. Uses the given text if none found.
698 * @return</code> "\n"</code> or</code> "\r"</code> or</code> "\r\n"</code>
700 private static String getLineSeparator(char[] text, char[] buffer) {
701 // search in this buffer's contents first
702 String lineSeparator = findLineSeparator(buffer);
703 if (lineSeparator == null) {
704 // search in the given text
705 lineSeparator = findLineSeparator(text);
706 if (lineSeparator == null) {
707 // default to system line separator
708 return net.sourceforge.phpdt.internal.compiler.util.Util.LINE_SEPARATOR;
711 return lineSeparator;
715 * Returns the number of parameter types in a method signature.
717 public static int getParameterCount(char[] sig) {
718 int i = CharOperation.indexOf('(', sig) + 1;
719 Assert.isTrue(i != 0);
721 int len = sig.length;
730 } else if (c == 'L') {
732 i = CharOperation.indexOf(';', sig, i + 1) + 1;
733 Assert.isTrue(i != 0);
743 * Put all the arguments in one String.
745 public static String getProblemArgumentsForMarker(String[] arguments) {
746 StringBuffer args = new StringBuffer(10);
748 args.append(arguments.length);
751 for (int j = 0; j < arguments.length; j++) {
753 args.append(ARGUMENTS_DELIMITER);
755 if (arguments[j].length() == 0) {
756 args.append(EMPTY_ARGUMENT);
758 args.append(arguments[j]);
762 return args.toString();
766 * Separate all the arguments of a String made by getProblemArgumentsForMarker
768 public static String[] getProblemArgumentsFromMarker(String argumentsString) {
769 if (argumentsString == null)
771 int index = argumentsString.indexOf(':');
775 int length = argumentsString.length();
778 numberOfArg = Integer.parseInt(argumentsString.substring(0, index));
779 } catch (NumberFormatException e) {
782 argumentsString = argumentsString.substring(index + 1, length);
784 String[] args = new String[length];
787 StringTokenizer tokenizer = new StringTokenizer(argumentsString, ARGUMENTS_DELIMITER);
788 while (tokenizer.hasMoreTokens()) {
789 String argument = tokenizer.nextToken();
790 if (argument.equals(EMPTY_ARGUMENT))
791 argument = ""; //$NON-NLS-1$
792 args[count++] = argument;
795 if (count != numberOfArg)
798 System.arraycopy(args, 0, args = new String[count], 0, count);
803 * Returns the given file's contents as a byte array.
805 public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException {
806 InputStream stream = null;
808 stream = new BufferedInputStream(file.getContents(true));
809 } catch (CoreException e) {
810 throw new JavaModelException(e);
813 return net.sourceforge.phpdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1);
814 } catch (IOException e) {
815 throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
819 } catch (IOException e) {
826 * Returns the given file's contents as a character array.
828 public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException {
829 // Get encoding from file
830 String encoding = null;
832 encoding = file.getCharset();
833 } catch (CoreException ce) {
834 // do not use any encoding
836 return getResourceContentsAsCharArray(file, encoding);
839 public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException {
840 // Get resource contents
841 InputStream stream = null;
843 stream = new BufferedInputStream(file.getContents(true));
844 } catch (CoreException e) {
845 throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST);
848 return net.sourceforge.phpdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding);
849 } catch (IOException e) {
850 throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
854 } catch (IOException e) {
861 * Returns a trimmed version the simples names returned by Signature.
863 public static String[] getTrimmedSimpleNames(String name) {
864 String[] result = Signature.getSimpleNames(name);
867 for (int i = 0, length = result.length; i < length; i++) {
868 result[i] = result[i].trim();
874 * Returns the index of the most specific argument paths which is strictly enclosing the path to check
876 public static int indexOfEnclosingPath(IPath checkedPath, IPath[] paths, int pathCount) {
878 int bestMatch = -1, bestLength = -1;
879 for (int i = 0; i < pathCount; i++) {
880 if (paths[i].equals(checkedPath))
882 if (paths[i].isPrefixOf(checkedPath)) {
883 int currentLength = paths[i].segmentCount();
884 if (currentLength > bestLength) {
885 bestLength = currentLength;
894 * Returns the index of the first argument paths which is equal to the path to check
896 public static int indexOfMatchingPath(IPath checkedPath, IPath[] paths, int pathCount) {
898 for (int i = 0; i < pathCount; i++) {
899 if (paths[i].equals(checkedPath))
906 * Returns the index of the first argument paths which is strictly nested inside the path to check
908 public static int indexOfNestedPath(IPath checkedPath, IPath[] paths, int pathCount) {
910 for (int i = 0; i < pathCount; i++) {
911 if (checkedPath.equals(paths[i]))
913 if (checkedPath.isPrefixOf(paths[i]))
920 * Returns whether the given java element is exluded from its root's classpath. It doesn't check whether the root itself is on the
923 public static final boolean isExcluded(IJavaElement element) {
924 int elementType = element.getElementType();
925 PackageFragmentRoot root = null;
926 IResource resource = null;
927 switch (elementType) {
928 case IJavaElement.JAVA_MODEL:
929 case IJavaElement.JAVA_PROJECT:
930 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
933 // case IJavaElement.PACKAGE_FRAGMENT:
934 // PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
935 // IResource resource = element.getResource();
936 // return resource != null && isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars());
938 case IJavaElement.COMPILATION_UNIT:
939 root = (PackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
940 resource = element.getResource();
941 // if (resource != null && isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars()))
943 return isExcluded(element.getParent());
946 IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
947 return cu != null && isExcluded(cu);
952 * Returns whether the given resource path matches one of the inclusion/exclusion patterns. NOTE: should not be asked directly
953 * using pkg root pathes
955 * @see IClasspathEntry#getInclusionPatterns
956 * @see IClasspathEntry#getExclusionPatterns
958 public final static boolean isExcluded(IPath resourcePath, char[][] inclusionPatterns, char[][] exclusionPatterns,
959 boolean isFolderPath) {
960 if (inclusionPatterns == null && exclusionPatterns == null)
962 char[] path = resourcePath.toString().toCharArray();
964 inclusionCheck: if (inclusionPatterns != null) {
965 for (int i = 0, length = inclusionPatterns.length; i < length; i++) {
966 char[] pattern = inclusionPatterns[i];
967 char[] folderPattern = pattern;
969 int lastSlash = CharOperation.lastIndexOf('/', pattern);
970 if (lastSlash != -1 && lastSlash != pattern.length - 1) { // trailing slash -> adds '**' for free (see
971 // http://ant.apache.org/manual/dirtasks.html)
972 int star = CharOperation.indexOf('*', pattern, lastSlash);
973 if ((star == -1 || star >= pattern.length - 1 || pattern[star + 1] != '*')) {
974 folderPattern = CharOperation.subarray(pattern, 0, lastSlash);
978 if (CharOperation.pathMatch(folderPattern, path, true, '/')) {
979 break inclusionCheck;
982 return true; // never included
985 path = CharOperation.concat(path, new char[] { '*' }, '/');
987 exclusionCheck: if (exclusionPatterns != null) {
988 for (int i = 0, length = exclusionPatterns.length; i < length; i++) {
989 if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/')) {
997 public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) {
998 IPath path = resource.getFullPath();
999 // ensure that folders are only excluded if all of their children are excluded
1000 return isExcluded(path, null, exclusionPatterns, resource.getType() == IResource.FOLDER);
1004 * Returns whether the given resource matches one of the exclusion patterns. NOTE: should not be asked directly using pkg root
1007 * @see IClasspathEntry#getExclusionPatterns
1009 public final static boolean isExcluded(IResource resource, char[][] inclusionPatterns, char[][] exclusionPatterns) {
1010 IPath path = resource.getFullPath();
1011 // ensure that folders are only excluded if all of their children are excluded
1012 return isExcluded(path, inclusionPatterns, exclusionPatterns, resource.getType() == IResource.FOLDER);
1016 * Validate the given .class file name. A .class file name must obey the following rules:
1018 * <li>it must not be null
1019 * <li>it must include the <code>".class"</code> suffix
1020 * <li>its prefix must be a valid identifier
1025 * the name of a .class file
1026 * @return a status object with code <code>IStatus.OK</code> if the given name is valid as a .class file name, otherwise a
1027 * status object indicating what is wrong with the name
1029 // public static boolean isValidClassFileName(String name) {
1030 // return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR;
1033 * Validate the given compilation unit name. A compilation unit name must obey the following rules:
1035 * <li>it must not be null
1036 * <li>it must include the <code>".java"</code> suffix
1037 * <li>its prefix must be a valid identifier
1042 * the name of a compilation unit
1043 * @return a status object with code <code>IStatus.OK</code> if the given name is valid as a compilation unit name, otherwise a
1044 * status object indicating what is wrong with the name
1046 public static boolean isValidCompilationUnitName(String name) {
1047 return PHPFileUtil.isPHPFileName(name);
1048 // return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR;
1052 * Returns true if the given folder name is valid for a package, false if it is not.
1054 public static boolean isValidFolderNameForPackage(String folderName) {
1055 // return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR;
1059 * Returns true if the given method signature is valid, false if it is not.
1061 public static boolean isValidMethodSignature(String sig) {
1062 int len = sig.length();
1066 char c = sig.charAt(i++);
1071 while (sig.charAt(i) != ')') {
1072 // Void is not allowed as a parameter type.
1073 i = checkTypeSignature(sig, i, len, false);
1080 i = checkTypeSignature(sig, i, len, true);
1085 * Returns true if the given type signature is valid, false if it is not.
1087 public static boolean isValidTypeSignature(String sig, boolean allowVoid) {
1088 int len = sig.length();
1089 return checkTypeSignature(sig, 0, len, allowVoid) == len;
1095 public static void log(Throwable e, String message) {
1096 Throwable nestedException;
1097 if (e instanceof JavaModelException && (nestedException = ((JavaModelException) e).getException()) != null) {
1098 e = nestedException;
1100 IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, IStatus.ERROR, message, e);
1101 JavaCore.getPlugin().getLog().log(status);
1105 * Normalizes the cariage returns in the given text. They are all changed to use the given buffer's line separator.
1107 public static char[] normalizeCRs(char[] text, char[] buffer) {
1108 CharArrayBuffer result = new CharArrayBuffer();
1110 int length = text.length;
1113 String lineSeparator = getLineSeparator(text, buffer);
1114 char nextChar = text[0];
1115 for (int i = 0; i < length; i++) {
1116 char currentChar = nextChar;
1117 nextChar = i < length - 1 ? text[i + 1] : ' ';
1118 switch (currentChar) {
1120 int lineLength = i - lineStart;
1121 char[] line = new char[lineLength];
1122 System.arraycopy(text, lineStart, line, 0, lineLength);
1123 result.append(line);
1124 result.append(lineSeparator);
1128 lineLength = i - lineStart;
1129 if (lineLength >= 0) {
1130 line = new char[lineLength];
1131 System.arraycopy(text, lineStart, line, 0, lineLength);
1132 result.append(line);
1133 result.append(lineSeparator);
1134 if (nextChar == '\n') {
1138 // when line separator are mixed in the same file
1139 // \r might not be followed by a \n. If not, we should increment
1140 // lineStart by one and not by two.
1144 // when line separator are mixed in the same file
1145 // we need to prevent NegativeArraySizeException
1152 if (lineStart > 0) {
1153 int lastLineLength = length - lineStart;
1154 if (lastLineLength > 0) {
1155 lastLine = new char[lastLineLength];
1156 System.arraycopy(text, lineStart, lastLine, 0, lastLineLength);
1157 result.append(lastLine);
1159 return result.getContents();
1165 * Normalizes the cariage returns in the given text. They are all changed to use given buffer's line sepatator.
1167 public static String normalizeCRs(String text, String buffer) {
1168 return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray()));
1172 * Converts the given relative path into a package name. Returns null if the path is not a valid package name.
1174 public static String packageName(IPath pkgPath) {
1175 StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
1176 for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
1177 String segment = pkgPath.segment(j);
1178 // if (!isValidFolderNameForPackage(segment)) {
1181 pkgName.append(segment);
1182 if (j < pkgPath.segmentCount() - 1) {
1183 pkgName.append("."); //$NON-NLS-1$
1186 return pkgName.toString();
1190 * Returns the length of the common prefix between s1 and s2.
1192 public static int prefixLength(char[] s1, char[] s2) {
1194 int max = Math.min(s1.length, s2.length);
1195 for (int i = 0; i < max && s1[i] == s2[i]; ++i)
1201 * Returns the length of the common prefix between s1 and s2.
1203 public static int prefixLength(String s1, String s2) {
1205 int max = Math.min(s1.length(), s2.length());
1206 for (int i = 0; i < max && s1.charAt(i) == s2.charAt(i); ++i)
1211 private static void quickSort(char[][] list, int left, int right) {
1212 int original_left = left;
1213 int original_right = right;
1214 char[] mid = list[(left + right) / 2];
1216 while (compare(list[left], mid) < 0) {
1219 while (compare(mid, list[right]) < 0) {
1222 if (left <= right) {
1223 char[] tmp = list[left];
1224 list[left] = list[right];
1229 } while (left <= right);
1230 if (original_left < right) {
1231 quickSort(list, original_left, right);
1233 if (left < original_right) {
1234 quickSort(list, left, original_right);
1239 * Sort the comparable objects in the given collection.
1241 private static void quickSort(Comparable[] sortedCollection, int left, int right) {
1242 int original_left = left;
1243 int original_right = right;
1244 Comparable mid = sortedCollection[(left + right) / 2];
1246 while (sortedCollection[left].compareTo(mid) < 0) {
1249 while (mid.compareTo(sortedCollection[right]) < 0) {
1252 if (left <= right) {
1253 Comparable tmp = sortedCollection[left];
1254 sortedCollection[left] = sortedCollection[right];
1255 sortedCollection[right] = tmp;
1259 } while (left <= right);
1260 if (original_left < right) {
1261 quickSort(sortedCollection, original_left, right);
1263 if (left < original_right) {
1264 quickSort(sortedCollection, left, original_right);
1268 private static void quickSort(int[] list, int left, int right) {
1269 int original_left = left;
1270 int original_right = right;
1271 int mid = list[(left + right) / 2];
1273 while (list[left] < mid) {
1276 while (mid < list[right]) {
1279 if (left <= right) {
1280 int tmp = list[left];
1281 list[left] = list[right];
1286 } while (left <= right);
1287 if (original_left < right) {
1288 quickSort(list, original_left, right);
1290 if (left < original_right) {
1291 quickSort(list, left, original_right);
1296 * Sort the objects in the given collection using the given comparer.
1298 private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) {
1299 int original_left = left;
1300 int original_right = right;
1301 Object mid = sortedCollection[(left + right) / 2];
1303 while (comparer.compare(sortedCollection[left], mid) < 0) {
1306 while (comparer.compare(mid, sortedCollection[right]) < 0) {
1309 if (left <= right) {
1310 Object tmp = sortedCollection[left];
1311 sortedCollection[left] = sortedCollection[right];
1312 sortedCollection[right] = tmp;
1316 } while (left <= right);
1317 if (original_left < right) {
1318 quickSort(sortedCollection, original_left, right, comparer);
1320 if (left < original_right) {
1321 quickSort(sortedCollection, left, original_right, comparer);
1326 * Sort the objects in the given collection using the given sort order.
1328 private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) {
1329 int original_left = left;
1330 int original_right = right;
1331 int mid = sortOrder[(left + right) / 2];
1333 while (sortOrder[left] < mid) {
1336 while (mid < sortOrder[right]) {
1339 if (left <= right) {
1340 Object tmp = sortedCollection[left];
1341 sortedCollection[left] = sortedCollection[right];
1342 sortedCollection[right] = tmp;
1343 int tmp2 = sortOrder[left];
1344 sortOrder[left] = sortOrder[right];
1345 sortOrder[right] = tmp2;
1349 } while (left <= right);
1350 if (original_left < right) {
1351 quickSort(sortedCollection, original_left, right, sortOrder);
1353 if (left < original_right) {
1354 quickSort(sortedCollection, left, original_right, sortOrder);
1359 * Sort the strings in the given collection.
1361 private static void quickSort(String[] sortedCollection, int left, int right) {
1362 int original_left = left;
1363 int original_right = right;
1364 String mid = sortedCollection[(left + right) / 2];
1366 while (sortedCollection[left].compareTo(mid) < 0) {
1369 while (mid.compareTo(sortedCollection[right]) < 0) {
1372 if (left <= right) {
1373 String 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);
1389 * Sort the strings in the given collection in reverse alphabetical order.
1391 private static void quickSortReverse(String[] sortedCollection, int left, int right) {
1392 int original_left = left;
1393 int original_right = right;
1394 String mid = sortedCollection[(left + right) / 2];
1396 while (sortedCollection[left].compareTo(mid) > 0) {
1399 while (mid.compareTo(sortedCollection[right]) > 0) {
1402 if (left <= right) {
1403 String tmp = sortedCollection[left];
1404 sortedCollection[left] = sortedCollection[right];
1405 sortedCollection[right] = tmp;
1409 } while (left <= right);
1410 if (original_left < right) {
1411 quickSortReverse(sortedCollection, original_left, right);
1413 if (left < original_right) {
1414 quickSortReverse(sortedCollection, left, original_right);
1419 * Reads in a string from the specified data input stream. The string has been encoded using a modified UTF-8 format.
1421 * The first two bytes are read as if by <code>readUnsignedShort</code>. This value gives the number of following bytes that
1422 * are in the encoded string, not the length of the resulting string. The following bytes are then interpreted as bytes encoding
1423 * characters in the UTF-8 format and are converted into characters.
1425 * This method blocks until all the bytes are read, the end of the stream is detected, or an exception is thrown.
1428 * a data input stream.
1429 * @return a Unicode string.
1430 * @exception EOFException
1431 * if the input stream reaches the end before all the bytes.
1432 * @exception IOException
1433 * if an I/O error occurs.
1434 * @exception UTFDataFormatException
1435 * if the bytes do not represent a valid UTF-8 encoding of a Unicode string.
1436 * @see java.io.DataInputStream#readUnsignedShort()
1438 public final static char[] readUTF(DataInput in) throws IOException {
1439 int utflen = in.readUnsignedShort();
1440 char str[] = new char[utflen];
1443 while (count < utflen) {
1444 int c = in.readUnsignedByte();
1457 str[strlen++] = (char) c;
1461 // 110x xxxx 10xx xxxx
1464 throw new UTFDataFormatException();
1465 char2 = in.readUnsignedByte();
1466 if ((char2 & 0xC0) != 0x80)
1467 throw new UTFDataFormatException();
1468 str[strlen++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
1471 // 1110 xxxx 10xx xxxx 10xx xxxx
1474 throw new UTFDataFormatException();
1475 char2 = in.readUnsignedByte();
1476 char3 = in.readUnsignedByte();
1477 if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
1478 throw new UTFDataFormatException();
1479 str[strlen++] = (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
1482 // 10xx xxxx, 1111 xxxx
1483 throw new UTFDataFormatException();
1486 if (strlen < utflen) {
1487 System.arraycopy(str, 0, str = new char[strlen], 0, strlen);
1493 * Creates a NLS catalog for the given locale.
1495 public static void relocalize() {
1497 bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
1498 } catch (MissingResourceException e) {
1499 System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
1504 public static void sort(char[][] list) {
1505 if (list.length > 1)
1506 quickSort(list, 0, list.length - 1);
1510 * Sorts an array of Comparable objects in place.
1512 public static void sort(Comparable[] objects) {
1513 if (objects.length > 1)
1514 quickSort(objects, 0, objects.length - 1);
1517 public static void sort(int[] list) {
1518 if (list.length > 1)
1519 quickSort(list, 0, list.length - 1);
1523 * Sorts an array of objects in place. The given comparer compares pairs of items.
1525 public static void sort(Object[] objects, Comparer comparer) {
1526 if (objects.length > 1)
1527 quickSort(objects, 0, objects.length - 1, comparer);
1531 * Sorts an array of objects in place, using the sort order given for each item.
1533 public static void sort(Object[] objects, int[] sortOrder) {
1534 if (objects.length > 1)
1535 quickSort(objects, 0, objects.length - 1, sortOrder);
1539 * Sorts an array of strings in place using quicksort.
1541 public static void sort(String[] strings) {
1542 if (strings.length > 1)
1543 quickSort(strings, 0, strings.length - 1);
1547 * Sorts an array of Comparable objects, returning a new array with the sorted items. The original array is left untouched.
1549 public static Comparable[] sortCopy(Comparable[] objects) {
1550 int len = objects.length;
1551 Comparable[] copy = new Comparable[len];
1552 System.arraycopy(objects, 0, copy, 0, len);
1558 * Sorts an array of Strings, returning a new array with the sorted items. The original array is left untouched.
1560 public static Object[] sortCopy(Object[] objects, Comparer comparer) {
1561 int len = objects.length;
1562 Object[] copy = new Object[len];
1563 System.arraycopy(objects, 0, copy, 0, len);
1564 sort(copy, comparer);
1569 * Sorts an array of Strings, returning a new array with the sorted items. The original array is left untouched.
1571 public static String[] sortCopy(String[] objects) {
1572 int len = objects.length;
1573 String[] copy = new String[len];
1574 System.arraycopy(objects, 0, copy, 0, len);
1580 * Sorts an array of strings in place using quicksort in reverse alphabetical order.
1582 public static void sortReverseOrder(String[] strings) {
1583 if (strings.length > 1)
1584 quickSortReverse(strings, 0, strings.length - 1);
1588 * Converts a String[] to char[][].
1590 public static char[][] toCharArrays(String[] a) {
1592 char[][] result = new char[len][];
1593 for (int i = 0; i < len; ++i) {
1594 result[i] = toChars(a[i]);
1600 * Converts a String to char[].
1602 public static char[] toChars(String s) {
1603 int len = s.length();
1604 char[] chars = new char[len];
1605 s.getChars(0, len, chars, 0);
1610 * Converts a String to char[][], where segments are separate by '.'.
1612 public static char[][] toCompoundChars(String s) {
1613 int len = s.length();
1615 return CharOperation.NO_CHAR_CHAR;
1618 for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) {
1621 char[][] segs = new char[segCount][];
1623 for (int i = 0; i < segCount; ++i) {
1624 int dot = s.indexOf('.', start);
1625 int end = (dot == -1 ? s.length() : dot);
1626 segs[i] = new char[end - start];
1627 s.getChars(start, end, segs[i], 0);
1634 * Converts a char[] to String.
1636 public static String toString(char[] c) {
1637 return new String(c);
1641 * Converts a char[][] to String, where segments are separated by '.'.
1643 public static String toString(char[][] c) {
1644 StringBuffer sb = new StringBuffer();
1645 for (int i = 0, max = c.length; i < max; ++i) {
1650 return sb.toString();
1654 * Converts a char[][] and a char[] to String, where segments are separated by '.'.
1656 public static String toString(char[][] c, char[] d) {
1658 return new String(d);
1659 StringBuffer sb = new StringBuffer();
1660 for (int i = 0, max = c.length; i < max; ++i) {
1665 return sb.toString();
1669 * Returns the unresolved type parameter signatures of the given method e.g. {"QString;", "[int", "[[Qjava.util.Vector;"}
1671 // public static String[] typeParameterSignatures(AbstractMethodDeclaration method) {
1672 // Argument[] args = method.arguments;
1673 // if (args != null) {
1674 // int length = args.length;
1675 // String[] signatures = new String[length];
1676 // for (int i = 0; i < args.length; i++) {
1677 // Argument arg = args[i];
1678 // signatures[i] = typeSignature(arg.type);
1680 // return signatures;
1682 // return new String[0];
1685 * Returns the unresolved type signature of the given type reference, e.g. "QString;", "[int", "[[Qjava.util.Vector;"
1687 // public static String typeSignature(TypeReference type) {
1688 // char[][] compoundName = type.getTypeName();
1689 // char[] typeName =CharOperation.concatWith(compoundName, '.');
1690 // String signature = Signature.createTypeSignature(typeName, false/*don't resolve*/);
1691 // int dimensions = type.dimensions();
1692 // if (dimensions > 0) {
1693 // signature = Signature.createArraySignature(signature, dimensions);
1695 // return signature;
1698 * Returns the unresolved type signature of the given type reference,
1699 * e.g. "QString;", "[int", "[[Qjava.util.Vector;"
1701 public static String typeSignature(TypeReference type) {
1702 char[][] compoundName = type.getTypeName();
1703 char[] typeName =CharOperation.concatWith(compoundName, '.');
1704 String signature = Signature.createTypeSignature(typeName, false/*don't resolve*/);
1705 int dimensions = type.dimensions();
1706 if (dimensions > 0) {
1707 signature = Signature.createArraySignature(signature, dimensions);
1712 * Asserts that the given method signature is valid.
1714 public static void validateMethodSignature(String sig) {
1715 Assert.isTrue(isValidMethodSignature(sig));
1719 * Asserts that the given type signature is valid.
1721 public static void validateTypeSignature(String sig, boolean allowVoid) {
1722 Assert.isTrue(isValidTypeSignature(sig, allowVoid));
1725 public static void verbose(String log) {
1726 verbose(log, System.out);
1729 public static synchronized void verbose(String log, PrintStream printStream) {
1732 int end = log.indexOf('\n', start);
1733 printStream.print(Thread.currentThread());
1734 printStream.print(" "); //$NON-NLS-1$
1735 printStream.print(log.substring(start, end == -1 ? log.length() : end + 1));
1737 } while (start != 0);
1738 printStream.println();
1742 * Writes a string to the given output stream using UTF-8 encoding in a machine-independent manner.
1744 * First, two bytes are written to the output stream as if by the <code>writeShort</code> method giving the number of bytes to
1745 * follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each
1746 * character of the string is output, in sequence, using the UTF-8 encoding for the character.
1749 * a string to be written.
1750 * @return the number of bytes written to the stream.
1751 * @exception IOException
1752 * if an I/O error occurs.
1755 public static int writeUTF(OutputStream out, char[] str) throws IOException {
1756 int strlen = str.length;
1758 for (int i = 0; i < strlen; i++) {
1760 if ((c >= 0x0001) && (c <= 0x007F)) {
1762 } else if (c > 0x07FF) {
1769 throw new UTFDataFormatException();
1770 out.write((utflen >>> 8) & 0xFF);
1771 out.write((utflen >>> 0) & 0xFF);
1772 if (strlen == utflen) {
1773 for (int i = 0; i < strlen; i++)
1776 for (int i = 0; i < strlen; i++) {
1778 if ((c >= 0x0001) && (c <= 0x007F)) {
1780 } else if (c > 0x07FF) {
1781 out.write(0xE0 | ((c >> 12) & 0x0F));
1782 out.write(0x80 | ((c >> 6) & 0x3F));
1783 out.write(0x80 | ((c >> 0) & 0x3F));
1785 out.write(0xC0 | ((c >> 6) & 0x1F));
1786 out.write(0x80 | ((c >> 0) & 0x3F));
1790 return utflen + 2; // the number of bytes written to the stream