core/src/main/java/gwtupload/shared/UConsts.java
public static final String MULTI_SUFFIX = "[]";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String PARAM_FILENAME = "filename";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_SIZE = "size";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_BLOBSTORE_NAME = "blobname";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String PARAM_BLOBKEY = "blob-key";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_WAIT = "wait";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String ATTR_BLOBSTORE_PARAM_NAME = "name";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_TOTAL_BYTES = "totalBytes";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_CANCELED = "canceled";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_BLOBSTORE_PARAM = "blobparam";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String PARAM_SHOW = "show";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_BLOBSTORE_PATH = "blobpath";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_NAME = "name";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_FILE = "file";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_CTYPE = "ctype";
core/src/main/java/gwtupload/client/dnd/IDragAndDropFileInput.java
public interface IDragAndDropFileInput {

    public boolean hasFiles();

    public FileList getFiles();

    public String getName();

    public void reset();

    public void lock();
}
core/src/main/java/gwtupload/shared/UConsts.java
public static final String PARAM_REMOVE = "remove";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String PARAM_CANCEL = "cancel";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_MESSAGE = "message";
core/src/main/java/gwtupload/client/bundle/UploadCss.java
public interface UploadCss extends ClientBundle {
    public static final UploadCss INSTANCE = GWT.create(UploadCss.class);

    @Source("Upload.gss")
    public CssResource css();

    @Source("cancel-upld.gif")
    ImageResource imgCancelUpload();

    @Source("cancel-upld-hover.gif")
    ImageResource imgCancelUploadHover();
}
core/src/main/java/gwtupload/client/IUploadStatus.java
public static enum Status {
  CANCELED, CANCELING, DELETED, DONE, ERROR, INPROGRESS, QUEUED, REPEATED, INVALID, SUBMITING, SUCCESS, UNINITIALIZED, CHANGED
}
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_CURRENT_BYTES = "currentBytes";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_KEY = "key";
core/src/main/java/gwtupload/client/ISession.java
public static class Session implements ISession {
  String sessionId;
  String servletPath = "servlet.gupld";

  public static ISession createSession(String path, RequestCallback callback) {
    Session ret;
    if (path.startsWith("http")) {
      ret = GWT.create(CORSSession.class);
    } else {
      ret = GWT.create(Session.class);
    }
    ret.servletPath = path;
    ret.getSession(callback);
    return ret;
  }

  /**
   * Sends a request to the server in order to get the session cookie,
   * when the response with the session comes, it submits the form.
   *
   * This is needed because this client application usually is part of
   * static files, and the server doesn't set the session until dynamic pages
   * are requested.
   *
   * If we submit the form without a session, the server creates a new
   * one and send a cookie in the response, but the response with the
   * cookie comes to the client at the end of the request, and in the
   * meanwhile the client needs to know the session in order to ask
   * the server for the upload status.
   */
  public void getSession(final RequestCallback callback) {
    sendRequest("session", new RequestCallback() {
      public void onResponseReceived(Request request, Response response) {
        String s  = Cookies.getCookie("JSESSIONID");
        if (s == null) {
          s = Utils.getXmlNodeValue(XMLParser.parse(response.getText()), TAG_SESSION_ID);
        }
        setSessionId(s);
        callback.onResponseReceived(request, response);
      }
      public void onError(Request request, Throwable exception) {
        setSessionId(null);
        callback.onError(request, exception);
      }
    }, PARAM_SESSION + "=true");
  }

  protected void setSessionId(String s) {
    sessionId = s;
  }

  public String getServletPath() {
    return servletPath;
  }

  public void sendRequest(String payload, RequestCallback callback, String... params) {
    // Using a reusable builder makes IE fail
    RequestBuilder reqBuilder = createRequest(RequestBuilder.GET, DEFAULT_AJAX_TIMEOUT, params);
    try {
      reqBuilder.sendRequest(payload, callback);
    } catch (RequestException e) {
      callback.onError(null, e);
    }
  }

  protected RequestBuilder createRequest(Method method, int timeout, String...params) {
    RequestBuilder reqBuilder = new RequestBuilder(RequestBuilder.GET, composeURL(params));
    reqBuilder.setTimeoutMillis(timeout);
    return reqBuilder;
  }

  public String composeURL(String... params) {
    String ret = servletPath;
    ret = ret.replaceAll("[\\?&]+$", "");
    String sep = ret.contains("?") ? "&" : "?";
    for (String par : params) {
      ret += sep + par;
      sep = "&";
    }
    for (Entry<String, List<String>> e : Window.Location.getParameterMap().entrySet()) {
      ret += sep + e.getKey() + "=" + e.getValue().get(0);
    }
    ret += sep + "random=" + Math.random();
    return ret;
  }
}
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_PERCENT = "percent";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_BLOBSTORE = "blobstore";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String PARAM_NAME = "name";
core/src/main/java/gwtupload/shared/UConsts.java
public static final String TAG_FINISHED = "finished";


Question: import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.FormElement;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.RequestTimeoutException;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitHandler;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Node;
import com.google.gwt.xml.client.NodeList;
import com.google.gwt.xml.client.XMLParser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
import gwtupload.client.dnd.DragAndDropFormPanel;
import gwtupload.client.dnd.IDragAndDropFileInput;
import static gwtupload.shared.UConsts.ATTR_BLOBSTORE_PARAM_NAME;
import static gwtupload.shared.UConsts.MULTI_SUFFIX;
import static gwtupload.shared.UConsts.PARAM_BLOBKEY;
import static gwtupload.shared.UConsts.PARAM_BLOBSTORE;
import static gwtupload.shared.UConsts.PARAM_CANCEL;
import static gwtupload.shared.UConsts.PARAM_FILENAME;
import static gwtupload.shared.UConsts.PARAM_NAME;
import static gwtupload.shared.UConsts.PARAM_REMOVE;
import static gwtupload.shared.UConsts.PARAM_SHOW;
import static gwtupload.shared.UConsts.TAG_BLOBSTORE;
import static gwtupload.shared.UConsts.TAG_BLOBSTORE_NAME;
import static gwtupload.shared.UConsts.TAG_BLOBSTORE_PARAM;
import static gwtupload.shared.UConsts.TAG_BLOBSTORE_PATH;
import static gwtupload.shared.UConsts.TAG_CANCELED;
import static gwtupload.shared.UConsts.TAG_CTYPE;
import static gwtupload.shared.UConsts.TAG_CURRENT_BYTES;
import static gwtupload.shared.UConsts.TAG_FILE;
import static gwtupload.shared.UConsts.TAG_FINISHED;
import static gwtupload.shared.UConsts.TAG_KEY;
import static gwtupload.shared.UConsts.TAG_MESSAGE;
import static gwtupload.shared.UConsts.TAG_NAME;
import static gwtupload.shared.UConsts.TAG_PERCENT;
import static gwtupload.shared.UConsts.TAG_SIZE;
import static gwtupload.shared.UConsts.TAG_TOTAL_BYTES;
import static gwtupload.shared.UConsts.TAG_WAIT;
import gwtupload.client.IFileInput.FileInputType;
import gwtupload.client.ISession.Session;
import gwtupload.client.IUploadStatus.Status;
import gwtupload.client.bundle.UploadCss;
      if (!multiple && avoidRepeatedFiles) {
        fileUploading.add(getFileName());
      }
    }
  }

  /**
   * Change the fileInput name, because the server uses it as an uniq identifier.
   */
  protected void assignNewNameToFileInput() {
    String fileInputName = (fileInputPrefix + "-" + Math.random()).replaceAll("\\.", "");
    if (multiple) {
      fileInputName += MULTI_SUFFIX;
    }
    fileInput.setName(fileInputName);
  }

  /**
   * Cancel upload process and show an error message to the user.
   */
  private void cancelUpload(String msg) {
    successful = false;
    uploadFinished();
    if (fileInput instanceof IDragAndDropFileInput) {
      ((IDragAndDropFileInput)fileInput).reset();
    }
    statusWidget.setStatus(IUploadStatus.Status.ERROR);
    statusWidget.setError(msg);
  }

  private JavaScriptObject getDataInfo(UploadedInfo info) {
    return info == null ? JavaScriptObject.createObject() :
       getDataImpl(info.fileUrl, info.field, info.name, Utils.basename(info.name), serverRawResponse, info.message, getStatus().toString(), info.size);
  }

  private native JavaScriptObject getDataImpl(String url, String inputName, String fileName, String baseName, String serverResponse, String serverMessage, String status, int size) /*-{
    return {
       url: url,
       name: inputName,
       filename: fileName,
       basename: baseName,
       response: serverResponse,
       message: serverMessage,
       status:  status,
       size: size
    };
  }-*/;

  private boolean isTheFirstInQueue() {
    return fileQueue.size() > 0 && fileQueue.get(0).equals(getInputName());
  }

  private void parseAjaxResponse(String responseTxt) {
    if (responseTxt == null) {
      return;
    }

    String error = null;
    Document doc = null;
    try {
      doc = XMLParser.parse(responseTxt);
      error = Utils.getXmlNodeValue(doc, "error");
      if (error == null) {
        // Response brings uploaded files info in either:
        // POST response or FINISHED status
        String msg = Utils.getXmlNodeValue(doc, TAG_MESSAGE);
        serverMessage.setMessage(msg);
        NodeList list = doc.getElementsByTagName(TAG_FILE);
        for (int i = 0, l = list.getLength(); i < l; i++) {
          UploadedInfo info = new UploadedInfo();
          info.setField(getInputName() + "-" + i);
          info.setName(Utils.getXmlNodeValue(doc, TAG_NAME, i));
          info.setCtype(Utils.getXmlNodeValue(doc, TAG_CTYPE, i));
          // TODO: test
          info.setKey (Utils.getXmlNodeValue(doc, TAG_KEY, i));
          // TODO: remove
          info.message = msg;
          String url = session.composeURL(PARAM_SHOW + "=" + info.getField());
          if (info.getKey() != null) {
            url += "&" + PARAM_BLOBKEY + "=" + info.getKey();
          }
          info.setFileUrl(url);

          String size = Utils.getXmlNodeValue(doc, TAG_SIZE, i);
          if (size != null) {
            info.setSize(Integer.parseInt(size));
          }
          serverMessage.getUploadedInfos().add(info);
        }
      }
    } catch (Exception e) {
      if (responseTxt.toLowerCase().matches("error")) {
        error = i18nStrs.uploaderServerError() + "\nAction: " + getServletPath() + "\nException: " + e.getMessage() + responseTxt;
      }
    }

    if (error != null) {
      successful = false;
      cancelUpload(error);
      return;
    } else if (Utils.getXmlNodeValue(doc, TAG_WAIT) != null) {
      if (serverRawResponse != null) {
        log("server response received, cancelling the upload " + getFileNames() + " " + serverRawResponse, null);
        successful = true;
        uploadFinished();
      }
    } else if (Utils.getXmlNodeValue(doc, TAG_CANCELED) != null) {
      log("server response is: canceled " + getFileNames(), null);
      successful = false;
      canceled = true;
      uploadFinished();
      return;
    } else if (Utils.getXmlNodeValue(doc, TAG_FINISHED) != null) {
      log("server response is: finished " + serverMessage.getUploadedFileNames(), null);
      successful = true;
      if (onSubmitComplete) {
        log("POST response from server has been received", null);
        uploadFinished();
      }
      return;
Answer:     } else if (Utils.getXmlNodeValue(doc, TAG_PERCENT) != null) {