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 );
- }
-
-
-}