org.nervousync.commons.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.commons.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.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.nervousync.commons.core.Globals;
/**
* Http Entity
* @author Steven Wee [email protected]
* @version $Revision: 1.0 $ $Date: Jan 2, 2018 2:05:04 PM $
*/
public final class HttpEntity {
// Boundary string used characters
private static final char[] BOUNDARY_CHAR_ARRAY = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
// TEXT content type
private static final String TEXT_CONTENT_TYPE = "text/plain";
// Encoded content type
private static final String ENCODED_CONTENT_TYPE = "application/x-www-form-urlencoded";
// Multipart content type
private static final String MULTIPART_CONTENT_TYPE = "multipart/form-data";
// Mixed content type
private static final String MIXED_CONTENT_TYPE = "multipart/mixed";
// Binary content type
private static final String BINARY_CONTENT_TYPE = "application/octet-stream";
// Content disposition
private static final String CONTENT_DISPOSITION = "form-data";
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* Boundary value, generated by system
*/
private String boundary = null;
/**
* List of entity info
* @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
*/
private HttpEntity() {
this.entityList = new ArrayList<>();
}
/**
* Generate a new HttpEntity
* @return HttpEntity instance
*/
public static HttpEntity newInstance() {
return new HttpEntity();
}
/**
* Add text parameter
* @param name Parameter name
* @param value Parameter value
*/
public void addTextEntity(String name, String value) {
this.entityList.add(EntityInfo.generateTextEntity(name, value));
}
/**
* Add binary parameter
* @param name Parameter name
* @param value The upload file path
*/
public void addBinaryEntity(String name, 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! ");
if (this.logger.isDebugEnabled()) {
this.logger.debug("Stack message: ", e);
}
}
}
/**
* Generate content type value
* @param charset Charset encoding
* @param methodOption Http method type
* @see HttpMethodOption
* @return Content type
* @throws UnsupportedEncodingException Charset encoding is not supported
*/
public String generateContentType(String charset, HttpMethodOption methodOption)
throws UnsupportedEncodingException {
if (charset == null || charset.trim().length() == 0) {
charset = "ISO-8859-1";
}
String contentType;
switch (methodOption) {
case POST: case PUT:
this.checkType();
if (this.multipart) {
if (this.mixed) {
contentType = MIXED_CONTENT_TYPE + ";boundary=" + this.boundary;
} else {
contentType = MULTIPART_CONTENT_TYPE + ";boundary=" + this.boundary;
}
} else {
contentType = ENCODED_CONTENT_TYPE + ";charset=" + charset;
}
break;
case GET: case TRACE: case HEAD: case DELETE: case OPTIONS:
contentType = TEXT_CONTENT_TYPE + ";charset=" + charset;
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 Write data to output stream error
*/
public void writeData(String charset, OutputStream outputStream) throws IOException {
if (this.entityList.isEmpty()) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Entity list is empty");
}
return;
}
if (charset == null || charset.trim().length() == 0) {
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:" + 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:" + BINARY_CONTENT_TYPE);
}
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(charset));
}
outputStream.write(FileUtils.CRLF.getBytes(charset));
}
outputStream.write(("--" + this.boundary).getBytes(charset));
} else {
StringBuilder stringBuilder = new StringBuilder();
for (EntityInfo entityInfo : this.entityList) {
stringBuilder.append("&");
stringBuilder.append(URLEncoder.encode(entityInfo.getEntityName(), charset));
stringBuilder.append("=");
stringBuilder.append(URLEncoder.encode(entityInfo.getEntityValue(), charset));
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Write data: {}", stringBuilder);
}
outputStream.write(stringBuilder.substring(1).getBytes(charset));
}
}
/**
* Setting value for field multipart and 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 = true;
if (formItemCount > 0) {
this.mixed = true;
}
}
}
/**
* Generate boundary value
* @return Generated boundary
*/
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();
}
/**
* Entity information
* @author Steven Wee [email protected]
* @version $Revision: 1.0 $ $Date: Jul 2, 2018 $
*/
private static final class EntityInfo {
/**
* Entity is binary
*/
private final boolean binary;
/**
* Entity name
*/
private final String entityName;
/**
* Entity value
*/
private final String entityValue;
private EntityInfo(boolean binary, String name, String value) {
this.binary = binary;
this.entityName = name;
this.entityValue = value;
}
public static EntityInfo generateTextEntity(String name, String value) {
return new EntityInfo(Boolean.FALSE, name, value);
}
public static EntityInfo generateBinaryEntity(String name, String value)
throws FileNotFoundException {
if (FileUtils.isExists(value)) {
return new EntityInfo(true, name, value);
}
throw new FileNotFoundException("File not exists");
}
/**
* @return the binary
*/
public boolean isBinary() {
return binary;
}
/**
* @return the entityName
*/
public String getEntityName() {
return entityName;
}
/**
* @return the entityValue
*/
public String getEntityValue() {
return entityValue;
}
}
}