Skip to content

Instantly share code, notes, and snippets.

@josefbetancourt
Last active November 20, 2015 01:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josefbetancourt/9116f8a684b91bedcd60 to your computer and use it in GitHub Desktop.
Save josefbetancourt/9116f8a684b91bedcd60 to your computer and use it in GitHub Desktop.
package com.octodecillion.util;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
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 javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
/**
* Detect duplicate properties when loading Properties from stream.
* <p>
* This version uses <a href="https://jboss-javassist.github.io/javassist/">Javassist</a> Dynamic Proxy support.
*
* @author jbetancourt
* @since Nov 18, 2015
*/
public class DuplicatePropertyDetectorWithJavassist {
/**
* 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";
try {
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(Properties.class);
factory.setFilter(new MethodFilter() {
@Override
public boolean isHandled(Method m) {
return m.getName().equals(put_method_name);
}
});
((Properties) factory.create(new Class<?>[0], new Object[0],
new MethodHandler() {
@Override
public Object invoke(Object self, Method thisMethod,
Method proceed, Object[] args) throws Throwable {
String key = (String) args[0],value = (String) args[1];
if (((Properties) self).containsKey(key)) {
List<String> list = new ArrayList<>();
if (dupeResults.containsKey(key)) {
list = dupeResults.get(key);
} else {
dupeResults.put(key, list);
}
list.add(value);
}
return proceed.invoke(self, args);
}
})).load(reader);
} catch (NoSuchMethodException | IllegalArgumentException
| InstantiationException | IllegalAccessException
| InvocationTargetException e) {
throw new RuntimeException(e);
}
return dupeResults;
}
}
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;
/**
* Test {@link DuplicatePropertyDetectorWithJavassist}.
* <p>
*
* @author Josef Betancourt (A17878)
* @since Nov 18, 2015
*
*/
public class DuplicatePropertyDetectorWithJavassistTest {
private static final String DATA1_PROPERTIES = "/Data1.properties";
/**
* @throws IOException
* @throws Exception
*/
@Test
public void testLoadFile() throws IOException, Exception {
InputStream is = this.getClass().getResourceAsStream(DATA1_PROPERTIES);
Assert.assertNotNull(is);
DuplicatePropertyDetectorWithJavassist detector = new DuplicatePropertyDetectorWithJavassist();
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