Java tutorial
/** * Copyright (c) 1997-2013, www.tinygroup.org (luo_guo@icloud.com). * * Licensed under the GPL, Version 3.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.gnu.org/licenses/gpl.html * * 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 org.tinygroup.weblayer.webcontext.parser.valueparser.impl; import org.apache.commons.fileupload.FileItem; import org.tinygroup.commons.tools.StringEscapeUtil; import org.tinygroup.commons.tools.StringUtil; import org.tinygroup.vfs.FileObject; import org.tinygroup.weblayer.webcontext.parser.ParserWebContext; import org.tinygroup.weblayer.webcontext.parser.exception.UploadException; import org.tinygroup.weblayer.webcontext.parser.exception.UploadSizeLimitExceededException; import org.tinygroup.weblayer.webcontext.parser.fileupload.TinyFileItem; import org.tinygroup.weblayer.webcontext.parser.fileupload.TinyItemFileObject; import org.tinygroup.weblayer.webcontext.parser.impl.*; import org.tinygroup.weblayer.webcontext.parser.upload.*; import org.tinygroup.weblayer.webcontext.parser.valueparser.AbstractValueParser; import org.tinygroup.weblayer.webcontext.parser.valueparser.ParameterParser; import org.tinygroup.weblayer.webcontext.parser.valueparser.ValueList; import org.tinygroup.weblayer.webcontext.util.QueryStringParser; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.util.ArrayList; import java.util.List; import java.util.Map; import static org.tinygroup.commons.tools.ArrayUtil.isEmptyArray; import static org.tinygroup.commons.tools.BasicConstant.EMPTY_STRING; import static org.tinygroup.commons.tools.CollectionUtil.createLinkedList; import static org.tinygroup.commons.tools.StringUtil.trimToEmpty; import static org.tinygroup.weblayer.webcontext.parser.ParserWebContext.DEFAULT_CHARSET_ENCODING; /** * ??HTTPGETPOST??<code>ParameterParser</code> * * @author renhui */ public class ParameterParserImpl extends AbstractValueParser implements ParameterParser { private final UploadService upload; private final boolean trimming; private boolean uploadProcessed; private final ParameterParserFilter[] filters; private final String htmlFieldSuffix; private List<FileItem> fileItems = new ArrayList<FileItem>(); /** requestparametersmultipart-form? */ public ParameterParserImpl(ParserWebContext webContext, UploadService upload, boolean trimming, ParameterParserFilter[] filters, String htmlFieldSuffix) { super(webContext); this.upload = upload; this.trimming = trimming; this.filters = filters; this.htmlFieldSuffix = htmlFieldSuffix; HttpServletRequestWrapper wrapper = (HttpServletRequestWrapper) webContext.getRequest(); HttpServletRequest wrappedRequest = (HttpServletRequest) wrapper.getRequest(); boolean isMultipart = false; // upload if (webContext.isAutoUpload() && upload != null) { // multipart/*upload service?? isMultipart = upload.isMultipartContent(wrappedRequest); if (isMultipart) { try { parseUpload(); } catch (UploadSizeLimitExceededException e) { add(ParserWebContext.UPLOAD_FAILED, Boolean.TRUE); add(ParserWebContext.UPLOAD_SIZE_LIMIT_EXCEEDED, Boolean.TRUE); logger.errorMessage("File upload exceeds the size limit", e); throw e; } catch (UploadException e) { add(ParserWebContext.UPLOAD_FAILED, Boolean.TRUE); logger.errorMessage("Upload failed", e); throw 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 (webContext.isUseServletEngineParser() || "post".equalsIgnoreCase(method) || "put".equalsIgnoreCase(method)) { parseByServletEngine(wrappedRequest); } else { parseQueryString(webContext, wrappedRequest); } postProcessParams(); } } /** 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(ParserWebContext 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) { 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) webContext.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); List<Object> paramValues = new ArrayList<Object>(); for (int i = 0; i < values.length; i++) { Object value = values[i]; if (value instanceof ItemFileObject) { FileItem fileItem = ((ItemFileObject) value).getFileItem(); if (fileItem.isFormField()) {//???String value = fileItem.toString(); } } //?? if (value instanceof String) { stringValueFilter(key, isHtmlField, filtering, value, paramValues); } else if (value instanceof ItemFileObject) { fileItemFilter(key, filtering, value, paramValues); } } if (paramValues.size() > 0) { if (paramValues.size() == 1) { webContext.put(key, paramValues.get(0)); } else { webContext.put(key, paramValues.toArray()); } } return paramValues.toArray(); } private void fileItemFilter(String key, boolean[] filtering, Object value, List<Object> paramValues) { FileItem fileItem = ((ItemFileObject) value).getFileItem(); FileItem processFileItem = fileItem; // if (filtering != null) { for (int j = 0; j < filters.length; j++) { ParameterParserFilter filter = filters[j]; if (filter instanceof UploadedFileFilter && filtering[j]) { processFileItem = ((UploadedFileFilter) filter).filter(key, processFileItem); } } } if (processFileItem == null) { remove(key, value);//?fileitem fileItems.remove(fileItem); fileItem.delete(); } else { fileItem = processFileItem; if (!fileItem.isFormField() && fileItem.getContentType() != null) {// paramValues.add(value); } } } private void stringValueFilter(String key, boolean isHtmlField, boolean[] filtering, Object value, List<Object> paramValues) { Object processValue = value; // ?HTML〹??unicode if (!isHtmlField && webContext.isUnescapeParameters()) { processValue = 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]) { processValue = ((ParameterValueFilter) filter).filter(key, (String) processValue, isHtmlField); } if (filter instanceof ParamValueFilter && filtering[j] && ((ParamValueFilter) filter).isFilter(key)) { processValue = ((ParamValueFilter) filter).valueFilter((String) processValue, webContext); } } } paramValues.add(processValue); } /** * ???<code>FileItem</code>?<code>null</code> * * @param key * ??? * @return <code>FileItem</code> */ public FileObject getFileObject(String key) { ValueList container = getValueList(key, false); return container == null ? null : container.getFileObject(); } /** * ???<code>FileItem</code>?<code>null</code> * * @param key * ??? * @return <code>FileItem</code> */ public FileObject[] getFileObjects(String key) { ValueList container = getValueList(key, false); return container == null ? new FileObject[0] : container.getFileObjects(); } /** * <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 * ? */ 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(webContext.getRequest(), params); for (FileItem item : items) { FileObject fileObject = null; if (item instanceof InMemoryFormFieldItem) { fileObject = new FileObjectInMemory((InMemoryFormFieldItem) item); } else if (item instanceof DiskFileItem) { fileObject = new FileObjectInDisk((DiskFileItem) item); } else if (item instanceof TinyFileItem) { fileObject = new TinyItemFileObject((TinyFileItem) item); } add(item.getFieldName(), fileObject); fileItems.add(item); } uploadProcessed = true; postProcessParams(); } /** * ??????????<code>ParameterParser</code> * ?<code>request.getCharacterEncoding()</code> * <p> * <code>ISO-8859-1</code> * </p> * * @return ? */ protected String getCharacterEncoding() { String charset = webContext.getRequest().getCharacterEncoding(); return charset == null ? ParserWebContext.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(); } public FileItem[] getFileItems() { if (fileItems.isEmpty()) { return new FileItem[0]; } return fileItems.toArray(new FileItem[0]); } }