/******************************************************************************* * Copyright (c) 2004, 2016 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.23.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(); } }