package com.gravspace.bases; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; import org.apache.http.Header; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.entity.ContentType; import org.apache.http.message.BasicHeader; import scala.concurrent.Await; import scala.concurrent.Future; import scala.concurrent.Promise; import scala.concurrent.duration.Duration; import akka.actor.ActorRef; import akka.actor.UntypedActorContext; import akka.dispatch.Futures; import akka.dispatch.OnComplete; import akka.pattern.Patterns; import akka.util.Timeout; import com.gravspace.abstractions.IPage; import com.gravspace.abstractions.ISession; import com.gravspace.calculation.form.CookieParser; import com.gravspace.calculation.form.FormParser; import com.gravspace.calculation.form.ICookieParser; import com.gravspace.calculation.form.IFormParser; import com.gravspace.exceptions.Redirect; import com.gravspace.messages.GetSession; import com.gravspace.messages.ResponseMessage; import com.gravspace.proxy.Calculations; import com.gravspace.proxy.Sessions; import com.gravspace.util.Cookie; import com.gravspace.util.Layers; public abstract class PageBase extends WidgetBase implements IPage { private static final String MEGAPODE_SESSION_ID_KEY = "MegapodeSessionId"; protected Map<String, String> params; protected String method; protected String path; protected Header[] requestHeaders; protected Map<String, String> requestCookies; protected List<NameValuePair> form; protected byte[] requestContent; protected String query; protected HttpStatus status; protected List<Header> responseHeaders = new ArrayList<Header>(); protected List<Cookie> responseCookies = new ArrayList<Cookie>(); protected String contentType = "text/html"; protected ISession session; public PageBase(final Map<Layers, ActorRef> routers, final ActorRef coordinatingActor, final UntypedActorContext actorContext){ super(routers, coordinatingActor, actorContext); } public void initialise(String path, String method, String query, Header[] headers, byte[] content, Map<String, String> params) { this.path = path; this.requestHeaders = headers; this.method = method; this.params = params; this.query = query; this.requestContent = content; runPreflightSetup(); } public void runPreflightSetup(){ final Promise<Object> delay = delayUntilComplete(); ICookieParser cookieParser = Calculations.get(ICookieParser.class, CookieParser.class, this); Future<Map<String, String>> parser = cookieParser.parseCookies(requestHeaders); set("requestCookies", parser); parser.onComplete(new OnComplete<Map<String, String>>(){ @Override public void onComplete(Throwable exception, Map<String, String> cookies) throws Throwable { if (exception != null){ delay.failure(exception); } else { String sessionId = cookies.get(MEGAPODE_SESSION_ID_KEY); if (sessionId == null){ sessionId = UUID.randomUUID().toString(); addCookie(new Cookie(MEGAPODE_SESSION_ID_KEY, sessionId)); } Timeout timeout = new Timeout(Duration.create(1, "minute")); Future<Object> sessionActor = Patterns.ask(routers.get(Layers.SESSION), new GetSession(sessionId), timeout); // Future<Object> f = new When(actorContext.dispatcher(), sessionActor){ // // @Override // public Future<?> finishes(Throwable exception, // Object... params) { // // TODO Auto-generated method stub // return null; // } // // }.itWill(); sessionActor.onComplete(new OnComplete<Object>(){ @Override public void onComplete(Throwable exception, Object actorRef) throws Throwable { if (exception != null){ delay.failure(exception); } else { ActorRef sessionRef = (ActorRef)actorRef; session = Sessions.get(sessionRef, getThis()); delay.success(session); } } }, actorContext.dispatcher()); } } }, actorContext.dispatcher()); if (hasForm()){ IFormParser formParser = Calculations.get(IFormParser.class, FormParser.class, this); set("form", formParser.parse(requestHeaders, requestContent)); } } public void collect(){ System.out.println("Got "); } public abstract void process(); public abstract Future<String> render() throws Exception; public Future<ResponseMessage> build() throws Exception { final Promise<ResponseMessage> pageRendered = Futures.promise(); final ResponseMessage response = new ResponseMessage(); try { Await.result(await(), Duration.create(1, "minute")); collect(); Await.result(await(), Duration.create(1, "minute")); process(); Await.result(await(), Duration.create(1, "minute")); Future<String> rendered = render(); response.setContentType(contentType); List<Header> headers = getCookiesAndHeaders(); response.setHeaders(headers); String result = (String) Await.result(rendered, Duration.create(1, "minute")); response.setStatus(HttpStatus.SC_OK); response.setResponseContent( result.getBytes(Charset.forName("UTF-8"))); pageRendered.success(response); } catch (Redirect redirect){ response.setStatus(redirect.getCode()); response.setContentType(ContentType.TEXT_HTML.getMimeType()); response.getHeaders().add(new BasicHeader("Location", redirect.getUri().toString())); response.setResponseContent( "redirected".getBytes(Charset.forName("UTF-8"))); pageRendered.success(response); } catch (Exception e){ pageRendered.failure(e); } return pageRendered.future(); } private List<Header> getCookiesAndHeaders() { List<Header> headers = new ArrayList<>(); headers.addAll(responseHeaders); for (Cookie cookie: responseCookies){ headers.add(new BasicHeader("Set-Cookie", cookie.toString())); } return headers; } private boolean hasForm() { return (((requestContent != null) && ((method.equals("POST")) || (method.equals("PUT"))))); } public void initialise(Object... args){} public List<NameValuePair> getForm() { return form; } public void setForm(List<NameValuePair> form) { this.form = form; } public HttpStatus getStatus() { return status; } public void setStatus(HttpStatus status) { this.status = status; } public List<Header> getResponseHeaders() { return responseHeaders; } public void setResponseHeaders(List<Header> responseHeaders) { this.responseHeaders = responseHeaders; } public List<Cookie> getResponseCookies() { return responseCookies; } public void setResponseCookies(List<Cookie> responseCookies) { this.responseCookies = responseCookies; } public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } public Map<String, String> getParams() { return params; } public String getMethod() { return method; } public String getPath() { return path; } public void addCookie(Cookie cookie){ responseCookies.add(cookie); } public void addHeader(Header header){ responseHeaders.add(header); } public Header[] getRequestHeaders() { return requestHeaders; } public byte[] getRequestContent() { return requestContent; } public String getQuery() { return query; } public Map<String, String> getRequestCookies() { return requestCookies; } public void setRequestCookies(Map<String, String> requestCookies) { this.requestCookies = requestCookies; } public ISession getSession() { return session; } public void setSession(ISession session) { this.session = session; } }