ParameterParser.java
Upload User: gdxydsw
Upload Date: 2019-01-29
Package Size: 16721k
Code Size: 8k
Category:

Java Develop

Development Platform:

Java

  1. /*
  2.  * Copyright 2001-2004 The Apache Software Foundation
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *     http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. package net.jforum.util.legacy.commons.fileupload;
  17. import java.util.HashMap;
  18. import java.util.Map;
  19. /**
  20.  * A simple parser intended to parse sequences of name/value pairs.
  21.  * Parameter values are exptected to be enclosed in quotes if they
  22.  * contain unsafe characters, such as '=' characters or separators.
  23.  * Parameter values are optional and can be omitted.
  24.  *
  25.  * <p>
  26.  *  <code>param1 = value; param2 = "anything goes; really"; param3</code>
  27.  * </p>
  28.  *
  29.  * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
  30.  */
  31. public class ParameterParser {
  32.     /**
  33.      * String to be parsed.
  34.      */
  35.     private char[] chars = null;
  36.     /**
  37.      * Current position in the string.
  38.      */
  39.     private int pos = 0;
  40.     /**
  41.      * Maximum position in the string.
  42.      */
  43.     private int len = 0;
  44.     /**
  45.      * Start of a token.
  46.      */
  47.     private int i1 = 0;
  48.     /**
  49.      * End of a token.
  50.      */
  51.     private int i2 = 0;
  52.     /**
  53.      * Whether names stored in the map should be converted to lower case.
  54.      */
  55.     private boolean lowerCaseNames = false;
  56.     /**
  57.      * Default ParameterParser constructor.
  58.      */
  59.     public ParameterParser() {
  60.         super();
  61.     }
  62.     /**
  63.      * Are there any characters left to parse?
  64.      *
  65.      * @return <tt>true</tt> if there are unparsed characters,
  66.      *         <tt>false</tt> otherwise.
  67.      */
  68.     private boolean hasChar() {
  69.         return this.pos < this.len;
  70.     }
  71.     /**
  72.      * A helper method to process the parsed token. This method removes
  73.      * leading and trailing blanks as well as enclosing quotation marks,
  74.      * when necessary.
  75.      *
  76.      * @param quoted <tt>true</tt> if quotation marks are expected,
  77.      *               <tt>false</tt> otherwise.
  78.      * @return the token
  79.      */
  80.     private String getToken(boolean quoted) {
  81.         // Trim leading white spaces
  82.         while ((i1 < i2) && (Character.isWhitespace(chars[i1]))) {
  83.             i1++;
  84.         }
  85.         // Trim trailing white spaces
  86.         while ((i2 > i1) && (Character.isWhitespace(chars[i2 - 1]))) {
  87.             i2--;
  88.         }
  89.         // Strip away quotation marks if necessary
  90.         if (quoted) {
  91.             if (((i2 - i1) >= 2)
  92.                 && (chars[i1] == '"')
  93.                 && (chars[i2 - 1] == '"')) {
  94.                 i1++;
  95.                 i2--;
  96.             }
  97.         }
  98.         String result = null;
  99.         if (i2 > i1) {
  100.             result = new String(chars, i1, i2 - i1);
  101.         }
  102.         return result;
  103.     }
  104.     /**
  105.      * Tests if the given character is present in the array of characters.
  106.      *
  107.      * @param ch the character to test for presense in the array of characters
  108.      * @param charray the array of characters to test against
  109.      *
  110.      * @return <tt>true</tt> if the character is present in the array of
  111.      *   characters, <tt>false</tt> otherwise.
  112.      */
  113.     private boolean isOneOf(char ch, final char[] charray) {
  114.         boolean result = false;
  115.         for (int i = 0; i < charray.length; i++) {
  116.             if (ch == charray[i]) {
  117.                 result = true;
  118.                 break;
  119.             }
  120.         }
  121.         return result;
  122.     }
  123.     /**
  124.      * Parses out a token until any of the given terminators
  125.      * is encountered.
  126.      *
  127.      * @param terminators the array of terminating characters. Any of these
  128.      * characters when encountered signify the end of the token
  129.      *
  130.      * @return the token
  131.      */
  132.     private String parseToken(final char[] terminators) {
  133.         char ch;
  134.         i1 = pos;
  135.         i2 = pos;
  136.         while (hasChar()) {
  137.             ch = chars[pos];
  138.             if (isOneOf(ch, terminators)) {
  139.                 break;
  140.             }
  141.             i2++;
  142.             pos++;
  143.         }
  144.         return getToken(false);
  145.     }
  146.     /**
  147.      * Parses out a token until any of the given terminators
  148.      * is encountered outside the quotation marks.
  149.      *
  150.      * @param terminators the array of terminating characters. Any of these
  151.      * characters when encountered outside the quotation marks signify the end
  152.      * of the token
  153.      *
  154.      * @return the token
  155.      */
  156.     private String parseQuotedToken(final char[] terminators) {
  157.         char ch;
  158.         i1 = pos;
  159.         i2 = pos;
  160.         boolean quoted = false;
  161.         boolean charEscaped = false;
  162.         while (hasChar()) {
  163.             ch = chars[pos];
  164.             if (!quoted && isOneOf(ch, terminators)) {
  165.                 break;
  166.             }
  167.             if (!charEscaped && ch == '"') {
  168.                 quoted = !quoted;
  169.             }
  170.             charEscaped = (!charEscaped && ch == '\');
  171.             i2++;
  172.             pos++;
  173.         }
  174.         return getToken(true);
  175.     }
  176.     /**
  177.      * Returns <tt>true</tt> if parameter names are to be converted to lower
  178.      * case when name/value pairs are parsed.
  179.      *
  180.      * @return <tt>true</tt> if parameter names are to be
  181.      * converted to lower case when name/value pairs are parsed.
  182.      * Otherwise returns <tt>false</tt>
  183.      */
  184.     public boolean isLowerCaseNames() {
  185.         return this.lowerCaseNames;
  186.     }
  187.     /**
  188.      * Sets the flag if parameter names are to be converted to lower case when
  189.      * name/value pairs are parsed.
  190.      *
  191.      * @param b <tt>true</tt> if parameter names are to be
  192.      * converted to lower case when name/value pairs are parsed.
  193.      * <tt>false</tt> otherwise.
  194.      */
  195.     public void setLowerCaseNames(boolean b) {
  196.         this.lowerCaseNames = b;
  197.     }
  198.     /**
  199.      * Extracts a map of name/value pairs from the given string. Names are
  200.      * expected to be unique.
  201.      *
  202.      * @param str the string that contains a sequence of name/value pairs
  203.      * @param separator the name/value pairs separator
  204.      *
  205.      * @return a map of name/value pairs
  206.      */
  207.     public Map parse(final String str, char separator) {
  208.         if (str == null) {
  209.             return new HashMap();
  210.         }
  211.         return parse(str.toCharArray(), separator);
  212.     }
  213.     /**
  214.      * Extracts a map of name/value pairs from the given array of
  215.      * characters. Names are expected to be unique.
  216.      *
  217.      * @param chars the array of characters that contains a sequence of
  218.      * name/value pairs
  219.      * @param separator the name/value pairs separator
  220.      *
  221.      * @return a map of name/value pairs
  222.      */
  223.     public Map parse(final char[] chars, char separator) {
  224.         if (chars == null) {
  225.             return new HashMap();
  226.         }
  227.         return parse(chars, 0, chars.length, separator);
  228.     }
  229.     /**
  230.      * Extracts a map of name/value pairs from the given array of
  231.      * characters. Names are expected to be unique.
  232.      *
  233.      * @param chars the array of characters that contains a sequence of
  234.      * name/value pairs
  235.      * @param offset - the initial offset.
  236.      * @param length - the length.
  237.      * @param separator the name/value pairs separator
  238.      *
  239.      * @return a map of name/value pairs
  240.      */
  241.     public Map parse(
  242.         final char[] chars,
  243.         int offset,
  244.         int length,
  245.         char separator) {
  246.         if (chars == null) {
  247.             return new HashMap();
  248.         }
  249.         HashMap params = new HashMap();
  250.         this.chars = chars;
  251.         this.pos = offset;
  252.         this.len = length;
  253.         String paramName = null;
  254.         String paramValue = null;
  255.         while (hasChar()) {
  256.             paramName = parseToken(new char[] {
  257.                     '=', separator });
  258.             paramValue = null;
  259.             if (hasChar() && (chars[pos] == '=')) {
  260.                 pos++; // skip '='
  261.                 paramValue = parseQuotedToken(new char[] {
  262.                         separator });
  263.             }
  264.             if (hasChar() && (chars[pos] == separator)) {
  265.                 pos++; // skip separator
  266.             }
  267.             if ((paramName != null) && (paramName.length() > 0)) {
  268.                 if (this.lowerCaseNames) {
  269.                     paramName = paramName.toLowerCase();
  270.                 }
  271.                 params.put(paramName, paramValue);
  272.             }
  273.         }
  274.         return params;
  275.     }
  276. }