### Eclipse Workspace Patch 1.0
#P JOSM
Index: src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- src/org/openstreetmap/josm/tools/Utils.java	(revision 8562)
+++ src/org/openstreetmap/josm/tools/Utils.java	(working copy)
@@ -39,11 +39,9 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
-import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.regex.Matcher;
@@ -149,7 +147,8 @@
      * Filter a collection by (sub)class.
      * This is an efficient read-only implementation.
      */
-    public static <S, T extends S> SubclassFilteredCollection<S, T> filteredCollection(Collection<S> collection, final Class<T> klass) {
+    public static <S, T extends S> SubclassFilteredCollection<S, T> filteredCollection(Collection<S> collection,
+            final Class<T> klass) {
         return new SubclassFilteredCollection<>(collection, new Predicate<S>() {
             @Override
             public boolean evaluate(S o) {
@@ -210,11 +209,9 @@
      * @param data Message parameters, optional
      * @throws AssertionError if the condition is not met
      */
-    public static void ensure(boolean condition, String message, Object...data) {
+    public static void ensure(boolean condition, String message, Object... data) {
         if (!condition)
-            throw new AssertionError(
-                    MessageFormat.format(message, data)
-            );
+            throw new AssertionError(MessageFormat.format(message, data));
     }
 
     /**
@@ -222,7 +219,7 @@
      */
     public static int mod(int a, int n) {
         if (n <= 0)
-            throw new IllegalArgumentException("n must be <= 0 but is "+n);
+            throw new IllegalArgumentException("n must be <= 0 but is " + n);
         int res = a % n;
         if (res < 0) {
             res += n;
@@ -380,7 +377,7 @@
         CheckParameterUtil.ensureParameterNotNull(in, "in");
         CheckParameterUtil.ensureParameterNotNull(out, "out");
         if (!out.exists() && !out.mkdirs()) {
-            Main.warn("Unable to create directory "+out.getPath());
+            Main.warn("Unable to create directory " + out.getPath());
         }
         File[] files = in.listFiles();
         if (files != null) {
@@ -427,7 +424,7 @@
                     if (file.isDirectory()) {
                         deleteDirectory(file);
                     } else if (!file.delete()) {
-                        Main.warn("Unable to delete file: "+file.getPath());
+                        Main.warn("Unable to delete file: " + file.getPath());
                     }
                 }
             }
@@ -441,7 +438,8 @@
      * @param c the closeable object. May be null.
      */
     public static void close(Closeable c) {
-        if (c == null) return;
+        if (c == null)
+            return;
         try {
             c.close();
         } catch (IOException e) {
@@ -455,7 +453,8 @@
      * @param zip the zip file. May be null.
      */
     public static void close(ZipFile zip) {
-        if (zip == null) return;
+        if (zip == null)
+            return;
         try {
             zip.close();
         } catch (IOException e) {
@@ -529,7 +528,8 @@
                 try {
                     Thread.sleep(1);
                 } catch (InterruptedException ex) {
-                    Main.warn("InterruptedException in "+Utils.class.getSimpleName()+" while getting clipboard content");
+                    Main.warn("InterruptedException in " + Utils.class.getSimpleName()
+                            + " while getting clipboard content");
                 }
             } catch (NullPointerException e) {
                 // JDK-6322854: On Linux/X11, NPE can happen for unknown reasons, on all versions of Java
@@ -573,7 +573,8 @@
         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'};
+    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.
@@ -630,7 +631,8 @@
                     break;
                 }
             }
-            if (parentless == null) throw new RuntimeException();
+            if (parentless == null)
+                throw new RuntimeException();
             sorted.add(parentless);
             deps.remove(parentless);
             for (T key : deps.keySet()) {
@@ -637,7 +639,8 @@
                 deps.remove(key, parentless);
             }
         }
-        if (sorted.size() != size) throw new RuntimeException();
+        if (sorted.size() != size)
+            throw new RuntimeException();
         return sorted;
     }
 
@@ -737,7 +740,7 @@
             throw new IllegalArgumentException("Invalid HTTP url");
         }
         if (Main.isDebugEnabled()) {
-            Main.debug("Opening HTTP connection to "+httpURL.toExternalForm());
+            Main.debug("Opening HTTP connection to " + httpURL.toExternalForm());
         }
         HttpURLConnection connection = (HttpURLConnection) httpURL.openConnection();
         connection.setRequestProperty("User-Agent", Version.getInstance().getFullAgentString());
@@ -792,7 +795,7 @@
         if (in == null) {
             return null;
         }
-        return new BZip2CompressorInputStream(in, /* see #9537 */ true);
+        return new BZip2CompressorInputStream(in, /* see #9537 */true);
     }
 
     /**
@@ -824,7 +827,7 @@
         // Positions the stream at the beginning of first entry
         ZipEntry ze = zis.getNextEntry();
         if (ze != null && Main.isDebugEnabled()) {
-            Main.debug("Zip entry: "+ze.getName());
+            Main.debug("Zip entry: " + ze.getName());
         }
         return zis;
     }
@@ -838,8 +841,8 @@
     public static URLConnection setupURLConnection(URLConnection connection) {
         if (connection != null) {
             connection.setRequestProperty("User-Agent", Version.getInstance().getFullAgentString());
-            connection.setConnectTimeout(Main.pref.getInteger("socket.timeout.connect", 15)*1000);
-            connection.setReadTimeout(Main.pref.getInteger("socket.timeout.read", 30)*1000);
+            connection.setConnectTimeout(Main.pref.getInteger("socket.timeout.connect", 15) * 1000);
+            connection.setReadTimeout(Main.pref.getInteger("socket.timeout.read", 30) * 1000);
         }
         return connection;
     }
@@ -883,7 +886,7 @@
         }
         if (Main.isDebugEnabled()) {
             try {
-                Main.debug("REQUEST: "+ connection.getRequestProperties());
+                Main.debug("REQUEST: " + connection.getRequestProperties());
             } catch (IllegalStateException e) {
                 Main.warn(e);
             }
@@ -891,6 +894,9 @@
         return connection;
     }
 
+    private static char[] DEFAULT_STRIP = { '\u200B', '\uFEFF' };
+
+
     /**
      * An alternative to {@link String#trim()} to effectively remove all leading and trailing white characters, including Unicode ones.
      * @param str The string to strip
@@ -901,7 +907,10 @@
      * @since 5772
      */
     public static String strip(final String str) {
-        return strip(str, null);
+        if (str == null || str.isEmpty()) {
+            return str;
+        }
+        return strip(str, DEFAULT_STRIP);
     }
 
     /**
@@ -913,41 +922,62 @@
      * @since 8435
      */
     public static String strip(final String str, final String skipChars) {
+
         if (str == null || str.isEmpty()) {
             return str;
         }
-        // create set with chars to skip
-        Set<Character> skipSet = new HashSet<>();
-        // '\u200B' (ZERO WIDTH SPACE character) needs to be handled manually because of change in Unicode 6.0 (Java 7, see #8918)
-        skipSet.add('\u200B');
-        // same for '\uFEFF' (ZERO WIDTH NO-BREAK SPACE)
-        skipSet.add('\uFEFF');
-        if (skipChars != null) {
-            for (char c : skipChars.toCharArray()) {
-                skipSet.add(c);
-            }
-        }
+
+        return strip(str, stripChars(skipChars));
+    }
+
+    private static String strip(final String str, final char[] skipChars) {
+
         int start = 0;
         int end = str.length();
         boolean leadingSkipChar = true;
         while (leadingSkipChar && start < end) {
             char c = str.charAt(start);
-            leadingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || skipSet.contains(c);
+            leadingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || stripChar(skipChars, c);
             if (leadingSkipChar) {
                 start++;
             }
         }
         boolean trailingSkipChar = true;
-        while (trailingSkipChar && end > start+1) {
-            char c = str.charAt(end-1);
-            trailingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || skipSet.contains(c);
+        while (trailingSkipChar && end > start + 1) {
+            char c = str.charAt(end - 1);
+            trailingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || stripChar(skipChars, c);
             if (trailingSkipChar) {
                 end--;
             }
         }
+
         return str.substring(start, end);
     }
 
+    private static char[] stripChars(final String skipChars) {
+        if (skipChars == null || skipChars.isEmpty()) {
+            return DEFAULT_STRIP;
+        }
+
+        char[] chars = new char[skipChars.length() + 2];
+        chars[0] = '\u200B';
+        chars[1] = '\uFEFF';
+        skipChars.getChars(0, skipChars.length(), chars, 2);
+
+        return chars;
+    }
+
+    private static boolean stripChar(final char[] strip, char c) {
+
+        for (char s : strip) {
+            if (c == s) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /**
      * Runs an external command and returns the standard output.
      *
@@ -962,7 +992,8 @@
             Main.debug(join(" ", command));
         }
         Process p = new ProcessBuilder(command).start();
-        try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
+        try (BufferedReader input = new BufferedReader(
+                new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
             StringBuilder all = null;
             String line;
             while ((line = input.readLine()) != null) {
@@ -989,7 +1020,7 @@
         }
         File josmTmpDir = new File(tmpDir, "JOSM");
         if (!josmTmpDir.exists() && !josmTmpDir.mkdirs()) {
-            Main.warn("Unable to create temp directory "+josmTmpDir);
+            Main.warn("Unable to create temp directory " + josmTmpDir);
         }
         return josmTmpDir;
     }
@@ -1016,15 +1047,18 @@
         // Is it less than 1 hour ?
         if (elapsedTime < MILLIS_OF_HOUR) {
             final long min = elapsedTime / MILLIS_OF_MINUTE;
-            return String.format("%d %s %d %s", min, tr("min"), (elapsedTime - min * MILLIS_OF_MINUTE) / MILLIS_OF_SECOND, tr("s"));
+            return String.format("%d %s %d %s", min, tr("min"), (elapsedTime - min * MILLIS_OF_MINUTE)
+                    / MILLIS_OF_SECOND, tr("s"));
         }
         // Is it less than 1 day ?
         if (elapsedTime < MILLIS_OF_DAY) {
             final long hour = elapsedTime / MILLIS_OF_HOUR;
-            return String.format("%d %s %d %s", hour, tr("h"), (elapsedTime - hour * MILLIS_OF_HOUR) / MILLIS_OF_MINUTE, tr("min"));
+            return String.format("%d %s %d %s", hour, tr("h"),
+                    (elapsedTime - hour * MILLIS_OF_HOUR) / MILLIS_OF_MINUTE, tr("min"));
         }
         long days = elapsedTime / MILLIS_OF_DAY;
-        return String.format("%d %s %d %s", days, trn("day", "days", days), (elapsedTime - days * MILLIS_OF_DAY) / MILLIS_OF_HOUR, tr("h"));
+        return String.format("%d %s %d %s", days, trn("day", "days", days), (elapsedTime - days * MILLIS_OF_DAY)
+                / MILLIS_OF_HOUR, tr("h"));
     }
 
     /**
@@ -1034,7 +1068,7 @@
      * @param positionList a list of positions
      * @return a human readable representation
      */
-    public static String getPositionListString(List<Integer> positionList)  {
+    public static String getPositionListString(List<Integer> positionList) {
         Collections.sort(positionList);
         final StringBuilder sb = new StringBuilder(32);
         sb.append(positionList.get(0));
@@ -1059,7 +1093,6 @@
         return sb.toString();
     }
 
-
     /**
      * Returns a list of capture groups if {@link Matcher#matches()}, or {@code null}.
      * The first element (index 0) is the complete match.
@@ -1158,7 +1191,7 @@
         StringBuilder sb = new StringBuilder(url.substring(0, url.indexOf('?') + 1));
 
         for (int i = 0; i < query.length(); i++) {
-            String c = query.substring(i, i+1);
+            String c = query.substring(i, i + 1);
             if (URL_CHARS.contains(c)) {
                 sb.append(c);
             } else {
@@ -1245,9 +1278,9 @@
         if (value != null) {
             String old = System.setProperty(key, value);
             if (!key.toLowerCase(Locale.ENGLISH).contains("password")) {
-                Main.debug("System property '"+key+"' set to '"+value+"'. Old value was '"+old+"'");
+                Main.debug("System property '" + key + "' set to '" + value + "'. Old value was '" + old + "'");
             } else {
-                Main.debug("System property '"+key+"' changed.");
+                Main.debug("System property '" + key + "' changed.");
             }
             return old;
         }
@@ -1279,14 +1312,15 @@
      * @throws IOException if any IO errors occur.
      * @since 8347
      */
-    public static void parseSafeSAX(InputSource is, DefaultHandler dh) throws ParserConfigurationException, SAXException, IOException {
+    public static void parseSafeSAX(InputSource is, DefaultHandler dh) throws ParserConfigurationException,
+            SAXException, IOException {
         long start = System.currentTimeMillis();
         if (Main.isDebugEnabled()) {
-            Main.debug("Starting SAX parsing of "+is+" using "+dh);
+            Main.debug("Starting SAX parsing of " + is + " using " + dh);
         }
         newSafeSAXParser().parse(is, dh);
         if (Main.isDebugEnabled()) {
-            Main.debug("SAX parsing done in " + getDurationString(System.currentTimeMillis()-start));
+            Main.debug("SAX parsing done in " + getDurationString(System.currentTimeMillis() - start));
         }
     }
 
@@ -1298,10 +1332,10 @@
      * @return {@code true} if the filename has one of the given extensions
      * @since 8404
      */
-    public static boolean hasExtension(String filename, String ... extensions) {
+    public static boolean hasExtension(String filename, String... extensions) {
         String name = filename.toLowerCase(Locale.ENGLISH);
         for (String ext : extensions) {
-            if (name.endsWith("."+ext.toLowerCase(Locale.ENGLISH)))
+            if (name.endsWith("." + ext.toLowerCase(Locale.ENGLISH)))
                 return true;
         }
         return false;
@@ -1315,7 +1349,7 @@
      * @return {@code true} if the file's name has one of the given extensions
      * @since 8404
      */
-    public static boolean hasExtension(File file, String ... extensions) {
+    public static boolean hasExtension(File file, String... extensions) {
         return hasExtension(file.getName(), extensions);
     }
 }
