package hirondelle.fish.exercise.fileupload;
import java.util.*;
import java.io.*;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.FileItem;
import static hirondelle.web4j.util.Consts.EMPTY_STRING;
import hirondelle.web4j.util.Util;
public class FileUploadWrapper extends HttpServletRequestWrapper {
public FileUploadWrapper(HttpServletRequest aRequest) throws IOException {
super(aRequest);
ServletFileUpload upload = new ServletFileUpload( new DiskFileItemFactory());
try {
List<FileItem> fileItems = upload.parseRequest(aRequest);
convertToMaps(fileItems);
}
catch(FileUploadException ex){
throw new IOException("Cannot parse underlying request: " + ex.toString());
}
}
@Override public Enumeration getParameterNames() {
Set<String> allNames = new LinkedHashSet<String>();
allNames.addAll(fRegularParams.keySet());
allNames.addAll(fFileParams.keySet());
return Collections.enumeration(allNames);
}
@Override public String getParameter(String aName) {
String result = null;
List<String> values = fRegularParams.get(aName);
if( values == null ){
String superValue = super.getParameter(aName);
if( Util.textHasContent(superValue)) {
result = superValue;
}
}
else if ( values.isEmpty() ) {
result = EMPTY_STRING;
}
else {
result = values.get(FIRST_VALUE);
}
return result;
}
@Override public String[] getParameterValues(String aName) {
String[] result = null;
List<String> values = fRegularParams.get(aName);
if( values != null ) {
result = values.toArray(new String[values.size()]);
}
return result;
}
@Override public Map getParameterMap() {
Map<String, String[]> result = new LinkedHashMap<String, String[]>();
for(String key: fRegularParams.keySet()){
result.put(key, fRegularParams.get(key).toArray(new String[0]));
}
return Collections.unmodifiableMap(result);
}
public List<FileItem> getFileItems(){
return new ArrayList<FileItem>(fFileParams.values());
}
public FileItem getFileItem(String aFieldName){
return fFileParams.get(aFieldName);
}
private final Map<String, List<String>> fRegularParams =
new LinkedHashMap<String, List<String>>()
;
private final Map<String, FileItem> fFileParams = new LinkedHashMap<String, FileItem>();
private static final int FIRST_VALUE = 0;
private void convertToMaps(List<FileItem> aFileItems){
for(FileItem item: aFileItems) {
if ( isFileUploadField(item) ) {
fFileParams.put(item.getFieldName(), item);
}
else {
if( alreadyHasValue(item) ){
addMultivaluedItem(item);
}
else {
addSingleValueItem(item);
}
}
}
}
private boolean isFileUploadField(FileItem aFileItem){
return ! aFileItem.isFormField();
}
private boolean alreadyHasValue(FileItem aItem){
return fRegularParams.get(aItem.getFieldName()) != null;
}
private void addSingleValueItem(FileItem aItem){
List<String> list = new ArrayList<String>();
list.add(aItem.getString());
fRegularParams.put(aItem.getFieldName(), list);
}
private void addMultivaluedItem(FileItem aItem){
List<String> values = fRegularParams.get(aItem.getFieldName());
values.add(aItem.getString());
}
}