Skip to content

Commit

Permalink
Encode transformed properties files with specified Charset
Browse files Browse the repository at this point in the history
Currently, the content from any properties file that is passed through
the `PropertiesFileTransformer` will have its output written into the
jar encoded as `ISO_8859_1`. If the source file contains UTF-8 content,
the output becomes corrupted.

This commit allows the buildscript to define the Charset to perform the
transformation with.
  • Loading branch information
Scott Steen committed Feb 13, 2023
1 parent d8117e9 commit 9bffd1e
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ class PropertiesFileTransformer implements Transformer {
@Input
String mergeSeparator = ','

@Input
String charset = 'ISO_8859_1'

@Internal
Closure<String> keyTransformer = IDENTITY

Expand Down Expand Up @@ -180,7 +183,8 @@ class PropertiesFileTransformer implements Transformer {

private Properties loadAndTransformKeys(InputStream is) {
Properties props = new Properties()
props.load(is)
// InputStream closed by caller, so we don't do it here.
props.load(new InputStreamReader(is, charset))
return transformKeys(props)
}

Expand Down Expand Up @@ -227,18 +231,23 @@ class PropertiesFileTransformer implements Transformer {

@Override
void modifyOutputStream(ZipOutputStream os, boolean preserveFileTimestamps) {
// cannot close the writer as the OutputStream needs to remain open
def zipWriter = new OutputStreamWriter(os, charset)
propertiesEntries.each { String path, Properties props ->
ZipEntry entry = new ZipEntry(path)
entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time)
os.putNextEntry(entry)
IOUtil.copy(toInputStream(props), os)
IOUtil.copy(readerFor(props, charset), zipWriter)
zipWriter.flush()
os.closeEntry()
}
}

private static InputStream toInputStream(Properties props) {
private static InputStreamReader readerFor(Properties props, String charset) {
ByteArrayOutputStream baos = new ByteArrayOutputStream()
props.store(baos, '')
new ByteArrayInputStream(baos.toByteArray())
baos.withWriter(charset) { w ->
props.store(w, '')
}
new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()), charset)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,23 @@ class PropertiesFileTransformerSpec extends TransformerSpecSupport {
'foo.properties' | { key -> 'bar.' + key.toLowerCase() } | ['foo': 'bar'] | ['FOO': 'baz'] || ['bar.foo': 'bar,baz']
'foo.properties' | { key -> key.replaceAll('^(foo)', 'bar.$1') } | ['foo': 'bar'] | ['FOO': 'baz'] || ['bar.foo': 'bar', 'FOO': 'baz']
}

void appliesCharset() {
given:
def element = getFileElement(path)
def transformer = new PropertiesFileTransformer()
transformer.charset = charset

when:
if (transformer.canTransformResource(element)) {
transformer.transform(context(path, input, charset))
}

then:
output == toMap(transformer.propertiesEntries[path])

where:
path | charset | input || output
'utf8.properties' | 'utf-8' | ['foo': '传傳磨宿说説'] || ['foo': '传傳磨宿说説']
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ class TransformerSpecSupport extends Specification {
return new ByteArrayInputStream(str.bytes)
}

protected static InputStream toInputStream(Properties props) {
protected static InputStream toInputStream(Properties props, String charset) {
ByteArrayOutputStream baos = new ByteArrayOutputStream()
props.store(baos, '')
baos.withWriter(charset) { w ->
props.store(w, '')
}
new ByteArrayInputStream(baos.toByteArray())
}

Expand All @@ -44,8 +46,8 @@ class TransformerSpecSupport extends Specification {
}
}

protected TransformerContext context(String path, Map input) {
TransformerContext.builder().path(path).is(toInputStream(toProperties(input))).relocators([]).stats(stats).build()
protected TransformerContext context(String path, Map input, String charset = 'ISO_8859_1') {
TransformerContext.builder().path(path).is(toInputStream(toProperties(input), charset)).relocators([]).stats(stats).build()
}

protected TransformerContext context(String path, String input) {
Expand Down

0 comments on commit 9bffd1e

Please sign in to comment.