Ticket #24940: utf8-file-names-dialog.patch
| File utf8-file-names-dialog.patch, 10.2 KB (added by , 14 hours ago) |
|---|
-
src/org/openstreetmap/josm/gui/bugreport/BugReportDialog.java
diff --git src/org/openstreetmap/josm/gui/bugreport/BugReportDialog.java src/org/openstreetmap/josm/gui/bugreport/BugReportDialog.java index af74571464..0f0ff68af2 100644
import org.openstreetmap.josm.spi.preferences.Config; 31 31 import org.openstreetmap.josm.tools.GBC; 32 32 import org.openstreetmap.josm.tools.ImageProvider; 33 33 import org.openstreetmap.josm.tools.InputMapUtils; 34 import org.openstreetmap.josm.tools.Utils; 34 35 import org.openstreetmap.josm.tools.bugreport.BugReport; 35 36 import org.openstreetmap.josm.tools.bugreport.BugReportQueue.SuppressionMode; 36 37 import org.openstreetmap.josm.tools.bugreport.BugReportSender; … … import org.openstreetmap.josm.tools.bugreport.ReportedException; 45 46 */ 46 47 public class BugReportDialog extends JDialog { 47 48 private static final int MAX_MESSAGE_SIZE = 500; 49 /** whether the user has been told about file names that cannot be represented, which is done once per session */ 50 private static volatile boolean unmappableFileNameExplained; 48 51 // This is explicitly not an ExtendedDialog - we still want to be able to display bug reports if there are problems with preferences/.. 49 52 private final JPanel content = new JPanel(new GridBagLayout()); 50 53 private final BugReport report; … … public class BugReportDialog extends JDialog { 228 231 JOptionPane.ERROR_MESSAGE 229 232 ); 230 233 return SuppressionMode.NONE; 234 } else if (e.isUnmappableFileName()) { 235 // Not a bug in JOSM, but a locale which cannot represent the name of a file, see #14596. Explain how to 236 // fix it rather than asking for a bug report, and only once: browsing other folders throws it again. 237 if (!unmappableFileNameExplained) { 238 unmappableFileNameExplained = true; 239 GuiHelper.runInEDTAndWait(() -> JOptionPane.showMessageDialog(MainApplication.getMainFrame(), 240 tr("<html>JOSM cannot handle the name of a file, because it is running with the character set {0} " 241 + "for file names, which cannot represent it.<br>" 242 + "This happens when JOSM is started without a UTF-8 locale, for example with {1}, " 243 + "or with a locale which is not installed.<br><br>" 244 + "Please start JOSM with the environment variable {2}.</html>", 245 Utils.getSystemProperty("sun.jnu.encoding"), "<tt>LANG=C</tt>", "<tt>LC_ALL=C.UTF-8</tt>"), 246 tr("Unsupported file name"), 247 JOptionPane.WARNING_MESSAGE)); 248 } 249 return SuppressionMode.NONE; 231 250 } else { 232 251 PluginDownloadTask downloadTask = PluginHandler.updateOrdisablePluginAfterException(e); 233 252 return GuiHelper.runInEDTAndWaitAndReturn(() -> { -
src/org/openstreetmap/josm/tools/bugreport/ReportedException.java
diff --git src/org/openstreetmap/josm/tools/bugreport/ReportedException.java src/org/openstreetmap/josm/tools/bugreport/ReportedException.java index 28774399ee..9a2d7f4543 100644
package org.openstreetmap.josm.tools.bugreport; 4 4 import java.io.PrintWriter; 5 5 import java.io.Serializable; 6 6 import java.lang.reflect.InvocationTargetException; 7 import java.nio.file.InvalidPathException; 7 8 import java.util.ArrayList; 8 9 import java.util.Arrays; 9 10 import java.util.Collection; … … import java.util.function.Supplier; 21 22 22 23 import org.openstreetmap.josm.tools.Logging; 23 24 import org.openstreetmap.josm.tools.StreamUtils; 25 import org.openstreetmap.josm.tools.Utils; 24 26 25 27 /** 26 28 * This is a special exception that cannot be directly thrown. … … public class ReportedException extends RuntimeException { 277 279 return StreamUtils.toStream(CauseTraceIterator::new).anyMatch(OutOfMemoryError.class::isInstance); 278 280 } 279 281 282 /** 283 * Check if this is caused by the name of a file which cannot be represented in the character set Java uses for 284 * file names. Java takes that character set from the locale, so this happens when JOSM runs in the C/POSIX locale, 285 * or with a locale which is not installed: file names are then ASCII only, and opening a folder which holds a 286 * non-ASCII name fails. See #14596. 287 * @return <code>true</code> if it is. 288 * @since xxx 289 */ 290 public boolean isUnmappableFileName() { 291 return !"UTF-8".equalsIgnoreCase(Utils.getSystemProperty("sun.jnu.encoding")) 292 && StreamUtils.toStream(CauseTraceIterator::new).anyMatch(t -> t instanceof InvalidPathException 293 && String.valueOf(((InvalidPathException) t).getReason()).contains("unmappable characters")); 294 } 295 280 296 /** 281 297 * Iterates over the causes for this exception. Ignores cycles and aborts iteration then. 282 298 * @author Michal Zangl -
new file test/unit/org/openstreetmap/josm/gui/bugreport/BugReportDialogTest.java
diff --git test/unit/org/openstreetmap/josm/gui/bugreport/BugReportDialogTest.java test/unit/org/openstreetmap/josm/gui/bugreport/BugReportDialogTest.java new file mode 100644 index 0000000000..086a0f5d9d
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.bugreport; 3 4 import static org.junit.jupiter.api.Assertions.assertEquals; 5 6 import java.nio.file.InvalidPathException; 7 import java.util.Collections; 8 9 import javax.swing.JOptionPane; 10 11 import org.junit.jupiter.api.Test; 12 import org.openstreetmap.josm.TestUtils; 13 import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker; 14 import org.openstreetmap.josm.tools.bugreport.BugReport; 15 import org.openstreetmap.josm.tools.bugreport.BugReportQueue.SuppressionMode; 16 import org.openstreetmap.josm.tools.bugreport.ReportedException; 17 18 /** 19 * Unit tests of {@link BugReportDialog}. 20 */ 21 class BugReportDialogTest { 22 23 /** 24 * A file name the locale cannot represent is explained to the user, once, instead of asking for a bug report. 25 * See #14596. 26 */ 27 @Test 28 void testUnmappableFileNameIsExplainedOnce() { 29 TestUtils.assumeWorkingJMockit(); 30 final JOptionPaneSimpleMocker mocker = new JOptionPaneSimpleMocker(Collections.singletonMap( 31 "<html>JOSM cannot handle the name of a file, because it is running with the character set ANSI_X3.4-1968 " 32 + "for file names, which cannot represent it.<br>" 33 + "This happens when JOSM is started without a UTF-8 locale, for example with <tt>LANG=C</tt>, " 34 + "or with a locale which is not installed.<br><br>" 35 + "Please start JOSM with the environment variable <tt>LC_ALL=C.UTF-8</tt>.</html>", 36 JOptionPane.OK_OPTION)); 37 final ReportedException e = BugReport.intercept(new InvalidPathException("/home/user/Capture d'écran.png", 38 "Malformed input or input contains unmappable characters")); 39 final String jnuEncoding = System.getProperty("sun.jnu.encoding"); 40 try { 41 System.setProperty("sun.jnu.encoding", "ANSI_X3.4-1968"); 42 // no bug report dialog: that would fail here, as the tests run headless 43 assertEquals(SuppressionMode.NONE, BugReportDialog.showFor(e, 0)); 44 // browsing another folder throws it again, which is not worth another message 45 assertEquals(SuppressionMode.NONE, BugReportDialog.showFor(e, 1)); 46 } finally { 47 System.setProperty("sun.jnu.encoding", jnuEncoding); 48 } 49 assertEquals(1, mocker.getInvocationLog().size()); 50 assertEquals("Unsupported file name", mocker.getInvocationLog().get(0)[2]); 51 } 52 } -
test/unit/org/openstreetmap/josm/tools/bugreport/ReportedExceptionTest.java
diff --git test/unit/org/openstreetmap/josm/tools/bugreport/ReportedExceptionTest.java test/unit/org/openstreetmap/josm/tools/bugreport/ReportedExceptionTest.java index 1125bfd5d2..36cf937fff 100644
2 2 package org.openstreetmap.josm.tools.bugreport; 3 3 4 4 import static org.junit.jupiter.api.Assertions.assertEquals; 5 import static org.junit.jupiter.api.Assertions.assertFalse; 6 import static org.junit.jupiter.api.Assertions.assertTrue; 5 7 8 import java.nio.file.InvalidPathException; 6 9 import java.util.Arrays; 7 10 8 11 import org.junit.jupiter.api.Test; … … class ReportedExceptionTest { 60 63 e.put("testList", Arrays.asList(a)); 61 64 } 62 65 66 /** 67 * Tests {@link ReportedException#isUnmappableFileName()}: a file name which the character set used for file names 68 * cannot represent is recognised, also as the cause of another exception, but only if that character set is not 69 * UTF-8 - otherwise the locale is not to blame. See #14596. 70 */ 71 @Test 72 void testIsUnmappableFileName() { 73 // the exception sun.nio.fs.UnixPath throws for "Capture d'écran.png" when the locale is C or not installed 74 InvalidPathException unmappable = new InvalidPathException("/home/user/Capture d'\u00e9cran.png", 75 "Malformed input or input contains unmappable characters"); 76 String jnuEncoding = System.getProperty("sun.jnu.encoding"); 77 try { 78 System.setProperty("sun.jnu.encoding", "ANSI_X3.4-1968"); 79 assertTrue(new ReportedException(unmappable).isUnmappableFileName()); 80 assertTrue(new ReportedException(new IllegalStateException(unmappable)).isUnmappableFileName()); 81 assertFalse(new ReportedException(new InvalidPathException("a\0b", "Nul character not allowed")).isUnmappableFileName()); 82 assertFalse(new ReportedException(new IllegalStateException()).isUnmappableFileName()); 83 84 System.setProperty("sun.jnu.encoding", "UTF-8"); 85 assertFalse(new ReportedException(unmappable).isUnmappableFileName()); 86 } finally { 87 System.setProperty("sun.jnu.encoding", jnuEncoding); 88 } 89 } 90 63 91 /** 64 92 * Tests that {@link ReportedException#isSame(ReportedException)} works as expected. 65 93 */
