001: /*
002: * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/util/ParameterParser.java,v 1.5 2004/05/13 04:01:22 mbecke Exp $
003: * $Revision: 480424 $
004: * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
005: *
006: * ====================================================================
007: *
008: * Licensed to the Apache Software Foundation (ASF) under one or more
009: * contributor license agreements. See the NOTICE file distributed with
010: * this work for additional information regarding copyright ownership.
011: * The ASF licenses this file to You under the Apache License, Version 2.0
012: * (the "License"); you may not use this file except in compliance with
013: * the License. You may obtain a copy of the License at
014: *
015: * http://www.apache.org/licenses/LICENSE-2.0
016: *
017: * Unless required by applicable law or agreed to in writing, software
018: * distributed under the License is distributed on an "AS IS" BASIS,
019: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
020: * See the License for the specific language governing permissions and
021: * limitations under the License.
022: * ====================================================================
023: *
024: * This software consists of voluntary contributions made by many
025: * individuals on behalf of the Apache Software Foundation. For more
026: * information on the Apache Software Foundation, please see
027: * <http://www.apache.org/>.
028: *
029: */
030:
031: package org.apache.commons.httpclient.util;
032:
033: import java.util.ArrayList;
034: import java.util.List;
035:
036: import org.apache.commons.httpclient.NameValuePair;
037:
038: /**
039: * A simple parser intended to parse sequences of name/value pairs.
040: * Parameter values are exptected to be enclosed in quotes if they
041: * contain unsafe characters, such as '=' characters or separators.
042: * Parameter values are optional and can be omitted.
043: *
044: * <p>
045: * <code>param1 = value; param2 = "anything goes; really"; param3</code>
046: * </p>
047: *
048: * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
049: *
050: * @since 3.0
051: */
052: public class ParameterParser {
053:
054: /** String to be parsed */
055: private char[] chars = null;
056:
057: /** Current position in the string */
058: private int pos = 0;
059:
060: /** Maximum position in the string */
061: private int len = 0;
062:
063: /** Start of a token */
064: private int i1 = 0;
065:
066: /** End of a token */
067: private int i2 = 0;
068:
069: /** Default ParameterParser constructor */
070: public ParameterParser() {
071: super ();
072: }
073:
074: /** Are there any characters left to parse? */
075: private boolean hasChar() {
076: return this .pos < this .len;
077: }
078:
079: /** A helper method to process the parsed token. */
080: private String getToken(boolean quoted) {
081: // Trim leading white spaces
082: while ((i1 < i2) && (Character.isWhitespace(chars[i1]))) {
083: i1++;
084: }
085: // Trim trailing white spaces
086: while ((i2 > i1) && (Character.isWhitespace(chars[i2 - 1]))) {
087: i2--;
088: }
089: // Strip away quotes if necessary
090: if (quoted) {
091: if (((i2 - i1) >= 2) && (chars[i1] == '"')
092: && (chars[i2 - 1] == '"')) {
093: i1++;
094: i2--;
095: }
096: }
097: String result = null;
098: if (i2 >= i1) {
099: result = new String(chars, i1, i2 - i1);
100: }
101: return result;
102: }
103:
104: /** Is given character present in the array of characters? */
105: private boolean isOneOf(char ch, char[] charray) {
106: boolean result = false;
107: for (int i = 0; i < charray.length; i++) {
108: if (ch == charray[i]) {
109: result = true;
110: break;
111: }
112: }
113: return result;
114: }
115:
116: /** Parse out a token until any of the given terminators
117: * is encountered. */
118: private String parseToken(final char[] terminators) {
119: char ch;
120: i1 = pos;
121: i2 = pos;
122: while (hasChar()) {
123: ch = chars[pos];
124: if (isOneOf(ch, terminators)) {
125: break;
126: }
127: i2++;
128: pos++;
129: }
130: return getToken(false);
131: }
132:
133: /** Parse out a token until any of the given terminators
134: * is encountered. Special characters in quoted tokens
135: * are escaped. */
136: private String parseQuotedToken(final char[] terminators) {
137: char ch;
138: i1 = pos;
139: i2 = pos;
140: boolean quoted = false;
141: boolean charEscaped = false;
142: while (hasChar()) {
143: ch = chars[pos];
144: if (!quoted && isOneOf(ch, terminators)) {
145: break;
146: }
147: if (!charEscaped && ch == '"') {
148: quoted = !quoted;
149: }
150: charEscaped = (!charEscaped && ch == '\\');
151: i2++;
152: pos++;
153:
154: }
155: return getToken(true);
156: }
157:
158: /**
159: * Extracts a list of {@link NameValuePair}s from the given string.
160: *
161: * @param str the string that contains a sequence of name/value pairs
162: * @return a list of {@link NameValuePair}s
163: *
164: */
165: public List parse(final String str, char separator) {
166:
167: if (str == null) {
168: return new ArrayList();
169: }
170: return parse(str.toCharArray(), separator);
171: }
172:
173: /**
174: * Extracts a list of {@link NameValuePair}s from the given array of
175: * characters.
176: *
177: * @param chars the array of characters that contains a sequence of
178: * name/value pairs
179: *
180: * @return a list of {@link NameValuePair}s
181: */
182: public List parse(final char[] chars, char separator) {
183:
184: if (chars == null) {
185: return new ArrayList();
186: }
187: return parse(chars, 0, chars.length, separator);
188: }
189:
190: /**
191: * Extracts a list of {@link NameValuePair}s from the given array of
192: * characters.
193: *
194: * @param chars the array of characters that contains a sequence of
195: * name/value pairs
196: * @param offset - the initial offset.
197: * @param length - the length.
198: *
199: * @return a list of {@link NameValuePair}s
200: */
201: public List parse(final char[] chars, int offset, int length,
202: char separator) {
203:
204: if (chars == null) {
205: return new ArrayList();
206: }
207: List params = new ArrayList();
208: this .chars = chars;
209: this .pos = offset;
210: this .len = length;
211:
212: String paramName = null;
213: String paramValue = null;
214: while (hasChar()) {
215: paramName = parseToken(new char[] { '=', separator });
216: paramValue = null;
217: if (hasChar() && (chars[pos] == '=')) {
218: pos++; // skip '='
219: paramValue = parseQuotedToken(new char[] { separator });
220: }
221: if (hasChar() && (chars[pos] == separator)) {
222: pos++; // skip separator
223: }
224: if (paramName != null
225: && !(paramName.equals("") && paramValue == null)) {
226: params.add(new NameValuePair(paramName, paramValue));
227: }
228: }
229: return params;
230: }
231: }
|