|
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; |
|
} |
|
|
|
} |