Author: akarasulu
Date: Sun Jan 27 18:03:44 2008
New Revision: 615699
URL: http://svn.apache.org/viewvc?rev=615699&view=rev
Log:
changes ...
o more cleanups
o more documentation
o adding client connection listener interface and plumbing for notification of
disconnect and idling
Added:
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/ClientListenerExample.java
- copied, changed from r615542,
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/helloworld/HelloWorldHttpService.java
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/Main.java
(with props)
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpClientListener.java
Modified:
mina/asyncweb/trunk/examples/src/main/resources/log4j.properties
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpService.java
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpServiceContext.java
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/context/AbstractHttpServiceContext.java
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/DefaultHttpIoHandler.java
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/MinaTransport.java
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/SingleHttpSessionIoHandler.java
Copied:
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/ClientListenerExample.java
(from r615542,
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/helloworld/HelloWorldHttpService.java)
URL:
http://svn.apache.org/viewvc/mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/ClientListenerExample.java?p2=mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/ClientListenerExample.java&p1=mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/helloworld/HelloWorldHttpService.java&r1=615542&r2=615699&rev=615699&view=diff
==============================================================================
---
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/helloworld/HelloWorldHttpService.java
(original)
+++
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/ClientListenerExample.java
Sun Jan 27 18:03:44 2008
@@ -17,152 +17,64 @@
* under the License.
*
*/
-package org.apache.asyncweb.examples.helloworld;
+package org.apache.asyncweb.examples.listener;
+
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.nio.charset.Charset;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.mina.common.IoBuffer;
-import org.apache.asyncweb.common.HttpRequest;
-import org.apache.asyncweb.common.HttpResponseStatus;
-import org.apache.asyncweb.common.MutableHttpResponse;
-import org.apache.asyncweb.common.Cookie;
-import org.apache.asyncweb.common.DefaultHttpResponse;
import org.apache.asyncweb.server.HttpService;
import org.apache.asyncweb.server.HttpServiceContext;
+import org.apache.asyncweb.server.HttpClientListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
- * A simple <code>HttpService</code> which sends "hello world"
- * responses to every request.
- *
- * Note that normally we wouldn't be generating html directly in a service :o)
- *
- * @author irvingd
+ * An <code>HttpService</code> which utilizes the HttpClientListener interface
+ * for long polling requests.
*
+ * @author The Apache MINA Project ([EMAIL PROTECTED])
+ * @version $Rev$, $Date$
*/
-public class HelloWorldHttpService implements HttpService {
-
- private String message = "Hello from AsyncWeb!!";
-
- /**
- * Sends the configured message as an HTTP response
- */
- public void handleRequest( HttpServiceContext context) throws Exception {
- MutableHttpResponse response = new DefaultHttpResponse();
-
- StringWriter buf = new StringWriter();
- PrintWriter writer = new PrintWriter(buf);
- writer.println("<html><body><b>Your message of the
day:</b><br/><br/>");
- writer.println("<h2><i>" + message + "</h2></i><br/><br/>");
- writeHeaders(context.getRequest(), writer);
- writer.println("<br/>");
- writeParameters(context.getRequest(), writer);
- writer.println("<br/>");
- writeCookies(context.getRequest(), writer);
- writer.flush();
-
- IoBuffer bb = IoBuffer.allocate(1024);
- bb.setAutoExpand(true);
- bb.putString(buf.toString(), Charset.forName("UTF-8").newEncoder());
- bb.flip();
- response.setContent(bb);
-
- response.setHeader("Pragma", "no-cache");
- response.setHeader("Cache-Control", "no-cache");
- response.setStatus(HttpResponseStatus.OK);
-
- context.commitResponse(response);
- }
-
- /**
- * Sets the message to return in responses.
- * This is called for you by the framework!
- *
- * @param message The message
- */
- public void setMessage(String message) {
- this.message = message;
- }
+public class ClientListenerExample implements HttpService
+{
+ private final Logger log = LoggerFactory.getLogger(
ClientListenerExample.class );
+
/**
- * Writes headers from the request to the specified writer
- *
- * @param request The request
- * @param writer The writer
+ * Does nothing with the request but just listens for disconnects and
+ * connection idling.
*/
- private void writeHeaders( HttpRequest request, PrintWriter writer) {
- writer.println("You sent these headers with your request:<br/>");
- writer.println("<ul>");
- for (String headerName : request.getHeaders().keySet()) {
- String headerValue = request.getHeader(headerName);
- writer.print("<li>" + headerName + " = " + headerValue + "</li>");
- }
- writer.println("</ul>");
- }
+ public void handleRequest( HttpServiceContext context ) throws Exception
+ {
+ final long requestTime = System.currentTimeMillis();
+ log.info( "Got request from client {} at {}",
context.getRemoteAddress(), requestTime );
+
+ context.addClientListener( new HttpClientListener()
+ {
+ public void clientDisconnected( HttpServiceContext ctx )
+ {
+ log.info( "Client {} disconnected after {} milliSeconds",
ctx.getRemoteAddress(),
+ ( System.currentTimeMillis() - requestTime ) );
+ }
- /**
- * Writes cookies from the request to the specified writer
- *
- * @param request The request
- * @param writer The writer
- */
- private void writeCookies(HttpRequest request, PrintWriter writer) {
- Collection<Cookie> cookies = request.getCookies();
- if (!cookies.isEmpty()) {
- writer.println("You sent these cookies with your request:<br/>");
- writer.println("<ul>");
- for ( Cookie cookie : cookies) {
- writer.println("<li>Name = " + cookie.getName() + " Value = "
- + cookie.getValue());
- writer.println(" Path = " + cookie.getPath() + " Version = "
- + cookie.getVersion() + "</li>");
+ public void clientIdle( HttpServiceContext ctx, long idleTime, int
idleCount )
+ {
+ log.info( "Client {} idle events after {} milliSeconds",
ctx.getRemoteAddress(),
+ ( System.currentTimeMillis() - requestTime ) );
+ log.info( "IdleTime = {}", idleTime );
+ log.info( "IdleCount = {}", idleCount );
}
- writer.println("</ul>");
- }
+ });
}
- /**
- * Writes request parameters to the specified writer
- *
- * @param request The request
- * @param writer The writer
- */
- private void writeParameters(HttpRequest request, PrintWriter writer) {
- if (request.getParameters().size() > 0) {
- writer
- .println("You sent these parameters with your
request:<br/><br/>");
- writer.println("<ul>");
-
- for (Map.Entry<String, List<String>> entry : request
- .getParameters().entrySet()) {
- writer.println("<li>");
- writer.print("'" + entry.getKey() + "' = ");
- for (Iterator<String> i = entry.getValue().iterator(); i
- .hasNext();) {
- String value = i.next();
- writer.print("'" + value + "'");
- if (i.hasNext()) {
- writer.print(", ");
- }
- }
- writer.println("</li/>");
- }
- writer.println("</ul>");
- }
+ public void start()
+ {
+ log.info( "Started listener service. Goto
http://localhost:9012/listener ang give it a try." );
}
- public void start() {
- // Dont care
- }
- public void stop() {
- // Dont care
+ public void stop()
+ {
+ log.info( "Stopped listener service." );
}
-
-}
+}
\ No newline at end of file
Added:
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/Main.java
URL:
http://svn.apache.org/viewvc/mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/Main.java?rev=615699&view=auto
==============================================================================
---
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/Main.java
(added)
+++
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/Main.java
Sun Jan 27 18:03:44 2008
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asyncweb.examples.listener;
+
+
+import org.apache.asyncweb.server.BasicServiceContainer;
+import org.apache.asyncweb.server.HttpServiceHandler;
+import org.apache.asyncweb.server.transport.mina.MinaTransport;
+import org.apache.asyncweb.server.transport.mina.DefaultHttpIoHandler;
+import org.apache.asyncweb.server.resolver.ExactMatchURIServiceResolver;
+
+
+/**
+ * An application launcher which runs the ClientListenerExample example.
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Apache MINA Project</a>
+ * @version $Rev$, $Date$
+ */
+public class Main
+{
+ public static void main( String[] args ) throws Exception
+ {
+ // Setup the default container with a service handler that contains
the helloWorldService
+ BasicServiceContainer container = new BasicServiceContainer();
+ HttpServiceHandler handler = new HttpServiceHandler();
+ handler.addHttpService( "clientListenerExample", new
ClientListenerExample() );
+ container.addServiceFilter( handler );
+
+ // Set up a resolver for the HttpServiceHandler
+ ExactMatchURIServiceResolver resolver = new
ExactMatchURIServiceResolver();
+ resolver.addURIMapping( "/listener", "clientListenerExample" );
+ handler.setServiceResolver( resolver );
+
+ // Create the mina transport and enable the container with it
+ MinaTransport transport = new MinaTransport();
+ container.addTransport( transport );
+ DefaultHttpIoHandler ioHandler = new DefaultHttpIoHandler();
+ ioHandler.setReadIdle( 10 );
+ transport.setIoHandler( ioHandler );
+
+ // Fire it up and go
+ container.start();
+ }
+}
Propchange:
mina/asyncweb/trunk/examples/src/main/java/org/apache/asyncweb/examples/listener/Main.java
------------------------------------------------------------------------------
svn:executable = *
Modified: mina/asyncweb/trunk/examples/src/main/resources/log4j.properties
URL:
http://svn.apache.org/viewvc/mina/asyncweb/trunk/examples/src/main/resources/log4j.properties?rev=615699&r1=615698&r2=615699&view=diff
==============================================================================
--- mina/asyncweb/trunk/examples/src/main/resources/log4j.properties (original)
+++ mina/asyncweb/trunk/examples/src/main/resources/log4j.properties Sun Jan 27
18:03:44 2008
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-log4j.rootLogger=WARN, stdout
+log4j.rootLogger=INFO, stdout
log4j.logger.org.safehaus.asyncweb=INFO
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
Added:
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpClientListener.java
URL:
http://svn.apache.org/viewvc/mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpClientListener.java?rev=615699&view=auto
==============================================================================
---
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpClientListener.java
(added)
+++
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpClientListener.java
Sun Jan 27 18:03:44 2008
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asyncweb.server;
+
+
+/**
+ * An HTTP client connection listener. Since Asyncweb allows asynchronous
+ * handling of responses (response need not be committed in the HttpService
+ * handleRequest() method), connections can be held open for some time. For
+ * this reason a mechanism is needed to be informed of client disconnects or
+ * for notifications when the connection idles.
+ *
+ * @author The Apache MINA Project ([EMAIL PROTECTED])
+ * @version $Rev$, $Date$
+ */
+public interface HttpClientListener
+{
+ /**
+ * Gets notification of client disconnects.
+ *
+ * @param ctx the context associated with the disconnect event
+ */
+ void clientDisconnected( HttpServiceContext ctx );
+
+
+ /**
+ * Gets notification of client idling.
+ *
+ * @param ctx the context of the client which has gone idle
+ * @param idleTime the time at which a client began idling
+ * @param idleCount the number of times we were informed of idling
+ */
+ void clientIdle( HttpServiceContext ctx, long idleTime, int idleCount );
+}
Modified:
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpService.java
URL:
http://svn.apache.org/viewvc/mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpService.java?rev=615699&r1=615698&r2=615699&view=diff
==============================================================================
---
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpService.java
(original)
+++
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpService.java
Sun Jan 27 18:03:44 2008
@@ -19,18 +19,18 @@
*/
package org.apache.asyncweb.server;
+
/**
* An application-level HTTP request processor.
*
- * @author irvingd
- *
+ * @author The Apache MINA Project ([EMAIL PROTECTED])
+ * @version $Rev$, $Date$
*/
-public interface HttpService {
-
- public void handleRequest(HttpServiceContext context) throws Exception;
-
- public void start();
+public interface HttpService
+{
+ void handleRequest( HttpServiceContext context ) throws Exception;
- public void stop();
+ void start();
+ void stop();
}
Modified:
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpServiceContext.java
URL:
http://svn.apache.org/viewvc/mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpServiceContext.java?rev=615699&r1=615698&r2=615699&view=diff
==============================================================================
---
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpServiceContext.java
(original)
+++
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/HttpServiceContext.java
Sun Jan 27 18:03:44 2008
@@ -19,40 +19,53 @@
*/
package org.apache.asyncweb.server;
+
import java.net.InetSocketAddress;
import org.apache.asyncweb.common.HttpRequest;
import org.apache.asyncweb.common.HttpResponse;
import org.apache.asyncweb.common.HttpResponseStatus;
+
/**
* Provides conversational context between a HTTP client and a [EMAIL
PROTECTED] HttpService}.
*
- * @author trustin
+ * @author The Apache MINA Project ([EMAIL PROTECTED])
+ * @version $Rev$, $Date$
*/
-public interface HttpServiceContext {
-
+public interface HttpServiceContext
+{
/**
* Returns the socket address of the client (or last proxy).
+ *
+ * @return the socket address of the client (or last proxy)
*/
InetSocketAddress getRemoteAddress();
+
/**
* Returns the request which is received from the client.
+ *
+ * @return the request from the client
*/
HttpRequest getRequest();
+
/**
* Returns <tt>true</tt> if a response for the request is committed.
+ *
+ * @return true if the response has been committed, false otherwise
*/
boolean isResponseCommitted();
+
/**
* @return The <code>Response</code> committed to this
<code>Request</code>,
* or <code>null</code> if no response has been comitted
*/
HttpResponse getCommittedResponse();
+
/**
* Writes the specified response back to the client.
* The response <i>must not</i> be modified after it has been
@@ -71,14 +84,17 @@
* @param response The response to provide
* @return <code>true</code> if the response was accepted
*/
- boolean commitResponse(HttpResponse response);
+ boolean commitResponse( HttpResponse response );
+
/**
* Commits a default response with a specified [EMAIL PROTECTED]
HttpResponseStatus}.
*
- * @return <code>true</code> if the response was accepted
+ * @param status the status to return
+ * @return <code>true</code> if the response was accepted
*/
- boolean commitResponse(HttpResponseStatus status);
+ boolean commitResponse( HttpResponseStatus status );
+
/**
* Returns the [EMAIL PROTECTED] HttpSession} which is associated with the
client.
@@ -88,6 +104,7 @@
*/
HttpSession getSession();
+
/**
* Returns the <code>Session</code> associated with this request.
*
@@ -97,5 +114,11 @@
* is associated with the client and <code>create</code> is
* <code>false</code>
*/
- HttpSession getSession(boolean create);
+ HttpSession getSession( boolean create );
+
+
+ boolean addClientListener( HttpClientListener listener );
+
+
+ boolean removeClientListener( HttpClientListener listener );
}
Modified:
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/context/AbstractHttpServiceContext.java
URL:
http://svn.apache.org/viewvc/mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/context/AbstractHttpServiceContext.java?rev=615699&r1=615698&r2=615699&view=diff
==============================================================================
---
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/context/AbstractHttpServiceContext.java
(original)
+++
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/context/AbstractHttpServiceContext.java
Sun Jan 27 18:03:44 2008
@@ -19,7 +19,9 @@
*/
package org.apache.asyncweb.server.context;
+
import java.net.InetSocketAddress;
+import java.util.ArrayList;
import org.apache.asyncweb.common.HttpHeaderConstants;
import org.apache.asyncweb.common.HttpRequest;
@@ -30,20 +32,21 @@
import org.apache.asyncweb.server.HttpServiceContext;
import org.apache.asyncweb.server.HttpSession;
import org.apache.asyncweb.server.ServiceContainer;
+import org.apache.asyncweb.server.HttpClientListener;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
/**
* A default implementation of [EMAIL PROTECTED] HttpServiceContext}.
*
- * @author trustin
- * @version $Rev:167 $, $Date:2006-11-15 11:10:05 +0000 (ì, 15 11ì 2006) $
+ * @author The Apache MINA Project ([EMAIL PROTECTED])
+ * @version $Rev$, $Date$
*/
public abstract class AbstractHttpServiceContext implements HttpServiceContext
{
-
- private final Logger log = LoggerFactory
- .getLogger(AbstractHttpServiceContext.class);
+ private final Logger log = LoggerFactory.getLogger(
AbstractHttpServiceContext.class );
private final InetSocketAddress remoteAddress;
@@ -57,41 +60,54 @@
private final ServiceContainer container;
- public AbstractHttpServiceContext(InetSocketAddress remoteAddress,
- HttpRequest request, ServiceContainer container) {
- if (remoteAddress == null) {
- throw new NullPointerException("remoteAddress");
+ private final ArrayList<HttpClientListener> listeners = new
ArrayList<HttpClientListener>( 2 );
+
+
+
+ public AbstractHttpServiceContext( InetSocketAddress remoteAddress,
+ HttpRequest request, ServiceContainer
container )
+ {
+ if ( remoteAddress == null )
+ {
+ throw new NullPointerException( "remoteAddress" );
}
- if (request == null) {
- throw new NullPointerException("request");
+
+ if ( request == null )
+ {
+ throw new NullPointerException( "request" );
}
- if (container == null) {
- throw new NullPointerException("container");
+
+ if ( container == null )
+ {
+ throw new NullPointerException( "container" );
}
this.remoteAddress = remoteAddress;
this.request = request;
this.container = container;
- this.session = container.getSessionAccessor().getSession(this, false);
+ this.session = container.getSessionAccessor().getSession( this, false
);
}
- public synchronized boolean isResponseCommitted() {
+
+ public synchronized boolean isResponseCommitted()
+ {
return committedResponse != null;
}
+
/**
* Commits a <code>HttpResponse</code> to this <code>Request</code>.
*
* @param response The response to commit
* @return <code>true</code> iff the response was committed
*/
- public boolean commitResponse(HttpResponse response) {
- synchronized (this) {
- if (isResponseCommitted()) {
- if (log.isDebugEnabled()) {
- log
- .info("Request already comitted to a response.
Disposing response");
- }
+ public boolean commitResponse( HttpResponse response )
+ {
+ synchronized ( this )
+ {
+ if ( isResponseCommitted() )
+ {
+ log.info( "Request already comitted to a response. Disposing
response" );
return false;
}
@@ -99,83 +115,98 @@
}
// Add the session identifier if the session was newly created.
- if (createdSession) {
- container.getSessionAccessor().addSessionIdentifier(this,
- (MutableHttpResponse) response);
+ if ( createdSession )
+ {
+ container.getSessionAccessor().addSessionIdentifier( this, (
MutableHttpResponse ) response );
}
// Only parsed requests can be formatted.
- if (getRequest().getMethod() != null) {
- container.getErrorResponseFormatter().formatResponse(getRequest(),
- (MutableHttpResponse) response);
+ if ( getRequest().getMethod() != null )
+ {
+ container.getErrorResponseFormatter().formatResponse(
getRequest(), ( MutableHttpResponse ) response );
}
- if (container.isSendServerHeader()) {
- ((MutableHttpResponse) response).setHeader(
- HttpHeaderConstants.KEY_SERVER, "AsyncWeb");
+ if ( container.isSendServerHeader() )
+ {
+ ( ( MutableHttpResponse ) response ).setHeader(
HttpHeaderConstants.KEY_SERVER, "AsyncWeb" );
}
// Normalize the response.
- ((MutableHttpResponse) response).normalize(getRequest());
+ ( ( MutableHttpResponse ) response ).normalize( getRequest() );
// Override connection header if needed.
- if (!container.getKeepAliveStrategy().keepAlive(this, response)) {
- ((MutableHttpResponse) response).setHeader(
- HttpHeaderConstants.KEY_CONNECTION,
- HttpHeaderConstants.VALUE_CLOSE);
+ if ( ! container.getKeepAliveStrategy().keepAlive( this, response ) )
+ {
+ ( ( MutableHttpResponse ) response ).setHeader(
HttpHeaderConstants.KEY_CONNECTION,
+ HttpHeaderConstants.VALUE_CLOSE );
}
- boolean requiresClosure = !HttpHeaderConstants.VALUE_KEEP_ALIVE
- .equalsIgnoreCase(response
- .getHeader(HttpHeaderConstants.KEY_CONNECTION));
+ boolean requiresClosure = ! HttpHeaderConstants.VALUE_KEEP_ALIVE
+ .equalsIgnoreCase(
response.getHeader(HttpHeaderConstants.KEY_CONNECTION ) );
- if (requiresClosure && log.isDebugEnabled()) {
+ if ( requiresClosure && log.isDebugEnabled() )
+ {
log.debug("Response status: " + response.getStatus());
log.debug("Keep-alive strategy requires closure of "
+ getRemoteAddress());
}
- if (log.isDebugEnabled()) {
- log.debug("Committing a response:");
- log.debug("Status: " + response.getStatus() + ' '
- + response.getStatusReasonPhrase());
- log.debug("Headers: " + response.getHeaders());
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "Committing a response:" );
+ log.debug( "Status: " + response.getStatus() + ' ' +
response.getStatusReasonPhrase() );
+ log.debug( "Headers: " + response.getHeaders() );
}
- doWrite(requiresClosure);
-
+ doWrite( requiresClosure );
return true;
}
- public boolean commitResponse(HttpResponseStatus status) {
+
+ public boolean commitResponse( HttpResponseStatus status )
+ {
MutableHttpResponse response = new DefaultHttpResponse();
- response.setStatus(status);
- return commitResponse(response);
+ response.setStatus( status );
+ return commitResponse( response );
}
- public synchronized HttpResponse getCommittedResponse() {
+
+ public synchronized HttpResponse getCommittedResponse()
+ {
return committedResponse;
}
- public InetSocketAddress getRemoteAddress() {
+
+ public InetSocketAddress getRemoteAddress()
+ {
return remoteAddress;
}
- public HttpRequest getRequest() {
+
+ public HttpRequest getRequest()
+ {
return request;
}
- public HttpSession getSession() {
- return getSession(true);
+
+ public HttpSession getSession()
+ {
+ return getSession( true );
}
- public synchronized HttpSession getSession(boolean create) {
- if (session != null && !session.isValid()) {
+
+ public synchronized HttpSession getSession( boolean create )
+ {
+ if ( session != null && ! session.isValid() )
+ {
session = null;
}
- if (session == null) {
- session = container.getSessionAccessor().getSession(this, create);
- if (create) {
+
+ if ( session == null )
+ {
+ session = container.getSessionAccessor().getSession( this, create
);
+ if ( create )
+ {
createdSession = true;
}
}
@@ -183,5 +214,50 @@
return session;
}
- protected abstract void doWrite(boolean requiresClosure);
+
+ protected void fireClientDisconnected()
+ {
+ ArrayList<HttpClientListener> cloned;
+ synchronized( listeners )
+ {
+ //noinspection unchecked
+ cloned = ( ArrayList<HttpClientListener> ) listeners.clone();
+ }
+
+ for ( HttpClientListener listener : cloned )
+ {
+ listener.clientDisconnected( this );
+ }
+ }
+
+
+ protected void fireClientIdle( long idleTime, int idleCount )
+ {
+ ArrayList<HttpClientListener> cloned;
+ synchronized( listeners )
+ {
+ //noinspection unchecked
+ cloned = ( ArrayList<HttpClientListener> ) listeners.clone();
+ }
+
+ for ( HttpClientListener listener : cloned )
+ {
+ listener.clientIdle( this, idleTime, idleCount );
+ }
+ }
+
+
+ public boolean addClientListener( HttpClientListener listener )
+ {
+ return listeners.add( listener );
+ }
+
+
+ public boolean removeClientListener( HttpClientListener listener )
+ {
+ return listeners != null && listeners.remove( listener );
+ }
+
+
+ protected abstract void doWrite( boolean requiresClosure );
}
Modified:
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/DefaultHttpIoHandler.java
URL:
http://svn.apache.org/viewvc/mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/DefaultHttpIoHandler.java?rev=615699&r1=615698&r2=615699&view=diff
==============================================================================
---
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/DefaultHttpIoHandler.java
(original)
+++
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/DefaultHttpIoHandler.java
Sun Jan 27 18:03:44 2008
@@ -35,6 +35,10 @@
*/
public class DefaultHttpIoHandler extends SingleSessionIoHandlerDelegate
implements HttpIoHandler
{
+ /** the default idle time in seconds - 5 minutes */
+ public static final int DEFAULT_IDLE_TIME = 300;
+
+
public DefaultHttpIoHandler()
{
super( new Factory() );
@@ -53,9 +57,16 @@
}
+ public void setReadIdle( int idleTime )
+ {
+ ( ( Factory ) getFactory() ).setReadIdle( idleTime );
+ }
+
+
private static class Factory implements SingleSessionIoHandlerFactory
{
private ServiceContainer container;
+ private int readIdleTime = DEFAULT_IDLE_TIME;
public ServiceContainer getContainer()
{
@@ -67,9 +78,17 @@
this.container = container;
}
+ public void setReadIdle( int idleTime )
+ {
+ this.readIdleTime = idleTime;
+ }
+
+
public SingleSessionIoHandler getHandler( IoSession session )
{
- return new SingleHttpSessionIoHandler( container, session );
+ SingleHttpSessionIoHandler handler = new
SingleHttpSessionIoHandler( container, session );
+ handler.setReadIdleTime( readIdleTime );
+ return handler;
}
}
}
Modified:
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/MinaTransport.java
URL:
http://svn.apache.org/viewvc/mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/MinaTransport.java?rev=615699&r1=615698&r2=615699&view=diff
==============================================================================
---
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/MinaTransport.java
(original)
+++
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/MinaTransport.java
Sun Jan 27 18:03:44 2008
@@ -46,14 +46,11 @@
*/
public class MinaTransport implements Transport
{
-
- private static final Logger LOG = LoggerFactory
- .getLogger(MinaTransport.class);
+ private static final Logger LOG = LoggerFactory.getLogger(
MinaTransport.class );
private static final int DEFAULT_PORT = 9012;
- private static final int DEFAULT_IO_THREADS = Runtime.getRuntime()
- .availableProcessors();
+ private static final int DEFAULT_IO_THREADS =
Runtime.getRuntime().availableProcessors();
private static final int DEFAULT_EVENT_THREADS = 16;
@@ -216,7 +213,7 @@
}
finally
{
- if ( !success )
+ if ( ! success )
{
acceptor.dispose();
acceptor = null;
Modified:
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/SingleHttpSessionIoHandler.java
URL:
http://svn.apache.org/viewvc/mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/SingleHttpSessionIoHandler.java?rev=615699&r1=615698&r2=615699&view=diff
==============================================================================
---
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/SingleHttpSessionIoHandler.java
(original)
+++
mina/asyncweb/trunk/server/src/main/java/org/apache/asyncweb/server/transport/mina/SingleHttpSessionIoHandler.java
Sun Jan 27 18:03:44 2008
@@ -52,6 +52,12 @@
import org.slf4j.LoggerFactory;
+/**
+ * The single session handler implementation.
+ *
+ * @author The Apache MINA Project ([EMAIL PROTECTED])
+ * @version $Rev$, $Date$
+ */
public class SingleHttpSessionIoHandler implements SingleSessionIoHandler
{
private static final Logger LOG = LoggerFactory.getLogger(
SingleHttpSessionIoHandler.class );
@@ -72,7 +78,7 @@
private final RequestPipeline pipeline;
/** the current context being processed */
- private HttpServiceContext currentContext;
+ private DefaultHttpServiceContext currentContext;
/** idle time for request reads */
private int readIdleTime = DEFAULT_IDLE_TIME;
@@ -112,6 +118,11 @@
public void sessionClosed()
{
LOG.info( "Connection closed" );
+
+ if ( currentContext != null )
+ {
+ currentContext.fireClientDisconnected();
+ }
}
@@ -129,8 +140,17 @@
// LOG.info("Read idled out while parsing request.
Scheduling timeout response");
// handleReadFailure(currentContext,
HttpResponseStatus.REQUEST_TIMEOUT, "Timeout while reading request");
// } else {
- LOG.info( "Idled with no current request. Scheduling closure when
pipeline empties" );
+ if ( currentContext != null )
+ {
+ if ( IdleStatus.BOTH_IDLE == idleType ||
IdleStatus.READER_IDLE == idleType )
+ {
+ currentContext.fireClientIdle(
session.getLastReaderIdleTime(), session.getReaderIdleCount() );
+ }
+ }
+
+ // TODO - look further into this - it may present serious issues
when dealing with HTTP/1.1
+ LOG.info( "Idled with no current request. Scheduling closure when
pipeline empties" );
pipeline.runWhenEmpty( new Runnable()
{
public void run()
@@ -249,10 +269,11 @@
public void setReadIdleTime( int readIdleTime )
{
this.readIdleTime = readIdleTime;
+ session.getConfig().setReaderIdleTime( readIdleTime );
}
- protected HttpServiceContext createContext( HttpRequest request )
+ protected DefaultHttpServiceContext createContext( HttpRequest request )
{
return new DefaultHttpServiceContext( request );
}
@@ -272,9 +293,8 @@
public void messageReceived( NextFilter nextFilter, IoSession session,
Object message ) throws Exception
{
HttpRequest request = ( HttpRequest ) message;
- HttpServiceContext context = createContext( request );
- currentContext = context;
- nextFilter.messageReceived( session, context );
+ currentContext = createContext( request );
+ nextFilter.messageReceived( session, currentContext );
}
}
@@ -405,6 +425,18 @@
LOG.debug( "Added CLOSE future listener." );
future.addListener( IoFutureListener.CLOSE );
}
+ }
+
+
+ public void fireClientIdle( long idleTime, int idleCount )
+ {
+ super.fireClientIdle( idleTime, idleCount );
+ }
+
+
+ public void fireClientDisconnected()
+ {
+ super.fireClientDisconnected();
}
}
}