package gwtupload.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestBuilder.Method;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Window;
import com.google.gwt.xml.client.XMLParser;
import java.util.List;
import java.util.Map.Entry;
import static gwtupload.shared.UConsts.PARAM_SESSION;
import static gwtupload.shared.UConsts.TAG_SESSION_ID;
public interface ISession {
public static class CORSSessionParameter extends Session {
@Override
protected void setSessionId(String s) {
super.setSessionId(s);
s = s == null? "" : (";jsessionid=" + s);
servletPath = servletPath.replaceFirst("^(.+)(/[^/\\?;]*)(;[^/\\?]*|)(\\?|/$|$)(.*)", "$1$2" + s + "$4$5");
System.err.println("CORS Session: " + servletPath);
}
}
public static class CORSSession extends Session {
@Override
protected RequestBuilder createRequest(Method method, int timeout, String... params) {
RequestBuilder req = super.createRequest(method, timeout, params);
req.setIncludeCredentials(true);
return req;
}
}
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;
}
}
static final int DEFAULT_AJAX_TIMEOUT = 10000;
public void getSession(RequestCallback callback);
public String composeURL(String... params);
public void sendRequest(String name, RequestCallback callback, String... params);
public String getServletPath();
}