package ddth.dasp.hetty.message.protobuf;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.jboss.netty.handler.codec.http.Cookie;
import org.jboss.netty.handler.codec.http.CookieDecoder;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.QueryStringDecoder;
import org.jboss.netty.util.CharsetUtil;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import ddth.dasp.common.id.IdGenerator;
import ddth.dasp.hetty.message.IMessageFactory;
import ddth.dasp.hetty.message.IRequest;
import ddth.dasp.hetty.message.IResponse;
public class ProtoBufMessageFactory implements IMessageFactory {
public void init() {
}
public void destroy() {
}
/**
* {@inheritDoc}
*/
@Override
public IRequest buildRequest(HttpRequest httpRequest, int channelId, byte[] requestContent) {
String uri = httpRequest.getUri();
String requestId = IdGenerator.getInstance(IdGenerator.getMacAddr()).generateId64Ascii();
HettyProtoBuf.Request.Builder requestProtoBuf = HettyProtoBuf.Request.newBuilder();
// populate required fields
requestProtoBuf.setTimestampNano(System.nanoTime());
requestProtoBuf.setId(requestId);
requestProtoBuf.setResponseTopic(requestId);
requestProtoBuf.setChannelId(channelId);
requestProtoBuf.setMethod(httpRequest.getMethod().toString());
requestProtoBuf.setUri(uri);
// parse path parameters
QueryStringDecoder qsd = new QueryStringDecoder(uri, CharsetUtil.UTF_8);
String path = qsd.getPath();
requestProtoBuf.setPath(path);
String[] pathTokens = path.replaceAll("^\\/+", "").replaceAll("\\/+$", "").split("\\/");
requestProtoBuf.addAllPathParams(Arrays.asList(pathTokens));
// parse url parameters
Map<String, List<String>> urlParams = qsd.getParameters();
for (Entry<String, List<String>> urlParam : urlParams.entrySet()) {
String name = urlParam.getKey();
String value = urlParam.getValue().size() > 0 ? urlParam.getValue().get(0) : "";
HettyProtoBuf.NameValue param = HettyProtoBuf.NameValue.newBuilder().setName(name)
.setValue(value).build();
requestProtoBuf.addUrlParams(param);
}
// parse host & port
String hostAndPort = httpRequest.getHeader("Host");
String[] tokens = hostAndPort.split(":");
requestProtoBuf.setDomain(tokens[0]);
try {
requestProtoBuf.setPort(Integer.parseInt(tokens[1]));
} catch (Exception e) {
requestProtoBuf.setPort(80);
}
// parse & populate cookies
String strCookie = httpRequest.getHeader("Cookie");
if (!StringUtils.isBlank(strCookie)) {
Set<Cookie> cookies = new CookieDecoder().decode(strCookie);
for (Cookie cookie : cookies) {
HettyProtoBuf.Cookie.Builder cookieProtoBuf = HettyProtoBuf.Cookie.newBuilder();
cookieProtoBuf.setName(cookie.getName());
cookieProtoBuf.setValue(cookie.getValue());
cookieProtoBuf.setDomain(cookie.getDomain() != null ? cookie.getDomain() : "");
cookieProtoBuf.setPath(cookie.getPath() != null ? cookie.getPath() : "");
cookieProtoBuf.setMaxAge(cookie.getMaxAge());
requestProtoBuf.addCookies(cookieProtoBuf);
}
}
// parse & populate other headers
httpRequest.removeHeader("Host");
httpRequest.removeHeader("Cookie");
for (Entry<String, String> entry : httpRequest.getHeaders()) {
HettyProtoBuf.NameValue.Builder headerProtoBuf = HettyProtoBuf.NameValue.newBuilder();
headerProtoBuf.setName(entry.getKey());
headerProtoBuf.setValue(entry.getValue());
requestProtoBuf.addHeaders(headerProtoBuf);
}
// populate content
requestProtoBuf.setContent(ByteString.copyFrom(requestContent));
return new ProtoBufRequest(requestProtoBuf.build());
}
/**
* {@inheritDoc}
*/
@Override
public IRequest deserializeRequest(byte[] serializedData) {
HettyProtoBuf.Request request;
try {
request = HettyProtoBuf.Request.parseFrom(serializedData);
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
return new ProtoBufRequest(request);
}
/**
* {@inheritDoc}
*/
@Override
public IResponse deserializeResponse(byte[] serializedData) {
HettyProtoBuf.Response response;
try {
response = HettyProtoBuf.Response.parseFrom(serializedData);
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
return new ProtoBufResponse(response);
}
}