package io.undertow.server.handlers.form;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import io.undertow.UndertowMessages;
import io.undertow.util.HeaderMap;
public final class FormData implements Iterable<String> {
private final Map<String, Deque<FormValue>> values = new LinkedHashMap<>();
private final int maxValues;
private int valueCount = 0;
public FormData(final int maxValues) {
this.maxValues = maxValues;
}
public Iterator<String> iterator() {
return values.keySet().iterator();
}
public FormValue getFirst(String name) {
final Deque<FormValue> deque = values.get(name);
return deque == null ? null : deque.peekFirst();
}
public FormValue getLast(String name) {
final Deque<FormValue> deque = values.get(name);
return deque == null ? null : deque.peekLast();
}
public Deque<FormValue> get(String name) {
return values.get(name);
}
public void add(String name, String value) {
add(name, value, null);
}
public void add(String name, String value, final HeaderMap headers) {
Deque<FormValue> values = this.values.get(name);
if (values == null) {
this.values.put(name, values = new ArrayDeque<>(1));
}
values.add(new FormValueImpl(value, headers));
if (++valueCount > maxValues) {
throw new RuntimeException(UndertowMessages.MESSAGES.tooManyParameters(maxValues));
}
}
public void add(String name, Path value, String fileName, final HeaderMap headers) {
Deque<FormValue> values = this.values.get(name);
if (values == null) {
this.values.put(name, values = new ArrayDeque<>(1));
}
values.add(new FormValueImpl(value, fileName, headers));
if (values.size() > maxValues) {
throw new RuntimeException(UndertowMessages.MESSAGES.tooManyParameters(maxValues));
}
if (++valueCount > maxValues) {
throw new RuntimeException(UndertowMessages.MESSAGES.tooManyParameters(maxValues));
}
}
public void put(String name, String value, final HeaderMap headers) {
Deque<FormValue> values = new ArrayDeque<>(1);
Deque<FormValue> old = this.values.put(name, values);
if (old != null) {
valueCount -= old.size();
}
values.add(new FormValueImpl(value, headers));
if (++valueCount > maxValues) {
throw new RuntimeException(UndertowMessages.MESSAGES.tooManyParameters(maxValues));
}
}
public Deque<FormValue> remove(String name) {
Deque<FormValue> old = values.remove(name);
if (old != null) {
valueCount -= old.size();
}
return old;
}
public boolean contains(String name) {
final Deque<FormValue> value = values.get(name);
return value != null && !value.isEmpty();
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final FormData strings = (FormData) o;
if (values != null ? !values.equals(strings.values) : strings.values != null) return false;
return true;
}
@Override
public int hashCode() {
return values != null ? values.hashCode() : 0;
}
@Override
public String toString() {
return "FormData{" +
"values=" + values +
'}';
}
public interface FormValue {
String getValue();
boolean isFile();
Path getPath();
@Deprecated
File getFile();
String getFileName();
HeaderMap getHeaders();
}
static class FormValueImpl implements FormValue {
private final String value;
private final String fileName;
private final Path file;
private final HeaderMap headers;
FormValueImpl(String value, HeaderMap headers) {
this.value = value;
this.headers = headers;
this.file = null;
this.fileName = null;
}
FormValueImpl(Path file, final String fileName, HeaderMap headers) {
this.file = file;
this.headers = headers;
this.fileName = fileName;
this.value = null;
}
@Override
public String getValue() {
if (value == null) {
throw UndertowMessages.MESSAGES.formValueIsAFile();
}
return value;
}
@Override
public boolean isFile() {
return file != null;
}
@Override
public Path getPath() {
if (file == null) {
throw UndertowMessages.MESSAGES.formValueIsAString();
}
return file;
}
@Override
public File getFile() {
return getPath().toFile();
}
@Override
public HeaderMap getHeaders() {
return headers;
}
public String getFileName() {
return fileName;
}
}
}