### Eclipse Workspace Patch 1.0
#P JOSM
|
|
|
|
| 39 | 39 | import java.util.Arrays; |
| 40 | 40 | import java.util.Collection; |
| 41 | 41 | import java.util.Collections; |
| 42 | | import java.util.HashSet; |
| 43 | 42 | import java.util.Iterator; |
| 44 | 43 | import java.util.List; |
| 45 | 44 | import java.util.Locale; |
| 46 | | import java.util.Set; |
| 47 | 45 | import java.util.concurrent.ExecutorService; |
| 48 | 46 | import java.util.concurrent.Executors; |
| 49 | 47 | import java.util.regex.Matcher; |
| … |
… |
|
| 149 | 147 | * Filter a collection by (sub)class. |
| 150 | 148 | * This is an efficient read-only implementation. |
| 151 | 149 | */ |
| 152 | | public static <S, T extends S> SubclassFilteredCollection<S, T> filteredCollection(Collection<S> collection, final Class<T> klass) { |
| | 150 | public static <S, T extends S> SubclassFilteredCollection<S, T> filteredCollection(Collection<S> collection, |
| | 151 | final Class<T> klass) { |
| 153 | 152 | return new SubclassFilteredCollection<>(collection, new Predicate<S>() { |
| 154 | 153 | @Override |
| 155 | 154 | public boolean evaluate(S o) { |
| … |
… |
|
| 210 | 209 | * @param data Message parameters, optional |
| 211 | 210 | * @throws AssertionError if the condition is not met |
| 212 | 211 | */ |
| 213 | | public static void ensure(boolean condition, String message, Object...data) { |
| | 212 | public static void ensure(boolean condition, String message, Object... data) { |
| 214 | 213 | if (!condition) |
| 215 | | throw new AssertionError( |
| 216 | | MessageFormat.format(message, data) |
| 217 | | ); |
| | 214 | throw new AssertionError(MessageFormat.format(message, data)); |
| 218 | 215 | } |
| 219 | 216 | |
| 220 | 217 | /** |
| … |
… |
|
| 222 | 219 | */ |
| 223 | 220 | public static int mod(int a, int n) { |
| 224 | 221 | if (n <= 0) |
| 225 | | throw new IllegalArgumentException("n must be <= 0 but is "+n); |
| | 222 | throw new IllegalArgumentException("n must be <= 0 but is " + n); |
| 226 | 223 | int res = a % n; |
| 227 | 224 | if (res < 0) { |
| 228 | 225 | res += n; |
| … |
… |
|
| 380 | 377 | CheckParameterUtil.ensureParameterNotNull(in, "in"); |
| 381 | 378 | CheckParameterUtil.ensureParameterNotNull(out, "out"); |
| 382 | 379 | if (!out.exists() && !out.mkdirs()) { |
| 383 | | Main.warn("Unable to create directory "+out.getPath()); |
| | 380 | Main.warn("Unable to create directory " + out.getPath()); |
| 384 | 381 | } |
| 385 | 382 | File[] files = in.listFiles(); |
| 386 | 383 | if (files != null) { |
| … |
… |
|
| 427 | 424 | if (file.isDirectory()) { |
| 428 | 425 | deleteDirectory(file); |
| 429 | 426 | } else if (!file.delete()) { |
| 430 | | Main.warn("Unable to delete file: "+file.getPath()); |
| | 427 | Main.warn("Unable to delete file: " + file.getPath()); |
| 431 | 428 | } |
| 432 | 429 | } |
| 433 | 430 | } |
| … |
… |
|
| 441 | 438 | * @param c the closeable object. May be null. |
| 442 | 439 | */ |
| 443 | 440 | public static void close(Closeable c) { |
| 444 | | if (c == null) return; |
| | 441 | if (c == null) |
| | 442 | return; |
| 445 | 443 | try { |
| 446 | 444 | c.close(); |
| 447 | 445 | } catch (IOException e) { |
| … |
… |
|
| 455 | 453 | * @param zip the zip file. May be null. |
| 456 | 454 | */ |
| 457 | 455 | public static void close(ZipFile zip) { |
| 458 | | if (zip == null) return; |
| | 456 | if (zip == null) |
| | 457 | return; |
| 459 | 458 | try { |
| 460 | 459 | zip.close(); |
| 461 | 460 | } catch (IOException e) { |
| … |
… |
|
| 529 | 528 | try { |
| 530 | 529 | Thread.sleep(1); |
| 531 | 530 | } catch (InterruptedException ex) { |
| 532 | | Main.warn("InterruptedException in "+Utils.class.getSimpleName()+" while getting clipboard content"); |
| | 531 | Main.warn("InterruptedException in " + Utils.class.getSimpleName() |
| | 532 | + " while getting clipboard content"); |
| 533 | 533 | } |
| 534 | 534 | } catch (NullPointerException e) { |
| 535 | 535 | // JDK-6322854: On Linux/X11, NPE can happen for unknown reasons, on all versions of Java |
| … |
… |
|
| 573 | 573 | return toHexString(byteDigest); |
| 574 | 574 | } |
| 575 | 575 | |
| 576 | | private static final char[] HEX_ARRAY = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; |
| | 576 | private static final char[] HEX_ARRAY = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', |
| | 577 | 'e', 'f' }; |
| 577 | 578 | |
| 578 | 579 | /** |
| 579 | 580 | * Converts a byte array to a string of hexadecimal characters. |
| … |
… |
|
| 630 | 631 | break; |
| 631 | 632 | } |
| 632 | 633 | } |
| 633 | | if (parentless == null) throw new RuntimeException(); |
| | 634 | if (parentless == null) |
| | 635 | throw new RuntimeException(); |
| 634 | 636 | sorted.add(parentless); |
| 635 | 637 | deps.remove(parentless); |
| 636 | 638 | for (T key : deps.keySet()) { |
| … |
… |
|
| 637 | 639 | deps.remove(key, parentless); |
| 638 | 640 | } |
| 639 | 641 | } |
| 640 | | if (sorted.size() != size) throw new RuntimeException(); |
| | 642 | if (sorted.size() != size) |
| | 643 | throw new RuntimeException(); |
| 641 | 644 | return sorted; |
| 642 | 645 | } |
| 643 | 646 | |
| … |
… |
|
| 737 | 740 | throw new IllegalArgumentException("Invalid HTTP url"); |
| 738 | 741 | } |
| 739 | 742 | if (Main.isDebugEnabled()) { |
| 740 | | Main.debug("Opening HTTP connection to "+httpURL.toExternalForm()); |
| | 743 | Main.debug("Opening HTTP connection to " + httpURL.toExternalForm()); |
| 741 | 744 | } |
| 742 | 745 | HttpURLConnection connection = (HttpURLConnection) httpURL.openConnection(); |
| 743 | 746 | connection.setRequestProperty("User-Agent", Version.getInstance().getFullAgentString()); |
| … |
… |
|
| 792 | 795 | if (in == null) { |
| 793 | 796 | return null; |
| 794 | 797 | } |
| 795 | | return new BZip2CompressorInputStream(in, /* see #9537 */ true); |
| | 798 | return new BZip2CompressorInputStream(in, /* see #9537 */true); |
| 796 | 799 | } |
| 797 | 800 | |
| 798 | 801 | /** |
| … |
… |
|
| 824 | 827 | // Positions the stream at the beginning of first entry |
| 825 | 828 | ZipEntry ze = zis.getNextEntry(); |
| 826 | 829 | if (ze != null && Main.isDebugEnabled()) { |
| 827 | | Main.debug("Zip entry: "+ze.getName()); |
| | 830 | Main.debug("Zip entry: " + ze.getName()); |
| 828 | 831 | } |
| 829 | 832 | return zis; |
| 830 | 833 | } |
| … |
… |
|
| 838 | 841 | public static URLConnection setupURLConnection(URLConnection connection) { |
| 839 | 842 | if (connection != null) { |
| 840 | 843 | connection.setRequestProperty("User-Agent", Version.getInstance().getFullAgentString()); |
| 841 | | connection.setConnectTimeout(Main.pref.getInteger("socket.timeout.connect", 15)*1000); |
| 842 | | connection.setReadTimeout(Main.pref.getInteger("socket.timeout.read", 30)*1000); |
| | 844 | connection.setConnectTimeout(Main.pref.getInteger("socket.timeout.connect", 15) * 1000); |
| | 845 | connection.setReadTimeout(Main.pref.getInteger("socket.timeout.read", 30) * 1000); |
| 843 | 846 | } |
| 844 | 847 | return connection; |
| 845 | 848 | } |
| … |
… |
|
| 883 | 886 | } |
| 884 | 887 | if (Main.isDebugEnabled()) { |
| 885 | 888 | try { |
| 886 | | Main.debug("REQUEST: "+ connection.getRequestProperties()); |
| | 889 | Main.debug("REQUEST: " + connection.getRequestProperties()); |
| 887 | 890 | } catch (IllegalStateException e) { |
| 888 | 891 | Main.warn(e); |
| 889 | 892 | } |
| … |
… |
|
| 891 | 894 | return connection; |
| 892 | 895 | } |
| 893 | 896 | |
| | 897 | private static char[] DEFAULT_STRIP = { '\u200B', '\uFEFF' }; |
| | 898 | |
| | 899 | |
| 894 | 900 | /** |
| 895 | 901 | * An alternative to {@link String#trim()} to effectively remove all leading and trailing white characters, including Unicode ones. |
| 896 | 902 | * @param str The string to strip |
| … |
… |
|
| 901 | 907 | * @since 5772 |
| 902 | 908 | */ |
| 903 | 909 | public static String strip(final String str) { |
| 904 | | return strip(str, null); |
| | 910 | if (str == null || str.isEmpty()) { |
| | 911 | return str; |
| | 912 | } |
| | 913 | return strip(str, DEFAULT_STRIP); |
| 905 | 914 | } |
| 906 | 915 | |
| 907 | 916 | /** |
| … |
… |
|
| 913 | 922 | * @since 8435 |
| 914 | 923 | */ |
| 915 | 924 | public static String strip(final String str, final String skipChars) { |
| | 925 | |
| 916 | 926 | if (str == null || str.isEmpty()) { |
| 917 | 927 | return str; |
| 918 | 928 | } |
| 919 | | // create set with chars to skip |
| 920 | | Set<Character> skipSet = new HashSet<>(); |
| 921 | | // '\u200B' (ZERO WIDTH SPACE character) needs to be handled manually because of change in Unicode 6.0 (Java 7, see #8918) |
| 922 | | skipSet.add('\u200B'); |
| 923 | | // same for '\uFEFF' (ZERO WIDTH NO-BREAK SPACE) |
| 924 | | skipSet.add('\uFEFF'); |
| 925 | | if (skipChars != null) { |
| 926 | | for (char c : skipChars.toCharArray()) { |
| 927 | | skipSet.add(c); |
| 928 | | } |
| 929 | | } |
| | 929 | |
| | 930 | return strip(str, stripChars(skipChars)); |
| | 931 | } |
| | 932 | |
| | 933 | private static String strip(final String str, final char[] skipChars) { |
| | 934 | |
| 930 | 935 | int start = 0; |
| 931 | 936 | int end = str.length(); |
| 932 | 937 | boolean leadingSkipChar = true; |
| 933 | 938 | while (leadingSkipChar && start < end) { |
| 934 | 939 | char c = str.charAt(start); |
| 935 | | leadingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || skipSet.contains(c); |
| | 940 | leadingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || stripChar(skipChars, c); |
| 936 | 941 | if (leadingSkipChar) { |
| 937 | 942 | start++; |
| 938 | 943 | } |
| 939 | 944 | } |
| 940 | 945 | boolean trailingSkipChar = true; |
| 941 | | while (trailingSkipChar && end > start+1) { |
| 942 | | char c = str.charAt(end-1); |
| 943 | | trailingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || skipSet.contains(c); |
| | 946 | while (trailingSkipChar && end > start + 1) { |
| | 947 | char c = str.charAt(end - 1); |
| | 948 | trailingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || stripChar(skipChars, c); |
| 944 | 949 | if (trailingSkipChar) { |
| 945 | 950 | end--; |
| 946 | 951 | } |
| 947 | 952 | } |
| | 953 | |
| 948 | 954 | return str.substring(start, end); |
| 949 | 955 | } |
| 950 | 956 | |
| | 957 | private static char[] stripChars(final String skipChars) { |
| | 958 | if (skipChars == null || skipChars.isEmpty()) { |
| | 959 | return DEFAULT_STRIP; |
| | 960 | } |
| | 961 | |
| | 962 | char[] chars = new char[skipChars.length() + 2]; |
| | 963 | chars[0] = '\u200B'; |
| | 964 | chars[1] = '\uFEFF'; |
| | 965 | skipChars.getChars(0, skipChars.length(), chars, 2); |
| | 966 | |
| | 967 | return chars; |
| | 968 | } |
| | 969 | |
| | 970 | private static boolean stripChar(final char[] strip, char c) { |
| | 971 | |
| | 972 | for (char s : strip) { |
| | 973 | if (c == s) { |
| | 974 | return true; |
| | 975 | } |
| | 976 | } |
| | 977 | |
| | 978 | return false; |
| | 979 | } |
| | 980 | |
| 951 | 981 | /** |
| 952 | 982 | * Runs an external command and returns the standard output. |
| 953 | 983 | * |
| … |
… |
|
| 962 | 992 | Main.debug(join(" ", command)); |
| 963 | 993 | } |
| 964 | 994 | Process p = new ProcessBuilder(command).start(); |
| 965 | | try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) { |
| | 995 | try (BufferedReader input = new BufferedReader( |
| | 996 | new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) { |
| 966 | 997 | StringBuilder all = null; |
| 967 | 998 | String line; |
| 968 | 999 | while ((line = input.readLine()) != null) { |
| … |
… |
|
| 989 | 1020 | } |
| 990 | 1021 | File josmTmpDir = new File(tmpDir, "JOSM"); |
| 991 | 1022 | if (!josmTmpDir.exists() && !josmTmpDir.mkdirs()) { |
| 992 | | Main.warn("Unable to create temp directory "+josmTmpDir); |
| | 1023 | Main.warn("Unable to create temp directory " + josmTmpDir); |
| 993 | 1024 | } |
| 994 | 1025 | return josmTmpDir; |
| 995 | 1026 | } |
| … |
… |
|
| 1016 | 1047 | // Is it less than 1 hour ? |
| 1017 | 1048 | if (elapsedTime < MILLIS_OF_HOUR) { |
| 1018 | 1049 | final long min = elapsedTime / MILLIS_OF_MINUTE; |
| 1019 | | return String.format("%d %s %d %s", min, tr("min"), (elapsedTime - min * MILLIS_OF_MINUTE) / MILLIS_OF_SECOND, tr("s")); |
| | 1050 | return String.format("%d %s %d %s", min, tr("min"), (elapsedTime - min * MILLIS_OF_MINUTE) |
| | 1051 | / MILLIS_OF_SECOND, tr("s")); |
| 1020 | 1052 | } |
| 1021 | 1053 | // Is it less than 1 day ? |
| 1022 | 1054 | if (elapsedTime < MILLIS_OF_DAY) { |
| 1023 | 1055 | final long hour = elapsedTime / MILLIS_OF_HOUR; |
| 1024 | | return String.format("%d %s %d %s", hour, tr("h"), (elapsedTime - hour * MILLIS_OF_HOUR) / MILLIS_OF_MINUTE, tr("min")); |
| | 1056 | return String.format("%d %s %d %s", hour, tr("h"), |
| | 1057 | (elapsedTime - hour * MILLIS_OF_HOUR) / MILLIS_OF_MINUTE, tr("min")); |
| 1025 | 1058 | } |
| 1026 | 1059 | long days = elapsedTime / MILLIS_OF_DAY; |
| 1027 | | return String.format("%d %s %d %s", days, trn("day", "days", days), (elapsedTime - days * MILLIS_OF_DAY) / MILLIS_OF_HOUR, tr("h")); |
| | 1060 | return String.format("%d %s %d %s", days, trn("day", "days", days), (elapsedTime - days * MILLIS_OF_DAY) |
| | 1061 | / MILLIS_OF_HOUR, tr("h")); |
| 1028 | 1062 | } |
| 1029 | 1063 | |
| 1030 | 1064 | /** |
| … |
… |
|
| 1034 | 1068 | * @param positionList a list of positions |
| 1035 | 1069 | * @return a human readable representation |
| 1036 | 1070 | */ |
| 1037 | | public static String getPositionListString(List<Integer> positionList) { |
| | 1071 | public static String getPositionListString(List<Integer> positionList) { |
| 1038 | 1072 | Collections.sort(positionList); |
| 1039 | 1073 | final StringBuilder sb = new StringBuilder(32); |
| 1040 | 1074 | sb.append(positionList.get(0)); |
| … |
… |
|
| 1059 | 1093 | return sb.toString(); |
| 1060 | 1094 | } |
| 1061 | 1095 | |
| 1062 | | |
| 1063 | 1096 | /** |
| 1064 | 1097 | * Returns a list of capture groups if {@link Matcher#matches()}, or {@code null}. |
| 1065 | 1098 | * The first element (index 0) is the complete match. |
| … |
… |
|
| 1158 | 1191 | StringBuilder sb = new StringBuilder(url.substring(0, url.indexOf('?') + 1)); |
| 1159 | 1192 | |
| 1160 | 1193 | for (int i = 0; i < query.length(); i++) { |
| 1161 | | String c = query.substring(i, i+1); |
| | 1194 | String c = query.substring(i, i + 1); |
| 1162 | 1195 | if (URL_CHARS.contains(c)) { |
| 1163 | 1196 | sb.append(c); |
| 1164 | 1197 | } else { |
| … |
… |
|
| 1245 | 1278 | if (value != null) { |
| 1246 | 1279 | String old = System.setProperty(key, value); |
| 1247 | 1280 | if (!key.toLowerCase(Locale.ENGLISH).contains("password")) { |
| 1248 | | Main.debug("System property '"+key+"' set to '"+value+"'. Old value was '"+old+"'"); |
| | 1281 | Main.debug("System property '" + key + "' set to '" + value + "'. Old value was '" + old + "'"); |
| 1249 | 1282 | } else { |
| 1250 | | Main.debug("System property '"+key+"' changed."); |
| | 1283 | Main.debug("System property '" + key + "' changed."); |
| 1251 | 1284 | } |
| 1252 | 1285 | return old; |
| 1253 | 1286 | } |
| … |
… |
|
| 1279 | 1312 | * @throws IOException if any IO errors occur. |
| 1280 | 1313 | * @since 8347 |
| 1281 | 1314 | */ |
| 1282 | | public static void parseSafeSAX(InputSource is, DefaultHandler dh) throws ParserConfigurationException, SAXException, IOException { |
| | 1315 | public static void parseSafeSAX(InputSource is, DefaultHandler dh) throws ParserConfigurationException, |
| | 1316 | SAXException, IOException { |
| 1283 | 1317 | long start = System.currentTimeMillis(); |
| 1284 | 1318 | if (Main.isDebugEnabled()) { |
| 1285 | | Main.debug("Starting SAX parsing of "+is+" using "+dh); |
| | 1319 | Main.debug("Starting SAX parsing of " + is + " using " + dh); |
| 1286 | 1320 | } |
| 1287 | 1321 | newSafeSAXParser().parse(is, dh); |
| 1288 | 1322 | if (Main.isDebugEnabled()) { |
| 1289 | | Main.debug("SAX parsing done in " + getDurationString(System.currentTimeMillis()-start)); |
| | 1323 | Main.debug("SAX parsing done in " + getDurationString(System.currentTimeMillis() - start)); |
| 1290 | 1324 | } |
| 1291 | 1325 | } |
| 1292 | 1326 | |
| … |
… |
|
| 1298 | 1332 | * @return {@code true} if the filename has one of the given extensions |
| 1299 | 1333 | * @since 8404 |
| 1300 | 1334 | */ |
| 1301 | | public static boolean hasExtension(String filename, String ... extensions) { |
| | 1335 | public static boolean hasExtension(String filename, String... extensions) { |
| 1302 | 1336 | String name = filename.toLowerCase(Locale.ENGLISH); |
| 1303 | 1337 | for (String ext : extensions) { |
| 1304 | | if (name.endsWith("."+ext.toLowerCase(Locale.ENGLISH))) |
| | 1338 | if (name.endsWith("." + ext.toLowerCase(Locale.ENGLISH))) |
| 1305 | 1339 | return true; |
| 1306 | 1340 | } |
| 1307 | 1341 | return false; |
| … |
… |
|
| 1315 | 1349 | * @return {@code true} if the file's name has one of the given extensions |
| 1316 | 1350 | * @since 8404 |
| 1317 | 1351 | */ |
| 1318 | | public static boolean hasExtension(File file, String ... extensions) { |
| | 1352 | public static boolean hasExtension(File file, String... extensions) { |
| 1319 | 1353 | return hasExtension(file.getName(), extensions); |
| 1320 | 1354 | } |
| 1321 | 1355 | } |