/*
* 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.parser;
import static com.alibaba.citrus.util.ArrayUtil.*;
import static com.alibaba.citrus.util.BasicConstant.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import com.alibaba.citrus.service.requestcontext.support.ValueListSupport;
import com.alibaba.citrus.service.requestcontext.util.ValueList;
import com.alibaba.citrus.service.upload.support.StringFileItemEditor;
import com.alibaba.citrus.util.ObjectUtil;
import com.alibaba.citrus.util.StringUtil;
import com.alibaba.citrus.util.ToStringBuilder.MapBuilder;
import org.slf4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeConverter;
import org.springframework.core.MethodParameter;
/**
* 代表一个解析器的基类,用来取得HTTP请求中的参数和cookies。
* <p>
* 注意:参数和cookie的名称可能被转换成全部大写或全部小写。 这是根据配置文件中的参数:<code>caseFolding</code> 来指定的。
* </p>
*/
public abstract class AbstractValueParser implements ValueParser {
protected final SimpleTypeConverter converter;
protected final Map<String, Object> parameters = createLinkedHashMap();
protected final Map<String, String> parameterKeys = createLinkedHashMap();
protected final ParserRequestContext requestContext;
public AbstractValueParser(ParserRequestContext requestContext) {
this.requestContext = requestContext;
this.converter = new SimpleTypeConverter();
this.converter.registerCustomEditor(String.class, new StringFileItemEditor());
if (requestContext.getPropertyEditorRegistrar() != null) {
requestContext.getPropertyEditorRegistrar().registerCustomEditors(converter);
}
}
protected abstract Logger getLogger();
public TypeConverter getTypeConverter() {
return converter;
}
// =============================================================
// 查询参数的方法
// =============================================================
/**
* 取得值的数量。
*
* @return 值的数量
*/
public int size() {
return parameters.size();
}
/**
* 判断是否无值。
*
* @return 如果无值,则返回<code>true</code>
*/
public boolean isEmpty() {
return parameters.isEmpty();
}
/**
* 检查是否包含指定名称的参数。
*
* @param key 要查找的参数名
* @return 如果存在,则返回<code>true</code>
*/
public boolean containsKey(String key) {
return parameters.containsKey(convert(key));
}
/*
* 取得所有参数名的集合。
* @return 所有参数名的集合
*/
public Set<String> keySet() {
return createLinkedHashSet(parameterKeys.values());
}
/*
* 取得所有参数名的数组。
* @return 所有参数名的数组
*/
public String[] getKeys() {
return parameterKeys.values().toArray(new String[parameterKeys.size()]);
}
// =============================================================
// 取得参数的值
// =============================================================
/**
* 取得参数值,如果指定名称的参数不存在,则返回<code>false</code>。
*
* @param key 参数名
* @return 参数值
*/
public boolean getBoolean(String key) {
ValueList container = getValueList(key, false);
return container == null ? false : container.getBooleanValue();
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值
*/
public boolean getBoolean(String key, boolean defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getBooleanValue(defaultValue);
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回<code>0</code>。
*
* @param key 参数名
* @return 参数值
*/
public byte getByte(String key) {
ValueList container = getValueList(key, false);
return container == null ? 0 : container.getByteValue();
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值
*/
public byte getByte(String key, byte defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getByteValue(defaultValue);
}
/**
* 取得指定参数的字节。这个字节是根据<code>getCharacterEncoding()</code>所返回的字符集进行编码的。
*
* @param key 参数名
* @return 参数值的字节数组,如果参数不存在,则返回<code>null</code>
* @throws UnsupportedEncodingException 如果指定了错误的编码字符集
*/
public byte[] getBytes(String key) throws UnsupportedEncodingException {
ValueList container = getValueList(key, false);
return container == null ? EMPTY_BYTE_ARRAY : container.getBytes(getCharacterEncoding());
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回<code>'\0'</code>。
*
* @param key 参数名
* @return 参数值
*/
public char getChar(String key) {
ValueList container = getValueList(key, false);
return container == null ? '\0' : container.getCharacterValue();
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值
*/
public char getChar(String key, char defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getCharacterValue(defaultValue);
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回<code>0</code>。
*
* @param key 参数名
* @return 参数值
*/
public double getDouble(String key) {
ValueList container = getValueList(key, false);
return container == null ? 0 : container.getDoubleValue();
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值
*/
public double getDouble(String key, double defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getDoubleValue(defaultValue);
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回<code>0</code>。
*
* @param key 参数名
* @return 参数值
*/
public float getFloat(String key) {
ValueList container = getValueList(key, false);
return container == null ? 0 : container.getFloatValue();
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值
*/
public float getFloat(String key, float defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getFloatValue(defaultValue);
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回<code>0</code>。
*
* @param key 参数名
* @return 参数值
*/
public int getInt(String key) {
ValueList container = getValueList(key, false);
return container == null ? 0 : container.getIntegerValue();
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值
*/
public int getInt(String key, int defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getIntegerValue(defaultValue);
}
/**
* 取得指定参数的所有值。如果参数不存在,则返回<code>null</code>。
*
* @param key 参数名
* @return 参数值的数组
*/
public int[] getInts(String key) {
ValueList container = getValueList(key, false);
return container == null ? EMPTY_INT_ARRAY : container.getIntegerValues();
}
/**
* 取得指定参数的所有值。如果参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值的数组
*/
public int[] getInts(String key, int[] defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getIntegerValues(defaultValue);
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回<code>0</code>。
*
* @param key 参数名
* @return 参数值
*/
public long getLong(String key) {
ValueList container = getValueList(key, false);
return container == null ? 0 : container.getLongValue();
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值
*/
public long getLong(String key, long defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getLongValue(defaultValue);
}
/**
* 取得指定参数的所有值。如果参数不存在,则返回<code>null</code>。
*
* @param key 参数名
* @return 参数值的数组
*/
public long[] getLongs(String key) {
ValueList container = getValueList(key, false);
return container == null ? EMPTY_LONG_ARRAY : container.getLongValues();
}
/**
* 取得指定参数的所有值。如果参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值的数组
*/
public long[] getLongs(String key, long[] defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getLongValues(defaultValue);
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回<code>0</code>。
*
* @param key 参数名
* @return 参数值
*/
public short getShort(String key) {
ValueList container = getValueList(key, false);
return container == null ? 0 : container.getShortValue();
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值
*/
public short getShort(String key, short defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getShortValue(defaultValue);
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回<code>null</code>。
*
* @param key 参数名
* @return 参数值
*/
public String getString(String key) {
ValueList container = getValueList(key, false);
return container == null ? null : container.getStringValue();
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值
*/
public String getString(String key, String defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getStringValue(defaultValue);
}
/**
* 取得指定参数的所有值。如果参数不存在,则返回<code>null</code>。
*
* @param key 参数名
* @return 参数值的数组
*/
public String[] getStrings(String key) {
ValueList container = getValueList(key, false);
return container == null ? EMPTY_STRING_ARRAY : container.getStringValues();
}
/**
* 取得指定参数的所有值。如果参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值的数组
*/
public String[] getStrings(String key, String[] defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getStringValues(defaultValue);
}
/**
* 取得参数值,如果指定名称的参数不存在,则返回<code>null</code>。 此方法和<code>getObject</code>
* 一样,但在模板中便易于使用。
*
* @param key 参数名
* @return 参数值
*/
public Object get(String key) {
return getObject(key);
}
/**
* 取得日期。字符串将使用指定的<code>DateFormat</code>来解析。如果不存在,则返回<code>null</code>。
*
* @param key 参数名
* @param format <code>DateFormat</code>对象
* @return <code>java.util.Date</code>对象
*/
public Date getDate(String key, DateFormat format) {
ValueList container = getValueList(key, false);
return container == null ? null : container.getDateValue(format);
}
/**
* 取得日期。字符串将使用指定的<code>DateFormat</code>来解析。如果不存在,则返回默认值。
*
* @param key 参数名
* @param format <code>DateFormat</code>对象
* @param defaultValue 默认值
* @return <code>java.util.Date</code>对象
*/
public Date getDate(String key, DateFormat format, Date defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getDateValue(format, defaultValue);
}
/**
* 取得指定参数的值。如果参数不存在,则返回<code>null</code>。
*
* @param key 参数名
* @return 参数值
*/
public Object getObject(String key) {
ValueList container = getValueList(key, false);
return container == null ? null : container.getValue();
}
/**
* 取得指定参数的值。如果参数不存在,则返回默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值
*/
public Object getObject(String key, Object defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getValue(defaultValue);
}
/**
* 取得指定参数的所有值。如果参数不存在,则返回<code>null</code>。
*
* @param key 参数名
* @return 参数值的数组
*/
public Object[] getObjects(String key) {
ValueList container = getValueList(key, false);
return container == null ? EMPTY_OBJECT_ARRAY : container.getValues();
}
/**
* 取得指定参数的所有值。如果参数不存在,则返回指定默认值。
*
* @param key 参数名
* @param defaultValue 默认值
* @return 参数值的数组
*/
public Object[] getObjects(String key, Object[] defaultValue) {
ValueList container = getValueList(key, false);
return container == null ? defaultValue : container.getValues(defaultValue);
}
/** 取得指定类型的对象。 */
public <T> T getObjectOfType(String key, Class<T> type) {
return getObjectOfType(key, type, null, null);
}
/** 取得指定类型的对象。 */
public <T> T getObjectOfType(String key, Class<T> type, MethodParameter methodParameter, Object[] defaultValues) {
return getObjectOfType(key, type, false, methodParameter, defaultValues);
}
/** 取得指定类型的对象。 */
<T> T getObjectOfType(String key, Class<T> type, boolean isPrimitive, MethodParameter methodParameter,
Object[] defaultValues) {
ValueList container = getValueList(key, false);
if (container == null) {
container = new ValueListSupport(getTypeConverter(), requestContext.isConverterQuiet());
if (!isEmptyArray(defaultValues)) {
for (Object value : defaultValues) {
container.addValue(value);
}
}
defaultValues = null;
}
return container.getValueOfType(type, isPrimitive, methodParameter, defaultValues);
}
public void setProperties(Object object) {
if (object == null) {
return;
}
if (getLogger().isDebugEnabled()) {
getLogger().debug("Set HTTP request parameters to object " + ObjectUtil.identityToString(object));
}
BeanWrapper bean = new BeanWrapperImpl(object);
requestContext.getPropertyEditorRegistrar().registerCustomEditors(bean);
for (String key : keySet()) {
String propertyName = StringUtil.toCamelCase(key);
if (bean.isWritableProperty(propertyName)) {
PropertyDescriptor pd = bean.getPropertyDescriptor(propertyName);
MethodParameter mp = BeanUtils.getWriteMethodParameter(pd);
Object value = getObjectOfType(key, pd.getPropertyType(), mp, null);
bean.setPropertyValue(propertyName, value);
} else {
getLogger().debug("No writable property \"{}\" found in type {}", propertyName,
object.getClass().getName());
}
}
}
// =============================================================
// 添加和修改参数的方法
// =============================================================
/**
* 添加参数名/参数值。
*
* @param key 参数名
* @param value 参数值
*/
public void add(String key, boolean value) {
getValueList(key, true).addValue(value);
}
/**
* 添加参数名/参数值。
*
* @param key 参数名
* @param value 参数值
*/
public void add(String key, byte value) {
getValueList(key, true).addValue(value);
}
/**
* 添加参数名/参数值。
*
* @param key 参数名
* @param value 参数值
*/
public void add(String key, char value) {
getValueList(key, true).addValue(value);
}
/**
* 添加参数名/参数值。
*
* @param key 参数名
* @param value 参数值
*/
public void add(String key, double value) {
getValueList(key, true).addValue(value);
}
/**
* 添加参数名/参数值。
*
* @param key 参数名
* @param value 参数值
*/
public void add(String key, float value) {
getValueList(key, true).addValue(value);
}
/**
* 添加参数名/参数值。
*
* @param key 参数名
* @param value 参数值
*/
public void add(String key, int value) {
getValueList(key, true).addValue(value);
}
/**
* 添加参数名/参数值。
*
* @param key 参数名
* @param value 参数值
*/
public void add(String key, long value) {
getValueList(key, true).addValue(value);
}
/**
* 添加参数名/参数值。
*
* @param key 参数名
* @param value 参数值
*/
public void add(String key, short value) {
getValueList(key, true).addValue(value);
}
/**
* 添加参数名/参数值。
*
* @param key 参数名
* @param value 参数值
*/
public void add(String key, Object value) {
getValueList(key, true).addValue(value);
}
/**
* 设置参数值。和<code>add</code>方法不同,此方法将覆盖原有的值。
*
* @param key 参数名
* @param value 参数值
*/
public void setString(String key, String value) {
setObject(key, value);
}
/**
* 设置参数值。和<code>add</code>方法不同,此方法将覆盖原有的值。
*
* @param key 参数名
* @param values 参数值的数组
*/
public void setStrings(String key, String[] values) {
setObjects(key, values);
}
/**
* 设置参数值。和<code>add</code>方法不同,此方法将覆盖原有的值。
*
* @param key 参数名
* @param value 参数值
*/
public void setObject(String key, Object value) {
getValueList(key, true).setValue(value);
}
/**
* 设置参数值。和<code>add</code>方法不同,此方法将覆盖原有的值。
*
* @param key 参数名
* @param values 参数值
*/
public void setObjects(String key, Object[] values) {
getValueList(key, true).setValues(values);
}
// =============================================================
// 清除参数的方法
// =============================================================
/**
* 删除指定名称的参数。
*
* @return 原先和指定名称对应的参数值,可能是<code>String[]</code>或<code>null</code>
*/
public Object remove(String key) {
key = convert(key);
parameterKeys.remove(key);
return parameters.remove(key);
}
/** 清除所有值。 */
public void clear() {
parameterKeys.clear();
parameters.clear();
}
// =============================================================
// 辅助方法
// =============================================================
/**
* 首先将参数名进行<code>trim()</code>,然后再进行大小写转换。转换是根据配置文件中的
* <code>url.case.folding</code>来设定的。
*
* @param key 要转换的参数名
* @return 被<code>trim()</code>和大小写转换后的参数名,如果是<code>null</code>,则转换成空字符串
*/
protected String convert(String key) {
if (requestContext == null) {
return key;
}
return requestContext.convertCase(key);
}
/**
* 取得指定参数的值的列表。
*
* @param key 参数名
* @param create 如果参数不存在,是否创建之
* @return 参数值的列表,如果参数不存在,且<code>create==false</code>,则返回<code>null</code>
*/
protected ValueList getValueList(String key, boolean create) {
String originalKey = key;
key = convert(key);
ValueList container = (ValueList) parameters.get(key);
if (create) {
if (container == null) {
container = new ValueListSupport(getTypeConverter(), requestContext.isConverterQuiet());
parameterKeys.put(key, originalKey);
parameters.put(key, container);
}
return container;
} else {
if (container == null || container.size() == 0) {
return null;
} else {
return container;
}
}
}
/**
* 取得用于解析参数的编码字符集。不同的实现取得编码字符集的方法也不同,例如,对于<code>ParameterParser</code>,
* 此编码字符集是由<code>request.getCharacterEncoding()</code>决定的。
* <p>
* 默认总是返回<code>ISO-8859-1</code>。
* </p>
*
* @return 编码字符集
*/
protected String getCharacterEncoding() {
return ParserRequestContext.DEFAULT_CHARSET_ENCODING;
}
/**
* 转换成字符串。
*
* @return 字符串表现
*/
@Override
public String toString() {
MapBuilder mb = new MapBuilder().setSortKeys(true);
for (String key : parameterKeys.values()) {
mb.append(key, getValueList(key, false));
}
return mb.toString();
}
}