Revision: 11014
http://wonder.svn.sourceforge.net/wonder/?rev=11014&view=rev
Author: rmendis
Date: 2010-07-20 07:33:35 +0000 (Tue, 20 Jul 2010)
Log Message:
-----------
A re-write using Netty (instead of Apache Mina2) based on the Http server example in the Netty docs
Modified Paths:
--------------
trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/.classpath
trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/ERWOAdaptor.java
Added Paths:
-----------
trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Libraries/netty-3.2.1.Final.jar
trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/WONettyAdaptorPipelineFactory.java
trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/WONettyAdaptorRequestHandler.java
Removed Paths:
-------------
trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Libraries/mina-core-2.0.0-RC1.jar
trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Libraries/tomcat-ajp-5.5.12.jar
Modified: trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/.classpath
===================================================================
--- trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/.classpath 2010-07-19 17:41:19 UTC (rev 11013)
+++ trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/.classpath 2010-07-20 07:33:35 UTC (rev 11014)
@@ -10,7 +10,6 @@
<classpathentry kind="con" path="WOFramework/JavaWebObjects"/>
<classpathentry kind="con" path="WOFramework/JavaXML"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="lib" path="Libraries/tomcat-ajp-5.5.12.jar"/>
- <classpathentry kind="lib" path="Libraries/mina-core-2.0.0-RC1.jar"/>
+ <classpathentry kind="lib" path="Libraries/netty-3.2.1.Final.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
Deleted: trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Libraries/mina-core-2.0.0-RC1.jar
===================================================================
(Binary files differ)
Added: trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Libraries/netty-3.2.1.Final.jar
===================================================================
(Binary files differ)
Property changes on: trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Libraries/netty-3.2.1.Final.jar
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Deleted: trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Libraries/tomcat-ajp-5.5.12.jar
===================================================================
(Binary files differ)
Modified: trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/ERWOAdaptor.java
===================================================================
--- trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/ERWOAdaptor.java 2010-07-19 17:41:19 UTC (rev 11013)
+++ trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/ERWOAdaptor.java 2010-07-20 07:33:35 UTC (rev 11014)
@@ -1,62 +1,19 @@
package er.woadaptor;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
import java.net.InetSocketAddress;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.Map.Entry;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.log4j.Logger;
-import org.apache.mina.core.buffer.IoBuffer;
-import org.apache.mina.core.service.IoAcceptor;
-import org.apache.mina.core.service.IoHandlerAdapter;
-import org.apache.mina.core.session.IdleStatus;
-import org.apache.mina.core.session.IoSession;
-import org.apache.mina.filter.codec.ProtocolCodecFilter;
-import org.apache.mina.filter.codec.ProtocolDecoderOutput;
-import org.apache.mina.filter.codec.ProtocolEncoderOutput;
-import org.apache.mina.filter.codec.demux.DemuxingProtocolCodecFactory;
-import org.apache.mina.filter.codec.demux.MessageDecoder;
-import org.apache.mina.filter.codec.demux.MessageDecoderResult;
-import org.apache.mina.filter.codec.demux.MessageEncoder;
-import org.apache.mina.filter.logging.LoggingFilter;
-import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import com.webobjects.appserver.WOAdaptor;
import com.webobjects.appserver.WOApplication;
-import com.webobjects.appserver.WORequest;
-import com.webobjects.appserver.WOResponse;
import com.webobjects.appserver._private.WOProperties;
-import com.webobjects.foundation.NSArray;
-import com.webobjects.foundation.NSData;
-import com.webobjects.foundation.NSDelayedCallbackCenter;
import com.webobjects.foundation.NSDictionary;
-import com.webobjects.foundation.NSMutableArray;
-import com.webobjects.foundation.NSMutableDictionary;
/**
- * Apache-mina based WOAdaptor, currently experimental.
- * <ul>
- * <li> Allows us to ditch
- * WOWorkerThread, WOHttpIO, WOLowercaseCharArray, WODefaultAdaptor and a bunch
- * of other classes.
- * <li> Has an extensible architecture, so SSL, throttling or AJP should be easily plug-able.
- * <li> uses NIO, which supposedly should give better performance (but hasn't, probably too much overhead).
- * </ul>
- * TODO: streaming, encoding, SSL, params (idle time etc), content-length, larger POST args.
- * @author ak
- *
+ * @author anjo (Original) Apache Mina version
+ * @author ravim ERWOAdaptor version
*/
public class ERWOAdaptor extends WOAdaptor {
@@ -66,336 +23,36 @@
private String _host;
- private int _maxSocketIdleTime;
-
- private static WOResponse _lastDitchErrorResponse;
-
- private static WOApplication _app;
-
- private IoAcceptor acceptor;
-
- private static ExecutorService _executor;
-
- public ERWOAdaptor(String name, NSDictionary config) {
+ public ERWOAdaptor(String name, NSDictionary config) {
super(name, config);
- _lastDitchErrorResponse = new WOResponse();
- _lastDitchErrorResponse.setStatus(500);
- _lastDitchErrorResponse.setContent("An error occured");
- _lastDitchErrorResponse.setHeaders(NSDictionary.EmptyDictionary);
- _app = WOApplication.application();
Number number = (Number) config.objectForKey(WOProperties._PortKey);
if (number != null)
_port = number.intValue();
if (_port < 0)
_port = 0;
- _app.setPort(_port);
- _executor = Executors.newCachedThreadPool();
+ WOApplication.application().setPort(_port);
_host = (String) config.objectForKey(WOProperties._HostKey);
- _app._setHost(_host);
- }
-
- @Override
- public int port() {
- return _port;
+ WOApplication.application()._setHost(_host);
}
- @Override
- public void registerForEvents() {
- try {
- acceptor = new NioSocketAcceptor();
- acceptor.getFilterChain().addLast("logger", new LoggingFilter());
- acceptor.getFilterChain().addLast("protocolFilter", new ProtocolCodecFilter(new CodecFactory()));
- acceptor.setHandler(new Handler());
- acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 60);
- acceptor.bind(new InetSocketAddress(_host, _port));
- log.info("Started adaptor");
- } catch (IOException ex) {
- log.error(ex, ex);
- }
- }
+ @Override
+ public void registerForEvents() {
+ // Configure the server.
+ ServerBootstrap bootstrap = new ServerBootstrap(
+ new NioServerSocketChannelFactory(
+ Executors.newCachedThreadPool(),
+ Executors.newCachedThreadPool()));
- @Override
- public void unregisterForEvents() {
- if (acceptor != null) {
- acceptor.unbind();
- acceptor = null;
- }
- }
+ // Set up the event pipeline factory.
+ bootstrap.setPipelineFactory(new WONettyAdaptorPipelineFactory());
- public boolean dispatchesRequestsConcurrently() {
- return true;
- }
+ // Bind and start to accept incoming connections.
+ bootstrap.bind(new InetSocketAddress(_port));
+ }
- public static class CodecFactory extends DemuxingProtocolCodecFactory {
- public CodecFactory() {
- addMessageDecoder(RequestDecoder.class);
- addMessageEncoder(ResponseWrapper.class, ResponseEncoder.class);
- }
- }
-
- public static class RequestDecoder implements MessageDecoder {
-
- private static final byte[] CONTENT_LENGTH = new String("Content-Length:").getBytes();
-
- private CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
-
- public RequestDecoder() {
- }
-
- public MessageDecoderResult decodable(IoSession session, IoBuffer in) {
- try {
- return headerComplete(in) ? MessageDecoderResult.OK : MessageDecoderResult.NEED_DATA;
- } catch (Exception ex) {
- ex.printStackTrace();
- }
-
- return MessageDecoderResult.NOT_OK;
- }
-
- public MessageDecoderResult decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
- // Try to decode body
- WORequest request = parseRequest(new StringReader(in.getString(decoder)));
-
- if (request == null) {
- return MessageDecoderResult.NEED_DATA;
- }
- out.write(request);
-
- return MessageDecoderResult.OK;
- }
-
- private boolean headerComplete(IoBuffer in) throws Exception {
-
- int last = in.remaining() - 1;
- if (in.remaining() < 4)
- return false;
-
- int eoh = -1;
- for (int i = 0; i < last - 2; i++) {
- if (in.get(i) == (byte) 0x0D && in.get(i + 1) == (byte) 0x0A && in.get(i + 2) == (byte) 0x0D && in.get(i + 3) == (byte) 0x0A) {
- eoh = i + 3;
- break;
- }
- }
- if (eoh == -1)
- return false;
- byte[] bytes = new byte[eoh - 3];
- for (int i = 0; i < bytes.length; i++) {
- bytes[i] = in.get(i);
- }
- String headers = new String(bytes);
- for (int i = 0; i < last; i++) {
- boolean found = false;
- for (int j = 0; j < CONTENT_LENGTH.length; j++) {
- if (in.get(i + j) != CONTENT_LENGTH[j]) {
- found = false;
- break;
- }
- found = true;
- }
- if (found) {
- // retrieve value from this position till next 0x0D 0x0A
- StringBuilder contentLength = new StringBuilder();
- for (int j = i + CONTENT_LENGTH.length; j < last; j++) {
- if (in.get(j) == 0x0D)
- break;
- contentLength.append(new String(new byte[] { in.get(j) }));
- }
- // if content-length worth of data has been received then
- // the message is complete
- return (Integer.parseInt(contentLength.toString().trim()) + eoh == in.remaining());
- } else {
- // this may be wrong...
- return true;
- }
- }
-
- // the message is not complete and we need more data
- return false;
- }
-
- private WORequest parseRequest(Reader is) throws IOException {
- BufferedReader rdr = new BufferedReader(is);
- String line = rdr.readLine();
- String[] parts = line.trim().split(" ", 3);
- String url = parts[1];
- String method = parts[0];
- String version = parts[2];
- NSMutableDictionary<String, NSMutableArray<String>> headers = new NSMutableDictionary<String, NSMutableArray<String>>() {
- @Override
- public NSMutableArray<String> objectForKey(Object key) {
- return super.objectForKey(key.toString().toLowerCase());
- }
- };
-
- // Read header
- while ((line = rdr.readLine()) != null && line.length() > 0) {
- String[] tokens = line.split(":\\s*", 2);
- String key = tokens[0];
- String value = tokens[1];
- NSMutableArray<String> items = headers.objectForKey(key);
- if (items == null) {
- items = new NSMutableArray<String>();
- headers.setObjectForKey(items, key.toLowerCase());
- }
- items.addObject(value);
- }
-
- NSData content = null;
- if (headers.objectForKey("Content-Length") != null) {
- int len = Integer.parseInt(headers.objectForKey("Content-Length").lastObject());
- char[] buf = new char[len];
- if (rdr.read(buf) == len) {
- line = String.copyValueOf(buf);
- content = new NSData(line);
- }
- }
- WORequest request = WOApplication.application().createRequest(method, url, version, headers, content, null); // TODO add form content data parsing
-
- return request;
- }
-
- public void finishDecode(IoSession iosession, ProtocolDecoderOutput protocoldecoderoutput) throws Exception {
- // TODO Auto-generated method stub
-
- }
- }
-
- public static class ResponseWrapper {
-
- private WOResponse _response;
-
- public ResponseWrapper(WOResponse response) {
- _response = response;
- }
-
- public WOResponse response() {
- return _response;
- }
-
- }
-
- public static class ResponseEncoder implements MessageEncoder {
-
- private static final Set TYPES;
-
- static {
- Set types = new HashSet();
- types.add(ResponseWrapper.class);
- TYPES = Collections.unmodifiableSet(types);
- }
-
- private static final byte[] CRLF = new byte[] { 0x0D, 0x0A };
-
- public ResponseEncoder() {
- }
-
- public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
- WOResponse msg = (WOResponse) ((ResponseWrapper) message).response();
- IoBuffer buf = IoBuffer.allocate(256);
- // Enable auto-expand for easier encoding
- buf.setAutoExpand(true);
-
- try {
- // output all headers except the content length
- CharsetEncoder encoder = Charset.defaultCharset().newEncoder();
- buf.putString(msg.httpVersion(), encoder);
- buf.putString(" ", encoder);
- buf.putString(String.valueOf(msg.status()), encoder);
- switch (msg.status()) {
- case WOResponse.HTTP_STATUS_OK:
- buf.putString(" OK", encoder);
- break;
- case WOResponse.HTTP_STATUS_NOT_FOUND:
- buf.putString(" Not Found", encoder);
- break;
- default:
- buf.putString(" Whatever", encoder);
- }
- buf.put(CRLF);
- if (msg.headers() != null) {
- for (Iterator<Entry<String, NSArray<String>>> it = msg.headers().entrySet().iterator(); it.hasNext();) {
- Entry<String, NSArray<String>> entry = it.next();
- for (Object item : entry.getValue()) {
- buf.putString(entry.getKey().toString(), encoder);
- buf.putString(": ", encoder);
- buf.putString(item.toString(), encoder);
- buf.put(CRLF);
- }
- }
- } else {
- buf.put(CRLF);
- }
- // now the content length is the body length
- buf.put(CRLF);
- // add body
- // FIXME: should loop, support contentStream
- buf.put(msg.content()._bytesNoCopy());
- } catch (CharacterCodingException ex) {
- ex.printStackTrace();
- }
-
- buf.flip();
- out.write(buf);
- }
-
- public Set getMessageTypes() {
- return TYPES;
- }
- }
-
- public static class Handler extends IoHandlerAdapter {
-
- private final class Runner implements Runnable {
-
- private WORequest request;
-
- private IoSession session;
-
- public Runner(IoSession session, WORequest message) {
- this.request = message;
- this.session = session;
- }
-
- public WOResponse runOnce() {
- WOResponse woresponse = _lastDitchErrorResponse;
- try {
- boolean process = request != null;
- process &= !(!WOApplication.application().isDirectConnectEnabled() && !request.isUsingWebServer());
- process &= !"womp".equals(request.requestHandlerKey());
-
- if (process) {
- woresponse = _app.dispatchRequest(request);
- NSDelayedCallbackCenter.defaultCenter().eventEnded();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return woresponse;
- }
-
- public void run() {
- WOResponse response = runOnce();
-
- if (response != null) {
- session.write(new ResponseWrapper(response));
- }
- // session.close();
- }
- }
-
- public void sessionClosed(IoSession session) {
- log.info("closed");
- }
-
- public void messageReceived(IoSession session, Object message) {
- Runnable callable = new Runner(session, (WORequest) message);
- _executor.submit(callable);
- }
-
- public void exceptionCaught(IoSession session, Throwable cause) {
- log.info("exceptionCaught: " + cause, cause);
- }
- }
+ @Override
+ public void unregisterForEvents() {
+ // TODO Auto-generated method stub
+ }
}
Added: trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/WONettyAdaptorPipelineFactory.java
===================================================================
--- trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/WONettyAdaptorPipelineFactory.java (rev 0)
+++ trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/WONettyAdaptorPipelineFactory.java 2010-07-20 07:33:35 UTC (rev 11014)
@@ -0,0 +1,39 @@
+package er.woadaptor;
+
+import static org.jboss.netty.channel.Channels.pipeline;
+
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.handler.codec.http.HttpContentCompressor;
+import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
+import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
+
+/**
+ * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
+ * @author Andy Taylor (andy.taylor@...)
+ * @author <a href="http://gleamynode.net/">Trustin Lee</a>
+ *
+ * {@link} http://docs.jboss.org/netty/3.2/xref/org/jboss/netty/example/http/snoop/HttpServerPipelineFactory.html
+ *
+ * @author ravim ERWOAdaptor version
+ */
+public class WONettyAdaptorPipelineFactory implements ChannelPipelineFactory {
+ public ChannelPipeline getPipeline() throws Exception {
+ // Create a default pipeline implementation.
+ ChannelPipeline pipeline = pipeline();
+
+ // Uncomment the following line if you want HTTPS
+ //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
+ //engine.setUseClientMode(false);
+ //pipeline.addLast("ssl", new SslHandler(engine));
+
+ pipeline.addLast("decoder", new HttpRequestDecoder());
+ // Uncomment the following line if you don't want to handle HttpChunks.
+ //pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
+ pipeline.addLast("encoder", new HttpResponseEncoder());
+ // Remove the following line if you don't want automatic content compression.
+ pipeline.addLast("deflater", new HttpContentCompressor());
+ pipeline.addLast("handler", new WONettyAdaptorRequestHandler());
+ return pipeline;
+ }
+}
Property changes on: trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/WONettyAdaptorPipelineFactory.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/WONettyAdaptorRequestHandler.java
===================================================================
--- trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/WONettyAdaptorRequestHandler.java (rev 0)
+++ trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/WONettyAdaptorRequestHandler.java 2010-07-20 07:33:35 UTC (rev 11014)
@@ -0,0 +1,135 @@
+package er.woadaptor;
+
+import static org.jboss.netty.handler.codec.http.HttpHeaders.isKeepAlive;
+import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH;
+import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
+import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.COOKIE;
+import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.SET_COOKIE;
+import static org.jboss.netty.handler.codec.http.HttpResponseStatus.OK;
+import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.ChannelFuture;
+import org.jboss.netty.channel.ChannelFutureListener;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+import org.jboss.netty.handler.codec.http.Cookie;
+import org.jboss.netty.handler.codec.http.CookieDecoder;
+import org.jboss.netty.handler.codec.http.CookieEncoder;
+import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
+import org.jboss.netty.handler.codec.http.HttpRequest;
+import org.jboss.netty.handler.codec.http.HttpResponse;
+
+import com.webobjects.appserver.WOApplication;
+import com.webobjects.appserver.WORequest;
+import com.webobjects.appserver.WOResponse;
+import com.webobjects.foundation.NSData;
+import com.webobjects.foundation.NSDelayedCallbackCenter;
+import com.webobjects.foundation.NSDictionary;
+import com.webobjects.foundation.NSMutableArray;
+import com.webobjects.foundation.NSMutableDictionary;
+
+/**
+* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
+* @author Andy Taylor (andy.taylor@...)
+* @author <a href="http://gleamynode.net/">Trustin Lee</a>
+*
+* {@link} http://docs.jboss.org/netty/3.2/xref/org/jboss/netty/example/http/snoop/HttpRequestHandler.html
+*
+* @author ravim ERWOAdaptor version
+*/
+public class WONettyAdaptorRequestHandler extends SimpleChannelUpstreamHandler {
+
+ private HttpRequest request;
+ /** Buffer that stores the response content */
+ private static WOResponse _lastDitchErrorResponse;
+ private WOResponse woresponse = _lastDitchErrorResponse;
+
+ static {
+ _lastDitchErrorResponse = new WOResponse();
+ _lastDitchErrorResponse.setStatus(500);
+ _lastDitchErrorResponse.setContent("An error occured");
+ _lastDitchErrorResponse.setHeaders(NSDictionary.EmptyDictionary);
+ }
+
+ @Override
+ public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+ request = (HttpRequest) e.getMessage();
+ NSMutableDictionary<String, NSMutableArray<String>> headers = new NSMutableDictionary<String, NSMutableArray<String>>();
+ for (Map.Entry<String, String> header: request.getHeaders()) {
+ headers.setObjectForKey(new NSMutableArray<String>(header.getValue()), header.getKey());
+ }
+ WORequest worequest = WOApplication.application().createRequest(
+ request.getMethod().getName(),
+ request.getUri(),
+ request.getProtocolVersion().getText(),
+ headers,
+ new NSData(request.getContent().array()),
+ null);
+
+ try {
+ boolean process = request != null;
+ process &= !(!WOApplication.application().isDirectConnectEnabled() && !worequest.isUsingWebServer());
+ process &= !"womp".equals(worequest.requestHandlerKey());
+
+ if (process) {
+ woresponse = WOApplication.application().dispatchRequest(worequest);
+ NSDelayedCallbackCenter.defaultCenter().eventEnded();
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ writeResponse(e);
+ }
+
+ private void writeResponse(MessageEvent e) {
+ // Decide whether to close the connection or not.
+ boolean keepAlive = isKeepAlive(request);
+
+ // Build the response object.
+ HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
+ response.setContent(ChannelBuffers.copiedBuffer(woresponse.contentString(), woresponse.contentEncoding()));
+ String contentType = woresponse.headerForKey(CONTENT_TYPE);
+ if (contentType != null) response.setHeader(CONTENT_TYPE, contentType);
+
+ if (keepAlive) {
+ // Add 'Content-Length' header only for a keep-alive connection.
+ response.setHeader(CONTENT_LENGTH, woresponse.content().bytes().length);
+ }
+
+ // Encode the cookie.
+ String cookieString = request.getHeader(COOKIE);
+ if (cookieString != null) {
+ CookieDecoder cookieDecoder = new CookieDecoder();
+ Set<Cookie> cookies = cookieDecoder.decode(cookieString);
+ if(!cookies.isEmpty()) {
+ // Reset the cookies if necessary.
+ CookieEncoder cookieEncoder = new CookieEncoder(true);
+ for (Cookie cookie : cookies) {
+ cookieEncoder.addCookie(cookie);
+ }
+ response.addHeader(SET_COOKIE, cookieEncoder.encode());
+ }
+ }
+
+ // Write the response.
+ ChannelFuture future = e.getChannel().write(response);
+
+ // Close the non-keep-alive connection after the write operation is done.
+ if (!keepAlive) {
+ future.addListener(ChannelFutureListener.CLOSE);
+ }
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
+ throws Exception {
+ e.getCause().printStackTrace();
+ e.getChannel().close();
+ }
+}
Property changes on: trunk/Wonder/Frameworks/WOAdaptors/ERWOAdaptor/Sources/er/woadaptor/WONettyAdaptorRequestHandler.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|