Java tutorial
/* * 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.impl; import static com.alibaba.citrus.service.requestcontext.parser.ParserRequestContext.*; import static com.alibaba.citrus.util.ArrayUtil.*; import static com.alibaba.citrus.util.BasicConstant.*; import static com.alibaba.citrus.util.CollectionUtil.*; import static com.alibaba.citrus.util.StringUtil.*; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import com.alibaba.citrus.service.requestcontext.parser.AbstractValueParser; import com.alibaba.citrus.service.requestcontext.parser.ParameterParser; import com.alibaba.citrus.service.requestcontext.parser.ParameterParserFilter; import com.alibaba.citrus.service.requestcontext.parser.ParameterValueFilter; import com.alibaba.citrus.service.requestcontext.parser.ParserRequestContext; import com.alibaba.citrus.service.requestcontext.parser.UploadedFileFilter; import com.alibaba.citrus.service.requestcontext.util.QueryStringParser; import com.alibaba.citrus.service.requestcontext.util.ValueList; import com.alibaba.citrus.service.upload.UploadException; import com.alibaba.citrus.service.upload.UploadParameters; import com.alibaba.citrus.service.upload.UploadService; import com.alibaba.citrus.service.upload.UploadSizeLimitExceededException; import com.alibaba.citrus.util.StringEscapeUtil; import com.alibaba.citrus.util.StringUtil; import org.apache.commons.fileupload.FileItem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** ??HTTPGETPOST??<code>ParameterParser</code> */ public class ParameterParserImpl extends AbstractValueParser implements ParameterParser { private final static Logger log = LoggerFactory.getLogger(ParameterParser.class); private final UploadService upload; private final boolean trimming; private boolean uploadProcessed; private final ParameterParserFilter[] filters; private final String htmlFieldSuffix; /** requestparametersmultipart-form? */ public ParameterParserImpl(ParserRequestContext requestContext, UploadService upload, boolean trimming, ParameterParserFilter[] filters, String htmlFieldSuffix) { super(requestContext); this.upload = upload; this.trimming = trimming; this.filters = filters; this.htmlFieldSuffix = htmlFieldSuffix; HttpServletRequestWrapper wrapper = (HttpServletRequestWrapper) requestContext.getRequest(); HttpServletRequest wrappedRequest = (HttpServletRequest) wrapper.getRequest(); boolean isMultipart = false; // upload if (requestContext.isAutoUpload() && upload != null) { // multipart/*upload service?? isMultipart = upload.isMultipartContent(wrappedRequest); if (isMultipart) { try { parseUpload(); } catch (UploadSizeLimitExceededException e) { add(ParserRequestContext.UPLOAD_FAILED, Boolean.TRUE); add(ParserRequestContext.UPLOAD_SIZE_LIMIT_EXCEEDED, Boolean.TRUE); log.warn("File upload exceeds the size limit", e); } catch (UploadException e) { add(ParserRequestContext.UPLOAD_FAILED, Boolean.TRUE); log.warn("Upload failed", e); } } } // request?? if (!isMultipart) { String method = wrappedRequest.getMethod(); // URL?US-ASCII?URL? // ????? // // ? // 1. ???????? // GBK?????GBK?methodGETPOST // // 2. ???URL????? // Windowsiefirefox?GBK // macsafarifirefox?UTF-8 // // ?? // 1. Tomcatserver.xml<Connector URIEncoding="xxx">??GET?8859_1 // 2. JettyUTF-8??GET? // 3. POSTrequest.setCharacterEncoding("xxx")?8859_1 // 4. Tomcat5?<Connector useBodyEncodingForURI="true">GETrequest.setCharacterEncoding("xxx")? // // ???Tomcat/Jetty8859_1UTF-8??URL query? // // ????POST/PUTGET???servlet engine? // ?useServletEngineParser=true if (requestContext.isUseServletEngineParser() || "post".equalsIgnoreCase(method) || "put".equalsIgnoreCase(method)) { parseByServletEngine(wrappedRequest); } else { parseQueryString(requestContext, wrappedRequest); } postProcessParams(); } } @Override protected Logger getLogger() { return log; } /** servlet engine??? */ private void parseByServletEngine(HttpServletRequest wrappedRequest) { @SuppressWarnings("unchecked") Map<String, String[]> parameters = wrappedRequest.getParameterMap(); if (parameters != null && parameters.size() > 0) { for (Map.Entry<String, String[]> entry : parameters.entrySet()) { String key = entry.getKey(); String[] values = entry.getValue(); for (String value : values) { add(key, value); } } } } /** ?query string */ private void parseQueryString(ParserRequestContext requestContext, HttpServletRequest wrappedRequest) { // useBodyEncodingForURI=truerequest.setCharacterEncoding()???URIEncodingUTF-8 // useBodyEncodingForURItrue // tomcat?tomcat8859_1 String charset = requestContext.isUseBodyEncodingForURI() ? wrappedRequest.getCharacterEncoding() : requestContext.getURIEncoding(); QueryStringParser parser = new QueryStringParser(charset, DEFAULT_CHARSET_ENCODING) { @Override protected void add(String key, String value) { ParameterParserImpl.this.add(key, value); } }; parser.parse(wrappedRequest.getQueryString()); } /** * ?? * <p> * ???.~htmlHTML??? * </p> */ private void postProcessParams() { HttpServletRequestWrapper wrapper = (HttpServletRequestWrapper) requestContext.getRequest(); HttpServletRequest wrappedRequest = (HttpServletRequest) wrapper.getRequest(); boolean[] filtering = null; if (!isEmptyArray(filters)) { filtering = new boolean[filters.length]; for (int i = 0; i < filters.length; i++) { filtering[i] = filters[i].isFiltering(wrappedRequest); } } String[] keys = getKeys(); List<String> keysToRemove = createLinkedList(); for (String key : keys) { if (key.endsWith(htmlFieldSuffix)) { keysToRemove.add(key); key = key.substring(0, key.length() - htmlFieldSuffix.length()); if (!containsKey(key)) { setObjects(key, processValues(key, true, filtering)); } continue; } boolean isHtml = !StringUtil.isBlank(getString(key + htmlFieldSuffix)); setObjects(key, processValues(key, isHtml, filtering)); } for (String key : keysToRemove) { remove(key); } } private Object[] processValues(String key, boolean isHtmlField, boolean[] filtering) { Object[] values = getObjects(key); for (int i = 0; i < values.length; i++) { Object value = values[i]; if (value instanceof String) { // ?HTML〹??unicode if (!isHtmlField && requestContext.isUnescapeParameters()) { value = StringEscapeUtil.unescapeEntities(null, (String) value); } // if (filtering != null) { for (int j = 0; j < filters.length; j++) { ParameterParserFilter filter = filters[j]; if (filter instanceof ParameterValueFilter && filtering[j]) { value = ((ParameterValueFilter) filter).filter(key, (String) value, isHtmlField); } } } } else if (value instanceof FileItem) { // if (filtering != null) { for (int j = 0; j < filters.length; j++) { ParameterParserFilter filter = filters[j]; if (filter instanceof UploadedFileFilter && filtering[j]) { value = ((UploadedFileFilter) filter).filter(key, (FileItem) value); } } } } values[i] = value; } return values; } /** * ???<code>FileItem</code>?<code>null</code> * * @param key ??? * @return <code>FileItem</code> */ public FileItem getFileItem(String key) { ValueList container = getValueList(key, false); return container == null ? null : container.getFileItem(); } /** * ???<code>FileItem</code>?<code>null</code> * * @param key ??? * @return <code>FileItem</code> */ public FileItem[] getFileItems(String key) { ValueList container = getValueList(key, false); return container == null ? new FileItem[0] : container.getFileItems(); } /** * <code>FileItem</code> * * @param key ??? * @param value ? */ public void add(String key, FileItem value) { if (value.isFormField()) { add(key, value.getString()); } else { // if (!StringUtil.isEmpty(value.getName()) || value.getSize() > 0) { add(key, (Object) value); } } } /** * ???/? * * @param key ??? * @param value ? */ @Override public void add(String key, Object value) { if (value == null) { value = EMPTY_STRING; } if (trimming && value instanceof String) { value = trimToEmpty((String) value); } getValueList(key, true).addValue(value); } /** * ??<a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> * <code>multipart/form-data</code>HTTP * <p> * ?<code>UploadService.automatic</code>???<code>false</code> * service?actionservlet * </p> * * @throws UploadException ? */ public void parseUpload() throws UploadException { parseUpload(null); } /** * ??<a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> * <code>multipart/form-data</code>HTTP * <p> * ?<code>UploadService.automatic</code>???<code>false</code> * service?actionservlet * </p> * * @param sizeThreshold ???0 * @param sizeMax HTTP * @param repositoryPath ? * @throws UploadException ? */ public void parseUpload(UploadParameters params) throws UploadException { if (uploadProcessed || upload == null) { return; } FileItem[] items = upload.parseRequest(requestContext.getRequest(), params); for (FileItem item : items) { add(item.getFieldName(), item); } uploadProcessed = true; postProcessParams(); } /** * ??????????<code>ParameterParser</code> * ?<code>request.getCharacterEncoding()</code> * <p> * <code>ISO-8859-1</code> * </p> * * @return ? */ @Override protected String getCharacterEncoding() { String charset = requestContext.getRequest().getCharacterEncoding(); return charset == null ? ParserRequestContext.DEFAULT_CHARSET_ENCODING : charset; } /** * parameters??query string * * @return query string?<code>null</code> */ public String toQueryString() { QueryStringParser parser = new QueryStringParser(); for (Object element : keySet()) { String key = (String) element; Object[] values = getObjects(key); if (isEmptyArray(values)) { continue; } for (Object valueObject : values) { if (valueObject == null || valueObject instanceof String) { parser.append(key, (String) valueObject); } } } return parser.toQueryString(); } }