Last active
November 20, 2015 01:13
-
-
Save josefbetancourt/3adb08922537ccbc2434 to your computer and use it in GitHub Desktop.
Source to accompany blog post, http://octodecillion.com/blog/java-properties-dupe-key-detect-using-cglib/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.octodecillion.util; | |
import java.io.IOException; | |
import java.io.Reader; | |
import java.lang.reflect.Method; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Properties; | |
import net.sf.cglib.proxy.Enhancer; | |
import net.sf.cglib.proxy.MethodInterceptor; | |
import net.sf.cglib.proxy.MethodProxy; | |
/** | |
* Detect duplicate properties when loading Properties from stream. | |
* <p> | |
* This version uses <a href="https://github.com/cglib/cglib/wiki">CGLIB</a> Dynamic Proxy support. | |
* | |
* @author jbetancourt | |
* @since Nov 18, 2015 | |
*/ | |
public class DuplicatePropertyDetectorWithCGLIB { | |
/** | |
* Detect duplicate keys in Properties resource. | |
* <p> | |
* @see Properties#load(Reader) | |
* | |
* @param reader The reader is <b>NOT</b> closed. | |
* @return Map Map where map key is duplicated key and list is values of those keys | |
* @throws IOException reading the stream | |
* @throws RuntimeException for any issue with proxying | |
*/ | |
public Map<String, List<String>> load(Reader reader) throws IOException { | |
if(reader==null){ throw new NullPointerException("reader cannot be null");} | |
final Map<String, List<String>> dupeResults = new HashMap<>(); | |
final String put_method_name = "put"; | |
Enhancer enhancer = new Enhancer(); | |
enhancer.setSuperclass(Properties.class); | |
enhancer.setCallback(new MethodInterceptor() { | |
@Override | |
public Object intercept(Object object, Method method, | |
Object[] args, MethodProxy proxy) throws Throwable { | |
if(method.getDeclaringClass() != Object.class && isPut(method.getName())) { | |
String key = (String) args[0],value = (String) args[1]; | |
if (((Properties) object).containsKey(key)) { | |
List<String> list = new ArrayList<>(); | |
if (dupeResults.containsKey(key)) { | |
list = dupeResults.get(key); | |
} else { | |
dupeResults.put(key, list); | |
} | |
list.add(value); | |
} | |
} | |
return proxy.invokeSuper(object, args); | |
} | |
private boolean isPut(String name) { | |
return name.equals(put_method_name); | |
} | |
}); | |
Properties props = (Properties) enhancer.create(); | |
props.load(reader); | |
return dupeResults; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.octodecillion.util; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.util.List; | |
import java.util.Map; | |
import org.junit.Assert; | |
import org.junit.Test; | |
/** | |
* @author jbetancourt | |
* | |
*/ | |
public class DuplicatePropertyDetectorWithCGLIBTest { | |
private static final String DATA1_PROPERTIES = "/Data1.properties"; | |
/** | |
* @throws IOException | |
* | |
*/ | |
@Test | |
public void testLoad() throws IOException { | |
InputStream is = this.getClass().getResourceAsStream(DATA1_PROPERTIES); | |
Assert.assertNotNull(is); | |
DuplicatePropertyDetectorWithCGLIB detector = new DuplicatePropertyDetectorWithCGLIB(); | |
Map<String, List<String>> map = detector.load(new InputStreamReader(is)); | |
Assert.assertEquals(1, map.size()); | |
Assert.assertTrue(map.containsKey("three")); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment