Java tutorial
/** * The MIT License * * Copyright (c) 2009 Carl Bystrom * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Snagged from the following RenderShark component: * https://code.google.com/p/rendershark * /source/browse/trunk/rendershark/src/main * /java/com/sun/jersey/server/impl/container/netty/NettyHandlerContainer.java * */ package com.netflix.recipes.rss.netty; import com.sun.jersey.api.core.ResourceConfig; import com.sun.jersey.core.header.InBoundHeaders; import com.sun.jersey.spi.container.ContainerRequest; import com.sun.jersey.spi.container.ContainerResponse; import com.sun.jersey.spi.container.ContainerResponseWriter; import com.sun.jersey.spi.container.WebApplication; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufInputStream; import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMessage; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import java.io.IOException; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Map; @Sharable public class NettyHandlerContainer extends ChannelInboundHandlerAdapter { public static final String PROPERTY_BASE_URI = "com.sun.jersey.server.impl.container.netty.baseUri"; private final WebApplication application; private final String baseUri; NettyHandlerContainer(WebApplication application, ResourceConfig resourceConfig) { this.application = application; this.baseUri = (String) resourceConfig.getProperty(PROPERTY_BASE_URI); } private final static class Writer implements ContainerResponseWriter { private final ChannelHandlerContext ctx; private DefaultFullHttpResponse response; private Writer(ChannelHandlerContext ctx) { this.ctx = ctx; } public OutputStream writeStatusAndHeaders(long contentLength, ContainerResponse cResponse) throws IOException { ByteBuf buffer = Unpooled.buffer(); response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.valueOf(cResponse.getStatus()), buffer); for (Map.Entry<String, List<Object>> e : cResponse.getHttpHeaders().entrySet()) { List<String> values = new ArrayList<String>(); for (Object v : e.getValue()) values.add(ContainerResponse.getHeaderValue(v)); response.headers().set(e.getKey(), values); } return new ByteBufOutputStream(buffer); } public void finish() throws IOException { // Streaming is not supported. Entire response will be written // downstream once finish() is called. final ChannelFuture f = ctx.writeAndFlush(response); f.addListener(ChannelFutureListener.CLOSE); } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws URISyntaxException, IOException { if (msg instanceof FullHttpRequest) { FullHttpRequest httpRequest = (FullHttpRequest) msg; String base = getBaseUri(httpRequest); URI baseUri = new URI(base); URI requestUri = new URI(base.substring(0, base.length() - 1) + httpRequest.getUri()); ContainerRequest cRequest = new ContainerRequest(application, httpRequest.getMethod().name(), baseUri, requestUri, getHeaders(httpRequest), new ByteBufInputStream(httpRequest.content())); application.handleRequest(cRequest, new Writer(ctx)); } } private String getBaseUri(HttpMessage httpMessage) { if (baseUri != null) { return baseUri; } return "http://" + HttpHeaders.getHost(httpMessage) + "/"; } private InBoundHeaders getHeaders(FullHttpRequest httpRequest) { InBoundHeaders headers = new InBoundHeaders(); HttpHeaders httpHeaders = httpRequest.headers(); for (String name : httpHeaders.names()) { headers.put(name, httpHeaders.getAll(name)); } return headers; } }