package com.revolsys.record.io; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; import com.revolsys.logging.Logs; import com.revolsys.record.schema.RecordStore; public class DelegatingRecordStoreHandler implements InvocationHandler { public static <T extends RecordStore> T newRecordStore(final String label, final Class<T> interfaceClass, final T recordStore) { final ClassLoader classLoader = recordStore.getClass().getClassLoader(); final Class<?>[] interfaces = new Class<?>[] { interfaceClass }; final DelegatingRecordStoreHandler handler = new DelegatingRecordStoreHandler(label, recordStore); final T proxyStore = (T)Proxy.newProxyInstance(classLoader, interfaces, handler); return proxyStore; } @SuppressWarnings("unchecked") public static <T extends RecordStore> T newRecordStore(final String label, final Map<String, ? extends Object> config) { final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); final Class<?>[] interfaces = new Class<?>[] { RecordStore.recordStoreInterfaceClass(config) }; final DelegatingRecordStoreHandler handler = new DelegatingRecordStoreHandler(label, config); final T proxyStore = (T)Proxy.newProxyInstance(classLoader, interfaces, handler); try { proxyStore.initialize(); } catch (final Throwable t) { Logs.error(DelegatingRecordStoreHandler.class, "Unable to initialize record store " + label, t); } return proxyStore; } private Map<String, Object> config; private String label; private RecordStore recordStore; public DelegatingRecordStoreHandler() { } public DelegatingRecordStoreHandler(final String label, final Map<String, ? extends Object> config) { this.label = label; this.config = new HashMap<>(config); } public DelegatingRecordStoreHandler(final String label, final RecordStore recordStore) { this.label = label; this.recordStore = recordStore; } public RecordStore getRecordStore() { if (this.recordStore == null) { this.recordStore = newRecordStore(); this.recordStore.initialize(); } return this.recordStore; } @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { int numArgs; if (args == null) { numArgs = 0; } else { numArgs = args.length; } if (method.getName().equals("toString") && numArgs == 0) { return this.label; } else if (method.getName().equals("getLabel") && numArgs == 0) { return this.label; } else if (method.getName().equals("hashCode") && numArgs == 0) { return this.label.hashCode(); } else if (method.getName().equals("equals") && numArgs == 1) { final boolean equal = args[0] == proxy; return equal; } else if (method.getName().equals("close") && numArgs == 0) { if (this.recordStore != null) { final RecordStore recordStore = getRecordStore(); recordStore.close(); this.recordStore = null; } return null; } else { final RecordStore recordStore = getRecordStore(); return method.invoke(recordStore, args); } } protected RecordStore newRecordStore() { if (this.config != null) { final RecordStore recordStore = RecordStore.newRecordStore(this.config); return recordStore; } else { throw new UnsupportedOperationException("Record store must be set manually"); } } }