// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.tools; import static org.openstreetmap.josm.tools.I18n.tr; import static org.openstreetmap.josm.tools.I18n.trn; import java.awt.Color; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.MessageFormat; import java.util.AbstractCollection; import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import java.util.zip.ZipFile; import org.apache.tools.bzip2.CBZip2InputStream; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.Version; import org.openstreetmap.josm.io.FileImporter; /** * Basic utils, that can be useful in different parts of the program. */ public final class Utils { public static final Pattern WHITE_SPACES_PATTERN = Pattern.compile("\\s+"); private Utils() { // Hide default constructor for utils classes } /** * UTF-8 (UCS Transformation Format—8-bit). * *
Every implementation of the Java platform is required to support UTF-8 (see {@link Charset}).
*/ public static final Charset UTF_8 = Charset.forName("UTF-8"); private static final int MILLIS_OF_SECOND = 1000; private static final int MILLIS_OF_MINUTE = 60000; private static final int MILLIS_OF_HOUR = 3600000; private static final int MILLIS_OF_DAY = 86400000; /** * Tests whether {@code predicate} applies to at least one elements from {@code collection}. */ public staticUtility method for closing a {@link java.io.Closeable} object.
* * @param c the closeable object. May be null. */ public static void close(Closeable c) { if (c == null) return; try { c.close(); } catch (IOException e) { Main.warn(e); } } /** *Utility method for closing a {@link java.util.zip.ZipFile}.
* * @param zip the zip file. May be null. */ public static void close(ZipFile zip) { if (zip == null) return; try { zip.close(); } catch (IOException e) { Main.warn(e); } } /** * Converts the given file to its URL. * @param f The file to get URL from * @return The URL of the given file, or {@code null} if not possible. * @since 6615 */ public static URL fileToURL(File f) { if (f != null) { try { return f.toURI().toURL(); } catch (MalformedURLException ex) { Main.error("Unable to convert filename " + f.getAbsolutePath() + " to URL"); } } return null; } private final static double EPSILON = 1e-11; /** * Determines if the two given double values are equal (their delta being smaller than a fixed epsilon) * @param a The first double value to compare * @param b The second double value to compare * @return {@code true} if {@code abs(a - b) <= 1e-11}, {@code false} otherwise */ public static boolean equalsEpsilon(double a, double b) { return Math.abs(a - b) <= EPSILON; } /** * Copies the string {@code s} to system clipboard. * @param s string to be copied to clipboard. * @return true if succeeded, false otherwise. */ public static boolean copyToClipboard(String s) { try { Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(s), new ClipboardOwner() { @Override public void lostOwnership(Clipboard clpbrd, Transferable t) { } }); return true; } catch (IllegalStateException ex) { Main.error(ex); return false; } } /** * Extracts clipboard content as string. * @return string clipboard contents if available, {@code null} otherwise. */ public static String getClipboardContent() { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Transferable t = null; for (int tries = 0; t == null && tries < 10; tries++) { try { t = clipboard.getContents(null); } catch (IllegalStateException e) { // Clipboard currently unavailable. On some platforms, the system clipboard is unavailable while it is accessed by another application. try { Thread.sleep(1); } catch (InterruptedException ex) { Main.warn("InterruptedException in "+Utils.class.getSimpleName()+" while getting clipboard content"); } } } try { if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) { return (String) t.getTransferData(DataFlavor.stringFlavor); } } catch (UnsupportedFlavorException ex) { Main.error(ex); return null; } catch (IOException ex) { Main.error(ex); return null; } return null; } /** * Calculate MD5 hash of a string and output in hexadecimal format. * @param data arbitrary String * @return MD5 hash of data, string of length 32 with characters in range [0-9a-f] */ public static String md5Hex(String data) { byte[] byteData = data.getBytes(UTF_8); MessageDigest md = null; try { md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } byte[] byteDigest = md.digest(byteData); return toHexString(byteDigest); } private static final char[] HEX_ARRAY = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; /** * Converts a byte array to a string of hexadecimal characters. * Preserves leading zeros, so the size of the output string is always twice * the number of input bytes. * @param bytes the byte array * @return hexadecimal representation */ public static String toHexString(byte[] bytes) { if (bytes == null) { return ""; } final int len = bytes.length; if (len == 0) { return ""; } char[] hexChars = new char[len * 2]; for (int i = 0, j = 0; i < len; i++) { final int v = bytes[i]; hexChars[j++] = HEX_ARRAY[(v & 0xf0) >> 4]; hexChars[j++] = HEX_ARRAY[v & 0xf]; } return new String(hexChars); } /** * Topological sort. * * @param dependencies contains mappings (key -> value). In the final list of sorted objects, the key will come * after the value. (In other words, the key depends on the value(s).) * There must not be cyclic dependencies. * @return the list of sorted objects */ public staticstr
, without leading and trailing characters, according to
* {@link Character#isWhitespace(char)} and {@link Character#isSpaceChar(char)}.
* @since 5772
*/
public static String strip(String str) {
if (str == null || str.isEmpty()) {
return str;
}
int start = 0, end = str.length();
boolean leadingWhite = true;
while (leadingWhite && start < end) {
char c = str.charAt(start);
// '\u200B' (ZERO WIDTH SPACE character) needs to be handled manually because of change in Unicode 6.0 (Java 7, see #8918)
// same for '\uFEFF' (ZERO WIDTH NO-BREAK SPACE)
leadingWhite = (Character.isWhitespace(c) || Character.isSpaceChar(c) || c == '\u200B' || c == '\uFEFF');
if (leadingWhite) {
start++;
}
}
boolean trailingWhite = true;
while (trailingWhite && end > start+1) {
char c = str.charAt(end-1);
trailingWhite = (Character.isWhitespace(c) || Character.isSpaceChar(c) || c == '\u200B' || c == '\uFEFF');
if (trailingWhite) {
end--;
}
}
return str.substring(start, end);
}
/**
* Runs an external command and returns the standard output.
*
* The program is expected to execute fast.
*
* @param command the command with arguments
* @return the output
* @throws IOException when there was an error, e.g. command does not exist
*/
public static String execOutput(List
* For instance, {@code [1,5,2,6,7} yields "1-2,5-7
* @param positionList a list of positions
* @return a human readable representation
*/
public static String getPositionListString(Listo
is null or the type o
is not
* a subclass of klass
. The casted value otherwise.
*/
@SuppressWarnings("unchecked")
public static