| /******************************************************************************* |
| * 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 org.eclipse.cdt.internal.core; |
| |
| import java.io.BufferedInputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.util.HashSet; |
| import java.util.Locale; |
| import java.util.MissingResourceException; |
| import java.util.ResourceBundle; |
| |
| import org.eclipse.cdt.internal.core.model.CModelManager; |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.IPath; |
| |
| 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 int DEFAULT_READING_SIZE = 8192; |
| |
| /* Bundle containing messages */ |
| protected static ResourceBundle bundle; |
| private final static String bundleName = "org.eclipse.cdt.internal.core.messages"; //$NON-NLS-1$ |
| static { |
| relocalize(); |
| } |
| /** |
| * 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}); |
| } |
| /** |
| * 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 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 |
| */ |
| public static String bind(String id) { |
| return bind(id, (String[])null); |
| } |
| /** |
| * 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; |
| } |
| } |
| |
| /** |
| * Returns the contents of the given file as a byte array. |
| * @throws IOException if a problem occured reading the file. |
| */ |
| public static byte[] getFileByteContent(File file) throws IOException { |
| InputStream stream = null; |
| try { |
| stream = new BufferedInputStream(new FileInputStream(file)); |
| return getInputStreamAsByteArray(stream, (int) file.length()); |
| } finally { |
| if (stream != null) { |
| try { |
| stream.close(); |
| } catch (IOException e) { |
| } |
| } |
| } |
| } |
| /** |
| * Returns the contents of the given file as a char array. |
| * When encoding is null, then the platform default one is used |
| * @throws IOException if a problem occured reading the file. |
| */ |
| public static char[] getFileCharContent(File file, String encoding) throws IOException { |
| InputStream stream = null; |
| try { |
| stream = new BufferedInputStream(new FileInputStream(file)); |
| return Util.getInputStreamAsCharArray(stream, (int) file.length(), encoding); |
| } finally { |
| if (stream != null) { |
| try { |
| stream.close(); |
| } catch (IOException e) { |
| } |
| } |
| } |
| } |
| |
| /** |
| * Returns the given input stream's contents as a byte array. |
| * If a length is specified (ie. if length != -1), only length bytes |
| * are returned. Otherwise all bytes in the stream are returned. |
| * Note this doesn't close the stream. |
| * @throws IOException if a problem occured reading the stream. |
| */ |
| public static byte[] getInputStreamAsByteArray(InputStream stream, int length) |
| throws IOException { |
| byte[] contents; |
| if (length == -1) { |
| contents = new byte[0]; |
| int contentsLength = 0; |
| int amountRead = -1; |
| do { |
| int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K |
| |
| // resize contents if needed |
| if (contentsLength + amountRequested > contents.length) { |
| System.arraycopy( |
| contents, |
| 0, |
| contents = new byte[contentsLength + amountRequested], |
| 0, |
| contentsLength); |
| } |
| |
| // read as many bytes as possible |
| amountRead = stream.read(contents, contentsLength, amountRequested); |
| |
| if (amountRead > 0) { |
| // remember length of contents |
| contentsLength += amountRead; |
| } |
| } while (amountRead != -1); |
| |
| // resize contents if necessary |
| if (contentsLength < contents.length) { |
| System.arraycopy( |
| contents, |
| 0, |
| contents = new byte[contentsLength], |
| 0, |
| contentsLength); |
| } |
| } else { |
| contents = new byte[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 = stream.read(contents, len, length - len); |
| } |
| } |
| |
| return contents; |
| } |
| |
| /** |
| * 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 = CharOperation.NO_CHAR; |
| int contentsLength = 0; |
| int amountRead = -1; |
| do { |
| int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K |
| |
| // resize contents if needed |
| if (contentsLength + amountRequested > contents.length) { |
| System.arraycopy( |
| contents, |
| 0, |
| contents = new char[contentsLength + amountRequested], |
| 0, |
| contentsLength); |
| } |
| |
| // read as many chars as possible |
| amountRead = reader.read(contents, contentsLength, amountRequested); |
| |
| if (amountRead > 0) { |
| // remember length of contents |
| contentsLength += amountRead; |
| } |
| } while (amountRead != -1); |
| |
| // 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; |
| } |
| |
| |
| /** |
| * Helper method - returns the targeted item (IResource if internal or java.io.File if external), |
| * or null if unbound |
| * Internal items must be referred to using container relative paths. |
| */ |
| public static Object getTarget(IContainer container, IPath path, boolean checkResourceExistence) { |
| |
| if (path == null) return null; |
| |
| // lookup - inside the container |
| if (path.getDevice() == null) { // container relative paths should not contain a device |
| // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684) |
| // (case of a workspace rooted at d:\ ) |
| IResource resource = container.findMember(path); |
| if (resource != null){ |
| if (!checkResourceExistence ||resource.exists()) return resource; |
| return null; |
| } |
| } |
| |
| // if path is relative, it cannot be an external path |
| // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517) |
| if (!path.isAbsolute()) return null; |
| |
| // lookup - outside the container |
| File externalFile = new File(path.toOSString()); |
| if (!checkResourceExistence) { |
| return externalFile; |
| } else if (existingExternalFiles.contains(externalFile)) { |
| return externalFile; |
| } else { |
| if (externalFile.exists()) { |
| // cache external file |
| existingExternalFiles.add(externalFile); |
| return externalFile; |
| } |
| } |
| |
| return null; |
| } |
| /** |
| * A set of java.io.Files used as a cache of external jars that |
| * are known to be existing. |
| * Note this cache is kept for the whole session. |
| */ |
| public static HashSet existingExternalFiles = new HashSet(); |
| |
| /* |
| * 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 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; |
| } |
| /** |
| * @param string |
| * @return |
| */ |
| public static boolean isCCFileName(String fileName) { |
| String[] sourceExtensions = CModelManager.sourceExtensions; |
| String[] headerExtensions = CModelManager.headerExtensions; |
| |
| int dot =fileName.lastIndexOf("."); |
| |
| //No extension, give benefit of doubt |
| if (dot == -1) |
| return true; |
| |
| //Extract extension |
| String extension = ""; |
| if (dot + 1 <= fileName.length()) |
| extension = fileName.substring(dot + 1); |
| |
| for (int i=0; i<sourceExtensions.length; i++){ |
| if (sourceExtensions[i].equals(extension)) |
| return true; |
| } |
| |
| for (int i=0; i<headerExtensions.length; i++){ |
| if (headerExtensions[i].equals(extension)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| } |
| |
| |