package com.aliyun.openservices.ons.api.impl.rocketmq;
import static com.aliyun.openservices.ons.api.impl.rocketmq.SessionCredentials.AccessKey;
import static com.aliyun.openservices.ons.api.impl.rocketmq.SessionCredentials.CHARSET;
import static com.aliyun.openservices.ons.api.impl.rocketmq.SessionCredentials.Signature;
import java.lang.reflect.Field;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.rocketmq.remoting.CommandCustomHeader;
import com.alibaba.rocketmq.remoting.RPCHook;
import com.alibaba.rocketmq.remoting.protocol.RemotingCommand;
import com.aliyun.openservices.ons.api.impl.rocketmq.spas.SpasSigner;
/**
* @auther lansheng.zj
*/
public class ClientRPCHook implements RPCHook {
private SessionCredentials sessionCredentials;
private ConcurrentHashMap<Class<? extends CommandCustomHeader>, Field[]> fieldCache;
public ClientRPCHook(SessionCredentials sessionCredentials) {
this.sessionCredentials = sessionCredentials;
fieldCache = new ConcurrentHashMap<Class<? extends CommandCustomHeader>, Field[]>();
}
@Override
public void doBeforeRequest(String remoteAddr, RemotingCommand request) {
CommandCustomHeader header = request.readCustomHeader();
try {
// sort property
SortedMap<String, String> map = new TreeMap<String, String>();
map.put(AccessKey, sessionCredentials.getAccessKey());
// add header properties
if (null != header) {
Field[] fields = fieldCache.get(header.getClass());
if (null == fields) {
fields = header.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
}
Field[] tmp = fieldCache.putIfAbsent(header.getClass(), fields);
if (null != tmp) {
fields = tmp;
}
}
for (Field field : fields) {
Object value = field.get(header);
if (null != value) {
map.put(field.getName(), value.toString());
}
}
}
StringBuilder sb = new StringBuilder("");
for (Entry<String, String> entry : map.entrySet()) {
sb.append(entry.getValue());
}
byte[] total = ONSUtil.combineBytes(sb.toString().getBytes(CHARSET), request.getBody());
String signature = SpasSigner.sign(total, sessionCredentials.getSecretKey());
request.addExtField(Signature, signature);
request.addExtField(AccessKey, sessionCredentials.getAccessKey());
}
catch (Exception e) {
throw new RuntimeException("incompatible exception.", e);
}
}
@Override
public void doAfterResponse(RemotingCommand request, RemotingCommand response) {
}
}