org.nervousync.http.entity.HttpEntity Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils-jdk11 Show documentation
Show all versions of utils-jdk11 Show documentation
Java utility collections, development by Nervousync Studio (NSYC)
/*
* Licensed to the Nervousync Studio (NSYC) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.nervousync.http.entity;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.nervousync.enumerations.web.HttpMethodOption;
import org.nervousync.utils.FileUtils;
import org.nervousync.utils.LoggerUtils;
import org.nervousync.utils.StringUtils;
import org.nervousync.commons.Globals;
/**
* Http Entity Define
* HTTP请求信息定义
*
* @author Steven Wee [email protected]
* @version $Revision: 1.0.0 $ $Date: Jan 2, 2018 14:05:04 $
*/
public final class HttpEntity {
/**
* Boundary string used characters
* Boundary字符串使用的字符数组
*/
private static final char[] BOUNDARY_CHAR_ARRAY = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
/**
* Logger instance
* 日志对象
*/
private final LoggerUtils.Logger logger = LoggerUtils.getLogger(this.getClass());
/**
* Boundary value, generated by system
* Boundary值,由系统自动生成
*/
private String boundary = null;
/**
* EntityInfo instance list
* EntityInfo实例对象列表
* @see HttpEntity.EntityInfo
*/
private final List entityList;
/**
* Is multipart request
* 多媒体请求状态
*/
private boolean multipart = Boolean.FALSE;
/**
* Is mixed parameters, means include form field and upload files
* 混合数据类型,表示数据中包含表单项和上传文件
*/
private boolean mixed = Boolean.FALSE;
/**
* Constructor method for HttpEntity
* HttpEntity构造方法
*/
public HttpEntity() {
this.entityList = new ArrayList<>();
}
/**
* Add text parameter
* 添加文本参数
*
* @param name parameter name
* 参数名
* @param value parameter value
* 参数值
*/
public void addTextEntity(final String name, final String value) {
this.entityList.add(EntityInfo.generateTextEntity(name, value));
}
/**
* Add upload file parameter
* 添加上传文件参数
*
* @param name parameter name
* 参数名
* @param value The upload file path
* 上传文件地址
*/
public void addBinaryEntity(final String name, final String value) {
try {
this.entityList.add(EntityInfo.generateBinaryEntity(name, value));
if (this.boundary == null) {
this.boundary = this.generateBoundary();
}
} catch (FileNotFoundException e) {
this.logger.error("Upload_File_Not_Found_Error");
if (this.logger.isDebugEnabled()) {
this.logger.debug("Stack_Message_Error", e);
}
}
}
/**
* Generate content type value
* 生成媒体类型信息
*
* @param charset Charset encoding
* 字符编码集
* @param methodOption HTTP method option Enumerations
* HTTP请求方法枚举
* @see org.nervousync.enumerations.web.HttpMethodOption
*
* @return Generated content type string
* 生成的媒体类型信息
* @throws UnsupportedEncodingException
* If charset encoding is not supported
* 如果字符编码集不被支持
*/
public String generateContentType(final String charset, final HttpMethodOption methodOption)
throws UnsupportedEncodingException {
String charsetEncoding = StringUtils.notBlank(charset) ? charset : "ISO-8859-1";
String contentType;
switch (methodOption) {
case POST: case PUT:
this.checkType();
if (this.multipart) {
if (this.mixed) {
contentType = Globals.DEFAULT_CONTENT_TYPE_MIXED + ";boundary=" + this.boundary;
} else {
contentType = Globals.FORM_DATA_CONTENT_TYPE_MULTIPART + ";boundary=" + this.boundary;
}
} else {
contentType = Globals.DEFAULT_CONTENT_TYPE_ENCODED + ";charset=" + charsetEncoding;
}
break;
case GET: case TRACE: case HEAD: case DELETE: case OPTIONS:
contentType = Globals.DEFAULT_CONTENT_TYPE_TEXT + ";charset=" + charsetEncoding;
break;
default:
throw new UnsupportedEncodingException("Unknown Request Method");
}
return contentType;
}
/**
* Write data to output stream
* 将数据写到输出流中
*
* @param charset Charset encoding
* 字符编码集
* @param outputStream Target output stream
* 目标输出流
*
* @throws IOException
* If an error occurs when write data to output stream
* 当写入数据到输出流中捕获异常
*/
public void writeData(final String charset, final OutputStream outputStream) throws IOException {
if (this.entityList.isEmpty()) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Entity_List_Empty_Debug");
}
return;
}
String charsetEncoding = StringUtils.notBlank(charset) ? charset : Globals.DEFAULT_ENCODING;
this.checkType();
if (this.multipart) {
StringBuilder stringBuilder;
for (EntityInfo entityInfo : this.entityList) {
stringBuilder = new StringBuilder();
stringBuilder.append("--").append(this.boundary).append(FileUtils.CRLF);
stringBuilder.append("Content-Disposition:" + Globals.FORM_DATA_CONTENT_DISPOSITION + ";");
stringBuilder.append("name=\"").append(entityInfo.getEntityName()).append("\"");
String value = entityInfo.getEntityValue();
if (entityInfo.isBinary()) {
stringBuilder.append(";filename=\"").append(StringUtils.getFilename(value)).append("\"");
stringBuilder.append(FileUtils.CRLF);
stringBuilder.append("Content-Type:" + Globals.DEFAULT_CONTENT_TYPE_BINARY);
}
stringBuilder.append(FileUtils.CRLF);
stringBuilder.append(FileUtils.CRLF);
outputStream.write(stringBuilder.toString().getBytes(Globals.DEFAULT_ENCODING));
if (entityInfo.isBinary()) {
outputStream.write(FileUtils.readFileBytes(value));
} else {
outputStream.write(value.getBytes(charsetEncoding));
}
outputStream.write(FileUtils.CRLF.getBytes(charsetEncoding));
}
outputStream.write(("--" + this.boundary).getBytes(charsetEncoding));
} else {
StringBuilder stringBuilder = new StringBuilder();
for (EntityInfo entityInfo : this.entityList) {
stringBuilder.append("&");
stringBuilder.append(URLEncoder.encode(entityInfo.getEntityName(), charsetEncoding));
stringBuilder.append("=");
stringBuilder.append(URLEncoder.encode(entityInfo.getEntityValue(), charsetEncoding));
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Write_Request_Data_Debug", stringBuilder);
}
outputStream.write(stringBuilder.substring(1).getBytes(charsetEncoding));
}
}
/**
* Check entity information, configure multipart and mixed value
* 检查当前的信息,设置multipart和mixed值
*/
private void checkType() {
int formItemCount = 0;
int fileItemCount = 0;
for (EntityInfo entityInfo : this.entityList) {
if (entityInfo.isBinary()) {
fileItemCount++;
} else {
formItemCount++;
}
}
if (fileItemCount > 0) {
this.multipart = Boolean.TRUE;
if (formItemCount > 0) {
this.mixed = Boolean.TRUE;
}
}
}
/**
* Generate random boundary string
* 生成随机Boundary字符串
*
* @return Generated string
* 生成的字符串
*/
private String generateBoundary() {
StringBuilder stringBuilder = new StringBuilder();
final Random random = new Random();
for (int i = 0 ; i < 32 ; i++) {
stringBuilder.append(BOUNDARY_CHAR_ARRAY[random.nextInt(BOUNDARY_CHAR_ARRAY.length)]);
}
return stringBuilder.toString();
}
/**
* Http Entity Information Define
* HTTP请求参数信息定义
*
* @author Steven Wee [email protected]
* @version $Revision: 1.0.0 $ $Date: Jul 2, 2018 14:08:33 $
*/
private static final class EntityInfo {
/**
* Binary data status
* 二进制数据状态
*/
private final boolean binary;
/**
* Entity name
* 参数名
*/
private final String entityName;
/**
* Entity value
* 参数值
*/
private final String entityValue;
/**
* Private constructor method for EntityInfo
* EntityInfo私有构造方法
*
* @param binary Binary status
* 二进制状态
* @param name Entity name
* 参数名
* @param value Entity value
* 参数值
*/
private EntityInfo(boolean binary, String name, String value) {
this.binary = binary;
this.entityName = name;
this.entityValue = value;
}
/**
* Static method for generate text EntityInfo instance
* 静态方法用于生成文字类型的EntityInfo实例对象
*
* @param name Entity name
* 参数名
* @param value Entity value
* 参数值
*
* @return Generated EntityInfo instance
* 生成的EntityInfo实例对象
*/
public static EntityInfo generateTextEntity(String name, String value) {
return new EntityInfo(Boolean.FALSE, name, value);
}
/**
* Static method for generate upload file EntityInfo instance
* 静态方法用于生成二进制类型的EntityInfo实例对象
*
* @param name Entity name
* 参数名
* @param value Upload file path
* 上传文件地址
*
* @return Generated EntityInfo instance
* 生成的EntityInfo实例对象
*/
public static EntityInfo generateBinaryEntity(String name, String value)
throws FileNotFoundException {
if (FileUtils.isExists(value)) {
return new EntityInfo(Boolean.TRUE, name, value);
}
throw new FileNotFoundException("File not exists");
}
/**
* Getter method for binary status
* 二进制状态的Getter方法
*
* @return Binary status
* 二进制状态
*/
public boolean isBinary() {
return binary;
}
/**
* Getter method for entity name
* 参数名的Getter方法
*
* @return Entity name
* 参数名
*/
public String getEntityName() {
return entityName;
}
/**
* Getter method for entity value
* 参数值的Getter方法
*
* @return Entity value
* 参数值
*/
public String getEntityValue() {
return entityValue;
}
}
}