/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * Licensed 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 com.alibaba.citrus.service.requestcontext.util; import static com.alibaba.citrus.util.Assert.*; import static com.alibaba.citrus.util.BasicConstant.*; import static com.alibaba.citrus.util.ObjectUtil.*; import static com.alibaba.citrus.util.StringUtil.*; import java.io.UnsupportedEncodingException; import java.util.Map; import com.alibaba.citrus.util.StringEscapeUtil; import com.alibaba.citrus.util.StringUtil; import com.alibaba.citrus.util.i18n.LocaleUtil; /** * 解析和组装query string。 * * @author Michael Zhou */ public class QueryStringParser { private final String charset; private final StringBuilder queryStringBuffer; private String equalSign = "="; private String andSign = "&"; public QueryStringParser() { this(null, null); } public QueryStringParser(String charset) { this(charset, null); } public QueryStringParser(String charset, String defaultCharset) { defaultCharset = defaultIfNull(trimToNull(defaultCharset), LocaleUtil.getContext().getCharset().name()); this.charset = defaultIfNull(trimToNull(charset), defaultCharset); this.queryStringBuffer = new StringBuilder(); } public String getCharacterEncoding() { return charset; } public String getEqualSign() { return equalSign; } public String getAndSign() { return andSign; } /** 设置用来替代“=”的字符。 */ public QueryStringParser setEqualSign(String equalSign) { this.equalSign = defaultIfNull(equalSign, "="); return this; } /** 设置用来替代“&”的字符。 */ public QueryStringParser setAndSign(String andSign) { this.andSign = defaultIfNull(andSign, "&"); return null; } public QueryStringParser append(String key, String value) { try { key = StringEscapeUtil.escapeURL(defaultIfNull(key, EMPTY_STRING), charset); value = StringEscapeUtil.escapeURL(defaultIfNull(value, EMPTY_STRING), charset); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException("invalid charset: " + charset, e); } if (queryStringBuffer.length() > 0) { queryStringBuffer.append(andSign); } queryStringBuffer.append(key).append(equalSign).append(value); return this; } public QueryStringParser append(Map<String, String> values) { for (Map.Entry<String, String> entry : values.entrySet()) { append(entry.getKey(), entry.getValue()); } return this; } public String toQueryString() { String queryString = queryStringBuffer.toString(); queryStringBuffer.setLength(0); return queryString.length() == 0 ? null : queryString; } /** 解析query string。 */ public void parse(String queryString) { queryString = trimToNull(queryString); if (queryString == null) { return; } int startIndex = 0; int ampIndex = queryString.indexOf(andSign); while (ampIndex >= 0) { addKeyValue(queryString.substring(startIndex, ampIndex)); startIndex = ampIndex + 1; ampIndex = queryString.indexOf(andSign, startIndex); } addKeyValue(queryString.substring(startIndex)); } protected void add(String key, String value) { unsupportedOperation("You should extend class " + getClass().getSimpleName() + " and override method add(String, String)"); } private void addKeyValue(String keyValue) { int index = keyValue.indexOf(equalSign); String key; String value; if (index < 0) { key = keyValue; value = null; } else { key = keyValue.substring(0, index).trim(); value = keyValue.substring(index + 1).trim(); } if (!StringUtil.isEmpty(key)) { key = decode(key); value = decode(value); add(key, defaultIfNull(value, EMPTY_STRING)); } } private String decode(String str) { try { return StringEscapeUtil.unescapeURL(str, charset); } catch (UnsupportedEncodingException e) { return str; } } }