/******************************************************************************
* Copyright © 2013-2016 The Nxt Core Developers. *
* *
* See the AUTHORS.txt, DEVELOPER-AGREEMENT.txt and LICENSE.txt files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* Nxt software, including this file, may be copied, modified, propagated, *
* or distributed except according to the terms contained in the LICENSE.txt *
* file. *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
package nxt.http;
import nxt.Account;
import nxt.Alias;
import nxt.Appendix;
import nxt.Asset;
import nxt.Attachment;
import nxt.Constants;
import nxt.Currency;
import nxt.CurrencyBuyOffer;
import nxt.CurrencySellOffer;
import nxt.DigitalGoodsStore;
import nxt.Nxt;
import nxt.NxtException;
import nxt.Poll;
import nxt.Shuffling;
import nxt.Transaction;
import nxt.crypto.Crypto;
import nxt.crypto.EncryptedData;
import nxt.util.Convert;
import nxt.util.Logger;
import nxt.util.Search;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import static nxt.http.JSONResponses.*;
final class ParameterParser {
static byte getByte(HttpServletRequest req, String name, byte min, byte max, boolean isMandatory) throws ParameterException {
String paramValue = Convert.emptyToNull(req.getParameter(name));
if (paramValue == null) {
if (isMandatory) {
throw new ParameterException(missing(name));
}
return 0;
}
try {
byte value = Byte.parseByte(paramValue);
if (value < min || value > max) {
throw new ParameterException(incorrect(name, String.format("value %d not in range [%d-%d]", value, min, max)));
}
return value;
} catch (RuntimeException e) {
throw new ParameterException(incorrect(name, String.format("value %s is not numeric", paramValue)));
}
}
static int getInt(HttpServletRequest req, String name, int min, int max, boolean isMandatory) throws ParameterException {
String paramValue = Convert.emptyToNull(req.getParameter(name));
if (paramValue == null) {
if (isMandatory) {
throw new ParameterException(missing(name));
}
return 0;
}
try {
int value = Integer.parseInt(paramValue);
if (value < min || value > max) {
throw new ParameterException(incorrect(name, String.format("value %d not in range [%d-%d]", value, min, max)));
}
return value;
} catch (RuntimeException e) {
throw new ParameterException(incorrect(name, String.format("value %s is not numeric", paramValue)));
}
}
static long getLong(HttpServletRequest req, String name, long min, long max,
boolean isMandatory) throws ParameterException {
String paramValue = Convert.emptyToNull(req.getParameter(name));
if (paramValue == null) {
if (isMandatory) {
throw new ParameterException(missing(name));
}
return 0;
}
try {
long value = Long.parseLong(paramValue);
if (value < min || value > max) {
throw new ParameterException(incorrect(name, String.format("value %d not in range [%d-%d]", value, min, max)));
}
return value;
} catch (RuntimeException e) {
throw new ParameterException(incorrect(name, String.format("value %s is not numeric", paramValue)));
}
}
static long getUnsignedLong(HttpServletRequest req, String name, boolean isMandatory) throws ParameterException {
String paramValue = Convert.emptyToNull(req.getParameter(name));
if (paramValue == null) {
if (isMandatory) {
throw new ParameterException(missing(name));
}
return 0;
}
try {
long value = Convert.parseUnsignedLong(paramValue);
if (value == 0) { // 0 is not allowed as an id
throw new ParameterException(incorrect(name));
}
return value;
} catch (RuntimeException e) {
throw new ParameterException(incorrect(name));
}
}
static long[] getUnsignedLongs(HttpServletRequest req, String name) throws ParameterException {
String[] paramValues = req.getParameterValues(name);
if (paramValues == null || paramValues.length == 0) {
throw new ParameterException(missing(name));
}
long[] values = new long[paramValues.length];
try {
for (int i = 0; i < paramValues.length; i++) {
if (paramValues[i] == null || paramValues[i].isEmpty()) {
throw new ParameterException(incorrect(name));
}
values[i] = Long.parseUnsignedLong(paramValues[i]);
if (values[i] == 0) {
throw new ParameterException(incorrect(name));
}
}
} catch (RuntimeException e) {
throw new ParameterException(incorrect(name));
}
return values;
}
static byte[] getBytes(HttpServletRequest req, String name, boolean isMandatory) throws ParameterException {
String paramValue = Convert.emptyToNull(req.getParameter(name));
if (paramValue == null) {
if (isMandatory) {
throw new ParameterException(missing(name));
}
return Convert.EMPTY_BYTE;
}
return Convert.parseHexString(paramValue);
}
static long getAccountId(HttpServletRequest req, boolean isMandatory) throws ParameterException {
return getAccountId(req, "account", isMandatory);
}
static long getAccountId(HttpServletRequest req, String name, boolean isMandatory) throws ParameterException {
String paramValue = Convert.emptyToNull(req.getParameter(name));
if (paramValue == null) {
if (isMandatory) {
throw new ParameterException(missing(name));
}
return 0;
}
try {
long value = Convert.parseAccountId(paramValue);
if (value == 0) {
throw new ParameterException(incorrect(name));
}
return value;
} catch (RuntimeException e) {
throw new ParameterException(incorrect(name));
}
}
static long[] getAccountIds(HttpServletRequest req, boolean isMandatory) throws ParameterException {
String[] paramValues = req.getParameterValues("account");
if (paramValues == null || paramValues.length == 0) {
if (isMandatory) {
throw new ParameterException(MISSING_ACCOUNT);
} else {
return Convert.EMPTY_LONG;
}
}
long[] values = new long[paramValues.length];
try {
for (int i = 0; i < paramValues.length; i++) {
if (paramValues[i] == null || paramValues[i].isEmpty()) {
throw new ParameterException(INCORRECT_ACCOUNT);
}
values[i] = Convert.parseAccountId(paramValues[i]);
if (values[i] == 0) {
throw new ParameterException(INCORRECT_ACCOUNT);
}
}
} catch (RuntimeException e) {
throw new ParameterException(INCORRECT_ACCOUNT);
}
return values;
}
static Alias getAlias(HttpServletRequest req) throws ParameterException {
long aliasId;
try {
aliasId = Convert.parseUnsignedLong(Convert.emptyToNull(req.getParameter("alias")));
} catch (RuntimeException e) {
throw new ParameterException(INCORRECT_ALIAS);
}
String aliasName = Convert.emptyToNull(req.getParameter("aliasName"));
Alias alias;
if (aliasId != 0) {
alias = Alias.getAlias(aliasId);
} else if (aliasName != null) {
alias = Alias.getAlias(aliasName);
} else {
throw new ParameterException(MISSING_ALIAS_OR_ALIAS_NAME);
}
if (alias == null) {
throw new ParameterException(UNKNOWN_ALIAS);
}
return alias;
}
static long getAmountNQT(HttpServletRequest req) throws ParameterException {
return getLong(req, "amountNQT", 1L, Constants.MAX_BALANCE_NQT, true);
}
static long getFeeNQT(HttpServletRequest req) throws ParameterException {
return getLong(req, "feeNQT", 0L, Constants.MAX_BALANCE_NQT, true);
}
static long getPriceNQT(HttpServletRequest req) throws ParameterException {
return getLong(req, "priceNQT", 1L, Constants.MAX_BALANCE_NQT, true);
}
static Poll getPoll(HttpServletRequest req) throws ParameterException {
Poll poll = Poll.getPoll(getUnsignedLong(req, "poll", true));
if (poll == null) {
throw new ParameterException(UNKNOWN_POLL);
}
return poll;
}
static Asset getAsset(HttpServletRequest req) throws ParameterException {
Asset asset = Asset.getAsset(getUnsignedLong(req, "asset", true));
if (asset == null) {
throw new ParameterException(UNKNOWN_ASSET);
}
return asset;
}
static Currency getCurrency(HttpServletRequest req) throws ParameterException {
return getCurrency(req, true);
}
static Currency getCurrency(HttpServletRequest req, boolean isMandatory) throws ParameterException {
Currency currency = Currency.getCurrency(getUnsignedLong(req, "currency", isMandatory));
if (isMandatory && currency == null) {
throw new ParameterException(UNKNOWN_CURRENCY);
}
return currency;
}
static CurrencyBuyOffer getBuyOffer(HttpServletRequest req) throws ParameterException {
CurrencyBuyOffer offer = CurrencyBuyOffer.getOffer(getUnsignedLong(req, "offer", true));
if (offer == null) {
throw new ParameterException(UNKNOWN_OFFER);
}
return offer;
}
static CurrencySellOffer getSellOffer(HttpServletRequest req) throws ParameterException {
CurrencySellOffer offer = CurrencySellOffer.getOffer(getUnsignedLong(req, "offer", true));
if (offer == null) {
throw new ParameterException(UNKNOWN_OFFER);
}
return offer;
}
static Shuffling getShuffling(HttpServletRequest req) throws ParameterException {
Shuffling shuffling = Shuffling.getShuffling(getUnsignedLong(req, "shuffling", true));
if (shuffling == null) {
throw new ParameterException(UNKNOWN_SHUFFLING);
}
return shuffling;
}
static long getQuantityQNT(HttpServletRequest req) throws ParameterException {
return getLong(req, "quantityQNT", 1L, Constants.MAX_ASSET_QUANTITY_QNT, true);
}
static long getAmountNQTPerQNT(HttpServletRequest req) throws ParameterException {
return getLong(req, "amountNQTPerQNT", 1L, Constants.MAX_BALANCE_NQT, true);
}
static DigitalGoodsStore.Goods getGoods(HttpServletRequest req) throws ParameterException {
DigitalGoodsStore.Goods goods = DigitalGoodsStore.Goods.getGoods(getUnsignedLong(req, "goods", true));
if (goods == null) {
throw new ParameterException(UNKNOWN_GOODS);
}
return goods;
}
static int getGoodsQuantity(HttpServletRequest req) throws ParameterException {
return getInt(req, "quantity", 0, Constants.MAX_DGS_LISTING_QUANTITY, true);
}
static EncryptedData getEncryptedData(HttpServletRequest req, String messageType) throws ParameterException {
String dataString = Convert.emptyToNull(req.getParameter(messageType + "Data"));
String nonceString = Convert.emptyToNull(req.getParameter(messageType + "Nonce"));
if (dataString == null || nonceString == null) {
return null;
}
byte[] data;
byte[] nonce;
try {
data = Convert.parseHexString(dataString);
} catch (RuntimeException e) {
throw new ParameterException(JSONResponses.incorrect(messageType + "Data"));
}
try {
nonce = Convert.parseHexString(nonceString);
} catch (RuntimeException e) {
throw new ParameterException(JSONResponses.incorrect(messageType + "Nonce"));
}
return new EncryptedData(data, nonce);
}
static Appendix.EncryptToSelfMessage getEncryptToSelfMessage(HttpServletRequest req) throws ParameterException {
boolean isText = !"false".equalsIgnoreCase(req.getParameter("messageToEncryptToSelfIsText"));
boolean compress = !"false".equalsIgnoreCase(req.getParameter("compressMessageToEncryptToSelf"));
byte[] plainMessageBytes = null;
EncryptedData encryptedData = ParameterParser.getEncryptedData(req, "encryptToSelfMessage");
if (encryptedData == null) {
String plainMessage = Convert.emptyToNull(req.getParameter("messageToEncryptToSelf"));
if (plainMessage == null) {
return null;
}
try {
plainMessageBytes = isText ? Convert.toBytes(plainMessage) : Convert.parseHexString(plainMessage);
} catch (RuntimeException e) {
throw new ParameterException(INCORRECT_MESSAGE_TO_ENCRYPT);
}
String secretPhrase = getSecretPhrase(req, false);
if (secretPhrase != null) {
byte[] publicKey = Crypto.getPublicKey(secretPhrase);
encryptedData = Account.encryptTo(publicKey, plainMessageBytes, secretPhrase, compress);
}
}
if (encryptedData != null) {
return new Appendix.EncryptToSelfMessage(encryptedData, isText, compress);
} else {
return new Appendix.UnencryptedEncryptToSelfMessage(plainMessageBytes, isText, compress);
}
}
static DigitalGoodsStore.Purchase getPurchase(HttpServletRequest req) throws ParameterException {
DigitalGoodsStore.Purchase purchase = DigitalGoodsStore.Purchase.getPurchase(getUnsignedLong(req, "purchase", true));
if (purchase == null) {
throw new ParameterException(INCORRECT_PURCHASE);
}
return purchase;
}
static String getSecretPhrase(HttpServletRequest req, boolean isMandatory) throws ParameterException {
String secretPhrase = Convert.emptyToNull(req.getParameter("secretPhrase"));
if (secretPhrase == null && isMandatory) {
throw new ParameterException(MISSING_SECRET_PHRASE);
}
return secretPhrase;
}
static byte[] getPublicKey(HttpServletRequest req) throws ParameterException {
return getPublicKey(req, null);
}
static byte[] getPublicKey(HttpServletRequest req, String prefix) throws ParameterException {
String secretPhraseParam = prefix == null ? "secretPhrase" : (prefix + "SecretPhrase");
String publicKeyParam = prefix == null ? "publicKey" : (prefix + "PublicKey");
String secretPhrase = Convert.emptyToNull(req.getParameter(secretPhraseParam));
if (secretPhrase == null) {
try {
byte[] publicKey = Convert.parseHexString(Convert.emptyToNull(req.getParameter(publicKeyParam)));
if (publicKey == null) {
throw new ParameterException(missing(secretPhraseParam, publicKeyParam));
}
if (!Crypto.isCanonicalPublicKey(publicKey)) {
throw new ParameterException(incorrect(publicKeyParam));
}
return publicKey;
} catch (RuntimeException e) {
throw new ParameterException(incorrect(publicKeyParam));
}
} else {
return Crypto.getPublicKey(secretPhrase);
}
}
static Account getSenderAccount(HttpServletRequest req) throws ParameterException {
byte[] publicKey = getPublicKey(req);
Account account = Account.getAccount(publicKey);
if (account == null) {
throw new ParameterException(UNKNOWN_ACCOUNT);
}
return account;
}
static Account getAccount(HttpServletRequest req) throws ParameterException {
return getAccount(req, true);
}
static Account getAccount(HttpServletRequest req, boolean isMandatory) throws ParameterException {
long accountId = getAccountId(req, "account", isMandatory);
if (accountId == 0 && !isMandatory) {
return null;
}
Account account = Account.getAccount(accountId);
if (account == null) {
throw new ParameterException(JSONResponses.unknownAccount(accountId));
}
return account;
}
static List<Account> getAccounts(HttpServletRequest req) throws ParameterException {
String[] accountValues = req.getParameterValues("account");
if (accountValues == null || accountValues.length == 0) {
throw new ParameterException(MISSING_ACCOUNT);
}
List<Account> result = new ArrayList<>();
for (String accountValue : accountValues) {
if (accountValue == null || accountValue.equals("")) {
continue;
}
try {
Account account = Account.getAccount(Convert.parseAccountId(accountValue));
if (account == null) {
throw new ParameterException(UNKNOWN_ACCOUNT);
}
result.add(account);
} catch (RuntimeException e) {
throw new ParameterException(INCORRECT_ACCOUNT);
}
}
return result;
}
static int getTimestamp(HttpServletRequest req) throws ParameterException {
return getInt(req, "timestamp", 0, Integer.MAX_VALUE, false);
}
static int getFirstIndex(HttpServletRequest req) {
try {
int firstIndex = Integer.parseInt(req.getParameter("firstIndex"));
if (firstIndex < 0) {
return 0;
}
return firstIndex;
} catch (NumberFormatException e) {
return 0;
}
}
static int getLastIndex(HttpServletRequest req) {
int lastIndex = Integer.MAX_VALUE;
try {
lastIndex = Integer.parseInt(req.getParameter("lastIndex"));
if (lastIndex < 0) {
lastIndex = Integer.MAX_VALUE;
}
} catch (NumberFormatException ignored) {}
if (!API.checkPassword(req)) {
int firstIndex = Math.min(getFirstIndex(req), Integer.MAX_VALUE - API.maxRecords + 1);
lastIndex = Math.min(lastIndex, firstIndex + API.maxRecords - 1);
}
return lastIndex;
}
static int getNumberOfConfirmations(HttpServletRequest req) throws ParameterException {
return getInt(req, "numberOfConfirmations", 0, Nxt.getBlockchain().getHeight(), false);
}
static int getHeight(HttpServletRequest req) throws ParameterException {
String heightValue = Convert.emptyToNull(req.getParameter("height"));
if (heightValue != null) {
try {
int height = Integer.parseInt(heightValue);
if (height < 0 || height > Nxt.getBlockchain().getHeight()) {
throw new ParameterException(INCORRECT_HEIGHT);
}
return height;
} catch (NumberFormatException e) {
throw new ParameterException(INCORRECT_HEIGHT);
}
}
return -1;
}
static String getSearchQuery(HttpServletRequest req) throws ParameterException {
String query = Convert.nullToEmpty(req.getParameter("query")).trim();
String tags = Convert.nullToEmpty(req.getParameter("tag")).trim();
if (query.isEmpty() && tags.isEmpty()) {
throw new ParameterException(JSONResponses.missing("query", "tag"));
}
if (!tags.isEmpty()) {
StringJoiner stringJoiner = new StringJoiner(" AND TAGS:", "TAGS:", "");
for (String tag : Search.parseTags(tags, 0, Integer.MAX_VALUE, Integer.MAX_VALUE)) {
stringJoiner.add(tag);
}
query = stringJoiner.toString() + (query.isEmpty() ? "" : (" AND (" + query + ")"));
}
return query;
}
static Transaction.Builder parseTransaction(String transactionJSON, String transactionBytes, String prunableAttachmentJSON) throws ParameterException {
if (transactionBytes == null && transactionJSON == null) {
throw new ParameterException(MISSING_TRANSACTION_BYTES_OR_JSON);
}
if (transactionBytes != null && transactionJSON != null) {
throw new ParameterException(either("transactionBytes", "transactionJSON"));
}
if (prunableAttachmentJSON != null && transactionBytes == null) {
throw new ParameterException(JSONResponses.missing("transactionBytes"));
}
if (transactionJSON != null) {
try {
JSONObject json = (JSONObject) JSONValue.parseWithException(transactionJSON);
return Nxt.newTransactionBuilder(json);
} catch (NxtException.ValidationException | RuntimeException | ParseException e) {
Logger.logDebugMessage(e.getMessage(), e);
JSONObject response = new JSONObject();
JSONData.putException(response, e, "Incorrect transactionJSON");
throw new ParameterException(response);
}
} else {
try {
byte[] bytes = Convert.parseHexString(transactionBytes);
JSONObject prunableAttachments = prunableAttachmentJSON == null ? null : (JSONObject)JSONValue.parseWithException(prunableAttachmentJSON);
return Nxt.newTransactionBuilder(bytes, prunableAttachments);
} catch (NxtException.ValidationException|RuntimeException | ParseException e) {
Logger.logDebugMessage(e.getMessage(), e);
JSONObject response = new JSONObject();
JSONData.putException(response, e, "Incorrect transactionBytes");
throw new ParameterException(response);
}
}
}
static Appendix getPlainMessage(HttpServletRequest req, boolean prunable) throws ParameterException {
String messageValue = Convert.emptyToNull(req.getParameter("message"));
if (messageValue != null) {
boolean messageIsText = !"false".equalsIgnoreCase(req.getParameter("messageIsText"));
try {
if (prunable) {
return new Appendix.PrunablePlainMessage(messageValue, messageIsText);
} else {
return new Appendix.Message(messageValue, messageIsText);
}
} catch (RuntimeException e) {
throw new ParameterException(INCORRECT_ARBITRARY_MESSAGE);
}
}
return null;
}
static Appendix getEncryptedMessage(HttpServletRequest req, Account recipient, boolean prunable) throws ParameterException {
boolean isText = !"false".equalsIgnoreCase(req.getParameter("messageToEncryptIsText"));
boolean compress = !"false".equalsIgnoreCase(req.getParameter("compressMessageToEncrypt"));
byte[] plainMessageBytes = null;
byte[] recipientPublicKey = null;
EncryptedData encryptedData = ParameterParser.getEncryptedData(req, "encryptedMessage");
if (encryptedData == null) {
String plainMessage = Convert.emptyToNull(req.getParameter("messageToEncrypt"));
if (plainMessage == null) {
return null;
}
if (recipient != null) {
recipientPublicKey = recipient.getPublicKey();
}
if (recipientPublicKey == null) {
recipientPublicKey = Convert.parseHexString(Convert.emptyToNull(req.getParameter("recipientPublicKey")));
}
if (recipientPublicKey == null) {
throw new ParameterException(MISSING_RECIPIENT_PUBLIC_KEY);
}
try {
plainMessageBytes = isText ? Convert.toBytes(plainMessage) : Convert.parseHexString(plainMessage);
} catch (RuntimeException e) {
throw new ParameterException(INCORRECT_MESSAGE_TO_ENCRYPT);
}
String secretPhrase = getSecretPhrase(req, false);
if (secretPhrase != null) {
encryptedData = Account.encryptTo(recipientPublicKey, plainMessageBytes, secretPhrase, compress);
}
}
if (encryptedData != null) {
if (prunable) {
return new Appendix.PrunableEncryptedMessage(encryptedData, isText, compress);
} else {
return new Appendix.EncryptedMessage(encryptedData, isText, compress);
}
} else {
if (prunable) {
return new Appendix.UnencryptedPrunableEncryptedMessage(plainMessageBytes, isText, compress, recipientPublicKey);
} else {
return new Appendix.UnencryptedEncryptedMessage(plainMessageBytes, isText, compress, recipientPublicKey);
}
}
}
static Attachment.TaggedDataUpload getTaggedData(HttpServletRequest req) throws ParameterException, NxtException.NotValidException {
String name = Convert.emptyToNull(req.getParameter("name"));
String description = Convert.nullToEmpty(req.getParameter("description"));
String tags = Convert.nullToEmpty(req.getParameter("tags"));
String type = Convert.nullToEmpty(req.getParameter("type")).trim();
String channel = Convert.nullToEmpty(req.getParameter("channel"));
boolean isText = !"false".equalsIgnoreCase(req.getParameter("isText"));
String filename = Convert.nullToEmpty(req.getParameter("filename")).trim();
String dataValue = Convert.emptyToNull(req.getParameter("data"));
byte[] data;
if (dataValue == null) {
try {
Part part = req.getPart("file");
if (part == null) {
throw new ParameterException(INCORRECT_TAGGED_DATA_FILE);
}
FileData fileData = new FileData(part).invoke();
data = fileData.getData();
// Depending on how the client submits the form, the filename, can be a regular parameter
// or encoded in the multipart form. If its not a parameter we take from the form
if (filename.isEmpty() && fileData.getFilename() != null) {
filename = fileData.getFilename().trim();
}
if (name == null) {
name = filename;
}
} catch (IOException | ServletException e) {
Logger.logDebugMessage("error in reading file data", e);
throw new ParameterException(INCORRECT_TAGGED_DATA_FILE);
}
} else {
data = isText ? Convert.toBytes(dataValue) : Convert.parseHexString(dataValue);
}
String detectedMimeType = Search.detectMimeType(data, filename);
if (detectedMimeType != null) {
isText = detectedMimeType.equals("text/plain");
if (type.isEmpty()) {
type = detectedMimeType.substring(0, Math.min(detectedMimeType.length(), Constants.MAX_TAGGED_DATA_TYPE_LENGTH));
}
}
if (name == null) {
throw new ParameterException(MISSING_NAME);
}
name = name.trim();
if (name.length() > Constants.MAX_TAGGED_DATA_NAME_LENGTH) {
throw new ParameterException(INCORRECT_TAGGED_DATA_NAME);
}
if (description.length() > Constants.MAX_TAGGED_DATA_DESCRIPTION_LENGTH) {
throw new ParameterException(INCORRECT_TAGGED_DATA_DESCRIPTION);
}
if (tags.length() > Constants.MAX_TAGGED_DATA_TAGS_LENGTH) {
throw new ParameterException(INCORRECT_TAGGED_DATA_TAGS);
}
type = type.trim();
if (type.length() > Constants.MAX_TAGGED_DATA_TYPE_LENGTH) {
throw new ParameterException(INCORRECT_TAGGED_DATA_TYPE);
}
channel = channel.trim();
if (channel.length() > Constants.MAX_TAGGED_DATA_CHANNEL_LENGTH) {
throw new ParameterException(INCORRECT_TAGGED_DATA_CHANNEL);
}
if (data.length == 0 || data.length > Constants.MAX_TAGGED_DATA_DATA_LENGTH) {
throw new ParameterException(INCORRECT_DATA);
}
if (filename.length() > Constants.MAX_TAGGED_DATA_FILENAME_LENGTH) {
throw new ParameterException(INCORRECT_TAGGED_DATA_FILENAME);
}
return new Attachment.TaggedDataUpload(name, description, tags, type, channel, isText, filename, data);
}
private ParameterParser() {} // never
static class FileData {
private final Part part;
private String filename;
private byte[] data;
public FileData(Part part) {
this.part = part;
}
public String getFilename() {
return filename;
}
public byte[] getData() {
return data;
}
public FileData invoke() throws IOException {
try (InputStream is = part.getInputStream()) {
int nRead;
byte[] bytes = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((nRead = is.read(bytes, 0, bytes.length)) != -1) {
baos.write(bytes, 0, nRead);
}
data = baos.toByteArray();
filename = part.getSubmittedFileName();
}
return this;
}
}
}