/******************************************************************************* * Copyright (c) 2002, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Rational Software - Initial API and implementation * Markus Schorn (Wind River Systems) * Anton Leherbauer (Wind River Systems) * IBM Corporation - EFS support *******************************************************************************/ package org.eclipse.cdt.internal.core.model; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; import com.ibm.icu.text.MessageFormat; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.ICLogConstants; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ICModelStatusConstants; import org.eclipse.cdt.internal.core.util.CharArrayBuffer; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; public class Util implements ICLogConstants { public static boolean VERBOSE_PARSER = false; public static boolean VERBOSE_SCANNER = false; public static boolean VERBOSE_MODEL = false; public static boolean VERBOSE_DELTA = false; public static boolean PARSER_EXCEPTIONS= false; public static String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$ private Util() { } public static StringBuffer getContent(IFile file) throws IOException { InputStream stream = null; try { stream = new BufferedInputStream(file.getContents(true)); } catch (CoreException e) { throw new IOException(e.getMessage()); } try { char[] b = getInputStreamAsCharArray(stream, -1, null); return new StringBuffer(b.length).append(b); } finally { try { stream.close(); } catch (IOException e) { } } } /** * Returns the given input stream's contents as a character array. If a * length is specified (ie. if length != -1), only length chars are * returned. Otherwise all chars in the stream are returned. Note this * doesn't close the stream. * * @throws IOException * if a problem occured reading the stream. */ public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding) throws IOException { InputStreamReader reader = null; reader = encoding == null ? new InputStreamReader(stream) : new InputStreamReader(stream, encoding); char[] contents; if (length == -1) { contents = new char[0]; int contentsLength = 0; int charsRead = -1; do { int available = stream.available(); // resize contents if needed if (contentsLength + available > contents.length) { System.arraycopy(contents, 0, contents = new char[contentsLength + available], 0, contentsLength); } // read as many chars as possible charsRead = reader.read(contents, contentsLength, available); if (charsRead > 0) { // remember length of contents contentsLength += charsRead; } } while (charsRead > 0); // resize contents if necessary if (contentsLength < contents.length) { System.arraycopy(contents, 0, contents = new char[contentsLength], 0, contentsLength); } } else { contents = new char[length]; int len = 0; int readSize = 0; while ((readSize != -1) && (len != length)) { // See PR 1FMS89U // We record first the read size. In this case len is the // actual read size. len += readSize; readSize = reader.read(contents, len, length - len); } // See PR 1FMS89U // Now we need to resize in case the default encoding used more // than one byte for each // character if (len != length) System.arraycopy(contents, 0, (contents = new char[len]), 0, len); } return contents; } public static void save(StringBuffer buffer, IFile file) throws CoreException { String encoding = null; try { encoding = file.getCharset(); } catch (CoreException ce) { // use no encoding } byte[] bytes = null; if (encoding != null) { try { bytes = buffer.toString().getBytes(encoding); } catch (Exception e) { } } else { bytes = buffer.toString().getBytes(); } ByteArrayInputStream stream = new ByteArrayInputStream(bytes); // use a platform operation to update the resource contents boolean force = true; file.setContents(stream, force, true, null); // record history } /** * Returns the given file's contents as a character array. */ public static char[] getResourceContentsAsCharArray(IFile file) throws CModelException { try { return getResourceContentsAsCharArray(file, file.getCharset()); } catch (CoreException exc) { throw new CModelException(exc, ICModelStatusConstants.CORE_EXCEPTION); } } public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws CModelException { InputStream stream = null; try { stream = new BufferedInputStream(file.getContents(true)); } catch (CoreException e) { throw new CModelException(e, ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST); } try { return Util.getInputStreamAsCharArray(stream, -1, encoding); } catch (IOException e) { throw new CModelException(e, ICModelStatusConstants.IO_EXCEPTION); } finally { try { stream.close(); } catch (IOException e) { } } } /* * Add a log entry */ public static void log(Throwable e, String message, LogConst logType) { IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, message,e); Util.log(status, logType); } public static void log(IStatus status, LogConst logType) { if (logType.equals(ICLogConstants.PDE)) { CCorePlugin.getDefault().getLog().log(status); } else if (logType.equals(ICLogConstants.CDT)) { CCorePlugin.getDefault().cdtLog.log(status); } } public static void log(String message, LogConst logType) { IStatus status = new Status(IStatus.INFO, CCorePlugin.PLUGIN_ID, IStatus.INFO, message, null); Util.log(status, logType); } public static void debugLog(String message, DebugLogConstants client) { Util.debugLog(message, client, true); } public static void debugLog(String message, DebugLogConstants client, boolean addTimeStamp) { if (CCorePlugin.getDefault() == null) return; if (CCorePlugin.getDefault().isDebugging() && isActive(client)) { // Time stamp if (addTimeStamp) message = MessageFormat.format("[{0}] {1}", new Object[]{ //$NON-NLS-1$ new Long(System.currentTimeMillis()), message}); while (message.length() > 100) { String partial = message.substring(0, 100); message = message.substring(100); System.out.println(partial + "\\"); //$NON-NLS-1$ } if (message.endsWith("\n")) { //$NON-NLS-1$ System.err.print(message); } else { System.out.println(message); } } } public static boolean isActive(DebugLogConstants client) { if (client.equals(DebugLogConstants.PARSER)) { return VERBOSE_PARSER; } else if (client.equals(DebugLogConstants.SCANNER)) return VERBOSE_SCANNER; else if (client.equals(DebugLogConstants.MODEL)) { return VERBOSE_MODEL; } return false; } public static void setDebugging(boolean value) { CCorePlugin.getDefault().setDebugging(value); } /** * Combines two hash codes to make a new one. */ public static int combineHashCodes(int hashCode1, int hashCode2) { return hashCode1 * 17 + hashCode2; } /** * 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 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 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); } /** * 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(); } 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())); } /** * Returns the line separator used by the given buffer. * Uses the given text if none found. * * @return </code>"\n"</code> or </code>"\r"</code> or </code>"\r\n"</code> */ 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 LINE_SEPARATOR; } } return lineSeparator; } /** * Finds the first line separator used by the given text. * * @return </code>"\n"</code> or </code>"\r"</code> or </code>"\r\n"</code>, * or <code>null</code> 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; } /** * Return true if the file is not a directory and has length > 0 */ public static boolean isNonZeroLengthFile(IPath path) { return isNonZeroLengthFile(URIUtil.toURI(path)); } /** * Return true if the file referred to by the URI is not a directory and has length > 0 */ public static boolean isNonZeroLengthFile(URI uri) { try { IFileInfo file = EFS.getStore(uri).fetchInfo(); if (file.getLength() == EFS.NONE) { return false; } return true; } catch (CoreException e) { // ignore } return false; } }