X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java new file mode 100644 index 0000000..ea8125b --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java @@ -0,0 +1,1365 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.core.util; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.StringTokenizer; + +import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.IJavaModelStatusConstants; +import net.sourceforge.phpdt.core.IPackageFragment; +import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.core.JavaCore; +import net.sourceforge.phpdt.core.Signature; +import net.sourceforge.phpdt.core.compiler.CharOperation; +import net.sourceforge.phpdt.internal.core.PackageFragmentRoot; +import net.sourceforge.phpdt.internal.corext.Assert; +import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * Provides convenient utility methods to other types in this package. + */ +public class Util { + + private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$ + private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$ + private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$ + private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$ + + public interface Comparable { + /** + * Returns 0 if this and c are equal, >0 if this is greater than c, + * or <0 if this is less than c. + */ + int compareTo(Comparable c); + } + + public interface Comparer { + /** + * Returns 0 if a and b are equal, >0 if a is greater than b, + * or <0 if a is less than b. + */ + int compare(Object a, Object b); + } + + public interface Displayable { + String displayString(Object o); + } + + public static final String[] fgEmptyStringArray = new String[0]; + + /** + * Are we running JDK 1.1? + */ + private static boolean JDK1_1 = false; + + /* Bundle containing messages */ + protected static ResourceBundle bundle; + private final static String bundleName = "net.sourceforge.phpdt.internal.core.messages"; //$NON-NLS-1$ + +// public final static char[] SUFFIX_class = ".class".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_CLASS = ".CLASS".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_java = ".java".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_JAVA = ".JAVA".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_jar = ".jar".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_JAR = ".JAR".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_zip = ".zip".toCharArray(); //$NON-NLS-1$ +// public final static char[] SUFFIX_ZIP = ".ZIP".toCharArray(); //$NON-NLS-1$ + + static { + String ver = System.getProperty("java.version"); //$NON-NLS-1$ + JDK1_1 = ((ver != null) && ver.startsWith("1.1")); //$NON-NLS-1$ + relocalize(); + } + + /** + * Lookup the message with the given ID in this catalog + */ + public static String bind(String id) { + return bind(id, (String[])null); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string values. + */ + public static String bind(String id, String[] bindings) { + if (id == null) + return "No message available"; //$NON-NLS-1$ + String message = null; + try { + message = bundle.getString(id); + } catch (MissingResourceException e) { + // If we got an exception looking for the message, fail gracefully by just returning + // the id we were looking for. In most cases this is semi-informative so is not too bad. + return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$ + } + // for compatibility with MessageFormat which eliminates double quotes in original message + char[] messageWithNoDoubleQuotes = + CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE); + message = new String(messageWithNoDoubleQuotes); + + if (bindings == null) + return message; + + int length = message.length(); + int start = -1; + int end = length; + StringBuffer output = new StringBuffer(80); + while (true) { + if ((end = message.indexOf('{', start)) > -1) { + output.append(message.substring(start + 1, end)); + if ((start = message.indexOf('}', end)) > -1) { + int index = -1; + try { + index = Integer.parseInt(message.substring(end + 1, start)); + output.append(bindings[index]); + } catch (NumberFormatException nfe) { + output.append(message.substring(end + 1, start + 1)); + } catch (ArrayIndexOutOfBoundsException e) { + output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$ + } + } else { + output.append(message.substring(end, length)); + break; + } + } else { + output.append(message.substring(start + 1, length)); + break; + } + } + return output.toString(); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string. + */ + public static String bind(String id, String binding) { + return bind(id, new String[] {binding}); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given strings. + */ + public static String bind(String id, String binding1, String binding2) { + return bind(id, new String[] {binding1, binding2}); + } + + /** + * Checks the type signature in String sig, + * starting at start and ending before end (end is not included). + * Returns the index of the character immediately after the signature if valid, + * or -1 if not valid. + */ + private static int checkTypeSignature(String sig, int start, int end, boolean allowVoid) { + if (start >= end) return -1; + int i = start; + char c = sig.charAt(i++); + int nestingDepth = 0; + while (c == '[') { + ++nestingDepth; + if (i >= end) return -1; + c = sig.charAt(i++); + } + switch (c) { + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + break; + case 'V': + if (!allowVoid) return -1; + // array of void is not allowed + if (nestingDepth != 0) return -1; + break; + case 'L': + int semicolon = sig.indexOf(';', i); + // Must have at least one character between L and ; + if (semicolon <= i || semicolon >= end) return -1; + i = semicolon + 1; + break; + default: + return -1; + } + return i; + } + + /** + * Combines two hash codes to make a new one. + */ + public static int combineHashCodes(int hashCode1, int hashCode2) { + return hashCode1 * 17 + hashCode2; + } + + /** + * 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 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 they are equal or both null. + */ + public static int compare(byte[] a, byte[] b) { + if (a == b) + return 0; + if (a == null) + return -1; + if (b == null) + return 1; + int len = Math.min(a.length, b.length); + for (int i = 0; i < len; ++i) { + int diff = a[i] - b[i]; + if (diff != 0) + return diff; + } + if (a.length > len) + return 1; + if (b.length > len) + return -1; + return 0; + } + + /** + * Compares two char arrays lexicographically. + * The comparison is based on the Unicode value of each character in + * the char arrays. + * @return the value 0 if a is equal to + * b; a value less than 0 if a + * is lexicographically less than b; and a + * value greater than 0 if a is + * lexicographically greater than b. + */ + public static int compare(char[] v1, char[] v2) { + int len1 = v1.length; + int len2 = v2.length; + int n = Math.min(len1, len2); + int i = 0; + while (n-- != 0) { + if (v1[i] != v2[i]) { + return v1[i] - v2[i]; + } + ++i; + } + return len1 - len2; + } + + /** + * Concatenate two strings with a char in between. + * @see #concat(String, String) + */ + public static String concat(String s1, char c, String s2) { + if (s1 == null) s1 = "null"; //$NON-NLS-1$ + if (s2 == null) s2 = "null"; //$NON-NLS-1$ + int l1 = s1.length(); + int l2 = s2.length(); + char[] buf = new char[l1 + 1 + l2]; + s1.getChars(0, l1, buf, 0); + buf[l1] = c; + s2.getChars(0, l2, buf, l1 + 1); + return new String(buf); + } + + /** + * Concatenate two strings. + * Much faster than using +, which: + * - creates a StringBuffer, + * - which is synchronized, + * - of default size, so the resulting char array is + * often larger than needed. + * This implementation creates an extra char array, since the + * String constructor copies its argument, but there's no way around this. + */ + public static String concat(String s1, String s2) { + if (s1 == null) s1 = "null"; //$NON-NLS-1$ + if (s2 == null) s2 = "null"; //$NON-NLS-1$ + int l1 = s1.length(); + int l2 = s2.length(); + char[] buf = new char[l1 + l2]; + s1.getChars(0, l1, buf, 0); + s2.getChars(0, l2, buf, l1); + return new String(buf); + } + + /** + * Concatenate three strings. + * @see #concat(String, String) + */ + public static String concat(String s1, String s2, String s3) { + if (s1 == null) s1 = "null"; //$NON-NLS-1$ + if (s2 == null) s2 = "null"; //$NON-NLS-1$ + if (s3 == null) s3 = "null"; //$NON-NLS-1$ + int l1 = s1.length(); + int l2 = s2.length(); + int l3 = s3.length(); + char[] buf = new char[l1 + l2 + l3]; + s1.getChars(0, l1, buf, 0); + s2.getChars(0, l2, buf, l1); + s3.getChars(0, l3, buf, l1 + l2); + return new String(buf); + } + + /** + * Converts a type signature from the IBinaryType representation to the DC representation. + */ + public static String convertTypeSignature(char[] sig) { + return new String(sig).replace('/', '.'); + } + + /** + * Returns true iff str.toLowerCase().endsWith(end.toLowerCase()) + * implementation is not creating extra strings. + */ + public final static boolean endsWithIgnoreCase(String str, String end) { + + int strLength = str == null ? 0 : str.length(); + int endLength = end == null ? 0 : end.length(); + + // return false if the string is smaller than the end. + if(endLength > strLength) + return false; + + // return false if any character of the end are + // not the same in lower case. + for(int i = 1 ; i <= endLength; i++){ + if(Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i))) + return false; + } + + return true; + } + + /** + * Compares two arrays using equals() on the elements. + * Either or both arrays may be null. + * Returns 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 + * all elements are equal. + */ + public static boolean equalArraysOrNull(int[] a, int[] b) { + if (a == b) + return true; + if (a == null || b == null) + return false; + int len = a.length; + if (len != b.length) + return false; + for (int i = 0; i < len; ++i) { + if (a[i] != b[i]) + return false; + } + return true; + } + + /** + * Compares two arrays using equals() on the elements. + * Either or both arrays may be null. + * Returns 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 + * all elements compare true with equals. + */ + public static boolean equalArraysOrNull(Object[] a, Object[] b) { + if (a == b) return true; + if (a == null || b == null) return false; + + int len = a.length; + if (len != b.length) return false; + for (int i = 0; i < len; ++i) { + if (a[i] == null) { + if (b[i] != null) return false; + } else { + if (!a[i].equals(b[i])) return false; + } + } + return true; + } + + /** + * Compares two String arrays using equals() on the elements. + * The arrays are first sorted. + * Either or both arrays may be null. + * Returns 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 + * iff, after sorting both arrays, all elements compare true with equals. + * The original arrays are left untouched. + */ + public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) { + if (a == b) return true; + if (a == null || b == null) return false; + int len = a.length; + if (len != b.length) return false; + if (len >= 2) { // only need to sort if more than two items + a = sortCopy(a); + b = sortCopy(b); + } + for (int i = 0; i < len; ++i) { + if (!a[i].equals(b[i])) return false; + } + return true; + } + + /** + * Compares two arrays using equals() on the elements. + * The arrays are first sorted. + * Either or both arrays may be null. + * Returns 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 + * iff, after sorting both arrays, all elements compare true with equals. + * The original arrays are left untouched. + */ + public static boolean equalArraysOrNullSortFirst(Comparable[] a, Comparable[] b) { + if (a == b) return true; + if (a == null || b == null) return false; + int len = a.length; + if (len != b.length) return false; + if (len >= 2) { // only need to sort if more than two items + a = sortCopy(a); + b = sortCopy(b); + } + for (int i = 0; i < len; ++i) { + if (!a[i].equals(b[i])) return false; + } + return true; + } + + /** + * Compares two objects using equals(). + * Either or both array may be null. + * Returns true if both are null. + * Returns false if only one is null. + * Otherwise, return the result of comparing with equals(). + */ + public static boolean equalOrNull(Object a, Object b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + return a.equals(b); + } + + /** + * Given a qualified name, extract the last component. + * If the input is not qualified, the same string is answered. + */ + public static String extractLastName(String qualifiedName) { + int i = qualifiedName.lastIndexOf('.'); + if (i == -1) return qualifiedName; + return qualifiedName.substring(i+1); + } + + /** + * Extracts the parameter types from a method signature. + */ + public static String[] extractParameterTypes(char[] sig) { + int count = getParameterCount(sig); + String[] result = new String[count]; + if (count == 0) + return result; + int i = CharOperation.indexOf('(', sig) + 1; + count = 0; + int len = sig.length; + int start = i; + for (;;) { + if (i == len) + break; + char c = sig[i]; + if (c == ')') + break; + if (c == '[') { + ++i; + } else + if (c == 'L') { + i = CharOperation.indexOf(';', sig, i + 1) + 1; + Assert.isTrue(i != 0); + result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i)); + start = i; + } else { + ++i; + result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i)); + start = i; + } + } + return result; + } + + /** + * Extracts the return type from a method signature. + */ + public static String extractReturnType(String sig) { + int i = sig.lastIndexOf(')'); + Assert.isTrue(i != -1); + return sig.substring(i+1); + } + + /** + * Finds the first line separator used by the given text. + * + * @return "\n" or "\r" or "\r\n", + * or null if none found + */ + public static String findLineSeparator(char[] text) { + // find the first line separator + int length = text.length; + if (length > 0) { + char nextChar = text[0]; + for (int i = 0; i < length; i++) { + char currentChar = nextChar; + nextChar = i < length-1 ? text[i+1] : ' '; + switch (currentChar) { + case '\n': return "\n"; //$NON-NLS-1$ + case '\r': return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + } + // not found + return null; + } + + /** + * Returns the line separator used by the given buffer. + * Uses the given text if none found. + * + * @return "\n" or "\r" or "\r\n" + */ + private static String getLineSeparator(char[] text, char[] buffer) { + // search in this buffer's contents first + String lineSeparator = findLineSeparator(buffer); + if (lineSeparator == null) { + // search in the given text + lineSeparator = findLineSeparator(text); + if (lineSeparator == null) { + // default to system line separator + return System.getProperty("line.separator"); + } + } + return lineSeparator; + } + + /** + * Returns the number of parameter types in a method signature. + */ + public static int getParameterCount(char[] sig) { + int i = CharOperation.indexOf('(', sig) + 1; + Assert.isTrue(i != 0); + int count = 0; + int len = sig.length; + for (;;) { + if (i == len) + break; + char c = sig[i]; + if (c == ')') + break; + if (c == '[') { + ++i; + } else + if (c == 'L') { + ++count; + i = CharOperation.indexOf(';', sig, i + 1) + 1; + Assert.isTrue(i != 0); + } else { + ++count; + ++i; + } + } + return count; + } + + /** + * Returns the given file's contents as a byte array. + */ + public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException { + InputStream stream= null; + try { + stream = new BufferedInputStream(file.getContents(true)); + } catch (CoreException e) { + throw new JavaModelException(e); + } + try { + return net.sourceforge.phpdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1); + } catch (IOException e) { + throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); + } finally { + try { + stream.close(); + } catch (IOException e) { + } + } + } + + /** + * Returns the given file's contents as a character array. + */ + public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException { + String encoding = JavaCore.create(file.getProject()).getOption(JavaCore.CORE_ENCODING, true); + return getResourceContentsAsCharArray(file, encoding); + } + + public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException { + InputStream stream= null; + try { + stream = new BufferedInputStream(file.getContents(true)); + } catch (CoreException e) { + throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST); + } + try { + return net.sourceforge.phpdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding); + } catch (IOException e) { + throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); + } finally { + try { + stream.close(); + } catch (IOException e) { + } + } + } + + /** + * Returns a trimmed version the simples names returned by Signature. + */ + public static String[] getTrimmedSimpleNames(String name) { + String[] result = Signature.getSimpleNames(name); + if (result == null) return null; + for (int i = 0, length = result.length; i < length; i++) { + result[i] = result[i].trim(); + } + return result; + } + + /** + * Returns true iff str.toLowerCase().endsWith(".class") + * implementation is not creating extra strings. + */ +// public final static boolean isClassFileName(String name) { +// int nameLength = name == null ? 0 : name.length(); +// int suffixLength = SUFFIX_CLASS.length; +// if (nameLength < suffixLength) return false; +// +// for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { +// char c = name.charAt(offset + i); +// if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false; +// } +// return true; +// } + + /* + * Returns whether the given java element is exluded from its root's classpath. + */ + public static final boolean isExcluded(IJavaElement element) { + int elementType = element.getElementType(); + PackageFragmentRoot root = null; + IResource resource = null; + switch (elementType) { +// case IJavaElement.PACKAGE_FRAGMENT: +// PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); +// IResource resource = element.getResource(); +// return resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars()); + case IJavaElement.COMPILATION_UNIT: + root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + resource = element.getResource(); +// if (resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars())) +// return true; + return isExcluded(element.getParent()); + default: + IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT); + return cu != null && isExcluded(cu); + } + } + /* + * Returns whether the given resource path matches one of the exclusion + * patterns. + * + * @see IClasspathEntry#getExclusionPatterns + */ + public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) { + if (exclusionPatterns == null) return false; + char[] path = resourcePath.toString().toCharArray(); + for (int i = 0, length = exclusionPatterns.length; i < length; i++) + if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/')) + return true; + return false; + } + + /* + * Returns whether the given resource matches one of the exclusion patterns. + * + * @see IClasspathEntry#getExclusionPatterns + */ + public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) { + IPath path = resource.getFullPath(); + // ensure that folders are only excluded if all of their children are excluded + if (resource.getType() == IResource.FOLDER) + path = path.append("*"); //$NON-NLS-1$ + return isExcluded(path, exclusionPatterns); + } + + /** + * Returns true iff str.toLowerCase().endsWith(".jar" or ".zip") + * implementation is not creating extra strings. + */ +// public final static boolean isArchiveFileName(String name) { +// int nameLength = name == null ? 0 : name.length(); +// int suffixLength = SUFFIX_JAR.length; +// if (nameLength < suffixLength) return false; +// +// int i, offset; +// for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { +// char c = name.charAt(offset + i); +// if (c != SUFFIX_jar[i] && c != SUFFIX_JAR[i]) break; +// } +// if (i == suffixLength) return true; +// for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { +// char c = name.charAt(offset + i); +// if (c != SUFFIX_zip[i] && c != SUFFIX_ZIP[i]) return false; +// } +// return true; +// } + + /** + * Validate the given compilation unit name. + * A compilation unit name must obey the following rules: + * + *

+ * @param name the name of a compilation unit + * @return a status object with code IStatus.OK if + * the given name is valid as a compilation unit name, otherwise a status + * object indicating what is wrong with the name + */ + public static boolean isValidCompilationUnitName(String name) { + return PHPFileUtil.isPHPFileName(name); +// return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR; + } + + /** + * Validate the given .class file name. + * A .class file name must obey the following rules: + * + *

+ * @param name the name of a .class file + * @return a status object with code IStatus.OK if + * the given name is valid as a .class file name, otherwise a status + * object indicating what is wrong with the name + */ +// public static boolean isValidClassFileName(String name) { +// return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR; +// } + + /** + * Returns true if the given method signature is valid, + * false if it is not. + */ + public static boolean isValidMethodSignature(String sig) { + int len = sig.length(); + if (len == 0) return false; + int i = 0; + char c = sig.charAt(i++); + if (c != '(') return false; + if (i >= len) return false; + while (sig.charAt(i) != ')') { + // Void is not allowed as a parameter type. + i = checkTypeSignature(sig, i, len, false); + if (i == -1) return false; + if (i >= len) return false; + } + ++i; + i = checkTypeSignature(sig, i, len, true); + return i == len; + } + + /** + * Returns true if the given type signature is valid, + * false if it is not. + */ + public static boolean isValidTypeSignature(String sig, boolean allowVoid) { + int len = sig.length(); + return checkTypeSignature(sig, 0, len, allowVoid) == len; + } + + /** + * Returns true if the given folder name is valid for a package, + * false if it is not. + */ + public static boolean isValidFolderNameForPackage(String folderName) { +// return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR; + return true; + } + + /* + * Add a log entry + */ + public static void log(Throwable e, String message) { + Throwable nestedException; + if (e instanceof JavaModelException + && (nestedException = ((JavaModelException)e).getException()) != null) { + e = nestedException; + } + IStatus status= new Status( + IStatus.ERROR, + JavaCore.getPlugin().getDescriptor().getUniqueIdentifier(), + IStatus.ERROR, + message, + e); + JavaCore.getPlugin().getLog().log(status); + } + + /** + * Normalizes the cariage returns in the given text. + * They are all changed to use the given buffer's line separator. + */ + public static char[] normalizeCRs(char[] text, char[] buffer) { + CharArrayBuffer result = new CharArrayBuffer(); + int lineStart = 0; + int length = text.length; + if (length == 0) return text; + String lineSeparator = getLineSeparator(text, buffer); + char nextChar = text[0]; + for (int i = 0; i < length; i++) { + char currentChar = nextChar; + nextChar = i < length-1 ? text[i+1] : ' '; + switch (currentChar) { + case '\n': + int lineLength = i-lineStart; + char[] line = new char[lineLength]; + System.arraycopy(text, lineStart, line, 0, lineLength); + result.append(line); + result.append(lineSeparator); + lineStart = i+1; + break; + case '\r': + lineLength = i-lineStart; + if (lineLength >= 0) { + line = new char[lineLength]; + System.arraycopy(text, lineStart, line, 0, lineLength); + result.append(line); + result.append(lineSeparator); + if (nextChar == '\n') { + nextChar = ' '; + lineStart = i+2; + } else { + // when line separator are mixed in the same file + // \r might not be followed by a \n. If not, we should increment + // lineStart by one and not by two. + lineStart = i+1; + } + } else { + // when line separator are mixed in the same file + // we need to prevent NegativeArraySizeException + lineStart = i+1; + } + break; + } + } + char[] lastLine; + if (lineStart > 0) { + int lastLineLength = length-lineStart; + if (lastLineLength > 0) { + lastLine = new char[lastLineLength]; + System.arraycopy(text, lineStart, lastLine, 0, lastLineLength); + result.append(lastLine); + } + return result.getContents(); + } else { + return text; + } + } + + /** + * Normalizes the cariage returns in the given text. + * They are all changed to use given buffer's line sepatator. + */ + public static String normalizeCRs(String text, String buffer) { + return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray())); + } + + /** + * Sort the objects in the given collection using the given sort order. + */ + private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) { + int original_left = left; + int original_right = right; + int mid = sortOrder[ (left + right) / 2]; + do { + while (sortOrder[left] < mid) { + left++; + } + while (mid < sortOrder[right]) { + right--; + } + if (left <= right) { + Object tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + int tmp2 = sortOrder[left]; + sortOrder[left] = sortOrder[right]; + sortOrder[right] = tmp2; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right, sortOrder); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right, sortOrder); + } + } + + /** + * Sort the objects in the given collection using the given comparer. + */ + private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) { + int original_left = left; + int original_right = right; + Object mid = sortedCollection[ (left + right) / 2]; + do { + while (comparer.compare(sortedCollection[left], mid) < 0) { + left++; + } + while (comparer.compare(mid, sortedCollection[right]) < 0) { + right--; + } + if (left <= right) { + Object tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right, comparer); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right, comparer); + } + } + + /** + * Sort the strings in the given collection. + */ + private static void quickSort(String[] sortedCollection, int left, int right) { + int original_left = left; + int original_right = right; + String mid = sortedCollection[ (left + right) / 2]; + do { + while (sortedCollection[left].compareTo(mid) < 0) { + left++; + } + while (mid.compareTo(sortedCollection[right]) < 0) { + right--; + } + if (left <= right) { + String tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right); + } + } + + /** + * Converts the given relative path into a package name. + * Returns null if the path is not a valid package name. + */ + public static String packageName(IPath pkgPath) { + StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME); + for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) { + String segment = pkgPath.segment(j); + if (!isValidFolderNameForPackage(segment)) { + return null; + } + pkgName.append(segment); + if (j < pkgPath.segmentCount() - 1) { + pkgName.append("." ); //$NON-NLS-1$ + } + } + return pkgName.toString(); + } + + /** + * Sort the comparable objects in the given collection. + */ + private static void quickSort(Comparable[] sortedCollection, int left, int right) { + int original_left = left; + int original_right = right; + Comparable mid = sortedCollection[ (left + right) / 2]; + do { + while (sortedCollection[left].compareTo(mid) < 0) { + left++; + } + while (mid.compareTo(sortedCollection[right]) < 0) { + right--; + } + if (left <= right) { + Comparable tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSort(sortedCollection, original_left, right); + } + if (left < original_right) { + quickSort(sortedCollection, left, original_right); + } + } + + /** + * Sort the strings in the given collection in reverse alphabetical order. + */ + private static void quickSortReverse(String[] sortedCollection, int left, int right) { + int original_left = left; + int original_right = right; + String mid = sortedCollection[ (left + right) / 2]; + do { + while (sortedCollection[left].compareTo(mid) > 0) { + left++; + } + while (mid.compareTo(sortedCollection[right]) > 0) { + right--; + } + if (left <= right) { + String tmp = sortedCollection[left]; + sortedCollection[left] = sortedCollection[right]; + sortedCollection[right] = tmp; + left++; + right--; + } + } while (left <= right); + if (original_left < right) { + quickSortReverse(sortedCollection, original_left, right); + } + if (left < original_right) { + quickSortReverse(sortedCollection, left, original_right); + } + } + + /** + * Sorts an array of objects in place, using the sort order given for each item. + */ + public static void sort(Object[] objects, int[] sortOrder) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1, sortOrder); + } + + /** + * Sorts an array of objects in place. + * The given comparer compares pairs of items. + */ + public static void sort(Object[] objects, Comparer comparer) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1, comparer); + } + + /** + * Sorts an array of strings in place using quicksort. + */ + public static void sort(String[] strings) { + if (strings.length > 1) + quickSort(strings, 0, strings.length - 1); + } + + /** + * Sorts an array of Comparable objects in place. + */ + public static void sort(Comparable[] objects) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1); + } + + /** + * Sorts an array of Strings, returning a new array + * with the sorted items. The original array is left untouched. + */ + public static Object[] sortCopy(Object[] objects, Comparer comparer) { + int len = objects.length; + Object[] copy = new Object[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy, comparer); + return copy; + } + + /** + * Sorts an array of Strings, returning a new array + * with the sorted items. The original array is left untouched. + */ + public static String[] sortCopy(String[] objects) { + int len = objects.length; + String[] copy = new String[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy); + return copy; + } + + /** + * Sorts an array of Comparable objects, returning a new array + * with the sorted items. The original array is left untouched. + */ + public static Comparable[] sortCopy(Comparable[] objects) { + int len = objects.length; + Comparable[] copy = new Comparable[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy); + return copy; + } + + /** + * Sorts an array of strings in place using quicksort + * in reverse alphabetical order. + */ + public static void sortReverseOrder(String[] strings) { + if (strings.length > 1) + quickSortReverse(strings, 0, strings.length - 1); + } + + /** + * Converts a String[] to char[][]. + */ + public static char[][] toCharArrays(String[] a) { + int len = a.length; + char[][] result = new char[len][]; + for (int i = 0; i < len; ++i) { + result[i] = toChars(a[i]); + } + return result; + } + + /** + * Converts a String to char[]. + */ + public static char[] toChars(String s) { + int len = s.length(); + char[] chars = new char[len]; + s.getChars(0, len, chars, 0); + return chars; + } + + /** + * Converts a String to char[][], where segments are separate by '.'. + */ + public static char[][] toCompoundChars(String s) { + int len = s.length(); + if (len == 0) { + return CharOperation.NO_CHAR_CHAR; + } + int segCount = 1; + for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) { + ++segCount; + } + char[][] segs = new char[segCount][]; + int start = 0; + for (int i = 0; i < segCount; ++i) { + int dot = s.indexOf('.', start); + int end = (dot == -1 ? s.length() : dot); + segs[i] = new char[end - start]; + s.getChars(start, end, segs[i], 0); + start = end + 1; + } + return segs; + } + + /** + * Converts a char[][] to String, where segments are separated by '.'. + */ + public static String toString(char[][] c) { + StringBuffer sb = new StringBuffer(); + for (int i = 0, max = c.length; i < max; ++i) { + if (i != 0) sb.append('.'); + sb.append(c[i]); + } + return sb.toString(); + } + + /** + * Converts a char[][] and a char[] to String, where segments are separated by '.'. + */ + public static String toString(char[][] c, char[] d) { + if (c == null) return new String(d); + StringBuffer sb = new StringBuffer(); + for (int i = 0, max = c.length; i < max; ++i) { + sb.append(c[i]); + sb.append('.'); + } + sb.append(d); + return sb.toString(); + } + + /** + * Converts a char[] to String. + */ + public static String toString(char[] c) { + return new String(c); + } + + /** + * Converts an array of Objects into String. + */ + public static String toString(Object[] objects) { + return toString(objects, + new Displayable(){ + public String displayString(Object o) { + if (o == null) return "null"; //$NON-NLS-1$ + return o.toString(); + } + }); + } + + /** + * Converts an array of Objects into String. + */ + public static String toString(Object[] objects, Displayable renderer) { + if (objects == null) return ""; //$NON-NLS-1$ + StringBuffer buffer = new StringBuffer(10); + for (int i = 0; i < objects.length; i++){ + if (i > 0) buffer.append(", "); //$NON-NLS-1$ + buffer.append(renderer.displayString(objects[i])); + } + return buffer.toString(); + } + + /** + * Asserts that the given method signature is valid. + */ + public static void validateMethodSignature(String sig) { + Assert.isTrue(isValidMethodSignature(sig)); + } + + /** + * Asserts that the given type signature is valid. + */ + public static void validateTypeSignature(String sig, boolean allowVoid) { + Assert.isTrue(isValidTypeSignature(sig, allowVoid)); + } + public static void verbose(String log) { + verbose(log, System.out); + } + public static synchronized void verbose(String log, PrintStream printStream) { + int start = 0; + do { + int end = log.indexOf('\n', start); + printStream.print(Thread.currentThread()); + printStream.print(" "); //$NON-NLS-1$ + printStream.print(log.substring(start, end == -1 ? log.length() : end+1)); + start = end+1; + } while (start != 0); + printStream.println(); + } + /** + * Creates a NLS catalog for the given locale. + */ + public static void relocalize() { + try { + bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault()); + } catch(MissingResourceException e) { + System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$ + throw e; + } + } + + /** + * Put all the arguments in one String. + */ + public static String getProblemArgumentsForMarker(String[] arguments){ + StringBuffer args = new StringBuffer(10); + + args.append(arguments.length); + args.append(':'); + + + for (int j = 0; j < arguments.length; j++) { + if(j != 0) + args.append(ARGUMENTS_DELIMITER); + + if(arguments[j].length() == 0) { + args.append(EMPTY_ARGUMENT); + } else { + args.append(arguments[j]); + } + } + + return args.toString(); + } + + /** + * Separate all the arguments of a String made by getProblemArgumentsForMarker + */ + public static String[] getProblemArgumentsFromMarker(String argumentsString){ + if (argumentsString == null) return null; + int index = argumentsString.indexOf(':'); + if(index == -1) + return null; + + int length = argumentsString.length(); + int numberOfArg; + try{ + numberOfArg = Integer.parseInt(argumentsString.substring(0 , index)); + } catch (NumberFormatException e) { + return null; + } + argumentsString = argumentsString.substring(index + 1, length); + + String[] args = new String[length]; + int count = 0; + + StringTokenizer tokenizer = new StringTokenizer(argumentsString, ARGUMENTS_DELIMITER); + while(tokenizer.hasMoreTokens()) { + String argument = tokenizer.nextToken(); + if(argument.equals(EMPTY_ARGUMENT)) + argument = ""; //$NON-NLS-1$ + args[count++] = argument; + } + + if(count != numberOfArg) + return null; + + System.arraycopy(args, 0, args = new String[count], 0, count); + return args; + } + +}