diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/button/CsvDownloadButtonPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/button/CsvDownloadButtonPanel.java index 7e4f4366584..8c489681d78 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/button/CsvDownloadButtonPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/button/CsvDownloadButtonPanel.java @@ -63,8 +63,21 @@ public CsvDownloadButtonPanel(String id) { private static final long serialVersionUID = 1L; + private String resolveExportEncoding() { + try { + CompiledGuiProfile profile = getPageBase().getCompiledGuiProfile(); + if (profile.getDefaultExportSettings() != null + && profile.getDefaultExportSettings().getEncoding() != null) { + return profile.getDefaultExportSettings().getEncoding(); + } + } catch (Exception ex) { + LOGGER.warn("Unable to get export encoding setting, falling back to utf-8", ex); + } + return "utf-8"; + } + private void initLayout() { - StreamingCsvDataExporter csvDataExporter = new StreamingCsvDataExporter(getPageBase()) { + StreamingCsvDataExporter csvDataExporter = new StreamingCsvDataExporter(getPageBase(), resolveExportEncoding()) { private static final long serialVersionUID = 1L; @Override diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/provider/StreamingCsvDataExporter.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/provider/StreamingCsvDataExporter.java index 50e1a601504..ced1736aaf4 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/provider/StreamingCsvDataExporter.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/provider/StreamingCsvDataExporter.java @@ -41,10 +41,31 @@ public class StreamingCsvDataExporter extends CSVDataExporter { private static final String DOT_CLASS = StreamingCsvDataExporter.class.getName() + "."; private static final String OPERATION_EXPORT_DATA = DOT_CLASS + "exportData"; + private static final String UTF_8_BOM_ENCODING = "utf-8-bom"; + private static final byte[] UTF8_BOM = { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }; + private final PageBase pageBase; + private final String configuredEncoding; - public StreamingCsvDataExporter(PageBase pageBase) { + public StreamingCsvDataExporter(PageBase pageBase, String encoding) { this.pageBase = pageBase; + this.configuredEncoding = encoding; + setCharacterSet(resolveEffectiveCharset(encoding)); + } + + public StreamingCsvDataExporter(PageBase pageBase) { + this(pageBase, null); + } + + private static String resolveEffectiveCharset(String encoding) { + if (encoding == null || UTF_8_BOM_ENCODING.equalsIgnoreCase(encoding)) { + return "utf-8"; + } + return encoding; + } + + private boolean isUtf8Bom() { + return UTF_8_BOM_ENCODING.equalsIgnoreCase(configuredEncoding); } @Override @@ -52,6 +73,11 @@ public void exportData(IDataProvider dataProvider, List> columns, OutputStream outputStream) throws IOException { + if (isUtf8Bom()) { + outputStream.write(UTF8_BOM); + outputStream.flush(); + } + if (!(dataProvider instanceof IterativeExportSupport) || !((IterativeExportSupport) dataProvider).supportsIterativeExport()) { // Fall back to standard export if provider doesn't support iterative export diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-gui-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-gui-3.xsd index c1e97cc8d4a..8ba996454ea 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-gui-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-gui-3.xsd @@ -3816,6 +3816,21 @@ + + + + Character encoding for exported CSV files. + Default is "utf-8". Use "utf-8-bom" to prepend a UTF-8 BOM + (byte order mark) to the exported file, which helps applications + like Microsoft Excel on non-UTF-8 locale systems correctly + recognize the file as UTF-8. + + + GuiExportSettingsType.encoding + 4.10.4 + + +