Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce keyTransformer property for PropertiesFileTransformer #247

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/docs/asciidoc/90-changes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* Build Shadow w/ Shadow. This will help prevent any future classpath conflicts with Gradle.
* Replace `startShadowScripts` tasks with Gradle's built-in `CreateStartScripts` type.
* Build with Gradle 3.1
* https://github.com/marcphilipp[Marc Philipp] - Add `keyTransformer` property to `PropertiesFileTransformer`

[discrete]
=== v1.2.4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import org.apache.tools.zip.ZipOutputStream
import org.gradle.api.file.FileTreeElement
import org.codehaus.plexus.util.IOUtil

import static groovy.lang.Closure.IDENTITY

/**
* Resources transformer that merges Properties files.
*
Expand Down Expand Up @@ -77,7 +79,8 @@ import org.codehaus.plexus.util.IOUtil
* <li>key3 = value3</li>
* </ul>
*
* <p>There are two additional properties that can be set: <tt>paths</tt> and <tt>mappings</tt>.
* <p>There are three additional properties that can be set: <tt>paths</tt>, <tt>mappings</tt>,
* and <tt>keyTransformer</tt>.
* The first contains a list of strings or regexes that will be used to determine if
* a path should be transformed or not. The merge strategy and merge separator are
* taken from the global settings.</p>
Expand All @@ -87,6 +90,10 @@ import org.codehaus.plexus.util.IOUtil
* entries will be merged. <tt>mappings</tt> has precedence over <tt>paths</tt> if both
* are defined.</p>
*
* <p>If you need to transform keys in properties files, e.g. because they contain class
* names about to be relocated, you can set the <tt>keyTransformer</tt> property to a
* closure that receives the original key and returns the key name to be used.</p>
*
* <p>Example:</p>
* <pre>
* import org.codehaus.griffon.gradle.shadow.transformers.*
Expand All @@ -95,11 +102,15 @@ import org.codehaus.plexus.util.IOUtil
* paths = [
* 'META-INF/editors/java.beans.PropertyEditor'
* ]
* keyTransformer = { key ->
* key.replaceAll('^(orig\.package\..*)$', 'new.prefix.$1')
* }
* }
* }
* </pre>
*
* @author Andres Almiray
* @author Marc Philipp
*/
class PropertiesFileTransformer implements Transformer {
private static final String PROPERTIES_SUFFIX = '.properties'
Expand All @@ -112,6 +123,7 @@ class PropertiesFileTransformer implements Transformer {
Map<String, Map<String, String>> mappings = [:]
String mergeStrategy = 'first' // latest, append
String mergeSeparator = ','
Closure<String> keyTransformer = IDENTITY

@Override
boolean canTransformResource(FileTreeElement element) {
Expand All @@ -132,13 +144,10 @@ class PropertiesFileTransformer implements Transformer {
@Override
void transform(TransformerContext context) {
Properties props = propertiesEntries[context.path]
Properties incoming = loadAndTransformKeys(context.is)
if (props == null) {
props = new Properties()
props.load(context.is)
propertiesEntries[context.path] = props
propertiesEntries[context.path] = incoming
} else {
Properties incoming = new Properties()
incoming.load(context.is)
incoming.each { key, value ->
if (props.containsKey(key)) {
switch (mergeStrategyFor(context.path).toLowerCase()) {
Expand All @@ -160,6 +169,22 @@ class PropertiesFileTransformer implements Transformer {
}
}

private Properties loadAndTransformKeys(InputStream is) {
Properties props = new Properties()
props.load(is)
return transformKeys(props)
}

private Properties transformKeys(Properties properties) {
if (keyTransformer == IDENTITY)
return properties
def result = new Properties()
properties.each { key, value ->
result.put(keyTransformer.call(key), value)
}
return result
}

private String mergeStrategyFor(String path) {
if (mappings.containsKey(path)) {
return mappings.get(path).mergeStrategy ?: mergeStrategy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ package com.github.jengelman.gradle.plugins.shadow.transformers

import spock.lang.Unroll

import static groovy.lang.Closure.IDENTITY

@Unroll
class PropertiesFileTransformerSpec extends TransformerSpecSupport {

Expand Down Expand Up @@ -116,4 +118,28 @@ class PropertiesFileTransformerSpec extends TransformerSpecSupport {
'foo.properties' | ['.*.properties': [mergeStrategy: 'first']] | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo']
'foo.properties' | ['.*bar': [mergeStrategy: 'first']] | ['foo': 'foo'] | ['foo': 'bar'] || [:]
}

void appliesKeyTransformer() {
given:
def element = getFileElement(path)
Transformer transformer = new PropertiesFileTransformer()
transformer.keyTransformer = keyTransformer
transformer.mergeStrategy = 'append'

when:
if (transformer.canTransformResource(element)) {
transformer.transform(context(path, input1))
transformer.transform(context(path, input2))
}

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

where:
path | keyTransformer | input1 | input2 || output
'foo.properties' | IDENTITY | ['foo': 'bar'] | ['FOO': 'baz'] || ['foo': 'bar', 'FOO': 'baz']
'foo.properties' | { key -> key.toUpperCase() } | ['foo': 'bar'] | ['FOO': 'baz'] || ['FOO': 'bar,baz']
'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']
}
}