JBossWeb SVN: r869 - in trunk: webapps/docs and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-11-28 11:17:45 -0500 (Fri, 28 Nov 2008)
New Revision: 869
Modified:
trunk/PATCHES.txt
trunk/ROADMAP.txt
trunk/webapps/docs/changelog.xml
Log:
- Update changelog.
Modified: trunk/PATCHES.txt
===================================================================
--- trunk/PATCHES.txt 2008-11-27 15:24:34 UTC (rev 868)
+++ trunk/PATCHES.txt 2008-11-28 16:17:45 UTC (rev 869)
@@ -1,22 +1,22 @@
Dropped Tomcat patches
SVN URL: http://svn.apache.org/viewvc?rev=XXXXXX&view=rev
-701358:
+701358
Some symlink fix (too many checks needed)
-701355:
+701355
XML parser in webapp fix (significant refactoring, partial)
-709821:
+709821
Endline configuration for PrintWriter based on a server system property
-709018:
+709018
Async logger is not ready
-710179:
+710179
Invoker servlet removal
-711711, 711714, 711716, 711720:
+711711 711714 711716 711720
Useless session access time refactoring
719602
Modified: trunk/ROADMAP.txt
===================================================================
--- trunk/ROADMAP.txt 2008-11-27 15:24:34 UTC (rev 868)
+++ trunk/ROADMAP.txt 2008-11-28 16:17:45 UTC (rev 869)
@@ -4,7 +4,7 @@
- Update digester XML parsing rules for web.xml updates
- Implement new APIs for programmatic deployment descriptor access
- Implement annotation scanning for JBoss Web standalone (likely disabled by default using conf/web.xml)
-- Implement any other Servlet 3.0 changes
+- Implement any other Servlet 3.0 changes (web.xml fragments, security, etc)
- Implement JSP 2.2 changes
- Implement Servlet 3.0 async for APR AJP connector
- Implement Servlet 3.0 async for java.io HTTP connector
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2008-11-27 15:24:34 UTC (rev 868)
+++ trunk/webapps/docs/changelog.xml 2008-11-28 16:17:45 UTC (rev 869)
@@ -48,6 +48,9 @@
<fix>
<bug>42077</bug>: In javax.el iterators, don't return null elements. Based on a patch by Mathias Broekelmann. (markt)
</fix>
+ <fix>
+ Possible NPE on shutdown of ClusterListener. (remm)
+ </fix>
</changelog>
</subsection>
</section>
16 years
JBossWeb SVN: r868 - trunk/java/org/jboss/web/cluster.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-11-27 10:24:34 -0500 (Thu, 27 Nov 2008)
New Revision: 868
Modified:
trunk/java/org/jboss/web/cluster/ClusterListener.java
Log:
- NO null checks anywhere, so better init value.
Modified: trunk/java/org/jboss/web/cluster/ClusterListener.java
===================================================================
--- trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-11-27 15:14:17 UTC (rev 867)
+++ trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-11-27 15:24:34 UTC (rev 868)
@@ -107,7 +107,7 @@
/**
* Proxies.
*/
- protected Proxy[] proxies = null;
+ protected Proxy[] proxies = new Proxy[0];
/**
16 years
JBossWeb SVN: r867 - trunk.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-11-27 10:14:17 -0500 (Thu, 27 Nov 2008)
New Revision: 867
Removed:
trunk/native/
Log:
- Right now, we're using straight tomcat-native, so remove it here.
16 years
JBossWeb SVN: r866 - trunk.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-11-27 08:35:13 -0500 (Thu, 27 Nov 2008)
New Revision: 866
Added:
trunk/ROADMAP.txt
Log:
- Since I'm bored, add a roadmap for JBW 3, that I'll detail more when I get the first real spec draft.
Added: trunk/ROADMAP.txt
===================================================================
--- trunk/ROADMAP.txt (rev 0)
+++ trunk/ROADMAP.txt 2008-11-27 13:35:13 UTC (rev 866)
@@ -0,0 +1,13 @@
+Roadmap for JBoss Web 3.0
+
+- Implement Servlet 3.0 async for APR HTTP connector
+- Update digester XML parsing rules for web.xml updates
+- Implement new APIs for programmatic deployment descriptor access
+- Implement annotation scanning for JBoss Web standalone (likely disabled by default using conf/web.xml)
+- Implement any other Servlet 3.0 changes
+- Implement JSP 2.2 changes
+- Implement Servlet 3.0 async for APR AJP connector
+- Implement Servlet 3.0 async for java.io HTTP connector
+- Implement Servlet 3.0 async for java.io AJP connector
+- Coordinate with AS 6 to implement new web.xml parsing (out of tree)
+- Coordinate with AS 6 for annotation updates (out of tree)
16 years
JBossWeb SVN: r865 - trunk.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-11-26 07:25:21 -0500 (Wed, 26 Nov 2008)
New Revision: 865
Modified:
trunk/PATCHES.txt
Log:
- Reject multiple pollers (I would be really surprised that this is actually a scalability issue, and JBW advanced event
stuff would require additional complexity).
Modified: trunk/PATCHES.txt
===================================================================
--- trunk/PATCHES.txt 2008-11-25 14:42:05 UTC (rev 864)
+++ trunk/PATCHES.txt 2008-11-26 12:25:21 UTC (rev 865)
@@ -22,3 +22,7 @@
719602
Dynamic change for maxThreads in the bare bones thread pool, which go against its simplicity goal
(an executor should be used instead)
+
+720728
+Multiple pollers, which adds the complexity of needing a map to track to which poller a connection belongs
+(needed in IO event mode). There are 3 pollers already, which should be able to handle a lot of traffic.
16 years
JBossWeb SVN: r864 - trunk/webapps/docs.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-11-25 09:42:05 -0500 (Tue, 25 Nov 2008)
New Revision: 864
Modified:
trunk/webapps/docs/aio.xml
Log:
- Add some bold otherwise it was not very readable.
Modified: trunk/webapps/docs/aio.xml
===================================================================
--- trunk/webapps/docs/aio.xml 2008-11-25 14:34:35 UTC (rev 863)
+++ trunk/webapps/docs/aio.xml 2008-11-25 14:42:05 UTC (rev 864)
@@ -22,7 +22,7 @@
</p>
<p>
- <b>IMPORTANT NOTE: Usage of these features requires using the APR connector.
+ <b>IMPORTANT NOTE: Usage of these features requires using the APR HTTP connector.
The classic java.io HTTP connector and the AJP connectors
do not support them.</b>
</p>
@@ -52,7 +52,7 @@
</p>
<ul>
- <li>EventType.BEGIN - will be called at the beginning
+ <li>EventType.<b>BEGIN</b> - will be called at the beginning
of the processing of the connection. It can be used to initialize any relevant
fields using the request and response objects. Between the end of the processing
of this event, and the beginning of the processing of the end or error events,
@@ -61,7 +61,7 @@
not synchronized, so when they are accessed by multiple threads adequate
synchronization is needed. After processing the initial event, the request
is considered to be committed.</li>
- <li>EventType.READ - This indicates that input data is available, and that at least one
+ <li>EventType.<b>READ</b> - This indicates that input data is available, and that at least one
read call can be made without blocking. The available and ready methods of the InputStream and
Reader may be used to determine if there is a risk of blocking: the servlet
must continue reading while data is reported available. When encountering a read error,
@@ -73,35 +73,35 @@
of the event. It is not allowed to attempt reading data from the request
outside of the event method scope.
</li>
- <li>EventType.END - End may be called to end the processing of the request. Fields that have
+ <li>EventType.<b>END</b> - End may be called to end the processing of the request. Fields that have
been initialized in the begin method should be reset. After this event has
been processed, the request and response objects, as well as all their dependent
objects will be recycled and used to process other requests. In particular,
this event will be called if the HTTP session associated with the connection
times out, if the web application is reloaded, if the server is shutdown, or
if the connection was closed asynchronously.</li>
- <li>EventType.EOF - The end of file of the input has been reached, and no further data is
+ <li>EventType.<b>EOF</b> - The end of file of the input has been reached, and no further data is
available. This event is sent because it can be difficult to detect otherwise, for
example when chunked transfer encoding is being used.
Following the processing of this event and the processing of any subsequent
event, the event will be automatically suspended, as and no additional read events
will be sent.</li>
- <li>EventType.ERROR - Error will be called by the container in the case where an IO exception
+ <li>EventType.<b>ERROR</b> - Error will be called by the container in the case where an IO exception
or a similar unrecoverable error occurs, or if the Servlet has thrown an exception during
the invocation of the event method. Fields that have
been initialized in the begin method should be reset (similar to what should be done
when the END event is received). After this event has
been processed, the request and response objects, as well as all their dependent
objects will be recycled and used to process other requests.</li>
- <li>EventType.TIMEOUT - The connection timed out according to the timeout value which has been
+ <li>EventType.<b>TIMEOUT</b> - The connection timed out according to the timeout value which has been
set (the default value is the timeout value of the connector), but the connection will not be closed unless
the servlet uses the close method of the event. The timeout is calculated from the last event sent
to the Servlet, any asynchronous writes are not monitored. Depending on the situation, the handling of the
event could change.</li>
- <li>EventType.EVENT - Event will be called by the container after the resume() method is called,
+ <li>EventType.<b>EVENT</b> - Event will be called by the container after the resume() method is called,
during which any operation can be performed, including closing the connection
using the close() method.</li>
- <li>EventType.WRITE - Write is sent if the servlet is using the isWriteReady method. This means that
+ <li>EventType.<b>WRITE</b> - Write is sent if the servlet is using the isWriteReady method. This means that
the connection is ready to receive data to be written out without blocking. This event will never
be received if the servlet is not using the isWriteReady method, or if the isWriteReady
method always returns true.</li>
@@ -114,13 +114,13 @@
</p>
<p>
- The close() method ends the request, which marks the end of the processing. This will send
+ The <b>close()</b> method ends the request, which marks the end of the processing. This will send
back to the client a notice that the server has no more data to send
as part of this request. An END event will be sent to the servlet.
</p>
<p>
- The setTimeout() method sets the timeout in milliseconds of idle time on the connection.
+ The <b>setTimeout()</b> method sets the timeout in milliseconds of idle time on the connection.
A timeout occurs if the amount of time since the last event processed by the Servlet is greater
than the timeout value. If a timeout occurs, the Servlet will receive an TIMEOUT event which
will not result in automatically closing the event (the event may be closed using the close() method
@@ -128,14 +128,14 @@
</p>
<p>
- The isReadReady() method returns true when data may be read from the connection (the flag becomes false if no data
+ The <b>isReadReady()</b> method returns true when data may be read from the connection (the flag becomes false if no data
is available to read). When the flag becomes false, the Servlet can attempt to read additional
data, but it will block until data is available. This method is equivalent to
Reader.ready() and (InputStream.available() > 0).
</p>
<p>
- The isWriteReady() method returns true when data may be written to the connection without
+ The <b>isWriteReady()</b> method returns true when data may be written to the connection without
blocking (the flag becomes false
when the client is unable to accept data fast enough). When the flag becomes false,
the servlet must stop writing data. If there's an attempt to flush additional data
@@ -154,14 +154,14 @@
</p>
<p>
- The suspend() method suspends processing of the connection until the configured timeout occurs,
+ The <b>suspend()</b> method suspends processing of the connection until the configured timeout occurs,
or resume() is called. In practice, this means the servlet will no longer
receive read events. Reading should always be performed synchronously in
the container threads unless the connection has been suspended.
</p>
<p>
- The resume() method will cause the servlet container to send a generic event
+ The <b>resume()</b> method will cause the servlet container to send a generic event
to the servlet, where the request can be processed synchronously
(for example, it is possible to use this to complete the request after
some asynchronous processing is done). This also resumes read events
16 years
JBossWeb SVN: r863 - trunk/webapps/docs.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-11-25 09:34:35 -0500 (Tue, 25 Nov 2008)
New Revision: 863
Modified:
trunk/webapps/docs/aio.xml
Log:
- Expand and clarify.
Modified: trunk/webapps/docs/aio.xml
===================================================================
--- trunk/webapps/docs/aio.xml 2008-11-24 18:13:18 UTC (rev 862)
+++ trunk/webapps/docs/aio.xml 2008-11-25 14:34:35 UTC (rev 863)
@@ -44,10 +44,9 @@
<p>
Servlets which implement the <code>org.jboss.servlet.http.HttpEventServlet</code>
interface will have their event method invoked rather than the usual service
- method, according to the event which occurred. The event object gives
- access to the usual request and response objects, which may be used in the
- usual way. The main difference is that those objects remain valid and fully
- functional at any time between processing of the BEGIN event until processing
+ method. The event type field indicates the event which occurred. The event object gives
+ access to the usual request and response objects. The main difference is that those objects
+ remain valid and fully functional at any time between processing of the BEGIN event until processing
an END or ERROR event, so that asynchronous operations are possible.
The following event types exist:
</p>
@@ -63,7 +62,7 @@
synchronization is needed. After processing the initial event, the request
is considered to be committed.</li>
<li>EventType.READ - This indicates that input data is available, and that at least one
- read can be made without blocking. The available and ready methods of the InputStream or
+ read call can be made without blocking. The available and ready methods of the InputStream and
Reader may be used to determine if there is a risk of blocking: the servlet
must continue reading while data is reported available. When encountering a read error,
the servlet should report it by propagating the exception properly. Throwing
@@ -72,8 +71,7 @@
Alternately, it is also possible to catch any exception, perform clean up
on any data structure the servlet may be using, and using the close method
of the event. It is not allowed to attempt reading data from the request
- object outside of the processing of this event, unless the suspend() method
- has been used.
+ outside of the event method scope.
</li>
<li>EventType.END - End may be called to end the processing of the request. Fields that have
been initialized in the begin method should be reset. After this event has
@@ -83,28 +81,35 @@
times out, if the web application is reloaded, if the server is shutdown, or
if the connection was closed asynchronously.</li>
<li>EventType.EOF - The end of file of the input has been reached, and no further data is
- available. This event is sent because it can be difficult to detect otherwise.
+ available. This event is sent because it can be difficult to detect otherwise, for
+ example when chunked transfer encoding is being used.
Following the processing of this event and the processing of any subsequent
- event, the event will be automatically suspended.</li>
+ event, the event will be automatically suspended, as and no additional read events
+ will be sent.</li>
<li>EventType.ERROR - Error will be called by the container in the case where an IO exception
- or a similar unrecoverable error occurs on the connection. Fields that have
- been initialized in the begin method should be reset. After this event has
+ or a similar unrecoverable error occurs, or if the Servlet has thrown an exception during
+ the invocation of the event method. Fields that have
+ been initialized in the begin method should be reset (similar to what should be done
+ when the END event is received). After this event has
been processed, the request and response objects, as well as all their dependent
objects will be recycled and used to process other requests.</li>
- <li>EventType.TIMEOUT - the connection timed out, but the connection will not be closed unless
- the servlet uses the close method of the event</li>
+ <li>EventType.TIMEOUT - The connection timed out according to the timeout value which has been
+ set (the default value is the timeout value of the connector), but the connection will not be closed unless
+ the servlet uses the close method of the event. The timeout is calculated from the last event sent
+ to the Servlet, any asynchronous writes are not monitored. Depending on the situation, the handling of the
+ event could change.</li>
<li>EventType.EVENT - Event will be called by the container after the resume() method is called,
- during which any operations can be performed, including closing the connection
+ during which any operation can be performed, including closing the connection
using the close() method.</li>
- <li>EventType.WRITE - Write is sent if the servlet is using the ready method. This means that
- the connection is ready to receive data to be written out. This event will never
- be received if the servlet is not using the ready() method, or if the ready()
+ <li>EventType.WRITE - Write is sent if the servlet is using the isWriteReady method. This means that
+ the connection is ready to receive data to be written out without blocking. This event will never
+ be received if the servlet is not using the isWriteReady method, or if the isWriteReady
method always returns true.</li>
</ul>
<p>
As described above, the typical lifecycle of a request will consist in a series of
- events such as: BEGIN -> READ -> READ -> READ -> TIMEOUT. At any time, the servlet
+ events such as: BEGIN -> READ -> READ -> READ -> TIMEOUT -> END. At any time, the servlet
may end processing of the request by using the close method of the event object.
</p>
@@ -116,9 +121,10 @@
<p>
The setTimeout() method sets the timeout in milliseconds of idle time on the connection.
- The timeout is reset every time data is received from the connection. If a timeout occurs, the
- servlet will receive an TIMEOUT event which will not result in automatically closing
- the event (the event may be closed using the close() method).
+ A timeout occurs if the amount of time since the last event processed by the Servlet is greater
+ than the timeout value. If a timeout occurs, the Servlet will receive an TIMEOUT event which
+ will not result in automatically closing the event (the event may be closed using the close() method
+ as usual).
</p>
<p>
@@ -126,11 +132,11 @@
is available to read). When the flag becomes false, the Servlet can attempt to read additional
data, but it will block until data is available. This method is equivalent to
Reader.ready() and (InputStream.available() > 0).
-
</p>
<p>
- The isWriteReady() method returns true when data may be written to the connection (the flag becomes false
+ The isWriteReady() method returns true when data may be written to the connection without
+ blocking (the flag becomes false
when the client is unable to accept data fast enough). When the flag becomes false,
the servlet must stop writing data. If there's an attempt to flush additional data
to the client and data still cannot be written immediately, an IOException will be
@@ -140,6 +146,11 @@
Note: If the servlet is not using ready, and is writing its output inside the
container threads, using this method is not mandatory, but any incomplete writes will be
performed again in blocking mode.
+ Note 2: When using the flag to perform non blocking writes, the Servlet should not be using
+ large buffers, and should rather rely more on the buffering done inside the OutputStream and
+ Writer objects provided through the Servlet API. In particular, a converted char array written
+ through the Writer should be able to fit inside the byte buffer internally used for the
+ Servlet output (which is 8 KB), and can be configured on the ServletResponse object if needed.
</p>
<p>
16 years
JBossWeb SVN: r862 - trunk/webapps/docs.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-11-24 13:13:18 -0500 (Mon, 24 Nov 2008)
New Revision: 862
Modified:
trunk/webapps/docs/aio.xml
Log:
- Expand on the docs, covering the thread model since I actually fixed it in 2.1.1.
Modified: trunk/webapps/docs/aio.xml
===================================================================
--- trunk/webapps/docs/aio.xml 2008-11-24 13:34:13 UTC (rev 861)
+++ trunk/webapps/docs/aio.xml 2008-11-24 18:13:18 UTC (rev 862)
@@ -29,16 +29,16 @@
</section>
- <section name="Comet support">
+ <section name="Event driven Servlets">
<p>
- Comet support allows a servlet to process IO asynchronously, receiving
+ This API allows writing Servlets which can process IO asynchronously, receiving
events when data is available for reading on the connection (rather than
always using a blocking read), and writing data back on connections
- asynchronously (most likely responding to some event raised from some
+ asynchronously without blocking (most likely responding to some event raised from some
other source).
</p>
-
+
<subsection name="HttpEvent">
<p>
@@ -48,7 +48,7 @@
access to the usual request and response objects, which may be used in the
usual way. The main difference is that those objects remain valid and fully
functional at any time between processing of the BEGIN event until processing
- an END or ERROR event.
+ an END or ERROR event, so that asynchronous operations are possible.
The following event types exist:
</p>
@@ -146,7 +146,7 @@
The suspend() method suspends processing of the connection until the configured timeout occurs,
or resume() is called. In practice, this means the servlet will no longer
receive read events. Reading should always be performed synchronously in
- the contaner threads unless the connection has been suspended.
+ the container threads unless the connection has been suspended.
</p>
<p>
@@ -158,6 +158,17 @@
again later. It is also possible to call resume without calling suspend before.
</p>
+ <p>
+ The Servlet container will never, under any circumstance, invoke the event method of a Servlet
+ with an event pertaining to a particular connection concurrently. For example, if
+ a READ event is being processed, and some asynchronous thread closes the event using event.close(),
+ an END event will only be called after the Servlet has completed processing of the READ event.
+ However, the application must still synchronize any concurrent access it makes to an event or any
+ objects provided by the Servlet API. The event object remains allocated for the entire duration
+ of the connection, and can safely be used for synchronization purposes. For example, two possibly
+ concurrent writes done on the same connection should likely synchronize on the event object.
+ </p>
+
</subsection>
<subsection name="HttpEventFilter">
@@ -326,6 +337,15 @@
</section>
+ <section name="Tomcat Bayeux API">
+
+ <p>
+ JBoss Web supports the Apache Tomcat Bayeux API which provides a ready to use
+ toolkit for building simple Comet enabled web applications.
+ </p>
+
+ </section>
+
<section name="Asynchronous writes">
<p>
16 years, 1 month
JBossWeb SVN: r861 - in trunk: java/javax/el and 2 other directories.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-11-24 08:34:13 -0500 (Mon, 24 Nov 2008)
New Revision: 861
Modified:
trunk/PATCHES.txt
trunk/java/javax/el/CompositeELResolver.java
trunk/java/org/apache/catalina/core/StandardThreadExecutor.java
trunk/webapps/docs/changelog.xml
Log:
- Port two patches.
- Add dynamic config for the default executor.
Modified: trunk/PATCHES.txt
===================================================================
--- trunk/PATCHES.txt 2008-11-20 18:37:18 UTC (rev 860)
+++ trunk/PATCHES.txt 2008-11-24 13:34:13 UTC (rev 861)
@@ -18,3 +18,7 @@
711711, 711714, 711716, 711720:
Useless session access time refactoring
+
+719602
+Dynamic change for maxThreads in the bare bones thread pool, which go against its simplicity goal
+(an executor should be used instead)
Modified: trunk/java/javax/el/CompositeELResolver.java
===================================================================
--- trunk/java/javax/el/CompositeELResolver.java 2008-11-20 18:37:18 UTC (rev 860)
+++ trunk/java/javax/el/CompositeELResolver.java 2008-11-24 13:34:13 UTC (rev 861)
@@ -19,158 +19,169 @@
import java.beans.FeatureDescriptor;
import java.util.Iterator;
+import java.util.NoSuchElementException;
public class CompositeELResolver extends ELResolver {
- private int size;
+ private int size;
- private ELResolver[] resolvers;
+ private ELResolver[] resolvers;
- public CompositeELResolver() {
- this.size = 0;
- this.resolvers = new ELResolver[2];
- }
+ public CompositeELResolver() {
+ this.size = 0;
+ this.resolvers = new ELResolver[2];
+ }
- public void add(ELResolver elResolver) {
- if (elResolver == null) {
- throw new NullPointerException();
- }
+ public void add(ELResolver elResolver) {
+ if (elResolver == null) {
+ throw new NullPointerException();
+ }
- if (this.size >= this.resolvers.length) {
- ELResolver[] nr = new ELResolver[this.size * 2];
- System.arraycopy(this.resolvers, 0, nr, 0, this.size);
- this.resolvers = nr;
- }
- this.resolvers[this.size++] = elResolver;
- }
+ if (this.size >= this.resolvers.length) {
+ ELResolver[] nr = new ELResolver[this.size * 2];
+ System.arraycopy(this.resolvers, 0, nr, 0, this.size);
+ this.resolvers = nr;
+ }
+ this.resolvers[this.size++] = elResolver;
+ }
- public Object getValue(ELContext context, Object base, Object property)
- throws NullPointerException, PropertyNotFoundException, ELException {
- context.setPropertyResolved(false);
- int sz = this.size;
- Object result = null;
- for (int i = 0; i < sz; i++) {
- result = this.resolvers[i].getValue(context, base, property);
- if (context.isPropertyResolved()) {
- return result;
- }
- }
- return null;
- }
+ public Object getValue(ELContext context, Object base, Object property)
+ throws NullPointerException, PropertyNotFoundException, ELException {
+ context.setPropertyResolved(false);
+ int sz = this.size;
+ Object result = null;
+ for (int i = 0; i < sz; i++) {
+ result = this.resolvers[i].getValue(context, base, property);
+ if (context.isPropertyResolved()) {
+ return result;
+ }
+ }
+ return null;
+ }
- public void setValue(ELContext context, Object base, Object property,
- Object value) throws NullPointerException,
- PropertyNotFoundException, PropertyNotWritableException,
- ELException {
- context.setPropertyResolved(false);
- int sz = this.size;
- for (int i = 0; i < sz; i++) {
- this.resolvers[i].setValue(context, base, property, value);
- if (context.isPropertyResolved()) {
- return;
- }
- }
- }
+ public void setValue(ELContext context, Object base, Object property,
+ Object value) throws NullPointerException,
+ PropertyNotFoundException, PropertyNotWritableException,
+ ELException {
+ context.setPropertyResolved(false);
+ int sz = this.size;
+ for (int i = 0; i < sz; i++) {
+ this.resolvers[i].setValue(context, base, property, value);
+ if (context.isPropertyResolved()) {
+ return;
+ }
+ }
+ }
- public boolean isReadOnly(ELContext context, Object base, Object property)
- throws NullPointerException, PropertyNotFoundException, ELException {
- context.setPropertyResolved(false);
- int sz = this.size;
- boolean readOnly = false;
- for (int i = 0; i < sz; i++) {
- readOnly = this.resolvers[i].isReadOnly(context, base, property);
- if (context.isPropertyResolved()) {
- return readOnly;
- }
- }
- return false;
- }
+ public boolean isReadOnly(ELContext context, Object base, Object property)
+ throws NullPointerException, PropertyNotFoundException, ELException {
+ context.setPropertyResolved(false);
+ int sz = this.size;
+ boolean readOnly = false;
+ for (int i = 0; i < sz; i++) {
+ readOnly = this.resolvers[i].isReadOnly(context, base, property);
+ if (context.isPropertyResolved()) {
+ return readOnly;
+ }
+ }
+ return false;
+ }
- public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
- return new FeatureIterator(context, base, this.resolvers, this.size);
- }
+ public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
+ return new FeatureIterator(context, base, this.resolvers, this.size);
+ }
- public Class<?> getCommonPropertyType(ELContext context, Object base) {
- int sz = this.size;
- Class<?> commonType = null, type = null;
- for (int i = 0; i < sz; i++) {
- type = this.resolvers[i].getCommonPropertyType(context, base);
- if (type != null
- && (commonType == null || commonType.isAssignableFrom(type))) {
- commonType = type;
- }
- }
- return commonType;
- }
+ public Class<?> getCommonPropertyType(ELContext context, Object base) {
+ int sz = this.size;
+ Class<?> commonType = null, type = null;
+ for (int i = 0; i < sz; i++) {
+ type = this.resolvers[i].getCommonPropertyType(context, base);
+ if (type != null
+ && (commonType == null || commonType.isAssignableFrom(type))) {
+ commonType = type;
+ }
+ }
+ return commonType;
+ }
- public Class<?> getType(ELContext context, Object base, Object property)
- throws NullPointerException, PropertyNotFoundException, ELException {
- context.setPropertyResolved(false);
- int sz = this.size;
- Class<?> type;
- for (int i = 0; i < sz; i++) {
- type = this.resolvers[i].getType(context, base, property);
- if (context.isPropertyResolved()) {
- return type;
- }
- }
- return null;
- }
+ public Class<?> getType(ELContext context, Object base, Object property)
+ throws NullPointerException, PropertyNotFoundException, ELException {
+ context.setPropertyResolved(false);
+ int sz = this.size;
+ Class<?> type;
+ for (int i = 0; i < sz; i++) {
+ type = this.resolvers[i].getType(context, base, property);
+ if (context.isPropertyResolved()) {
+ return type;
+ }
+ }
+ return null;
+ }
- private final static class FeatureIterator implements Iterator<FeatureDescriptor> {
+ private final static class FeatureIterator implements Iterator<FeatureDescriptor> {
- private final ELContext context;
+ private final ELContext context;
- private final Object base;
+ private final Object base;
- private final ELResolver[] resolvers;
+ private final ELResolver[] resolvers;
- private final int size;
+ private final int size;
- private Iterator itr;
+ private Iterator<FeatureDescriptor> itr;
- private int idx;
+ private int idx;
- public FeatureIterator(ELContext context, Object base,
- ELResolver[] resolvers, int size) {
- this.context = context;
- this.base = base;
- this.resolvers = resolvers;
- this.size = size;
+ private FeatureDescriptor next;
- this.idx = 0;
- this.guaranteeIterator();
- }
-
- private void guaranteeIterator() {
- while (this.itr == null && this.idx < this.size) {
- this.itr = this.resolvers[this.idx].getFeatureDescriptors(
- this.context, this.base);
- this.idx++;
- }
- }
+ public FeatureIterator(ELContext context, Object base,
+ ELResolver[] resolvers, int size) {
+ this.context = context;
+ this.base = base;
+ this.resolvers = resolvers;
+ this.size = size;
- public boolean hasNext() {
- return this.itr != null;
- }
+ this.idx = 0;
+ this.guaranteeIterator();
+ }
+
+ private void guaranteeIterator() {
+ while (this.itr == null && this.idx < this.size) {
+ this.itr = this.resolvers[this.idx].getFeatureDescriptors(
+ this.context, this.base);
+ this.idx++;
+ }
+ }
- public FeatureDescriptor next() {
- Object result = null;
- if (this.itr != null) {
- if (this.itr.hasNext()) {
- result = this.itr.next();
- if (!this.itr.hasNext()) {
- this.itr = null;
- this.guaranteeIterator();
- }
- }
- }
- return (FeatureDescriptor) result;
- }
+ public boolean hasNext() {
+ if (this.next != null)
+ return true;
+ if (this.itr != null){
+ while (this.next == null && itr.hasNext()) {
+ this.next = itr.next();
+ }
+ } else {
+ return false;
+ }
+ if (this.next == null) {
+ this.itr = null;
+ this.guaranteeIterator();
+ }
+ return hasNext();
+ }
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
+ public FeatureDescriptor next() {
+ if (!hasNext())
+ throw new NoSuchElementException();
+ FeatureDescriptor next = this.next;
+ this.next = null;
+ return next;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
}
Modified: trunk/java/org/apache/catalina/core/StandardThreadExecutor.java
===================================================================
--- trunk/java/org/apache/catalina/core/StandardThreadExecutor.java 2008-11-20 18:37:18 UTC (rev 860)
+++ trunk/java/org/apache/catalina/core/StandardThreadExecutor.java 2008-11-24 13:34:13 UTC (rev 861)
@@ -130,14 +130,23 @@
public void setMaxIdleTime(int maxIdleTime) {
this.maxIdleTime = maxIdleTime;
+ if (executor != null) {
+ executor.setKeepAliveTime(maxIdleTime, TimeUnit.MILLISECONDS);
+ }
}
public void setMaxThreads(int maxThreads) {
this.maxThreads = maxThreads;
+ if (executor != null) {
+ executor.setMaximumPoolSize(maxThreads);
+ }
}
public void setMinSpareThreads(int minSpareThreads) {
this.minSpareThreads = minSpareThreads;
+ if (executor != null) {
+ executor.setCorePoolSize(minSpareThreads);
+ }
}
public void setName(String name) {
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2008-11-20 18:37:18 UTC (rev 860)
+++ trunk/webapps/docs/changelog.xml 2008-11-24 13:34:13 UTC (rev 861)
@@ -42,6 +42,12 @@
<fix>
Create configBase also when dealing with directory deployment. (markt)
</fix>
+ <fix>
+ Pass attribute changes to the executor to allow dynamic configuration. (markt)
+ </fix>
+ <fix>
+ <bug>42077</bug>: In javax.el iterators, don't return null elements. Based on a patch by Mathias Broekelmann. (markt)
+ </fix>
</changelog>
</subsection>
</section>
16 years, 1 month
JBossWeb SVN: r860 - trunk/java/org/apache/tomcat/bayeux.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-11-20 13:37:18 -0500 (Thu, 20 Nov 2008)
New Revision: 860
Modified:
trunk/java/org/apache/tomcat/bayeux/ClientImpl.java
trunk/java/org/apache/tomcat/bayeux/RequestBase.java
Log:
- Simplify the client code.
- I don't see how multiple events can be associated with a single client. Maybe I missed something and will revert.
- Publishing messages to a client should be synced (multiple channels could publish to a client), but I also don't
see any other syncs being needed (given the thread model used by events after all the fixes).
Modified: trunk/java/org/apache/tomcat/bayeux/ClientImpl.java
===================================================================
--- trunk/java/org/apache/tomcat/bayeux/ClientImpl.java 2008-11-18 16:30:54 UTC (rev 859)
+++ trunk/java/org/apache/tomcat/bayeux/ClientImpl.java 2008-11-20 18:37:18 UTC (rev 860)
@@ -16,6 +16,7 @@
*/
package org.apache.tomcat.bayeux;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@@ -49,9 +50,9 @@
protected LinkedList<Message> messages = null;
/**
- *
+ * Currently associated event.
*/
- protected Queue<HttpEvent> events = new LinkedList<HttpEvent>();
+ protected HttpEvent event;
/**
* Unique id representing this client
@@ -91,21 +92,20 @@
if (!local) messages = new LinkedList<Message>();
}
- protected ClientImpl(String id, HttpEvent event) {
+/* protected ClientImpl(String id, HttpEvent event) {
this(id,false);
- events = new ConcurrentLinkedQueue<HttpEvent>();
addCometEvent(event);
- }
+ }*/
- public synchronized void deliver(Message message) {
+ public void deliver(Message message) {
deliverInternal(null,new MessageImpl[] {(MessageImpl)message});
}
- public synchronized void deliver(Message[] message) {
+ public void deliver(Message[] message) {
deliverInternal(null,message);
}
- protected synchronized void deliverInternal(ChannelImpl channel, MessageImpl message) {
+ protected void deliverInternal(ChannelImpl channel, MessageImpl message) {
deliverInternal(channel,new MessageImpl[] {message});
}
@@ -130,36 +130,32 @@
//we are not implementing forever responses, if the client is connected
//then we will fire off the message
//first we check to see if we have any existing connections we can piggy back on
- HttpEvent event = events.poll();
boolean delivered = false;
- //TODO TODO - check on thread safety, for writing and for getting last request.
if (event!=null) {
- synchronized (event) {
- RequestBase rq = (RequestBase)event.getHttpServletRequest().getAttribute(RequestBase.LAST_REQ_ATTR);
- if (rq!=null) {
- Map map = new HashMap();
- try {
- map.put(Bayeux.CHANNEL_FIELD,message.getChannel().getId());
- map.put(Bayeux.DATA_FIELD,message);
- JSONObject json = new JSONObject(map);
- if (log.isTraceEnabled()) {
- log.trace("Message instantly delivered to remote client["+this+"] message:"+json);
- }
- rq.addToDeliveryQueue(this, json);
- //deliver the batch
- if (i==(msgs.length-1)) {
- rq.deliver(event, this);
- event.close(); //todo, figure out a better way, this means only one message gets delivered
- removeCometEvent(event); //and delivered instantly
- }
- delivered = true;
- } catch (Exception e) {
- // TODO: fix
- log.warn("Exception", e);
+ RequestBase rq = (RequestBase)event.getHttpServletRequest().getAttribute(RequestBase.LAST_REQ_ATTR);
+ if (rq!=null) {
+ Map map = new HashMap();
+ try {
+ map.put(Bayeux.CHANNEL_FIELD,message.getChannel().getId());
+ map.put(Bayeux.DATA_FIELD,message);
+ JSONObject json = new JSONObject(map);
+ if (log.isTraceEnabled()) {
+ log.trace("Message instantly delivered to remote client["+this+"] message:"+json);
}
+ rq.addToDeliveryQueue(this, json);
+ //deliver the batch
+ if (i==(msgs.length-1)) {
+ rq.deliver(event, this);
+ event.close(); //todo, figure out a better way, this means only one message gets delivered
+ removeCometEvent(event); //and delivered instantly
+ }
+ delivered = true;
+ } catch (Exception e) {
+ // TODO: fix
+ log.warn("Exception", e);
}
}
- }
+ }
if (!delivered) {
if (log.isTraceEnabled()) {
log.trace("Message added to queue for remote client["+this+"] message:"+message);
@@ -244,23 +240,25 @@
return nrofsubscriptions.get()>0;
}
- protected synchronized boolean addCometEvent(HttpEvent event) {
- boolean result = false;
- if (!events.contains(event)) {
- events.add(event);
- result = true;
+ protected void addCometEvent(HttpEvent event) {
+ if (this.event != null) {
+ try {
+ this.event.close();
+ } catch (IOException e) {
+ // Nothing
+ }
}
+ this.event = event;
event.getHttpServletRequest().setAttribute(COMET_EVENT_ATTR,this);
- return result;
}
- protected synchronized boolean removeCometEvent(HttpEvent event) {
- boolean result = events.remove(event);
+ protected void removeCometEvent(HttpEvent event) {
+ if (this.event != null && this.event == event) {
+ this.event = null;
+ }
event.getHttpServletRequest().removeAttribute(COMET_EVENT_ATTR);
- return result;
}
-
protected void subscribed(ChannelImpl ch) {
nrofsubscriptions.addAndGet(1);
}
Modified: trunk/java/org/apache/tomcat/bayeux/RequestBase.java
===================================================================
--- trunk/java/org/apache/tomcat/bayeux/RequestBase.java 2008-11-18 16:30:54 UTC (rev 859)
+++ trunk/java/org/apache/tomcat/bayeux/RequestBase.java 2008-11-20 18:37:18 UTC (rev 860)
@@ -194,7 +194,6 @@
out.print(");");
}
out.flush();
- event.getHttpServletResponse().flushBuffer();
}
16 years, 1 month