In a prior post I used Javassist for Dynamic Proxying of Properties class’s load method. This allowed detection of duplicate keys in a Properties file.
In this post I use the Class Generation Library (CGLIB).
Listing 1, Source available at Gist
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())) { System.out.println("Putting: " + args[0]); 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; } }
Links