/**
*
*/
package jframe.netty.http.handler;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.ReferenceCountUtil;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.regex.Pattern;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author dzh
* @date Jul 25, 2014 9:04:17 AM
* @since 1.0
*/
@Sharable
public class HttpReqDispatcher extends SimpleChannelInboundHandler<HttpObject> {
private static final Logger LOG = LoggerFactory
.getLogger(HttpReqDispatcher.class);
/**
* <id,Dispatcher>
*/
private List<Dispatcher> _dispatcher = new LinkedList<Dispatcher>();
/**
* <url,handler clazz>
*/
private Map<String, WeakReference<String>> _cache = new WeakHashMap<String, WeakReference<String>>();
static String FILE_DISPATCHER = "dispatcher.xml";
public HttpReqDispatcher() {
loadDispatcher(FILE_DISPATCHER, _dispatcher);
}
public void loadDispatcher(String file, List<Dispatcher> dispatcher) {
InputStream is = getClass().getResourceAsStream(file);
if (is == null) {
LOG.error("Not found dispatcher.xml");
return;
}
_dispatcher.clear();
SAXReader reader = new SAXReader();
try {
Document doc = reader.read(is);
@SuppressWarnings("unchecked")
List<Element> elements = doc.getRootElement()
.elements("dispatcher");
Dispatcher d = null;
for (Element e : elements) {
d = new Dispatcher();
d.setId(e.attributeValue("id"));
d.setUrl(e.elementText("url-pattern"));
d.setClazz(e.elementText("handler"));
dispatcher.add(d);
}
} catch (DocumentException e) {
LOG.error(e.getMessage());
} finally {
try {
is.close();
reader.resetHandlers();
} catch (IOException e) {
LOG.error(e.getMessage());
}
}
}
/**
* request regular expression
*/
// public final static Pattern Req_Regx = Pattern
// .compile("\\/(.*?)\\/(.*?)(?:\\/(.*))?");
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg)
throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest req = (HttpRequest) msg;
if (LOG.isDebugEnabled()) {
LOG.debug("Dispatch req path {}", req.getUri());
}
// pay client req
final String reqUrl = req.getUri();
Map<String, WeakReference<String>> cache = _cache;
WeakReference<String> wr = cache.get(reqUrl);
String clazz = wr != null && wr.get() != null ? wr.get() : null;
if (clazz != null) {
if (reqUrl.startsWith("/img/down/")) {
ctx.pipeline().addLast("http aggregator",
new HttpObjectAggregator(65536));
ctx.pipeline().addLast("http chunk",
new ChunkedWriteHandler());
}
ctx.pipeline().addLast(
(ChannelHandler) getClass().getClassLoader()
.loadClass(clazz).newInstance());
} else {
List<Dispatcher> list = _dispatcher;
for (Dispatcher d : list) {
if (Pattern.matches(d.getUrl(), reqUrl)) {
if (d.getId().equals("img.down")) {
ctx.pipeline().remove("http compressor");
ctx.pipeline()
.addLast(
"http aggregator",
new HttpObjectAggregator(
65536)); //
ctx.pipeline().addLast("http chunk",
new ChunkedWriteHandler());
}
ctx.pipeline().addLast(
(ChannelHandler) getClass().getClassLoader()
.loadClass(d.getClazz()).newInstance());
cache.put(reqUrl,
new WeakReference<String>(d.getClazz()));
break;
}
}
}
}
// ReferenceCountUtil.retain(msg);
ctx.fireChannelRead(msg);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
super.exceptionCaught(ctx, cause);
LOG.error(cause.getMessage(), cause);
}
}