JBossWeb SVN: r573 - trunk/java/org/apache/catalina/connector.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-03-31 12:23:06 -0400 (Mon, 31 Mar 2008)
New Revision: 573
Modified:
trunk/java/org/apache/catalina/connector/InputBuffer.java
Log:
- Remove the "grow for a minimum amount" thing, which may not be that useful.
Modified: trunk/java/org/apache/catalina/connector/InputBuffer.java
===================================================================
--- trunk/java/org/apache/catalina/connector/InputBuffer.java 2008-03-31 15:17:04 UTC (rev 572)
+++ trunk/java/org/apache/catalina/connector/InputBuffer.java 2008-03-31 16:23:06 UTC (rev 573)
@@ -501,13 +501,9 @@
cb.setOffset(0);
}
}
- int offset = readAheadLimit;
- if (offset < size) {
- offset = size;
+ if (cb.getStart() + readAheadLimit > cb.getLimit()) {
+ cb.setLimit(cb.getStart() + readAheadLimit);
}
- if (cb.getStart() + offset > cb.getLimit()) {
- cb.setLimit(cb.getStart() + offset);
- }
markPos = cb.getStart();
}
16 years, 8 months
JBossWeb SVN: r572 - trunk/java/org/apache/tomcat/util/buf.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-03-31 11:17:04 -0400 (Mon, 31 Mar 2008)
New Revision: 572
Modified:
trunk/java/org/apache/tomcat/util/buf/CharChunk.java
Log:
- One (last ?) mark fix: when resizing, we need to save the whole array, because the beginning could be marked
and read again.
Modified: trunk/java/org/apache/tomcat/util/buf/CharChunk.java
===================================================================
--- trunk/java/org/apache/tomcat/util/buf/CharChunk.java 2008-03-31 13:59:32 UTC (rev 571)
+++ trunk/java/org/apache/tomcat/util/buf/CharChunk.java 2008-03-31 15:17:04 UTC (rev 572)
@@ -480,7 +480,7 @@
tmp=new char[newSize];
}
- System.arraycopy(buff, start, tmp, start, end-start);
+ System.arraycopy(buff, 0, tmp, 0, end);
buff = tmp;
tmp = null;
}
16 years, 8 months
JBossWeb SVN: r571 - in trunk: webapps/docs and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-03-31 09:59:32 -0400 (Mon, 31 Mar 2008)
New Revision: 571
Modified:
trunk/java/org/apache/catalina/valves/CometConnectionManagerValve.java
trunk/java/org/apache/catalina/valves/LocalStrings.properties
trunk/webapps/docs/changelog.xml
Log:
- 44646: Fix tracking problems in the Comet utility valve (which provides
notification for certain events such as session expiration and server shutdown).
Modified: trunk/java/org/apache/catalina/valves/CometConnectionManagerValve.java
===================================================================
--- trunk/java/org/apache/catalina/valves/CometConnectionManagerValve.java 2008-03-31 13:51:46 UTC (rev 570)
+++ trunk/java/org/apache/catalina/valves/CometConnectionManagerValve.java 2008-03-31 13:59:32 UTC (rev 571)
@@ -20,8 +20,10 @@
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
@@ -39,6 +41,7 @@
import org.apache.catalina.util.LifecycleSupport;
import org.apache.catalina.util.StringManager;
import org.jboss.web.comet.CometEvent;
+import org.jboss.web.comet.CometProcessor;
/**
@@ -86,12 +89,19 @@
/**
- * Connection list.
+ * List of current Coment connections.
*/
- protected ConcurrentHashMap<String, ConnectionInfo[]> connections
- = new ConcurrentHashMap<String, ConnectionInfo[]>();
+ protected List<Request> cometRequests =
+ Collections.synchronizedList(new ArrayList<Request>());
+ /**
+ * Name of session attribute used to store list of comet connections.
+ */
+ protected String cometRequestsAttribute =
+ "org.apache.tomcat.comet.connectionList";
+
+
// ------------------------------------------------------------- Properties
@@ -178,53 +188,34 @@
((Lifecycle) container).removeLifecycleListener(this);
}
- // The webapp is getting stopped, so all current connections
- // should be closed
- // Close all Comet connections associated with this session
- // Note: this will only be done if the container was not a Context
- // (otherwise, this needs to be done before stop, as the servlet would
- // be deallocated already)
- Iterator<ConnectionInfo[]> iterator = connections.values().iterator();
- while (iterator.hasNext()) {
- ConnectionInfo[] connectionInfos = iterator.next();
- if (connectionInfos != null) {
- for (int i = 0; i < connectionInfos.length; i++) {
- ConnectionInfo connectionInfo = connectionInfos[i];
- try {
- connectionInfo.event.close();
- } catch (Exception e) {
- container.getLogger().warn(sm.getString("cometConnectionManagerValve.event"), e);
- }
- }
- }
- }
- connections.clear();
-
}
public void lifecycleEvent(LifecycleEvent event) {
if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) {
- // The webapp is getting stopped, so all current connections
- // should be closed
- // Close all Comet connections associated with this session
- Iterator<ConnectionInfo[]> iterator = connections.values().iterator();
+ // The container is getting stopped, close all current connections
+ Iterator<Request> iterator = cometRequests.iterator();
while (iterator.hasNext()) {
- ConnectionInfo[] connectionInfos = iterator.next();
- if (connectionInfos != null) {
- for (int i = 0; i < connectionInfos.length; i++) {
- ConnectionInfo connectionInfo = connectionInfos[i];
- try {
- ((CometEventImpl) connectionInfo.event).setType(CometEvent.EventType.END);
- getNext().event(connectionInfo.request, connectionInfo.response, connectionInfo.event);
- connectionInfo.event.close();
- } catch (Exception e) {
- container.getLogger().warn(sm.getString("cometConnectionManagerValve.event"), e);
- }
- }
+ Request request = iterator.next();
+ // Remove the session tracking attribute as it isn't
+ // serializable or required.
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ session.removeAttribute(cometRequestsAttribute);
}
+ // Close the comet connection
+ try {
+ CometEventImpl cometEvent = request.getEvent();
+ cometEvent.setType(CometEvent.EventType.END);
+ getNext().event(request, request.getResponse(), cometEvent);
+ cometEvent.close();
+ } catch (Exception e) {
+ container.getLogger().warn(
+ sm.getString("cometConnectionManagerValve.event"),
+ e);
+ }
}
- connections.clear();
+ cometRequests.clear();
}
}
@@ -258,25 +249,27 @@
// Start tracking this connection, since this is a
// begin event, and Comet mode is on
HttpSession session = request.getSession(true);
- ConnectionInfo newConnectionInfo = new ConnectionInfo();
- newConnectionInfo.request = request;
- newConnectionInfo.response = response;
- newConnectionInfo.event = request.getEvent();
+
+ // Track the conection for webapp reload
+ cometRequests.add(request);
+
+ // Track the connection for session expiration
synchronized (session) {
- String id = session.getId();
- ConnectionInfo[] connectionInfos = connections.get(id);
- if (connectionInfos == null) {
- connectionInfos = new ConnectionInfo[1];
- connectionInfos[0] = newConnectionInfo;
- connections.put(id, connectionInfos);
+ Request[] requests = (Request[])
+ session.getAttribute(cometRequestsAttribute);
+ if (requests == null) {
+ requests = new Request[1];
+ requests[0] = request;
+ session.setAttribute(cometRequestsAttribute,
+ requests);
} else {
- ConnectionInfo[] newConnectionInfos =
- new ConnectionInfo[connectionInfos.length + 1];
- for (int i = 0; i < connectionInfos.length; i++) {
- newConnectionInfos[i] = connectionInfos[i];
+ Request[] newRequests =
+ new Request[requests.length + 1];
+ for (int i = 0; i < requests.length; i++) {
+ newRequests[i] = requests[i];
}
- newConnectionInfos[connectionInfos.length] = newConnectionInfo;
- connections.put(id, newConnectionInfos);
+ newRequests[requests.length] = request;
+ session.setAttribute(cometRequestsAttribute, newRequests);
}
}
}
@@ -305,31 +298,46 @@
if (!ok || response.isClosed()
|| (event.getType() == CometEvent.EventType.END)
|| (event.getType() == CometEvent.EventType.ERROR)) {
- // Remove from tracked list, the connection is done
- HttpSession session = request.getSession(true);
- synchronized (session) {
- ConnectionInfo[] connectionInfos = connections.get(session.getId());
- if (connectionInfos != null) {
- boolean found = false;
- for (int i = 0; !found && (i < connectionInfos.length); i++) {
- found = (connectionInfos[i].request == request);
- }
- if (found) {
- ConnectionInfo[] newConnectionInfos =
- new ConnectionInfo[connectionInfos.length - 1];
- int pos = 0;
- for (int i = 0; i < connectionInfos.length; i++) {
- if (connectionInfos[i].request != request) {
- newConnectionInfos[pos++] = connectionInfos[i];
+
+ // Remove the connection from webapp reload tracking
+ cometRequests.remove(request);
+
+ // Remove connection from session expiration tracking
+ // Note: can't get the session if it has been invalidated but
+ // OK since session listener will have done clean-up
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ synchronized (session) {
+ Request[] reqs = (Request[])
+ session.getAttribute(cometRequestsAttribute);
+ if (reqs != null) {
+ boolean found = false;
+ for (int i = 0; !found && (i < reqs.length); i++) {
+ found = (reqs[i] == request);
+ }
+ if (found) {
+ if (reqs.length > 1) {
+ Request[] newConnectionInfos =
+ new Request[reqs.length - 1];
+ int pos = 0;
+ for (int i = 0; i < reqs.length; i++) {
+ if (reqs[i] != request) {
+ newConnectionInfos[pos++] = reqs[i];
+ }
+ }
+ session.setAttribute(cometRequestsAttribute,
+ newConnectionInfos);
+ } else {
+ session.removeAttribute(
+ cometRequestsAttribute);
}
}
- connections.put(session.getId(), newConnectionInfos);
}
}
- }
+ }
}
}
-
+
}
@@ -339,30 +347,22 @@
public void sessionDestroyed(HttpSessionEvent se) {
// Close all Comet connections associated with this session
- ConnectionInfo[] connectionInfos = connections.remove(se.getSession().getId());
- if (connectionInfos != null) {
- for (int i = 0; i < connectionInfos.length; i++) {
- ConnectionInfo connectionInfo = connectionInfos[i];
+ Request[] reqs = (Request[])
+ se.getSession().getAttribute(cometRequestsAttribute);
+ if (reqs != null) {
+ for (int i = 0; i < reqs.length; i++) {
+ Request req = reqs[i];
try {
- ((CometEventImpl) connectionInfo.event).setType(CometEvent.EventType.END);
- getNext().event(connectionInfo.request, connectionInfo.response, connectionInfo.event);
- connectionInfo.event.close();
+ CometEventImpl event = req.getEvent();
+ event.setType(CometEvent.EventType.END);
+ ((CometProcessor) req.getWrapper().getServlet()).event(event);
+ event.close();
} catch (Exception e) {
- container.getLogger().warn(sm.getString("cometConnectionManagerValve.event"), e);
+ req.getWrapper().getParent().getLogger().warn(sm.getString(
+ "cometConnectionManagerValve.listenerEvent"), e);
}
}
}
}
-
- // --------------------------------------------- ConnectionInfo Inner Class
-
-
- protected class ConnectionInfo {
- public CometEvent event;
- public Request request;
- public Response response;
- }
-
-
}
Modified: trunk/java/org/apache/catalina/valves/LocalStrings.properties
===================================================================
--- trunk/java/org/apache/catalina/valves/LocalStrings.properties 2008-03-31 13:51:46 UTC (rev 570)
+++ trunk/java/org/apache/catalina/valves/LocalStrings.properties 2008-03-31 13:59:32 UTC (rev 571)
@@ -12,6 +12,7 @@
jdbcAccessLogValve.exception=Exception performing insert access entry
jdbcAccessLogValve.close=Exception closing database connection
cometConnectionManagerValve.event=Exception processing event
+cometConnectionManagerValve.listenerEvent=Exception processing session listener event
# Error report valve
errorReportValve.errorReport=Error report
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2008-03-31 13:51:46 UTC (rev 570)
+++ trunk/webapps/docs/changelog.xml 2008-03-31 13:59:32 UTC (rev 571)
@@ -52,6 +52,10 @@
<bug>44611</bug>: Implement DirContextURLConnection.getHeaderFields(), fix case
sensitivity problem and return null for header values which don't exist. (markt)
</fix>
+ <fix>
+ <bug>44646</bug>: Fix tracking problems in the Comet utility valve (which provides
+ notification for certain events such as session expiration and server shutdown). (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
16 years, 8 months
JBossWeb SVN: r570 - in trunk: webapps/docs and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-03-31 09:51:46 -0400 (Mon, 31 Mar 2008)
New Revision: 570
Modified:
trunk/java/org/apache/naming/resources/DirContextURLConnection.java
trunk/java/org/apache/naming/resources/ResourceAttributes.java
trunk/webapps/docs/changelog.xml
Log:
- 44611: Implement DirContextURLConnection.getHeaderFields(), fix case
sensitivity problem and return null for header values which don't exist.
Modified: trunk/java/org/apache/naming/resources/DirContextURLConnection.java
===================================================================
--- trunk/java/org/apache/naming/resources/DirContextURLConnection.java 2008-03-31 13:42:42 UTC (rev 569)
+++ trunk/java/org/apache/naming/resources/DirContextURLConnection.java 2008-03-31 13:51:46 UTC (rev 570)
@@ -23,8 +23,12 @@
import java.io.InputStream;
import java.io.FileNotFoundException;
import java.security.Permission;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Vector;
import javax.naming.NamingException;
import javax.naming.NamingEnumeration;
@@ -61,7 +65,7 @@
("Directory context can't be null");
if (org.apache.naming.Constants.IS_SECURITY_ENABLED) {
this.permission = new JndiPermission(url.toString());
- }
+ }
this.context = context;
}
@@ -217,7 +221,47 @@
return 0;
}
+
+ /**
+ * Returns an unmodifiable Map of the header fields.
+ */
+ public Map getHeaderFields() {
+
+ if (!connected) {
+ // Try to connect (silently)
+ try {
+ connect();
+ } catch (IOException e) {
+ }
+ }
+
+ if (attributes == null)
+ return (Collections.EMPTY_MAP);
+
+ HashMap headerFields = new HashMap(attributes.size());
+ NamingEnumeration attributeEnum = attributes.getIDs();
+ try {
+ while (attributeEnum.hasMore()) {
+ String attributeID = (String)attributeEnum.next();
+ Attribute attribute = attributes.get(attributeID);
+ if (attribute == null) continue;
+ ArrayList attributeValueList = new ArrayList(attribute.size());
+ NamingEnumeration attributeValues = attribute.getAll();
+ while (attributeValues.hasMore()) {
+ attributeValueList.add(attributeValues.next().toString());
+ }
+ attributeValueList.trimToSize(); // should be a no-op if attribute.size() didn't lie
+ headerFields.put(attributeID, Collections.unmodifiableList(attributeValueList));
+ }
+ } catch (NamingException ne) {
+ // Shouldn't happen
+ }
+
+ return Collections.unmodifiableMap(headerFields);
+
+ }
+
/**
* Returns the name of the specified header field.
*/
@@ -234,11 +278,18 @@
if (attributes == null)
return (null);
- Attribute attribute = attributes.get(name);
+ NamingEnumeration attributeEnum = attributes.getIDs();
try {
- return attribute.get().toString();
- } catch (Exception e) {
- // Shouldn't happen, unless the attribute has no value
+ while (attributeEnum.hasMore()) {
+ String attributeID = (String)attributeEnum.next();
+ if (attributeID.equalsIgnoreCase(name)) {
+ Attribute attribute = attributes.get(attributeID);
+ if (attribute == null) return null;
+ return attribute.get(attribute.size()-1).toString();
+ }
+ }
+ } catch (NamingException ne) {
+ // Shouldn't happen
}
return (null);
Modified: trunk/java/org/apache/naming/resources/ResourceAttributes.java
===================================================================
--- trunk/java/org/apache/naming/resources/ResourceAttributes.java 2008-03-31 13:42:42 UTC (rev 569)
+++ trunk/java/org/apache/naming/resources/ResourceAttributes.java 2008-03-31 13:51:46 UTC (rev 570)
@@ -263,7 +263,7 @@
*/
public boolean isCollection() {
if (attributes != null) {
- return (getResourceType().equals(COLLECTION_TYPE));
+ return (COLLECTION_TYPE.equals(getResourceType()));
} else {
return (collection);
}
@@ -683,7 +683,7 @@
if (collection)
result = COLLECTION_TYPE;
else
- result = "";
+ result = null;
}
return result;
}
@@ -775,28 +775,41 @@
public Attribute get(String attrID) {
if (attributes == null) {
if (attrID.equals(CREATION_DATE)) {
- return new BasicAttribute(CREATION_DATE, getCreationDate());
+ Date creationDate = getCreationDate();
+ if (creationDate == null) return null;
+ return new BasicAttribute(CREATION_DATE, creationDate);
} else if (attrID.equals(ALTERNATE_CREATION_DATE)) {
- return new BasicAttribute(ALTERNATE_CREATION_DATE,
- getCreationDate());
+ Date creationDate = getCreationDate();
+ if (creationDate == null) return null;
+ return new BasicAttribute(ALTERNATE_CREATION_DATE, creationDate);
} else if (attrID.equals(LAST_MODIFIED)) {
- return new BasicAttribute(LAST_MODIFIED,
- getLastModifiedDate());
+ Date lastModifiedDate = getLastModifiedDate();
+ if (lastModifiedDate == null) return null;
+ return new BasicAttribute(LAST_MODIFIED, lastModifiedDate);
} else if (attrID.equals(ALTERNATE_LAST_MODIFIED)) {
- return new BasicAttribute(ALTERNATE_LAST_MODIFIED,
- getLastModifiedDate());
+ Date lastModifiedDate = getLastModifiedDate();
+ if (lastModifiedDate == null) return null;
+ return new BasicAttribute(ALTERNATE_LAST_MODIFIED, lastModifiedDate);
} else if (attrID.equals(NAME)) {
- return new BasicAttribute(NAME, getName());
+ String name = getName();
+ if (name == null) return null;
+ return new BasicAttribute(NAME, name);
} else if (attrID.equals(TYPE)) {
- return new BasicAttribute(TYPE, getResourceType());
+ String resourceType = getResourceType();
+ if (resourceType == null) return null;
+ return new BasicAttribute(TYPE, resourceType);
} else if (attrID.equals(ALTERNATE_TYPE)) {
- return new BasicAttribute(ALTERNATE_TYPE, getResourceType());
+ String resourceType = getResourceType();
+ if (resourceType == null) return null;
+ return new BasicAttribute(ALTERNATE_TYPE, resourceType);
} else if (attrID.equals(CONTENT_LENGTH)) {
- return new BasicAttribute(CONTENT_LENGTH,
- new Long(getContentLength()));
+ long contentLength = getContentLength();
+ if (contentLength < 0) return null;
+ return new BasicAttribute(CONTENT_LENGTH, new Long(contentLength));
} else if (attrID.equals(ALTERNATE_CONTENT_LENGTH)) {
- return new BasicAttribute(ALTERNATE_CONTENT_LENGTH,
- new Long(getContentLength()));
+ long contentLength = getContentLength();
+ if (contentLength < 0) return null;
+ return new BasicAttribute(ALTERNATE_CONTENT_LENGTH, new Long(contentLength));
}
} else {
return attributes.get(attrID);
@@ -851,15 +864,35 @@
public NamingEnumeration getAll() {
if (attributes == null) {
Vector attributes = new Vector();
- attributes.addElement(new BasicAttribute
- (CREATION_DATE, getCreationDate()));
- attributes.addElement(new BasicAttribute
- (LAST_MODIFIED, getLastModifiedDate()));
- attributes.addElement(new BasicAttribute(NAME, getName()));
- attributes.addElement(new BasicAttribute(TYPE, getResourceType()));
- attributes.addElement
- (new BasicAttribute(CONTENT_LENGTH,
- new Long(getContentLength())));
+ Date creationDate = getCreationDate();
+ if (creationDate != null) {
+ attributes.addElement(new BasicAttribute
+ (CREATION_DATE, creationDate));
+ attributes.addElement(new BasicAttribute
+ (ALTERNATE_CREATION_DATE, creationDate));
+ }
+ Date lastModifiedDate = getLastModifiedDate();
+ if (lastModifiedDate != null) {
+ attributes.addElement(new BasicAttribute
+ (LAST_MODIFIED, lastModifiedDate));
+ attributes.addElement(new BasicAttribute
+ (ALTERNATE_LAST_MODIFIED, lastModifiedDate));
+ }
+ String name = getName();
+ if (name != null) {
+ attributes.addElement(new BasicAttribute(NAME, name));
+ }
+ String resourceType = getResourceType();
+ if (resourceType != null) {
+ attributes.addElement(new BasicAttribute(TYPE, resourceType));
+ attributes.addElement(new BasicAttribute(ALTERNATE_TYPE, resourceType));
+ }
+ long contentLength = getContentLength();
+ if (contentLength >= 0) {
+ Long contentLengthLong = new Long(contentLength);
+ attributes.addElement(new BasicAttribute(CONTENT_LENGTH, contentLengthLong));
+ attributes.addElement(new BasicAttribute(ALTERNATE_CONTENT_LENGTH, contentLengthLong));
+ }
return new RecyclableNamingEnumeration(attributes);
} else {
return attributes.getAll();
@@ -873,11 +906,29 @@
public NamingEnumeration getIDs() {
if (attributes == null) {
Vector attributeIDs = new Vector();
- attributeIDs.addElement(CREATION_DATE);
- attributeIDs.addElement(LAST_MODIFIED);
- attributeIDs.addElement(NAME);
- attributeIDs.addElement(TYPE);
- attributeIDs.addElement(CONTENT_LENGTH);
+ Date creationDate = getCreationDate();
+ if (creationDate != null) {
+ attributeIDs.addElement(CREATION_DATE);
+ attributeIDs.addElement(ALTERNATE_CREATION_DATE);
+ }
+ Date lastModifiedDate = getLastModifiedDate();
+ if (lastModifiedDate != null) {
+ attributeIDs.addElement(LAST_MODIFIED);
+ attributeIDs.addElement(ALTERNATE_LAST_MODIFIED);
+ }
+ if (getName() != null) {
+ attributeIDs.addElement(NAME);
+ }
+ String resourceType = getResourceType();
+ if (resourceType != null) {
+ attributeIDs.addElement(TYPE);
+ attributeIDs.addElement(ALTERNATE_TYPE);
+ }
+ long contentLength = getContentLength();
+ if (contentLength >= 0) {
+ attributeIDs.addElement(CONTENT_LENGTH);
+ attributeIDs.addElement(ALTERNATE_CONTENT_LENGTH);
+ }
return new RecyclableNamingEnumeration(attributeIDs);
} else {
return attributes.getIDs();
@@ -890,7 +941,13 @@
*/
public int size() {
if (attributes == null) {
- return 5;
+ int size = 0;
+ if (getCreationDate() != null) size += 2;
+ if (getLastModifiedDate() != null) size += 2;
+ if (getName() != null) size++;
+ if (getResourceType() != null) size += 2;
+ if (getContentLength() >= 0) size += 2;
+ return size;
} else {
return attributes.size();
}
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2008-03-31 13:42:42 UTC (rev 569)
+++ trunk/webapps/docs/changelog.xml 2008-03-31 13:51:46 UTC (rev 570)
@@ -48,6 +48,10 @@
<fix>
<bug>44673</bug>: Fix ServletInputStream still readable when closed. (markt)
</fix>
+ <fix>
+ <bug>44611</bug>: Implement DirContextURLConnection.getHeaderFields(), fix case
+ sensitivity problem and return null for header values which don't exist. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
16 years, 8 months
JBossWeb SVN: r569 - in trunk: java/org/apache/catalina/realm and 2 other directories.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-03-31 09:42:42 -0400 (Mon, 31 Mar 2008)
New Revision: 569
Modified:
trunk/java/org/apache/catalina/connector/InputBuffer.java
trunk/java/org/apache/catalina/connector/LocalStrings.properties
trunk/java/org/apache/catalina/realm/RealmBase.java
trunk/java/org/apache/catalina/servlets/CGIServlet.java
trunk/webapps/docs/changelog.xml
Log:
- Port 3 patches.
- Remove hackish code to get the System environment in the CGI Servlet.
- 44529: No roles (deny all) trumps no auth-constraint (allow all).
- 44673: Fix ServletInputStream still readable when closed.
Modified: trunk/java/org/apache/catalina/connector/InputBuffer.java
===================================================================
--- trunk/java/org/apache/catalina/connector/InputBuffer.java 2008-03-31 13:13:26 UTC (rev 568)
+++ trunk/java/org/apache/catalina/connector/InputBuffer.java 2008-03-31 13:42:42 UTC (rev 569)
@@ -25,6 +25,7 @@
import java.util.HashMap;
import org.apache.catalina.security.SecurityUtil;
+import org.apache.catalina.util.StringManager;
import org.apache.coyote.ActionCode;
import org.apache.coyote.Request;
import org.apache.tomcat.util.buf.B2CConverter;
@@ -47,6 +48,13 @@
// -------------------------------------------------------------- Constants
+ /**
+ * The string manager for this package.
+ */
+ protected static StringManager sm =
+ StringManager.getManager(Constants.Package);
+
+
public static final String DEFAULT_ENCODING =
org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING;
public static final int DEFAULT_BUFFER_SIZE = 8*1024;
@@ -266,6 +274,9 @@
public int available() {
+ if (eof || closed) {
+ return -1;
+ }
int available = 0;
if (state == BYTE_STATE) {
available = bb.getLength();
@@ -336,12 +347,20 @@
public int readByte()
throws IOException {
+
+ if (closed)
+ throw new IOException(sm.getString("inputBuffer.streamClosed"));
+
return bb.substract();
}
public int read(byte[] b, int off, int len)
throws IOException {
+
+ if (closed)
+ throw new IOException(sm.getString("inputBuffer.streamClosed"));
+
return bb.substract(b, off, len);
}
@@ -390,6 +409,10 @@
public int read()
throws IOException {
+
+ if (closed)
+ throw new IOException(sm.getString("inputBuffer.streamClosed"));
+
return cb.substract();
}
@@ -402,6 +425,10 @@
public int read(char[] cbuf, int off, int len)
throws IOException {
+
+ if (closed)
+ throw new IOException(sm.getString("inputBuffer.streamClosed"));
+
return cb.substract(cbuf, off, len);
}
@@ -409,6 +436,9 @@
public long skip(long n)
throws IOException {
+ if (closed)
+ throw new IOException(sm.getString("inputBuffer.streamClosed"));
+
if (n < 0) {
throw new IllegalArgumentException();
}
@@ -440,6 +470,10 @@
public boolean ready()
throws IOException {
+
+ if (closed)
+ throw new IOException(sm.getString("inputBuffer.streamClosed"));
+
return (available() > 0);
}
@@ -451,6 +485,10 @@
public void mark(int readAheadLimit)
throws IOException {
+
+ if (closed)
+ throw new IOException(sm.getString("inputBuffer.streamClosed"));
+
if (cb.getLength() <= 0) {
cb.setOffset(0);
cb.setEnd(0);
@@ -476,6 +514,10 @@
public void reset()
throws IOException {
+
+ if (closed)
+ throw new IOException(sm.getString("inputBuffer.streamClosed"));
+
if (state == CHAR_STATE) {
if (markPos < 0) {
throw new IOException();
Modified: trunk/java/org/apache/catalina/connector/LocalStrings.properties
===================================================================
--- trunk/java/org/apache/catalina/connector/LocalStrings.properties 2008-03-31 13:13:26 UTC (rev 568)
+++ trunk/java/org/apache/catalina/connector/LocalStrings.properties 2008-03-31 13:42:42 UTC (rev 569)
@@ -49,9 +49,6 @@
coyoteRequest.attributeEvent=Exception thrown by attributes event listener
coyoteRequest.parseParameters=Exception thrown whilst processing POSTed parameters
coyoteRequest.postTooLarge=Parameters were not parsed because the size of the posted data was too big. Use the maxPostSize attribute of the connector to resolve this if the application should accept large POSTs.
-requestFacade.nullRequest=The request object has been recycled and is no longer associated with this facade
-responseFacade.nullResponse=The response object has been recycled and is no longer associated with this facade
-cometEvent.nullRequest=The event object has been recycled and is no longer associated with a request
#
# MapperListener
@@ -63,5 +60,11 @@
mapperListener.unregisterContext=Unregister Context {0}
mapperListener.registerWrapper=Register Wrapper {0} in Context {1}
+#
+# Others
+#
-
+requestFacade.nullRequest=The request object has been recycled and is no longer associated with this facade
+responseFacade.nullResponse=The response object has been recycled and is no longer associated with this facade
+cometEvent.nullRequest=The event object has been recycled and is no longer associated with a request
+inputBuffer.streamClosed=Stream closed
Modified: trunk/java/org/apache/catalina/realm/RealmBase.java
===================================================================
--- trunk/java/org/apache/catalina/realm/RealmBase.java 2008-03-31 13:13:26 UTC (rev 568)
+++ trunk/java/org/apache/catalina/realm/RealmBase.java 2008-03-31 13:42:42 UTC (rev 569)
@@ -751,7 +751,7 @@
// Which user principal have we already authenticated?
Principal principal = request.getPrincipal();
boolean status = false;
- boolean denyfromall = false;
+ boolean denyFromAll = false;
for(int i=0; i < constraints.length; i++) {
SecurityConstraint constraint = constraints[i];
@@ -774,18 +774,17 @@
if( log.isDebugEnabled() )
log.debug("No roles ");
status = false; // No listed roles means no access at all
- denyfromall = true;
+ denyFromAll = true;
+ break;
} else {
if(log.isDebugEnabled())
log.debug("Passing all access");
- return (true);
+ status = true;
}
} else if (principal == null) {
if (log.isDebugEnabled())
log.debug(" No user authenticated, cannot grant access");
- status = false;
- } else if(!denyfromall) {
-
+ } else {
for (int j = 0; j < roles.length; j++) {
if (hasRole(principal, roles[j]))
status = true;
@@ -795,7 +794,7 @@
}
}
- if (allRolesMode != AllRolesMode.STRICT_MODE && !status && principal != null) {
+ if (!denyFromAll && allRolesMode != AllRolesMode.STRICT_MODE && !status && principal != null) {
if (log.isDebugEnabled()) {
log.debug("Checking for all roles mode: " + allRolesMode);
}
Modified: trunk/java/org/apache/catalina/servlets/CGIServlet.java
===================================================================
--- trunk/java/org/apache/catalina/servlets/CGIServlet.java 2008-03-31 13:13:26 UTC (rev 568)
+++ trunk/java/org/apache/catalina/servlets/CGIServlet.java 2008-03-31 13:42:42 UTC (rev 569)
@@ -304,13 +304,7 @@
Boolean.valueOf(getServletConfig().getInitParameter("passShellEnvironment")).booleanValue();
if (passShellEnvironment) {
- try {
- shellEnv.putAll(getShellEnvironment());
- } catch (IOException ioe) {
- ServletException e = new ServletException(
- "Unable to read shell environment variables", ioe);
- throw e;
- }
+ shellEnv.putAll(System.getenv());
}
if (getServletConfig().getInitParameter("executable") != null) {
@@ -631,62 +625,12 @@
} //doGet
-
/** For future testing use only; does nothing right now */
public static void main(String[] args) {
System.out.println("$Header$");
}
- /**
- * Get all shell environment variables. Have to do it this rather ugly way
- * as the API to obtain is not available in 1.4 and earlier APIs.
- *
- * See <a href="http://www.rgagnon.com/javadetails/java-0150.html">Read environment
- * variables from an application</a> for original source and article.
- */
- private Hashtable<String,String> getShellEnvironment() throws IOException {
- Hashtable<String,String> envVars = new Hashtable<String,String>();
- Process p = null;
- Runtime r = Runtime.getRuntime();
- String OS = System.getProperty("os.name").toLowerCase();
- boolean ignoreCase;
- if (OS.indexOf("windows 9") > -1) {
- p = r.exec( "command.com /c set" );
- ignoreCase = true;
- } else if ( (OS.indexOf("nt") > -1)
- || (OS.indexOf("windows 20") > -1)
- || (OS.indexOf("windows xp") > -1) ) {
- // thanks to JuanFran for the xp fix!
- p = r.exec( "cmd.exe /c set" );
- ignoreCase = true;
- } else {
- // our last hope, we assume Unix (thanks to H. Ware for the fix)
- p = r.exec( "env" );
- ignoreCase = false;
- }
-
- BufferedReader br = new BufferedReader
- ( new InputStreamReader( p.getInputStream() ) );
- String line;
- while( (line = br.readLine()) != null ) {
- int idx = line.indexOf( '=' );
- String key = line.substring( 0, idx );
- String value = line.substring( idx+1 );
- if (ignoreCase) {
- key = key.toUpperCase();
- }
- envVars.put(key, value);
- }
- return envVars;
- }
-
-
-
-
-
-
-
/**
* Encapsulates the CGI environment and rules to derive
* that environment from the servlet container and request information.
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2008-03-31 13:13:26 UTC (rev 568)
+++ trunk/webapps/docs/changelog.xml 2008-03-31 13:42:42 UTC (rev 569)
@@ -39,6 +39,15 @@
<update>
Add Comet EOF event when the end of the stream is reached without an error. (remm)
</update>
+ <fix>
+ Remove hackish code to get the System environment in the CGI Servlet. (markt)
+ </fix>
+ <fix>
+ <bug>44529</bug>: No roles (deny all) trumps no auth-constraint (allow all). (markt)
+ </fix>
+ <fix>
+ <bug>44673</bug>: Fix ServletInputStream still readable when closed. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
@@ -72,6 +81,10 @@
Move the parameters backend to the probably more efficient MultiMap from Hashtable,
and remove the nesting capabilities inherited from Tomcat 3. (remm)
</update>
+ <update>
+ Repackage MimeHeaders and Parameters using inner classes, and remove all obsolete
+ collections. (remm)
+ </update>
</changelog>
</subsection>
</section>
16 years, 8 months
JBossWeb SVN: r568 - branches/JBOSSWEB_2_0_0_GA_CP/src/share/classes/org/apache/tomcat/util/http.
by jbossweb-commits@lists.jboss.org
Author: jfrederic.clere(a)jboss.com
Date: 2008-03-31 09:13:26 -0400 (Mon, 31 Mar 2008)
New Revision: 568
Modified:
branches/JBOSSWEB_2_0_0_GA_CP/src/share/classes/org/apache/tomcat/util/http/Parameters.java
Log:
Fix JBWEB-105 = JBPAPP-729
Modified: branches/JBOSSWEB_2_0_0_GA_CP/src/share/classes/org/apache/tomcat/util/http/Parameters.java
===================================================================
--- branches/JBOSSWEB_2_0_0_GA_CP/src/share/classes/org/apache/tomcat/util/http/Parameters.java 2008-03-31 11:02:10 UTC (rev 567)
+++ branches/JBOSSWEB_2_0_0_GA_CP/src/share/classes/org/apache/tomcat/util/http/Parameters.java 2008-03-31 13:13:26 UTC (rev 568)
@@ -503,17 +503,12 @@
public void processParameters( MessageBytes data, String encoding ) {
if( data==null || data.isNull() || data.getLength() <= 0 ) return;
- if( data.getType() == MessageBytes.T_BYTES ) {
- ByteChunk bc=data.getByteChunk();
- processParameters( bc.getBytes(), bc.getOffset(),
- bc.getLength(), encoding);
- } else {
- if (data.getType()!= MessageBytes.T_CHARS )
- data.toChars();
- CharChunk cc=data.getCharChunk();
- processParameters( cc.getChars(), cc.getOffset(),
- cc.getLength());
+ if (data.getType() != MessageBytes.T_BYTES) {
+ data.toBytes();
}
+ ByteChunk bc=data.getByteChunk();
+ processParameters( bc.getBytes(), bc.getOffset(),
+ bc.getLength(), encoding);
}
/** Debug purpose
16 years, 8 months
JBossWeb SVN: r567 - trunk/java/org/apache/catalina/connector.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-03-31 07:02:10 -0400 (Mon, 31 Mar 2008)
New Revision: 567
Modified:
trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
trunk/java/org/apache/catalina/connector/InputBuffer.java
trunk/java/org/apache/catalina/connector/Request.java
Log:
- Add a separate EOF flag (since close checks are to be added, and throwing an IOE on reads when the EOF has been
reached is not ok).
Modified: trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
===================================================================
--- trunk/java/org/apache/catalina/connector/CoyoteAdapter.java 2008-03-31 10:09:38 UTC (rev 566)
+++ trunk/java/org/apache/catalina/connector/CoyoteAdapter.java 2008-03-31 11:02:10 UTC (rev 567)
@@ -241,13 +241,13 @@
error = true;
connector.getContainer().getPipeline().getFirst().event(request, response, request.getEvent());
}
- if (!error && !eof && (status == SocketStatus.OPEN_READ) && request.isClosed()) {
+ if (!error && !eof && (status == SocketStatus.OPEN_READ) && request.isEof()) {
// Send an EOF event
request.getEvent().setType(CometEvent.EventType.EOF);
eof = true;
connector.getContainer().getPipeline().getFirst().event(request, response, request.getEvent());
}
- if (!error && request.isClosed()) {
+ if (!error && request.isEof()) {
request.suspend();
}
if (error || close) {
Modified: trunk/java/org/apache/catalina/connector/InputBuffer.java
===================================================================
--- trunk/java/org/apache/catalina/connector/InputBuffer.java 2008-03-31 10:09:38 UTC (rev 566)
+++ trunk/java/org/apache/catalina/connector/InputBuffer.java 2008-03-31 11:02:10 UTC (rev 567)
@@ -86,6 +86,12 @@
/**
+ * Flag which indicates if the end of stream has been reached.
+ */
+ private boolean eof = false;
+
+
+ /**
* Encoding to use.
*/
private String enc;
@@ -212,6 +218,7 @@
markPos = -1;
bb.recycle();
closed = false;
+ eof = false;
if (conv != null) {
conv.recycle();
@@ -250,6 +257,14 @@
}
+ /**
+ * Returns if the eof has been reached.
+ */
+ public boolean isEof() {
+ return eof;
+ }
+
+
public int available() {
int available = 0;
if (state == BYTE_STATE) {
@@ -294,7 +309,7 @@
public int realReadBytes(byte cbuf[], int off, int len)
throws IOException {
- if (closed)
+ if (eof)
return -1;
if (coyoteRequest == null)
return -1;
@@ -305,7 +320,7 @@
try {
int n = coyoteRequest.doRead(bb);
if (n < 0) {
- closed = true;
+ eof = true;
}
return n;
} catch (IOException e) {
Modified: trunk/java/org/apache/catalina/connector/Request.java
===================================================================
--- trunk/java/org/apache/catalina/connector/Request.java 2008-03-31 10:09:38 UTC (rev 566)
+++ trunk/java/org/apache/catalina/connector/Request.java 2008-03-31 11:02:10 UTC (rev 567)
@@ -473,11 +473,11 @@
/**
- * Read bytes into the low level buffer.
+ * Return true if the EOF has been reached.
*/
- public boolean isClosed()
+ public boolean isEof()
throws IOException {
- return (inputBuffer.isClosed());
+ return (inputBuffer.isEof());
}
16 years, 8 months
JBossWeb SVN: r566 - trunk/java/org/apache/tomcat/util.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-03-31 06:09:38 -0400 (Mon, 31 Mar 2008)
New Revision: 566
Removed:
trunk/java/org/apache/tomcat/util/collections/
Log:
- Remove the collections, which are useless old code (if needed, they are easy to find anyway).
- As it is a specialized structure like MimeHeaders, repackage all relevant MultiMap code in Parameters
(this avoids exposing broken code like remove).
- Repackage all package private classes as protected inner classes.
16 years, 8 months
JBossWeb SVN: r565 - in trunk/java/org/apache/tomcat/util: http and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-03-31 06:02:17 -0400 (Mon, 31 Mar 2008)
New Revision: 565
Removed:
trunk/java/org/apache/tomcat/util/collections/EmptyEnumeration.java
trunk/java/org/apache/tomcat/util/collections/LRUCache.java
trunk/java/org/apache/tomcat/util/collections/MultiMap.java
trunk/java/org/apache/tomcat/util/collections/MultiMapNamesEnumeration.java
trunk/java/org/apache/tomcat/util/collections/MultiMapValuesEnumeration.java
trunk/java/org/apache/tomcat/util/collections/Queue.java
trunk/java/org/apache/tomcat/util/collections/SimpleHashtable.java
trunk/java/org/apache/tomcat/util/collections/SimplePool.java
trunk/java/org/apache/tomcat/util/collections/package.html
trunk/java/org/apache/tomcat/util/http/Parameters2.java
Modified:
trunk/java/org/apache/tomcat/util/http/MimeHeaders.java
trunk/java/org/apache/tomcat/util/http/Parameters.java
Log:
- Remove the collections, which are useless old code (if needed, they are easy to find anyway).
- As it is a specialized structure like MimeHeaders, repackage all relevant MultiMap code in Parameters
(this avoids exposing broken code like remove).
- Repackage all package private classes as protected inner classes.
Deleted: trunk/java/org/apache/tomcat/util/collections/EmptyEnumeration.java
===================================================================
--- trunk/java/org/apache/tomcat/util/collections/EmptyEnumeration.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/collections/EmptyEnumeration.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -1,42 +0,0 @@
-/*
- * 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.tomcat.util.collections;
-
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
-
-public class EmptyEnumeration implements Enumeration {
-
- static EmptyEnumeration staticInstance=new EmptyEnumeration();
-
- public EmptyEnumeration() {
- }
-
- public static Enumeration getEmptyEnumeration() {
- return staticInstance;
- }
-
- public Object nextElement( ) {
- throw new NoSuchElementException( "EmptyEnumeration");
- }
-
- public boolean hasMoreElements() {
- return false;
- }
-
-}
Deleted: trunk/java/org/apache/tomcat/util/collections/LRUCache.java
===================================================================
--- trunk/java/org/apache/tomcat/util/collections/LRUCache.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/collections/LRUCache.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -1,151 +0,0 @@
-/*
- * 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.tomcat.util.collections;
-
-import java.util.Hashtable;
-
-/**
- * This class implements a Generic LRU Cache
- *
- *
- * @author Ignacio J. Ortega
- *
- */
-
-public class LRUCache
-{
- class CacheNode
- {
-
- CacheNode prev;
- CacheNode next;
- Object value;
- Object key;
-
- CacheNode()
- {
- }
- }
-
-
- public LRUCache(int i)
- {
- currentSize = 0;
- cacheSize = i;
- nodes = new Hashtable(i);
- }
-
- public Object get(Object key)
- {
- CacheNode node = (CacheNode)nodes.get(key);
- if(node != null)
- {
- moveToHead(node);
- return node.value;
- }
- else
- {
- return null;
- }
- }
-
- public void put(Object key, Object value)
- {
- CacheNode node = (CacheNode)nodes.get(key);
- if(node == null)
- {
- if(currentSize >= cacheSize)
- {
- if(last != null)
- nodes.remove(last.key);
- removeLast();
- }
- else
- {
- currentSize++;
- }
- node = new CacheNode();
- }
- node.value = value;
- node.key = key;
- moveToHead(node);
- nodes.put(key, node);
- }
-
- public Object remove(Object key) {
- CacheNode node = (CacheNode)nodes.get(key);
- if (node != null) {
- if (node.prev != null) {
- node.prev.next = node.next;
- }
- if (node.next != null) {
- node.next.prev = node.prev;
- }
- if (last == node)
- last = node.prev;
- if (first == node)
- first = node.next;
- }
- return node;
- }
-
- public void clear()
- {
- first = null;
- last = null;
- }
-
- private void removeLast()
- {
- if(last != null)
- {
- if(last.prev != null)
- last.prev.next = null;
- else
- first = null;
- last = last.prev;
- }
- }
-
- private void moveToHead(CacheNode node)
- {
- if(node == first)
- return;
- if(node.prev != null)
- node.prev.next = node.next;
- if(node.next != null)
- node.next.prev = node.prev;
- if(last == node)
- last = node.prev;
- if(first != null)
- {
- node.next = first;
- first.prev = node;
- }
- first = node;
- node.prev = null;
- if(last == null)
- last = first;
- }
-
- private int cacheSize;
- private Hashtable nodes;
- private int currentSize;
- private CacheNode first;
- private CacheNode last;
-}
Deleted: trunk/java/org/apache/tomcat/util/collections/MultiMap.java
===================================================================
--- trunk/java/org/apache/tomcat/util/collections/MultiMap.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/collections/MultiMap.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -1,245 +0,0 @@
-/*
- * 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.tomcat.util.collections;
-
-import java.util.Enumeration;
-
-import org.apache.tomcat.util.buf.MessageBytes;
-
-// Originally MimeHeaders
-
-/**
- * An efficient representation for certain type of map. The keys
- * can have a single or multi values, but most of the time there are
- * single values.
- *
- * The data is of "MessageBytes" type, meaning bytes[] that can be
- * converted to Strings ( if needed, and encoding is lazy-binded ).
- *
- * This is a base class for MimeHeaders, Parameters and Cookies.
- *
- * Data structures: each field is a single-valued key/value.
- * The fields are allocated when needed, and are recycled.
- * The current implementation does linear search, in future we'll
- * also use the hashkey.
- *
- * @author dac(a)eng.sun.com
- * @author James Todd [gonzo(a)eng.sun.com]
- * @author Costin Manolache
- */
-public class MultiMap {
-
- protected Field[] fields;
- // fields in use
- protected int count;
-
- /**
- *
- */
- public MultiMap(int initial_size) {
- fields=new Field[initial_size];
- }
-
- /**
- * Clears all header fields.
- */
- public void recycle() {
- for (int i = 0; i < count; i++) {
- fields[i].recycle();
- }
- count = 0;
- }
-
- // -------------------- Idx access to headers ----------
- // This allows external iterators.
-
- /**
- * Returns the current number of header fields.
- */
- public int size() {
- return count;
- }
-
- /**
- * Return names enumeration.
- */
- public Enumeration names() {
- return new MultiMapNamesEnumeration(this, true, true);
- }
-
- /**
- * Returns the Nth header name
- * This may be used to iterate through all header fields.
- *
- * An exception is thrown if the index is not valid ( <0 or >size )
- */
- public MessageBytes getName(int n) {
- // n >= 0 && n < count ? headers[n].getName() : null
- return fields[n].name;
- }
-
- /**
- * Returns the Nth header value
- * This may be used to iterate through all header fields.
- */
- public MessageBytes getValue(int n) {
- return fields[n].value;
- }
-
- /** Find the index of a field with the given name.
- */
- public int find( String name, int starting ) {
- // We can use a hash - but it's not clear how much
- // benefit you can get - there is an overhead
- // and the number of headers is small (4-5 ?)
- // Another problem is that we'll pay the overhead
- // of constructing the hashtable
-
- // A custom search tree may be better
- for (int i = starting; i < count; i++) {
- if (fields[i].name.equals(name)) {
- return i;
- }
- }
- return -1;
- }
-
- /** Find the index of a field with the given name.
- */
- public int findIgnoreCase( String name, int starting ) {
- // We can use a hash - but it's not clear how much
- // benefit you can get - there is an overhead
- // and the number of headers is small (4-5 ?)
- // Another problem is that we'll pay the overhead
- // of constructing the hashtable
-
- // A custom search tree may be better
- for (int i = starting; i < count; i++) {
- if (fields[i].name.equalsIgnoreCase(name)) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Removes the field at the specified position.
- *
- * MultiMap will preserve the order of field add unless remove()
- * is called. This is not thread-safe, and will invalidate all
- * iterators.
- *
- * This is not a frequent operation for Headers and Parameters -
- * there are better ways ( like adding a "isValid" field )
- */
- public void remove( int i ) {
- // reset and swap with last header
- Field mh = fields[i];
- // reset the field
- mh.recycle();
-
- fields[i] = fields[count - 1];
- fields[count - 1] = mh;
- count--;
- }
-
- /** Create a new, unitialized entry.
- */
- public int addField() {
- int len = fields.length;
- int pos=count;
- if (count >= len) {
- // expand header list array
- Field tmp[] = new Field[pos * 2];
- System.arraycopy(fields, 0, tmp, 0, len);
- fields = tmp;
- }
- if (fields[pos] == null) {
- fields[pos] = new Field();
- }
- count++;
- return pos;
- }
-
- public MessageBytes get( String name) {
- for (int i = 0; i < count; i++) {
- if (fields[i].name.equals(name)) {
- return fields[i].value;
- }
- }
- return null;
- }
-
- public int findFirst( String name ) {
- for (int i = 0; i < count; i++) {
- if (fields[i].name.equals(name)) {
- return i;
- }
- }
- return -1;
- }
-
- public int findNext( int startPos ) {
- int next= fields[startPos].nextPos;
- if( next != MultiMap.NEED_NEXT ) {
- return next;
- }
-
- // next==NEED_NEXT, we never searched for this header
- MessageBytes name=fields[startPos].name;
- for (int i = (startPos + 1); i < count; i++) {
- if (fields[i].name.equals(name)) {
- // cache the search result
- fields[startPos].nextPos=i;
- return i;
- }
- }
- fields[startPos].nextPos= MultiMap.LAST;
- return -1;
- }
-
- // workaround for JDK1.1.8/solaris
- static final int NEED_NEXT=-2;
- static final int LAST=-1;
-
- // -------------------- Internal representation --------------------
- final class Field {
- MessageBytes name = MessageBytes.newInstance();
- MessageBytes value = MessageBytes.newInstance();
-
- // Extra info for speed
-
- // multiple fields with same name - a linked list will
- // speed up multiple name enumerations and search.
- int nextPos;
-
- // hashkey
- int hash;
- Field nextSameHash;
-
- Field() {
- nextPos=MultiMap.NEED_NEXT;
- }
-
- void recycle() {
- name.recycle();
- value.recycle();
- nextPos=MultiMap.NEED_NEXT;
- }
- }
-}
Deleted: trunk/java/org/apache/tomcat/util/collections/MultiMapNamesEnumeration.java
===================================================================
--- trunk/java/org/apache/tomcat/util/collections/MultiMapNamesEnumeration.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/collections/MultiMapNamesEnumeration.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -1,81 +0,0 @@
-/*
- * 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.tomcat.util.collections;
-
-import java.util.Enumeration;
-
-/** Enumerate the distinct header names.
- Each nextElement() is O(n) ( a comparation is
- done with all previous elements ).
-
- This is less frequesnt than add() -
- we want to keep add O(1).
-*/
-public final class MultiMapNamesEnumeration implements Enumeration {
- int pos;
- int size;
- String next;
- MultiMap headers;
-
- // toString and unique options are not implemented -
- // we allways to toString and unique.
-
- /** Create a new multi-map enumeration.
- * @param headers the collection to enumerate
- * @param toString convert each name to string
- * @param unique return only unique names
- */
- MultiMapNamesEnumeration(MultiMap headers, boolean toString,
- boolean unique) {
- this.headers=headers;
- pos=0;
- size = headers.size();
- findNext();
- }
-
- private void findNext() {
- next=null;
- for( ; pos< size; pos++ ) {
- next=headers.getName( pos ).toString();
- for( int j=0; j<pos ; j++ ) {
- if( headers.getName( j ).equalsIgnoreCase( next )) {
- // duplicate.
- next=null;
- break;
- }
- }
- if( next!=null ) {
- // it's not a duplicate
- break;
- }
- }
- // next time findNext is called it will try the
- // next element
- pos++;
- }
-
- public boolean hasMoreElements() {
- return next!=null;
- }
-
- public Object nextElement() {
- String current=next;
- findNext();
- return current;
- }
-}
Deleted: trunk/java/org/apache/tomcat/util/collections/MultiMapValuesEnumeration.java
===================================================================
--- trunk/java/org/apache/tomcat/util/collections/MultiMapValuesEnumeration.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/collections/MultiMapValuesEnumeration.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -1,64 +0,0 @@
-/*
- * 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.tomcat.util.collections;
-
-import java.util.Enumeration;
-
-import org.apache.tomcat.util.buf.MessageBytes;
-
-/** Enumerate the values for a (possibly ) multiple
- * value element.
- */
-class MultiMapValuesEnumeration implements Enumeration {
- int pos;
- int size;
- MessageBytes next;
- MultiMap headers;
- String name;
-
- MultiMapValuesEnumeration(MultiMap headers, String name,
- boolean toString) {
- this.name=name;
- this.headers=headers;
- pos=0;
- size = headers.size();
- findNext();
- }
-
- private void findNext() {
- next=null;
- for( ; pos< size; pos++ ) {
- MessageBytes n1=headers.getName( pos );
- if( n1.equalsIgnoreCase( name )) {
- next=headers.getValue( pos );
- break;
- }
- }
- pos++;
- }
-
- public boolean hasMoreElements() {
- return next!=null;
- }
-
- public Object nextElement() {
- MessageBytes current=next;
- findNext();
- return current.toString();
- }
-}
Deleted: trunk/java/org/apache/tomcat/util/collections/Queue.java
===================================================================
--- trunk/java/org/apache/tomcat/util/collections/Queue.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/collections/Queue.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -1,103 +0,0 @@
-/*
- * 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.tomcat.util.collections;
-
-import java.util.Vector;
-
-/**
- * A simple FIFO queue class which causes the calling thread to wait
- * if the queue is empty and notifies threads that are waiting when it
- * is not empty.
- *
- * @author Anil V (akv(a)eng.sun.com)
- */
-public class Queue {
- private Vector vector = new Vector();
- private boolean stopWaiting=false;
- private boolean waiting=false;
-
- /**
- * Put the object into the queue.
- *
- * @param object the object to be appended to the
- * queue.
- */
- public synchronized void put(Object object) {
- vector.addElement(object);
- notify();
- }
-
- /** Break the pull(), allowing the calling thread to exit
- */
- public synchronized void stop() {
- stopWaiting=true;
- // just a hack to stop waiting
- if( waiting ) notify();
- }
-
- /**
- * Pull the first object out of the queue. Wait if the queue is
- * empty.
- */
- public synchronized Object pull() {
- while (isEmpty()) {
- try {
- waiting=true;
- wait();
- } catch (InterruptedException ex) {
- }
- waiting=false;
- if( stopWaiting ) return null;
- }
- return get();
- }
-
- /**
- * Get the first object out of the queue. Return null if the queue
- * is empty.
- */
- public synchronized Object get() {
- Object object = peek();
- if (object != null)
- vector.removeElementAt(0);
- return object;
- }
-
- /**
- * Peek to see if something is available.
- */
- public Object peek() {
- if (isEmpty())
- return null;
- return vector.elementAt(0);
- }
-
- /**
- * Is the queue empty?
- */
- public boolean isEmpty() {
- return vector.isEmpty();
- }
-
- /**
- * How many elements are there in this queue?
- */
- public int size() {
- return vector.size();
- }
-}
Deleted: trunk/java/org/apache/tomcat/util/collections/SimpleHashtable.java
===================================================================
--- trunk/java/org/apache/tomcat/util/collections/SimpleHashtable.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/collections/SimpleHashtable.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -1,324 +0,0 @@
-/*
- * 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.tomcat.util.collections;
-
-import java.util.Enumeration;
-
-/* **************************************** Stolen from Crimson ******************** */
-/* From Crimson/Parser - in a perfect world we'll just have a common set of
- utilities, and all apache project will just use those.
-
-*/
-
-// can't be replaced using a Java 2 "Collections" API
-// since this package must also run on JDK 1.1
-
-
-/**
- * This class implements a special purpose hashtable. It works like a
- * normal <code>java.util.Hashtable</code> except that: <OL>
- *
- * <LI> Keys to "get" are strings which are known to be interned,
- * so that "==" is used instead of "String.equals". (Interning
- * could be document-relative instead of global.)
- *
- * <LI> It's not synchronized, since it's to be used only by
- * one thread at a time.
- *
- * <LI> The keys () enumerator allocates no memory, with live
- * updates to the data disallowed.
- *
- * <LI> It's got fewer bells and whistles: fixed threshold and
- * load factor, no JDK 1.2 collection support, only keys can be
- * enumerated, things can't be removed, simpler inheritance; more.
- *
- * </OL>
- *
- * <P> The overall result is that it's less expensive to use these in
- * performance-critical locations, in terms both of CPU and memory,
- * than <code>java.util.Hashtable</code> instances. In this package
- * it makes a significant difference when normalizing attributes,
- * which is done for each start-element construct.
- *
- */
-public final class SimpleHashtable implements Enumeration
-{
-
- private static org.jboss.logging.Logger log=
- org.jboss.logging.Logger.getLogger( SimpleHashtable.class );
-
- // entries ...
- private Entry table[];
-
- // currently enumerated key
- private Entry current = null;
- private int currentBucket = 0;
-
- // number of elements in hashtable
- private int count;
- private int threshold;
-
- private static final float loadFactor = 0.75f;
-
-
- /**
- * Constructs a new, empty hashtable with the specified initial
- * capacity.
- *
- * @param initialCapacity the initial capacity of the hashtable.
- */
- public SimpleHashtable(int initialCapacity) {
- if (initialCapacity < 0)
- throw new IllegalArgumentException("Illegal Capacity: "+
- initialCapacity);
- if (initialCapacity==0)
- initialCapacity = 1;
- table = new Entry[initialCapacity];
- threshold = (int)(initialCapacity * loadFactor);
- }
-
- /**
- * Constructs a new, empty hashtable with a default capacity.
- */
- public SimpleHashtable() {
- this(11);
- }
-
- /**
- */
- public void clear ()
- {
- count = 0;
- currentBucket = 0;
- current = null;
- for (int i = 0; i < table.length; i++)
- table [i] = null;
- }
-
- /**
- * Returns the number of keys in this hashtable.
- *
- * @return the number of keys in this hashtable.
- */
- public int size() {
- return count;
- }
-
- /**
- * Returns an enumeration of the keys in this hashtable.
- *
- * @return an enumeration of the keys in this hashtable.
- * @see Enumeration
- */
- public Enumeration keys() {
- currentBucket = 0;
- current = null;
- hasMoreElements();
- return this;
- }
-
- /**
- * Used to view this as an enumeration; returns true if there
- * are more keys to be enumerated.
- */
- public boolean hasMoreElements ()
- {
- if (current != null)
- return true;
- while (currentBucket < table.length) {
- current = table [currentBucket++];
- if (current != null)
- return true;
- }
- return false;
- }
-
- /**
- * Used to view this as an enumeration; returns the next key
- * in the enumeration.
- */
- public Object nextElement ()
- {
- Object retval;
-
- if (current == null)
- throw new IllegalStateException ();
- retval = current.key;
- current = current.next;
- // Advance to the next position ( we may call next after next,
- // without hasMore )
- hasMoreElements();
- return retval;
- }
-
-
- /**
- * Returns the value to which the specified key is mapped in this hashtable.
- */
- public Object getInterned (String key) {
- Entry tab[] = table;
- int hash = key.hashCode();
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index] ; e != null ; e = e.next) {
- if ((e.hash == hash) && (e.key == key))
- return e.value;
- }
- return null;
- }
-
- /**
- * Returns the value to which the specified key is mapped in this
- * hashtable ... the key isn't necessarily interned, though.
- */
- public Object get(String key) {
- Entry tab[] = table;
- int hash = key.hashCode();
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index] ; e != null ; e = e.next) {
- if ((e.hash == hash) && e.key.equals(key))
- return e.value;
- }
- return null;
- }
-
- /**
- * Increases the capacity of and internally reorganizes this
- * hashtable, in order to accommodate and access its entries more
- * efficiently. This method is called automatically when the
- * number of keys in the hashtable exceeds this hashtable's capacity
- * and load factor.
- */
- private void rehash() {
- int oldCapacity = table.length;
- Entry oldMap[] = table;
-
- int newCapacity = oldCapacity * 2 + 1;
- Entry newMap[] = new Entry[newCapacity];
-
- threshold = (int)(newCapacity * loadFactor);
- table = newMap;
-
- /*
- System.out.pr intln("rehash old=" + oldCapacity
- + ", new=" + newCapacity
- + ", thresh=" + threshold
- + ", count=" + count);
- */
-
- for (int i = oldCapacity ; i-- > 0 ;) {
- for (Entry old = oldMap[i] ; old != null ; ) {
- Entry e = old;
- old = old.next;
-
- int index = (e.hash & 0x7FFFFFFF) % newCapacity;
- e.next = newMap[index];
- newMap[index] = e;
- }
- }
- }
-
- /**
- * Maps the specified <code>key</code> to the specified
- * <code>value</code> in this hashtable. Neither the key nor the
- * value can be <code>null</code>.
- *
- * <P>The value can be retrieved by calling the <code>get</code> method
- * with a key that is equal to the original key.
- */
- public Object put(Object key, Object value) {
- // Make sure the value is not null
- if (value == null) {
- throw new NullPointerException();
- }
-
- // Makes sure the key is not already in the hashtable.
- Entry tab[] = table;
- int hash = key.hashCode();
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index] ; e != null ; e = e.next) {
- // if ((e.hash == hash) && e.key.equals(key)) {
- if ((e.hash == hash) && (e.key == key)) {
- Object old = e.value;
- e.value = value;
- return old;
- }
- }
-
- if (count >= threshold) {
- // Rehash the table if the threshold is exceeded
- rehash();
-
- tab = table;
- index = (hash & 0x7FFFFFFF) % tab.length;
- }
-
- // Creates the new entry.
- Entry e = new Entry(hash, key, value, tab[index]);
- tab[index] = e;
- count++;
- return null;
- }
-
- public Object remove(Object key) {
- Entry tab[] = table;
- Entry prev=null;
- int hash = key.hashCode();
- int index = (hash & 0x7FFFFFFF) % tab.length;
- if( dL > 0 ) d("Idx " + index + " " + tab[index] );
- for (Entry e = tab[index] ; e != null ; prev=e, e = e.next) {
- if( dL > 0 ) d("> " + prev + " " + e.next + " " + e + " " + e.key);
- if ((e.hash == hash) && e.key.equals(key)) {
- if( prev!=null ) {
- prev.next=e.next;
- } else {
- tab[index]=e.next;
- }
- if( dL > 0 ) d("Removing from list " + tab[index] + " " + prev +
- " " + e.value);
- count--;
- Object res=e.value;
- e.value=null;
- return res;
- }
- }
- return null;
- }
-
- /**
- * Hashtable collision list.
- */
- private static class Entry {
- int hash;
- Object key;
- Object value;
- Entry next;
-
- protected Entry(int hash, Object key, Object value, Entry next) {
- this.hash = hash;
- this.key = key;
- this.value = value;
- this.next = next;
- }
- }
-
- private static final int dL=0;
- private void d(String s ) {
- if (log.isDebugEnabled())
- log.debug( "SimpleHashtable: " + s );
- }
-}
Deleted: trunk/java/org/apache/tomcat/util/collections/SimplePool.java
===================================================================
--- trunk/java/org/apache/tomcat/util/collections/SimplePool.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/collections/SimplePool.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -1,128 +0,0 @@
-/*
- * 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.tomcat.util.collections;
-
-/**
- * Simple object pool. Based on ThreadPool and few other classes
- *
- * The pool will ignore overflow and return null if empty.
- *
- * @author Gal Shachor
- * @author Costin Manolache
- */
-public final class SimplePool {
-
-
- private static org.jboss.logging.Logger log=
- org.jboss.logging.Logger.getLogger(SimplePool.class );
-
- /*
- * Where the threads are held.
- */
- private Object pool[];
-
- private int max;
- private int last;
- private int current=-1;
-
- private Object lock;
- public static final int DEFAULT_SIZE=32;
- static final int debug=0;
-
- public SimplePool() {
- this(DEFAULT_SIZE,DEFAULT_SIZE);
- }
-
- public SimplePool(int size) {
- this(size, size);
- }
-
- public SimplePool(int size, int max) {
- this.max=max;
- pool=new Object[size];
- this.last=size-1;
- lock=new Object();
- }
-
- public void set(Object o) {
- put(o);
- }
-
- /**
- * Add the object to the pool, silent nothing if the pool is full
- */
- public void put(Object o) {
- synchronized( lock ) {
- if( current < last ) {
- current++;
- pool[current] = o;
- } else if( current < max ) {
- // realocate
- int newSize=pool.length*2;
- if( newSize > max ) newSize=max+1;
- Object tmp[]=new Object[newSize];
- last=newSize-1;
- System.arraycopy( pool, 0, tmp, 0, pool.length);
- pool=tmp;
- current++;
- pool[current] = o;
- }
- if( debug > 0 ) log("put " + o + " " + current + " " + max );
- }
- }
-
- /**
- * Get an object from the pool, null if the pool is empty.
- */
- public Object get() {
- Object item = null;
- synchronized( lock ) {
- if( current >= 0 ) {
- item = pool[current];
- pool[current] = null;
- current -= 1;
- }
- if( debug > 0 )
- log("get " + item + " " + current + " " + max);
- }
- return item;
- }
-
- /**
- * Return the size of the pool
- */
- public int getMax() {
- return max;
- }
-
- /**
- * Number of object in the pool
- */
- public int getCount() {
- return current+1;
- }
-
-
- public void shutdown() {
- }
-
- private void log( String s ) {
- if (log.isDebugEnabled())
- log.debug("SimplePool: " + s );
- }
-}
Deleted: trunk/java/org/apache/tomcat/util/collections/package.html
===================================================================
--- trunk/java/org/apache/tomcat/util/collections/package.html 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/collections/package.html 2008-03-31 10:02:17 UTC (rev 565)
@@ -1,17 +0,0 @@
-<html>
-<head>
-<title>util.collections</title>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-</head>
-
-<body bgcolor="#FFFFFF">
-<h1>Specialized collections</h1>
-
-This package includes a number of special collections, tunned for server-side
-applications.
-
-The utils are not tomcat specific, but use MessageBytes and few other
-top-level utils.
-
-</body>
-</html>
Modified: trunk/java/org/apache/tomcat/util/http/MimeHeaders.java
===================================================================
--- trunk/java/org/apache/tomcat/util/http/MimeHeaders.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/http/MimeHeaders.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -49,24 +49,22 @@
*/
/* Headers are first parsed and stored in the order they are
- received. This is based on the fact that most servlets will not
- directly access all headers, and most headers are single-valued.
- ( the alternative - a hash or similar data structure - will add
- an overhead that is not needed in most cases )
-
- Apache seems to be using a similar method for storing and manipulating
- headers.
-
- Future enhancements:
- - hash the headers the first time a header is requested ( i.e. if the
- servlet needs direct access to headers).
- - scan "common" values ( length, cookies, etc ) during the parse
- ( addHeader hook )
-
-*/
-
+ received. This is based on the fact that most servlets will not
+ directly access all headers, and most headers are single-valued.
+ ( the alternative - a hash or similar data structure - will add
+ an overhead that is not needed in most cases )
+ Apache seems to be using a similar method for storing and manipulating
+ headers.
+ Future enhancements:
+ - hash the headers the first time a header is requested ( i.e. if the
+ servlet needs direct access to headers).
+ - scan "common" values ( length, cookies, etc ) during the parse
+ ( addHeader hook )
+
+ */
+
/**
* Memory-efficient repository for Mime Headers. When the object is recycled, it
* will keep the allocated headers[] and all the MimeHeaderField - no GC is generated.
@@ -92,16 +90,140 @@
* @author kevin seguin
*/
public class MimeHeaders {
+
+ /**
+ * Enumerate the distinct header names.
+ * Each nextElement() is O(n) ( a comparation is
+ * done with all previous elements ).
+ * This is less frequesnt than add() -
+ * we want to keep add O(1).
+ */
+ protected class NamesEnumerator implements Enumeration {
+ int pos;
+ int size;
+ String next;
+ MimeHeaders headers;
+
+ NamesEnumerator(MimeHeaders headers) {
+ this.headers = headers;
+ pos = 0;
+ size = headers.size();
+ findNext();
+ }
+
+ private void findNext() {
+ next = null;
+ for (; pos < size; pos++) {
+ next = headers.getName(pos).toString();
+ for (int j = 0; j < pos; j++) {
+ if (headers.getName(j).equalsIgnoreCase(next)) {
+ // duplicate.
+ next = null;
+ break;
+ }
+ }
+ if (next != null) {
+ // it's not a duplicate
+ break;
+ }
+ }
+ // next time findNext is called it will try the
+ // next element
+ pos++;
+ }
+
+ public boolean hasMoreElements() {
+ return next != null;
+ }
+
+ public Object nextElement() {
+ String current = next;
+ findNext();
+ return current;
+ }
+ }
+
+ /** Enumerate the values for a (possibly ) multiple
+ value element.
+ */
+ protected class ValuesEnumerator implements Enumeration {
+ int pos;
+ int size;
+ MessageBytes next;
+ MimeHeaders headers;
+ String name;
+
+ ValuesEnumerator(MimeHeaders headers, String name) {
+ this.name = name;
+ this.headers = headers;
+ pos = 0;
+ size = headers.size();
+ findNext();
+ }
+
+ private void findNext() {
+ next = null;
+ for (; pos < size; pos++) {
+ MessageBytes n1 = headers.getName(pos);
+ if (n1.equalsIgnoreCase(name)) {
+ next = headers.getValue(pos);
+ break;
+ }
+ }
+ pos++;
+ }
+
+ public boolean hasMoreElements() {
+ return next != null;
+ }
+
+ public Object nextElement() {
+ MessageBytes current = next;
+ findNext();
+ return current.toString();
+ }
+ }
+
+ protected class MimeHeaderField {
+ // multiple headers with same name - a linked list will
+ // speed up name enumerations and search ( both cpu and
+ // GC)
+ MimeHeaderField next;
+ MimeHeaderField prev;
+
+ protected final MessageBytes nameB = MessageBytes.newInstance();
+ protected final MessageBytes valueB = MessageBytes.newInstance();
+
+ /**
+ * Creates a new, uninitialized header field.
+ */
+ public MimeHeaderField() {
+ }
+
+ public void recycle() {
+ nameB.recycle();
+ valueB.recycle();
+ next = null;
+ }
+
+ public MessageBytes getName() {
+ return nameB;
+ }
+
+ public MessageBytes getValue() {
+ return valueB;
+ }
+ }
+
/** Initial size - should be == average number of headers per request
* XXX make it configurable ( fine-tuning of web-apps )
*/
- public static final int DEFAULT_HEADER_SIZE=8;
-
+ public static final int DEFAULT_HEADER_SIZE = 8;
+
/**
* The header fields.
*/
- private MimeHeaderField[] headers = new
- MimeHeaderField[DEFAULT_HEADER_SIZE];
+ private MimeHeaderField[] headers = new MimeHeaderField[DEFAULT_HEADER_SIZE];
/**
* The current number of header fields.
@@ -141,14 +263,14 @@
pw.println("=== MimeHeaders ===");
Enumeration e = names();
while (e.hasMoreElements()) {
- String n = (String)e.nextElement();
+ String n = (String) e.nextElement();
pw.println(n + " = " + getHeader(n));
}
return sw.toString();
}
// -------------------- Idx access to headers ----------
-
+
/**
* Returns the current number of header fields.
*/
@@ -174,7 +296,7 @@
/** Find the index of a header with the given name.
*/
- public int findHeader( String name, int starting ) {
+ public int findHeader(String name, int starting) {
// We can use a hash - but it's not clear how much
// benefit you can get - there is an overhead
// and the number of headers is small (4-5 ?)
@@ -189,7 +311,7 @@
}
return -1;
}
-
+
// -------------------- --------------------
/**
@@ -206,7 +328,6 @@
}
// -------------------- Adding headers --------------------
-
/**
* Adds a partially constructed field to the header. This
@@ -230,9 +351,9 @@
/** Create a new named header , return the MessageBytes
container for the new value
- */
- public MessageBytes addValue( String name ) {
- MimeHeaderField mh = createHeader();
+ */
+ public MessageBytes addValue(String name) {
+ MimeHeaderField mh = createHeader();
mh.getName().setString(name);
return mh.getValue();
}
@@ -241,18 +362,16 @@
The conversion to chars can be delayed until
encoding is known.
*/
- public MessageBytes addValue(byte b[], int startN, int len)
- {
- MimeHeaderField mhf=createHeader();
+ public MessageBytes addValue(byte b[], int startN, int len) {
+ MimeHeaderField mhf = createHeader();
mhf.getName().setBytes(b, startN, len);
return mhf.getValue();
}
/** Create a new named header using translated char[].
*/
- public MessageBytes addValue(char c[], int startN, int len)
- {
- MimeHeaderField mhf=createHeader();
+ public MessageBytes addValue(char c[], int startN, int len) {
+ MimeHeaderField mhf = createHeader();
mhf.getName().setChars(c, startN, len);
return mhf.getValue();
}
@@ -261,12 +380,12 @@
return a MessageBytes container for the
header value ( existing header or new
if this .
- */
- public MessageBytes setValue( String name ) {
- for ( int i = 0; i < count; i++ ) {
- if(headers[i].getName().equalsIgnoreCase(name)) {
- for ( int j=i+1; j < count; j++ ) {
- if(headers[j].getName().equalsIgnoreCase(name)) {
+ */
+ public MessageBytes setValue(String name) {
+ for (int i = 0; i < count; i++) {
+ if (headers[i].getName().equalsIgnoreCase(name)) {
+ for (int j = i + 1; j < count; j++) {
+ if (headers[j].getName().equalsIgnoreCase(name)) {
removeHeader(j--);
}
}
@@ -342,7 +461,7 @@
*/
private void removeHeader(int idx) {
MimeHeaderField mh = headers[idx];
-
+
mh.recycle();
headers[idx] = headers[count - 1];
headers[count - 1] = mh;
@@ -350,127 +469,3 @@
}
}
-
-/** Enumerate the distinct header names.
- Each nextElement() is O(n) ( a comparation is
- done with all previous elements ).
-
- This is less frequesnt than add() -
- we want to keep add O(1).
-*/
-class NamesEnumerator implements Enumeration {
- int pos;
- int size;
- String next;
- MimeHeaders headers;
-
- NamesEnumerator(MimeHeaders headers) {
- this.headers=headers;
- pos=0;
- size = headers.size();
- findNext();
- }
-
- private void findNext() {
- next=null;
- for( ; pos< size; pos++ ) {
- next=headers.getName( pos ).toString();
- for( int j=0; j<pos ; j++ ) {
- if( headers.getName( j ).equalsIgnoreCase( next )) {
- // duplicate.
- next=null;
- break;
- }
- }
- if( next!=null ) {
- // it's not a duplicate
- break;
- }
- }
- // next time findNext is called it will try the
- // next element
- pos++;
- }
-
- public boolean hasMoreElements() {
- return next!=null;
- }
-
- public Object nextElement() {
- String current=next;
- findNext();
- return current;
- }
-}
-
-/** Enumerate the values for a (possibly ) multiple
- value element.
-*/
-class ValuesEnumerator implements Enumeration {
- int pos;
- int size;
- MessageBytes next;
- MimeHeaders headers;
- String name;
-
- ValuesEnumerator(MimeHeaders headers, String name) {
- this.name=name;
- this.headers=headers;
- pos=0;
- size = headers.size();
- findNext();
- }
-
- private void findNext() {
- next=null;
- for( ; pos< size; pos++ ) {
- MessageBytes n1=headers.getName( pos );
- if( n1.equalsIgnoreCase( name )) {
- next=headers.getValue( pos );
- break;
- }
- }
- pos++;
- }
-
- public boolean hasMoreElements() {
- return next!=null;
- }
-
- public Object nextElement() {
- MessageBytes current=next;
- findNext();
- return current.toString();
- }
-}
-
-class MimeHeaderField {
- // multiple headers with same name - a linked list will
- // speed up name enumerations and search ( both cpu and
- // GC)
- MimeHeaderField next;
- MimeHeaderField prev;
-
- protected final MessageBytes nameB = MessageBytes.newInstance();
- protected final MessageBytes valueB = MessageBytes.newInstance();
-
- /**
- * Creates a new, uninitialized header field.
- */
- public MimeHeaderField() {
- }
-
- public void recycle() {
- nameB.recycle();
- valueB.recycle();
- next=null;
- }
-
- public MessageBytes getName() {
- return nameB;
- }
-
- public MessageBytes getValue() {
- return valueB;
- }
-}
Modified: trunk/java/org/apache/tomcat/util/http/Parameters.java
===================================================================
--- trunk/java/org/apache/tomcat/util/http/Parameters.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/http/Parameters.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -25,24 +25,114 @@
import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.buf.UDecoder;
-import org.apache.tomcat.util.collections.MultiMap;
/**
*
* @author Costin Manolache
* @author Remy Maucherat
*/
-public final class Parameters extends MultiMap {
+public final class Parameters {
- protected static org.jboss.logging.Logger log =
- org.jboss.logging.Logger.getLogger(Parameters.class);
+ protected static org.jboss.logging.Logger log = org.jboss.logging.Logger
+ .getLogger(Parameters.class);
+ protected static final int NEED_NEXT = -2;
+ protected static final int LAST = -1;
public static final int INITIAL_SIZE = 8;
protected static final String[] ARRAY_TYPE = new String[0];
+ protected class Field {
+ MessageBytes name = MessageBytes.newInstance();
+ MessageBytes value = MessageBytes.newInstance();
+
+ // Extra info for speed
+
+ // multiple fields with same name - a linked list will
+ // speed up multiple name enumerations and search.
+ int nextPos;
+
+ // hashkey
+ int hash;
+ Field nextSameHash;
+
+ Field() {
+ nextPos = NEED_NEXT;
+ }
+
+ void recycle() {
+ name.recycle();
+ value.recycle();
+ nextPos = NEED_NEXT;
+ }
+ }
+
+ /**
+ * Enumerate the distinct header names. Each nextElement() is O(n) ( a
+ * comparation is done with all previous elements ).
+ *
+ * This is less frequesnt than add() - we want to keep add O(1).
+ */
+ protected class NamesEnumeration implements Enumeration {
+ int pos;
+ String next;
+
+ // toString and unique options are not implemented -
+ // we allways to toString and unique.
+
+ /**
+ * Create a new multi-map enumeration.
+ *
+ * @param headers
+ * the collection to enumerate
+ * @param toString
+ * convert each name to string
+ * @param unique
+ * return only unique names
+ */
+ public NamesEnumeration() {
+ pos = 0;
+ findNext();
+ }
+
+ private void findNext() {
+ next = null;
+ for (; pos < count; pos++) {
+ next = getName(pos).toString();
+ for (int j = 0; j < pos; j++) {
+ if (getName(j).equalsIgnoreCase(next)) {
+ // duplicate.
+ next = null;
+ break;
+ }
+ }
+ if (next != null) {
+ // it's not a duplicate
+ break;
+ }
+ }
+ // next time findNext is called it will try the
+ // next element
+ pos++;
+ }
+
+ public boolean hasMoreElements() {
+ return next != null;
+ }
+
+ public Object nextElement() {
+ String current = next;
+ findNext();
+ return current;
+ }
+ }
+
+ protected Field[] fields;
+ // fields in use
+ protected int count;
+
protected boolean didQueryParameters = false;
protected boolean didMerge = false;
-
+
protected MessageBytes queryMB;
protected UDecoder urlDec;
@@ -50,12 +140,12 @@
protected String encoding = null;
protected String queryStringEncoding = null;
-
+
/**
*
*/
public Parameters() {
- super(INITIAL_SIZE);
+ fields = new Field[INITIAL_SIZE];
}
public void setQuery(MessageBytes queryMB) {
@@ -79,17 +169,93 @@
}
public void recycle() {
- super.recycle();
+ for (int i = 0; i < count; i++) {
+ fields[i].recycle();
+ }
+ count = 0;
didQueryParameters = false;
didMerge = false;
encoding = null;
decodedQuery.recycle();
}
-
+
+ /**
+ * Returns the current number of header fields.
+ */
+ protected int size() {
+ return count;
+ }
+
+ /**
+ * Returns the Nth header name This may be used to iterate through all
+ * header fields.
+ *
+ * An exception is thrown if the index is not valid ( <0 or >size )
+ */
+ protected MessageBytes getName(int n) {
+ // n >= 0 && n < count ? headers[n].getName() : null
+ return fields[n].name;
+ }
+
+ /**
+ * Returns the Nth header value This may be used to iterate through all
+ * header fields.
+ */
+ protected MessageBytes getValue(int n) {
+ return fields[n].value;
+ }
+
+ /**
+ * Create a new, unitialized entry.
+ */
+ protected int addField() {
+ int len = fields.length;
+ int pos = count;
+ if (count >= len) {
+ // expand header list array
+ Field tmp[] = new Field[pos * 2];
+ System.arraycopy(fields, 0, tmp, 0, len);
+ fields = tmp;
+ }
+ if (fields[pos] == null) {
+ fields[pos] = new Field();
+ }
+ count++;
+ return pos;
+ }
+
+ protected int findFirst(String name) {
+ for (int i = 0; i < count; i++) {
+ if (fields[i].name.equals(name)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ protected int findNext(int startPos) {
+ int next = fields[startPos].nextPos;
+ if (next != NEED_NEXT) {
+ return next;
+ }
+
+ // next==NEED_NEXT, we never searched for this header
+ MessageBytes name = fields[startPos].name;
+ for (int i = (startPos + 1); i < count; i++) {
+ if (fields[i].name.equals(name)) {
+ // cache the search result
+ fields[startPos].nextPos = i;
+ return i;
+ }
+ }
+ fields[startPos].nextPos = LAST;
+ return -1;
+ }
+
// -------------------- Data access --------------------
// Access to the current name/values, no side effect ( processing ).
// You must explicitely call handleQueryParameters and the post methods.
-
+
// This is the original data representation ( hash of String->String[])
public void addParameterValues(String name, String[] values) {
@@ -118,10 +284,10 @@
return null;
}
}
-
+
public Enumeration getParameterNames() {
handleQueryParameters();
- return names();
+ return new NamesEnumeration();
}
// Shortcut.
@@ -134,30 +300,32 @@
return null;
}
}
+
// -------------------- Processing --------------------
/** Process the query string into parameters
*/
public void handleQueryParameters() {
- if( didQueryParameters ) return;
+ if (didQueryParameters)
+ return;
- didQueryParameters=true;
+ didQueryParameters = true;
- if( queryMB==null || queryMB.isNull() )
+ if (queryMB == null || queryMB.isNull())
return;
-
- if( debug > 0 )
- log( "Decoding query " + decodedQuery + " " + queryStringEncoding);
+ if (debug > 0)
+ log("Decoding query " + decodedQuery + " " + queryStringEncoding);
+
try {
- decodedQuery.duplicate( queryMB );
+ decodedQuery.duplicate(queryMB);
} catch (IOException e) {
// Can't happen, as decodedQuery can't overflow
e.printStackTrace();
}
- processParameters( decodedQuery, queryStringEncoding );
+ processParameters(decodedQuery, queryStringEncoding);
}
- protected void addParam( String name, String value ) {
+ protected void addParam(String name, String value) {
if (name == null) {
return;
}
@@ -175,87 +343,88 @@
protected CharChunk tmpNameC = new CharChunk(32);
protected CharChunk tmpValueC = new CharChunk(128);
- public void processParameters( MessageBytes data ) {
+ public void processParameters(MessageBytes data) {
processParameters(data, encoding);
}
- public void processParameters( MessageBytes data, String encoding ) {
- if( data==null || data.isNull() || data.getLength() <= 0 ) return;
+ public void processParameters(MessageBytes data, String encoding) {
+ if (data == null || data.isNull() || data.getLength() <= 0)
+ return;
if (data.getType() != MessageBytes.T_BYTES) {
data.toBytes();
}
- ByteChunk bc=data.getByteChunk();
- processParameters( bc.getBytes(), bc.getOffset(),
- bc.getLength(), encoding);
+ ByteChunk bc = data.getByteChunk();
+ processParameters(bc.getBytes(), bc.getOffset(), bc.getLength(),
+ encoding);
}
- public void processParameters( byte bytes[], int start, int len ) {
+ public void processParameters(byte bytes[], int start, int len) {
processParameters(bytes, start, len, encoding);
}
- public void processParameters( byte bytes[], int start, int len,
- String enc ) {
- int end=start+len;
- int pos=start;
-
- if( debug>0 )
- log( "Bytes: " + new String( bytes, start, len ));
+ public void processParameters(byte bytes[], int start, int len, String enc) {
+ int end = start + len;
+ int pos = start;
+ if (debug > 0)
+ log("Bytes: " + new String(bytes, start, len));
+
do {
- boolean noEq=false;
- int valStart=-1;
- int valEnd=-1;
-
- int nameStart=pos;
- int nameEnd=ByteChunk.indexOf(bytes, nameStart, end, '=' );
+ boolean noEq = false;
+ int valStart = -1;
+ int valEnd = -1;
+
+ int nameStart = pos;
+ int nameEnd = ByteChunk.indexOf(bytes, nameStart, end, '=');
// Workaround for a&b&c encoding
- int nameEnd2=ByteChunk.indexOf(bytes, nameStart, end, '&' );
- if( (nameEnd2!=-1 ) &&
- ( nameEnd==-1 || nameEnd > nameEnd2) ) {
- nameEnd=nameEnd2;
- noEq=true;
- valStart=nameEnd;
- valEnd=nameEnd;
- if( debug>0) log("no equal " + nameStart + " " + nameEnd + " " + new String(bytes, nameStart, nameEnd-nameStart) );
+ int nameEnd2 = ByteChunk.indexOf(bytes, nameStart, end, '&');
+ if ((nameEnd2 != -1) && (nameEnd == -1 || nameEnd > nameEnd2)) {
+ nameEnd = nameEnd2;
+ noEq = true;
+ valStart = nameEnd;
+ valEnd = nameEnd;
+ if (debug > 0)
+ log("no equal " + nameStart + " " + nameEnd + " "
+ + new String(bytes, nameStart, nameEnd - nameStart));
}
- if( nameEnd== -1 )
- nameEnd=end;
+ if (nameEnd == -1)
+ nameEnd = end;
- if( ! noEq ) {
- valStart= (nameEnd < end) ? nameEnd+1 : end;
- valEnd=ByteChunk.indexOf(bytes, valStart, end, '&');
- if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
+ if (!noEq) {
+ valStart = (nameEnd < end) ? nameEnd + 1 : end;
+ valEnd = ByteChunk.indexOf(bytes, valStart, end, '&');
+ if (valEnd == -1)
+ valEnd = (valStart < end) ? end : valStart;
}
-
- pos=valEnd+1;
-
- if( nameEnd<=nameStart ) {
+
+ pos = valEnd + 1;
+
+ if (nameEnd <= nameStart) {
log.warn("Parameters: Invalid chunk ignored.");
continue;
// invalid chunk - it's better to ignore
}
- tmpName.setBytes( bytes, nameStart, nameEnd-nameStart );
- tmpValue.setBytes( bytes, valStart, valEnd-valStart );
+ tmpName.setBytes(bytes, nameStart, nameEnd - nameStart);
+ tmpValue.setBytes(bytes, valStart, valEnd - valStart);
try {
- addParam( urlDecode(tmpName, enc), urlDecode(tmpValue, enc) );
+ addParam(urlDecode(tmpName, enc), urlDecode(tmpValue, enc));
} catch (IOException e) {
// Exception during character decoding: skip parameter
- log.warn("Parameters: Character decoding failed. " +
- "Parameter skipped.", e);
+ log.warn("Parameters: Character decoding failed. "
+ + "Parameter skipped.", e);
}
tmpName.recycle();
tmpValue.recycle();
- } while( pos<end );
+ } while (pos < end);
}
- protected String urlDecode(ByteChunk bc, String enc)
- throws IOException {
- if( urlDec==null ) {
- urlDec=new UDecoder();
+ protected String urlDecode(ByteChunk bc, String enc) throws IOException {
+ if (urlDec == null) {
+ urlDec = new UDecoder();
}
urlDec.convert(bc);
String result = null;
@@ -283,23 +452,24 @@
/** Debug purpose
*/
public String paramsAsString() {
- StringBuffer sb=new StringBuffer();
- Enumeration en= names();
- while( en.hasMoreElements() ) {
- String k=(String)en.nextElement();
- sb.append( k ).append("=");
- String v[]=(String[])getParameterValues(k);
- for( int i=0; i<v.length; i++ )
- sb.append( v[i] ).append(",");
+ StringBuffer sb = new StringBuffer();
+ Enumeration en = getParameterNames();
+ while (en.hasMoreElements()) {
+ String k = (String) en.nextElement();
+ sb.append(k).append("=");
+ String v[] = (String[]) getParameterValues(k);
+ for (int i = 0; i < v.length; i++)
+ sb.append(v[i]).append(",");
sb.append("\n");
}
return sb.toString();
}
- private static int debug=0;
- private void log(String s ) {
+ private static int debug = 0;
+
+ private void log(String s) {
if (log.isDebugEnabled())
- log.debug("Parameters: " + s );
+ log.debug("Parameters: " + s);
}
-
+
}
Deleted: trunk/java/org/apache/tomcat/util/http/Parameters2.java
===================================================================
--- trunk/java/org/apache/tomcat/util/http/Parameters2.java 2008-03-29 06:57:17 UTC (rev 564)
+++ trunk/java/org/apache/tomcat/util/http/Parameters2.java 2008-03-31 10:02:17 UTC (rev 565)
@@ -1,611 +0,0 @@
-/*
- * 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.tomcat.util.http;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.CharChunk;
-import org.apache.tomcat.util.buf.MessageBytes;
-import org.apache.tomcat.util.buf.UDecoder;
-import org.apache.tomcat.util.collections.MultiMap;
-
-/**
- *
- * @author Costin Manolache
- * @deprecated
- */
-public final class Parameters2 extends MultiMap {
-
-
- private static org.jboss.logging.Logger log=
- org.jboss.logging.Logger.getLogger(Parameters2.class );
-
- // Transition: we'll use the same Hashtable( String->String[] )
- // for the beginning. When we are sure all accesses happen through
- // this class - we can switch to MultiMap
- private Hashtable paramHashStringArray=new Hashtable();
- private boolean didQueryParameters=false;
- private boolean didMerge=false;
-
- MessageBytes queryMB;
- MimeHeaders headers;
-
- UDecoder urlDec;
- MessageBytes decodedQuery=MessageBytes.newInstance();
-
- public static final int INITIAL_SIZE=4;
-
- // Garbage-less parameter merging.
- // In a sub-request with parameters, the new parameters
- // will be stored in child. When a getParameter happens,
- // the 2 are merged togheter. The child will be altered
- // to contain the merged values - the parent is allways the
- // original request.
- private Parameters2 child=null;
- private Parameters2 parent=null;
- private Parameters2 currentChild=null;
-
- String encoding=null;
- String queryStringEncoding=null;
-
- /**
- *
- */
- public Parameters2() {
- super( INITIAL_SIZE );
- }
-
- public void setQuery( MessageBytes queryMB ) {
- this.queryMB=queryMB;
- }
-
- public void setHeaders( MimeHeaders headers ) {
- this.headers=headers;
- }
-
- public void setEncoding( String s ) {
- encoding=s;
- if(debug>0) log( "Set encoding to " + s );
- }
-
- public void setQueryStringEncoding( String s ) {
- queryStringEncoding=s;
- if(debug>0) log( "Set query string encoding to " + s );
- }
-
- public void recycle() {
- super.recycle();
- paramHashStringArray.clear();
- didQueryParameters=false;
- currentChild=null;
- didMerge=false;
- encoding=null;
- decodedQuery.recycle();
- }
-
- // -------------------- Sub-request support --------------------
-
- public Parameters2 getCurrentSet() {
- if( currentChild==null )
- return this;
- return currentChild;
- }
-
- /** Create ( or reuse ) a child that will be used during a sub-request.
- All future changes ( setting query string, adding parameters )
- will affect the child ( the parent request is never changed ).
- Both setters and getters will return the data from the deepest
- child, merged with data from parents.
- */
- public void push() {
- // We maintain a linked list, that will grow to the size of the
- // longest include chain.
- // The list has 2 points of interest:
- // - request.parameters() is the original request and head,
- // - request.parameters().currentChild() is the current set.
- // The ->child and parent<- links are preserved ( currentChild is not
- // the last in the list )
-
- // create a new element in the linked list
- // note that we reuse the child, if any - pop will not
- // set child to null !
- if( currentChild==null ) {
- currentChild=new Parameters2();
- currentChild.setURLDecoder( urlDec );
- currentChild.parent=this;
- return;
- }
- if( currentChild.child==null ) {
- currentChild.child=new Parameters2();
- currentChild.setURLDecoder( urlDec );
- currentChild.child.parent=currentChild;
- } // it is not null if this object already had a child
- // i.e. a deeper include() ( we keep it )
-
- // the head will be the new element.
- currentChild=currentChild.child;
- currentChild.setEncoding( encoding );
- }
-
- /** Discard the last child. This happens when we return from a
- sub-request and the parameters are locally modified.
- */
- public void pop() {
- if( currentChild==null ) {
- throw new RuntimeException( "Attempt to pop without a push" );
- }
- currentChild.recycle();
- currentChild=currentChild.parent;
- // don't remove the top.
- }
-
- // -------------------- Data access --------------------
- // Access to the current name/values, no side effect ( processing ).
- // You must explicitely call handleQueryParameters and the post methods.
-
- // This is the original data representation ( hash of String->String[])
-
- public void addParameterValues( String key, String[] newValues) {
- if ( key==null ) return;
- String values[];
- if (paramHashStringArray.containsKey(key)) {
- String oldValues[] = (String[])paramHashStringArray.get(key);
- values = new String[oldValues.length + newValues.length];
- for (int i = 0; i < oldValues.length; i++) {
- values[i] = oldValues[i];
- }
- for (int i = 0; i < newValues.length; i++) {
- values[i+ oldValues.length] = newValues[i];
- }
- } else {
- values = newValues;
- }
-
- paramHashStringArray.put(key, values);
- }
-
- public String[] getParameterValues(String name) {
- handleQueryParameters();
- // sub-request
- if( currentChild!=null ) {
- currentChild.merge();
- return (String[])currentChild.paramHashStringArray.get(name);
- }
-
- // no "facade"
- String values[]=(String[])paramHashStringArray.get(name);
- return values;
- }
-
- public Enumeration getParameterNames() {
- handleQueryParameters();
- // Slow - the original code
- if( currentChild!=null ) {
- currentChild.merge();
- return currentChild.paramHashStringArray.keys();
- }
-
- // merge in child
- return paramHashStringArray.keys();
- }
-
- /** Combine the parameters from parent with our local ones
- */
- private void merge() {
- // recursive
- if( debug > 0 ) {
- log("Before merging " + this + " " + parent + " " + didMerge );
- log( paramsAsString());
- }
- // Local parameters first - they take precedence as in spec.
- handleQueryParameters();
-
- // we already merged with the parent
- if( didMerge ) return;
-
- // we are the top level
- if( parent==null ) return;
-
- // Add the parent props to the child ( lower precedence )
- parent.merge();
- Hashtable parentProps=parent.paramHashStringArray;
- merge2( paramHashStringArray , parentProps);
- didMerge=true;
- if(debug > 0 )
- log("After " + paramsAsString());
- }
-
-
- // Shortcut.
- public String getParameter(String name ) {
- String[] values = getParameterValues(name);
- if (values != null) {
- if( values.length==0 ) return "";
- return values[0];
- } else {
- return null;
- }
- }
- // -------------------- Processing --------------------
- /** Process the query string into parameters
- */
- public void handleQueryParameters() {
- if( didQueryParameters ) return;
-
- didQueryParameters=true;
-
- if( queryMB==null || queryMB.isNull() )
- return;
-
- if( debug > 0 )
- log( "Decoding query " + decodedQuery + " " + queryStringEncoding);
-
- try {
- decodedQuery.duplicate( queryMB );
- } catch (IOException e) {
- // Can't happen, as decodedQuery can't overflow
- e.printStackTrace();
- }
- processParameters( decodedQuery, queryStringEncoding );
- }
-
- // --------------------
-
- /** Combine 2 hashtables into a new one.
- * ( two will be added to one ).
- * Used to combine child parameters ( RequestDispatcher's query )
- * with parent parameters ( original query or parent dispatcher )
- */
- private static void merge2(Hashtable one, Hashtable two ) {
- Enumeration e = two.keys();
-
- while (e.hasMoreElements()) {
- String name = (String) e.nextElement();
- String[] oneValue = (String[]) one.get(name);
- String[] twoValue = (String[]) two.get(name);
- String[] combinedValue;
-
- if (twoValue == null) {
- continue;
- } else {
- if( oneValue==null ) {
- combinedValue = new String[twoValue.length];
- System.arraycopy(twoValue, 0, combinedValue,
- 0, twoValue.length);
- } else {
- combinedValue = new String[oneValue.length +
- twoValue.length];
- System.arraycopy(oneValue, 0, combinedValue, 0,
- oneValue.length);
- System.arraycopy(twoValue, 0, combinedValue,
- oneValue.length, twoValue.length);
- }
- one.put(name, combinedValue);
- }
- }
- }
-
- // incredibly inefficient data representation for parameters,
- // until we test the new one
- private void addParam( String key, String value ) {
- if( key==null ) return;
- String values[];
- if (paramHashStringArray.containsKey(key)) {
- String oldValues[] = (String[])paramHashStringArray.
- get(key);
- values = new String[oldValues.length + 1];
- for (int i = 0; i < oldValues.length; i++) {
- values[i] = oldValues[i];
- }
- values[oldValues.length] = value;
- } else {
- values = new String[1];
- values[0] = value;
- }
-
-
- paramHashStringArray.put(key, values);
- }
-
- public void setURLDecoder( UDecoder u ) {
- urlDec=u;
- }
-
- // -------------------- Parameter parsing --------------------
-
- // This code is not used right now - it's the optimized version
- // of the above.
-
- // we are called from a single thread - we can do it the hard way
- // if needed
- ByteChunk tmpName=new ByteChunk();
- ByteChunk tmpValue=new ByteChunk();
- CharChunk tmpNameC=new CharChunk(1024);
- CharChunk tmpValueC=new CharChunk(1024);
-
- public void processParameters( byte bytes[], int start, int len ) {
- processParameters(bytes, start, len, encoding);
- }
-
- public void processParameters( byte bytes[], int start, int len,
- String enc ) {
- int end=start+len;
- int pos=start;
-
- if( debug>0 )
- log( "Bytes: " + new String( bytes, start, len ));
-
- do {
- boolean noEq=false;
- int valStart=-1;
- int valEnd=-1;
-
- int nameStart=pos;
- int nameEnd=ByteChunk.indexOf(bytes, nameStart, end, '=' );
- // Workaround for a&b&c encoding
- int nameEnd2=ByteChunk.indexOf(bytes, nameStart, end, '&' );
- if( (nameEnd2!=-1 ) &&
- ( nameEnd==-1 || nameEnd > nameEnd2) ) {
- nameEnd=nameEnd2;
- noEq=true;
- valStart=nameEnd;
- valEnd=nameEnd;
- if( debug>0) log("no equal " + nameStart + " " + nameEnd + " " + new String(bytes, nameStart, nameEnd-nameStart) );
- }
- if( nameEnd== -1 )
- nameEnd=end;
-
- if( ! noEq ) {
- valStart= (nameEnd < end) ? nameEnd+1 : end;
- valEnd=ByteChunk.indexOf(bytes, valStart, end, '&');
- if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
- }
-
- pos=valEnd+1;
-
- if( nameEnd<=nameStart ) {
- log.warn("Parameters: Invalid chunk ignored.");
- continue;
- // invalid chunk - it's better to ignore
- }
- tmpName.setBytes( bytes, nameStart, nameEnd-nameStart );
- tmpValue.setBytes( bytes, valStart, valEnd-valStart );
-
- try {
- addParam( urlDecode(tmpName, enc), urlDecode(tmpValue, enc) );
- } catch (IOException e) {
- // Exception during character decoding: skip parameter
- log.warn("Parameters: Character decoding failed. " +
- "Parameter skipped.", e);
- }
-
- tmpName.recycle();
- tmpValue.recycle();
-
- } while( pos<end );
- }
-
- private String urlDecode(ByteChunk bc, String enc)
- throws IOException {
- if( urlDec==null ) {
- urlDec=new UDecoder();
- }
- urlDec.convert(bc);
- String result = null;
- if (enc != null) {
- bc.setEncoding(enc);
- result = bc.toString();
- } else {
- CharChunk cc = tmpNameC;
- int length = bc.getLength();
- cc.allocate(length, -1);
- // Default encoding: fast conversion
- byte[] bbuf = bc.getBuffer();
- char[] cbuf = cc.getBuffer();
- int start = bc.getStart();
- for (int i = 0; i < length; i++) {
- cbuf[i] = (char) (bbuf[i + start] & 0xff);
- }
- cc.setChars(cbuf, 0, length);
- result = cc.toString();
- cc.recycle();
- }
- return result;
- }
-
- public void processParameters( char chars[], int start, int len ) {
- int end=start+len;
- int pos=start;
-
- if( debug>0 )
- log( "Chars: " + new String( chars, start, len ));
- do {
- boolean noEq=false;
- int nameStart=pos;
- int valStart=-1;
- int valEnd=-1;
-
- int nameEnd=CharChunk.indexOf(chars, nameStart, end, '=' );
- int nameEnd2=CharChunk.indexOf(chars, nameStart, end, '&' );
- if( (nameEnd2!=-1 ) &&
- ( nameEnd==-1 || nameEnd > nameEnd2) ) {
- nameEnd=nameEnd2;
- noEq=true;
- valStart=nameEnd;
- valEnd=nameEnd;
- if( debug>0) log("no equal " + nameStart + " " + nameEnd + " " + new String(chars, nameStart, nameEnd-nameStart) );
- }
- if( nameEnd== -1 ) nameEnd=end;
-
- if( ! noEq ) {
- valStart= (nameEnd < end) ? nameEnd+1 : end;
- valEnd=CharChunk.indexOf(chars, valStart, end, '&');
- if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
- }
-
- pos=valEnd+1;
-
- if( nameEnd<=nameStart ) {
- continue;
- // invalid chunk - no name, it's better to ignore
- // XXX log it ?
- }
-
- try {
- tmpNameC.append( chars, nameStart, nameEnd-nameStart );
- tmpValueC.append( chars, valStart, valEnd-valStart );
-
- if( debug > 0 )
- log( tmpNameC + "= " + tmpValueC);
-
- if( urlDec==null ) {
- urlDec=new UDecoder();
- }
-
- urlDec.convert( tmpNameC );
- urlDec.convert( tmpValueC );
-
- if( debug > 0 )
- log( tmpNameC + "= " + tmpValueC);
-
- addParam( tmpNameC.toString(), tmpValueC.toString() );
- } catch( IOException ex ) {
- ex.printStackTrace();
- }
-
- tmpNameC.recycle();
- tmpValueC.recycle();
-
- } while( pos<end );
- }
-
- public void processParameters( MessageBytes data ) {
- processParameters(data, encoding);
- }
-
- public void processParameters( MessageBytes data, String encoding ) {
- if( data==null || data.isNull() || data.getLength() <= 0 ) return;
-
- if (data.getType() != MessageBytes.T_BYTES) {
- data.toBytes();
- }
- ByteChunk bc=data.getByteChunk();
- processParameters( bc.getBytes(), bc.getOffset(),
- bc.getLength(), encoding);
- }
-
- /** Debug purpose
- */
- public String paramsAsString() {
- StringBuffer sb=new StringBuffer();
- Enumeration en= paramHashStringArray.keys();
- while( en.hasMoreElements() ) {
- String k=(String)en.nextElement();
- sb.append( k ).append("=");
- String v[]=(String[])paramHashStringArray.get( k );
- for( int i=0; i<v.length; i++ )
- sb.append( v[i] ).append(",");
- sb.append("\n");
- }
- return sb.toString();
- }
-
- private static int debug=0;
- private void log(String s ) {
- if (log.isDebugEnabled())
- log.debug("Parameters: " + s );
- }
-
- // -------------------- Old code, needs rewrite --------------------
-
- /** Used by RequestDispatcher
- */
- public void processParameters( String str ) {
- int end=str.length();
- int pos=0;
- if( debug > 0)
- log("String: " + str );
-
- do {
- boolean noEq=false;
- int valStart=-1;
- int valEnd=-1;
-
- int nameStart=pos;
- int nameEnd=str.indexOf('=', nameStart );
- int nameEnd2=str.indexOf('&', nameStart );
- if( nameEnd2== -1 ) nameEnd2=end;
- if( (nameEnd2!=-1 ) &&
- ( nameEnd==-1 || nameEnd > nameEnd2) ) {
- nameEnd=nameEnd2;
- noEq=true;
- valStart=nameEnd;
- valEnd=nameEnd;
- if( debug>0) log("no equal " + nameStart + " " + nameEnd + " " + str.substring(nameStart, nameEnd) );
- }
-
- if( nameEnd== -1 ) nameEnd=end;
-
- if( ! noEq ) {
- valStart=nameEnd+1;
- valEnd=str.indexOf('&', valStart);
- if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
- }
-
- pos=valEnd+1;
-
- if( nameEnd<=nameStart ) {
- continue;
- }
- if( debug>0)
- log( "XXX " + nameStart + " " + nameEnd + " "
- + valStart + " " + valEnd );
-
- try {
- tmpNameC.append(str, nameStart, nameEnd-nameStart );
- tmpValueC.append(str, valStart, valEnd-valStart );
-
- if( debug > 0 )
- log( tmpNameC + "= " + tmpValueC);
-
- if( urlDec==null ) {
- urlDec=new UDecoder();
- }
-
- urlDec.convert( tmpNameC );
- urlDec.convert( tmpValueC );
-
- if( debug > 0 )
- log( tmpNameC + "= " + tmpValueC);
-
- addParam( tmpNameC.toString(), tmpValueC.toString() );
- } catch( IOException ex ) {
- ex.printStackTrace();
- }
-
- tmpNameC.recycle();
- tmpValueC.recycle();
-
- } while( pos<end );
- }
-
-
-}
16 years, 8 months
JBossWeb SVN: r564 - trunk/res/procrun.
by jbossweb-commits@lists.jboss.org
Author: mladen.turk(a)jboss.com
Date: 2008-03-29 02:57:17 -0400 (Sat, 29 Mar 2008)
New Revision: 564
Removed:
trunk/res/procrun/jbosswebw.i64.exe
trunk/res/procrun/jbosswebw.x64.exe
Modified:
trunk/res/procrun/jbossweb.exe
trunk/res/procrun/jbossweb.i64.exe
trunk/res/procrun/jbossweb.x64.exe
trunk/res/procrun/jbosswebw.exe
Log:
Update procrun binaries. Remove 64-Bit managers. 32-Bit manager will run on all platforms, so we only need 64-Bit service wrappers
Modified: trunk/res/procrun/jbossweb.exe
===================================================================
(Binary files differ)
Modified: trunk/res/procrun/jbossweb.i64.exe
===================================================================
(Binary files differ)
Modified: trunk/res/procrun/jbossweb.x64.exe
===================================================================
(Binary files differ)
Modified: trunk/res/procrun/jbosswebw.exe
===================================================================
(Binary files differ)
Deleted: trunk/res/procrun/jbosswebw.i64.exe
===================================================================
(Binary files differ)
Deleted: trunk/res/procrun/jbosswebw.x64.exe
===================================================================
(Binary files differ)
16 years, 9 months