/******************************************************************************* | |
* 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.22.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(); | |
} | |
} |