/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.smis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Invocation handler for the CIMObjectPathFactoryAdapter internal proxy instance. When a method is invoked
* on the proxy instance, the method invocation is encoded and dispatched to the invoke method where we
* decide which factory to delegate to.
*/
public class CIMObjectPathFactoryInvocationHandler implements InvocationHandler {
private static final Logger log = LoggerFactory.getLogger(CIMObjectPathFactoryInvocationHandler.class);
private static final String MSG = "Delegating %s to %s";
private enum Factory {
query, creator
}
private Map<Factory, CIMObjectPathFactory> factories;
private Factory defaultFactory = Factory.creator;
private Set<String> queryMethods;
private Set<String> creatorMethods;
public void setQueryFactory(CIMObjectPathFactory queryFactory) {
addFactory(Factory.query, queryFactory);
}
public void setCreatorFactory(CIMObjectPathFactory creatorFactory) {
addFactory(Factory.creator, creatorFactory);
}
public void setDefaultFactory(String defaultFactory) {
this.defaultFactory = Factory.valueOf(defaultFactory);
}
public void setQueryMethods(Set<String> queryMethods) {
this.queryMethods = queryMethods;
}
public void setCreatorMethods(Set<String> creatorMethods) {
this.creatorMethods = creatorMethods;
}
/**
* The invoke method is passed the CIMObjectPathFactory method invocation details which
* we inspect to determine where to delegate to.
*
* @param proxy The dynamic proxy.
* @param method The encoded method.
* @param args The arguments passed to the method.
* @return Based on the CIMObjectPathFactory method.
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Factory useFactory = null;
if (isQueryMethod(method)) {
useFactory = Factory.query;
} else if (isCreatorMethod(method)) {
useFactory = Factory.creator;
} else {
useFactory = defaultFactory;
}
return delegate(method, args, factories.get(useFactory));
}
private boolean isQueryMethod(Method method) {
return queryMethods != null && !queryMethods.isEmpty() && queryMethods.contains(method.getName());
}
private boolean isCreatorMethod(Method method) {
return creatorMethods != null && !creatorMethods.isEmpty() && creatorMethods.contains(method.getName());
}
private Object delegate(Method method, Object[] args, CIMObjectPathFactory factory)
throws InvocationTargetException, IllegalAccessException {
log.debug(String.format(MSG, method.getName(), factory.getClass().getSimpleName()));
return method.invoke(factory, args);
}
private void addFactory(Factory name, CIMObjectPathFactory factory) {
if (factories == null) {
factories = new HashMap<>();
}
factories.put(name, factory);
}
}