| /******************************************************************************* |
| * Copyright (c) 2004, 2012 Tasktop Technologies 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: |
| * Tasktop Technologies - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.commons.core; |
| |
| import java.util.Map; |
| |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.parsers.SAXParser; |
| import javax.xml.parsers.SAXParserFactory; |
| |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.Version; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.XMLReader; |
| |
| /** |
| * @since 3.0 |
| * @author Steffen Pingel |
| * @author Benjamin Muskalla |
| * @noinstantiate This class is not intended to be instantiated by clients. |
| */ |
| public class CoreUtil { |
| |
| /** |
| * @since 3.0 |
| */ |
| public static final boolean TEST_MODE; |
| |
| static { |
| String application = System.getProperty("eclipse.application", ""); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (application.length() > 0) { |
| TEST_MODE = application.endsWith("testapplication") || application.endsWith("uitest"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } else { |
| // eclipse 3.3 does not the eclipse.application property |
| String commands = System.getProperty("eclipse.commands", ""); //$NON-NLS-1$ //$NON-NLS-2$ |
| TEST_MODE = commands.contains("testapplication\n"); //$NON-NLS-1$ |
| } |
| } |
| |
| private static final String FRAMEWORK_VERSION = "3.15.0"; //$NON-NLS-1$ |
| |
| private static final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); |
| static { |
| saxParserFactory.setNamespaceAware(true); |
| } |
| |
| /** |
| * Returns a string representation of <code>object</code>. If object is a map or array the returned string will |
| * contains a comma separated list of contained elements. |
| * |
| * @since 3.4 |
| */ |
| public static String toString(Object object) { |
| StringBuilder sb = new StringBuilder(); |
| toString(sb, object); |
| return sb.toString(); |
| } |
| |
| private static void toString(StringBuilder sb, Object object) { |
| if (object instanceof Object[]) { |
| sb.append("["); //$NON-NLS-1$ |
| Object[] entries = (Object[]) object; |
| boolean prependSeparator = false; |
| for (Object entry : entries) { |
| if (prependSeparator) { |
| sb.append(", "); //$NON-NLS-1$ |
| } |
| toString(sb, entry); |
| prependSeparator = true; |
| } |
| sb.append("]"); //$NON-NLS-1$ |
| } else if (object instanceof Map<?, ?>) { |
| sb.append("{"); //$NON-NLS-1$ |
| boolean prependSeparator = false; |
| for (Map.Entry<?, ?> entry : ((Map<?, ?>) object).entrySet()) { |
| if (prependSeparator) { |
| sb.append(", "); //$NON-NLS-1$ |
| } |
| toString(sb, entry.getKey()); |
| sb.append("="); //$NON-NLS-1$ |
| toString(sb, entry.getValue()); |
| prependSeparator = true; |
| } |
| sb.append("}"); //$NON-NLS-1$ |
| } else { |
| sb.append(object); |
| } |
| } |
| |
| /** |
| * Returns the version of the bundle. |
| * |
| * @since 3.7 |
| * @deprecated use {@link Bundle#getVersion()} instead |
| */ |
| @Deprecated |
| public static Version getVersion(Bundle bundle) { |
| return bundle.getVersion(); |
| } |
| |
| /** |
| * Returns true, if <code>o1</code> is equal to <code>o2</code> or <code>o1</code> and <code>o2</code> are |
| * <code>null</code>. |
| * |
| * @see Object#equals(Object) |
| * @since 3.7 |
| */ |
| public static boolean areEqual(Object o1, Object o2) { |
| if (o1 == null) { |
| return (o2 == null); |
| } else { |
| return o1.equals(o2); |
| } |
| } |
| |
| /** |
| * Compares <code>o1</code> and <code>o2</code>. |
| * |
| * @since 3.7 |
| * @return a negative integer, 0, or a positive, if o1 is less than o2, o1 equals o2 or o1 is more than o2; null is |
| * considered less than any value |
| */ |
| public static <T> int compare(Comparable<T> o1, T o2) { |
| if (o1 == null) { |
| return (o2 != null) ? 1 : 0; |
| } else if (o2 == null) { |
| return -1; |
| } |
| return o1.compareTo(o2); |
| } |
| |
| /** |
| * Compares a boolean value. |
| * |
| * @since 3.7 |
| * @see Boolean#equals(Object) |
| */ |
| public static boolean propertyEquals(boolean value, Object expectedValue) { |
| return (expectedValue == null) ? value == true : Boolean.valueOf(value).equals(expectedValue); |
| } |
| |
| /** |
| * Disables logging through the Apache commons logging system by default. This can be overridden by specifying the |
| * <code>org.apache.commons.logging.Log</code> system property. |
| * |
| * @since 3.7 |
| */ |
| public static void initializeLoggingSettings() { |
| defaultSystemProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| /** |
| * Only sets system property if they are not already set to a value. |
| */ |
| private static void defaultSystemProperty(String key, String defaultValue) { |
| if (System.getProperty(key) == null) { |
| System.setProperty(key, defaultValue); |
| } |
| } |
| |
| /** |
| * Returns the version of the Java runtime. |
| * |
| * @since 3.7 |
| * @return {@link Version#emptyVersion} if the version can not be determined |
| */ |
| public static Version getRuntimeVersion() { |
| Version result = parseRuntimeVersion(System.getProperty("java.runtime.version")); //$NON-NLS-1$ |
| if (result == Version.emptyVersion) { |
| result = parseRuntimeVersion(System.getProperty("java.version")); //$NON-NLS-1$ |
| } |
| return result; |
| } |
| |
| private static Version parseRuntimeVersion(String versionString) { |
| if (versionString != null) { |
| int firstSeparator = versionString.indexOf('.'); |
| if (firstSeparator != -1) { |
| try { |
| int secondSeparator = versionString.indexOf('.', firstSeparator + 1); |
| if (secondSeparator != -1) { |
| int index = findLastNumberIndex(versionString, secondSeparator); |
| String qualifier = versionString.substring(index + 1); |
| if (qualifier.startsWith("_") && qualifier.length() > 1) { //$NON-NLS-1$ |
| versionString = versionString.substring(0, index + 1) + "." + qualifier.substring(1); //$NON-NLS-1$ |
| } else { |
| versionString = versionString.substring(0, index + 1); |
| } |
| return new Version(versionString); |
| } |
| return new Version(versionString.substring(0, |
| findLastNumberIndex(versionString, firstSeparator) + 1)); |
| } catch (IllegalArgumentException e) { |
| // ignore |
| } |
| } |
| } |
| return Version.emptyVersion; |
| } |
| |
| private static int findLastNumberIndex(String versionString, int secondSeparator) { |
| int lastDigit = secondSeparator; |
| for (int i = secondSeparator + 1; i < versionString.length(); i++) { |
| if (Character.isDigit(versionString.charAt(i))) { |
| lastDigit++; |
| } else { |
| break; |
| } |
| } |
| if (lastDigit == secondSeparator) { |
| return secondSeparator - 1; |
| } |
| return lastDigit; |
| } |
| |
| /** |
| * Returns the running Mylyn version without the qualifier. |
| * |
| * @since 3.7 |
| */ |
| public static Version getFrameworkVersion() { |
| return new Version(FRAMEWORK_VERSION); |
| } |
| |
| /** |
| * Returns a representation of <code>name</code> that is a valid file name. |
| * |
| * @since 3.7 |
| */ |
| public static String asFileName(String name) { |
| StringBuffer sb = new StringBuffer(name.length()); |
| char[] chars = name.toCharArray(); |
| for (char c : chars) { |
| if (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '.') { |
| sb.append(c); |
| } else { |
| sb.append("%" + Integer.toHexString(c).toUpperCase()); //$NON-NLS-1$ |
| } |
| } |
| return sb.toString(); |
| } |
| |
| /** |
| * Returns the decoded form of <code>text</code>. |
| * |
| * @since 3.8 |
| * @see #encode(String) |
| * @throws IllegalArgumentException |
| * if text is not in a valid form, i.e. it was not encoded using {@link CoreUtil#encode(String)} |
| */ |
| public static String decode(String text) { |
| boolean escaped = false; |
| StringBuilder sb = new StringBuilder(text.length()); |
| StringBuilder escapedText = new StringBuilder(4); |
| char[] chars = text.toCharArray(); |
| for (char c : chars) { |
| if (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '.') { |
| if (escaped) { |
| escapedText.append(c); |
| } else { |
| sb.append(c); |
| } |
| } else if (c == '%') { |
| if (escaped) { |
| throw new IllegalArgumentException("Unexpected '%' sign in '" + text + "'"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| escaped = !escaped; |
| } else if (c == '_') { |
| if (!escaped) { |
| throw new IllegalArgumentException("Unexpected '_' sign in '" + text + "'"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| try { |
| sb.append((char) Integer.parseInt(escapedText.toString(), 16)); |
| escapedText.setLength(0); |
| } catch (NumberFormatException e) { |
| throw new IllegalArgumentException("Invalid escape code in '" + text + "'"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| escaped = !escaped; |
| } else { |
| throw new IllegalArgumentException("Unexpected character '" + c + "' in '" + text + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| } |
| return sb.toString(); |
| } |
| |
| /** |
| * An encoded form of <code>text</code> that is suitable as a filename. |
| * |
| * @param text |
| * the string to encode |
| * @see #decode(String) |
| * @since 3.8 |
| */ |
| public static String encode(String text) { |
| StringBuilder sb = new StringBuilder(text.length()); |
| char[] chars = text.toCharArray(); |
| for (char c : chars) { |
| if (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '.') { |
| sb.append(c); |
| } else { |
| sb.append("%"); //$NON-NLS-1$ |
| sb.append(Integer.toHexString(c).toUpperCase()); |
| sb.append("_"); //$NON-NLS-1$ |
| } |
| } |
| return sb.toString(); |
| } |
| |
| /** |
| * Returns a new {@link XMLReader} instance using default factories. |
| * |
| * @since 3.9 |
| */ |
| public static SAXParser newSaxParser() throws SAXException { |
| try { |
| return saxParserFactory.newSAXParser(); |
| } catch (ParserConfigurationException e) { |
| throw new SAXException(e); |
| } |
| } |
| |
| /** |
| * Returns a new {@link XMLReader} instance using default factories. |
| * |
| * @since 3.9 |
| */ |
| public static XMLReader newXmlReader() throws SAXException { |
| return newSaxParser().getXMLReader(); |
| } |
| |
| } |