diff options
author | Jesse Morgan <jesse@jesterpm.net> | 2014-03-31 22:35:43 -0700 |
---|---|---|
committer | Jesse Morgan <jesse@jesterpm.net> | 2014-03-31 22:35:43 -0700 |
commit | dcb9d839c9a30adc833af51e5c0f5a0df8175ce2 (patch) | |
tree | 523be788e99a196c0df64e11a06d831b64a38179 /src/net | |
parent | adba5974bae4da0def1f13d47cfcf28a37e3cf7a (diff) |
Locking down restlet library version.20140331a
While trying to fix this issue, I also moved FMFacade into this package
and fixed a couple bugs that snuck into the last commit.
Diffstat (limited to 'src/net')
-rw-r--r-- | src/net/jesterpm/fmfacade/FMFacade.java | 98 | ||||
-rw-r--r-- | src/net/jesterpm/fmfacade/FreeMarkerPageResource.java | 97 | ||||
-rw-r--r-- | src/net/jesterpm/fmfacade/ftl/GetMethod.java | 94 | ||||
-rw-r--r-- | src/net/jesterpm/fmfacade/json/ClientException.java | 20 | ||||
-rw-r--r-- | src/net/jesterpm/fmfacade/json/JsonRequestClient.java | 109 | ||||
-rw-r--r-- | src/net/jesterpm/fmfacade/json/JsonResponse.java | 87 | ||||
-rw-r--r-- | src/net/jesterpm/session/Session.java | 59 | ||||
-rw-r--r-- | src/net/jesterpm/session/SessionAuthenticator.java | 36 | ||||
-rw-r--r-- | src/net/jesterpm/session/SessionCheckingAuthenticator.java | 39 | ||||
-rw-r--r-- | src/net/jesterpm/session/SessionCookieAuthenticator.java | 59 | ||||
-rw-r--r-- | src/net/jesterpm/session/SessionCreatingAuthenticator.java | 46 | ||||
-rw-r--r-- | src/net/jesterpm/session/Sessions.java | 155 |
12 files changed, 899 insertions, 0 deletions
diff --git a/src/net/jesterpm/fmfacade/FMFacade.java b/src/net/jesterpm/fmfacade/FMFacade.java new file mode 100644 index 0000000..0ea44f8 --- /dev/null +++ b/src/net/jesterpm/fmfacade/FMFacade.java @@ -0,0 +1,98 @@ +/* + * Copyright 2013 Jesse Morgan <jesse@jesterpm.net> + */ + +package net.jesterpm.fmfacade; + +import java.io.IOException; + +import org.restlet.Application; +import org.restlet.Component; +import org.restlet.data.Protocol; +import org.restlet.Restlet; +import org.restlet.routing.Router; + +import freemarker.template.Configuration; +import freemarker.template.DefaultObjectWrapper; +import freemarker.template.Template; + +import org.apache.log4j.Logger; + +/** + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class FMFacade extends Application { + private static final Logger cLog = Logger.getLogger(FMFacade.class); + private final Configuration mFMConfig; + + public FMFacade() { + mFMConfig = new Configuration(); + mFMConfig.setClassForTemplateLoading(getClass(), "/templates"); + mFMConfig.setObjectWrapper(new DefaultObjectWrapper()); + } + + @Override + public synchronized Restlet createInboundRoot() { + return createRouter(); + } + + /** + * Retrieve a template. + * + * @param name The template name. + * @return A FreeMarker template or null on error. + */ + public Template getTemplate(String name) { + try { + return mFMConfig.getTemplate(name); + + } catch (IOException e) { + cLog.error("Could not load template \"" + name + "\"", e); + return null; + } + } + + /** + * Create the router to be used by this application. This can be overriden + * by sub-classes to add additional routes. + * + * @return The router. + */ + protected Router createRouter() { + Router router = new Router(getContext()); + router.attachDefault(FreeMarkerPageResource.class); + + return router; + } + + /** + * Stand-alone main for testing. + */ + public static void main(String[] args) { + // Start the HTTP Server + final Component component = new Component(); + component.getServers().add(Protocol.HTTP, 8085); + component.getClients().add(Protocol.HTTP); + component.getDefaultHost().attach(new FMFacade()); + + // Setup shutdown hook + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + try { + component.stop(); + } catch (Exception e) { + cLog.error("Exception during cleanup", e); + } + } + }); + + cLog.info("Starting server..."); + + try { + component.start(); + } catch (Exception e) { + cLog.fatal("Could not start: " + e.getMessage(), e); + } + } +} diff --git a/src/net/jesterpm/fmfacade/FreeMarkerPageResource.java b/src/net/jesterpm/fmfacade/FreeMarkerPageResource.java new file mode 100644 index 0000000..dfdba39 --- /dev/null +++ b/src/net/jesterpm/fmfacade/FreeMarkerPageResource.java @@ -0,0 +1,97 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.fmfacade; + +import java.util.Map; +import java.util.HashMap; + +import freemarker.template.Template; + +import org.restlet.Context; +import org.restlet.data.MediaType; +import org.restlet.data.Status; +import org.restlet.ext.freemarker.TemplateRepresentation; +import org.restlet.representation.Representation; +import org.restlet.resource.ServerResource; +import org.restlet.security.User; + +import org.apache.log4j.Logger; + +import net.jesterpm.fmfacade.ftl.GetMethod; + +import net.jesterpm.session.Session; +import net.jesterpm.session.Sessions; + +/** + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class FreeMarkerPageResource extends ServerResource { + private static Logger cLog = Logger.getLogger(FreeMarkerPageResource.class); + + public static Map<String, Object> baseRootObject(Context context) { + Map<String, Object> root = new HashMap<String, Object>(); + + root.put("get", new GetMethod(context.getClientDispatcher())); + + return root; + } + + private FMFacade mFMF; + private String mCurrentPage; + + @Override + public void doInit() { + mFMF = (FMFacade) getApplication(); + mCurrentPage = getReference().getRemainingPart(false, false); + } + + protected Representation get() { + try { + Template t = mFMF.getTemplate("pages" + mCurrentPage + ".ftl"); + + if (t == null) { + setStatus(Status.CLIENT_ERROR_NOT_FOUND); + return null; + } + + return new TemplateRepresentation(t, getRootObject(), + MediaType.TEXT_HTML); + + } catch (Exception e) { + cLog.fatal("Could not render page: " + e.getMessage(), e); + setStatus(Status.SERVER_ERROR_INTERNAL); + return null; + } + } + + /** + * Build and return the root object to pass to the FTL Template. + * @return A map of objects and methods for the template to access. + */ + protected Map<String, Object> getRootObject() { + Map<String, Object> root = baseRootObject(getContext()); + + root.put("attributes", getRequestAttributes()); + root.put("query", getQuery().getValuesMap()); + + if (getClientInfo().isAuthenticated()) { + final User user = getClientInfo().getUser(); + final Map<String, String> userMap = new HashMap<String, String>(); + userMap.put("id", user.getIdentifier()); + userMap.put("firstName", user.getFirstName()); + userMap.put("lastName", user.getLastName()); + userMap.put("email", user.getEmail()); + root.put("user", userMap); + } + + Session s = Sessions.getInstance().get(getRequest()); + if (s != null) { + root.put("session", s.getMap()); + } + + return root; + } +} diff --git a/src/net/jesterpm/fmfacade/ftl/GetMethod.java b/src/net/jesterpm/fmfacade/ftl/GetMethod.java new file mode 100644 index 0000000..8b92406 --- /dev/null +++ b/src/net/jesterpm/fmfacade/ftl/GetMethod.java @@ -0,0 +1,94 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.fmfacade.ftl; + +import java.util.List; +import java.util.Map; +import java.util.HashMap; + +import java.io.IOException; + +import freemarker.core.Environment; +import freemarker.template.SimpleScalar; +import freemarker.template.TemplateMethodModel; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; + +import org.apache.log4j.Logger; + +import org.restlet.data.Status; +import org.restlet.data.Method; +import org.restlet.representation.Representation; +import org.restlet.Request; +import org.restlet.Response; +import org.restlet.Restlet; + +import org.restlet.ext.jackson.JacksonRepresentation; + +/** + * This method allows templates to make GET requests. + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class GetMethod implements TemplateMethodModel { + private static final Logger cLog = Logger.getLogger(GetMethod.class); + + private final Restlet mDispatcher; + + public GetMethod(Restlet dispatcher) { + mDispatcher = dispatcher; + } + + /** + * @param args List with exactly two arguments: + * * The variable in which to put the result. + * * The URI to GET. + */ + public TemplateModel exec(List args) throws TemplateModelException { + final Environment env = Environment.getCurrentEnvironment(); + + if (args.size() != 2) { + throw new TemplateModelException( + "Expecting exactly one argument containing the URI"); + } + + Request request = new Request(Method.GET, (String) args.get(1)); + Response response = mDispatcher.handle(request); + Status status = response.getStatus(); + Representation representation = response.getEntity(); + + try { + if (response.getStatus().isSuccess()) { + JacksonRepresentation<Map> mapRepresentation; + if (representation instanceof JacksonRepresentation) { + mapRepresentation = (JacksonRepresentation<Map>) representation; + } else { + mapRepresentation = new JacksonRepresentation<Map>( + representation, Map.class); + } + try { + TemplateModel mapModel = env.getObjectWrapper().wrap(mapRepresentation.getObject()); + + env.setVariable((String) args.get(0), mapModel); + + } catch (IOException e) { + cLog.warn("Exception occurred when calling getObject(): " + + e.getMessage(), e); + status = Status.SERVER_ERROR_INTERNAL; + } + } + + Map statusMap = new HashMap(); + statusMap.put("code", status.getCode()); + statusMap.put("reason", status.getReasonPhrase()); + statusMap.put("succeeded", status.isSuccess()); + return env.getObjectWrapper().wrap(statusMap); + } finally { + if (representation != null) { + representation.release(); + } + } + } +} diff --git a/src/net/jesterpm/fmfacade/json/ClientException.java b/src/net/jesterpm/fmfacade/json/ClientException.java new file mode 100644 index 0000000..fc8bf41 --- /dev/null +++ b/src/net/jesterpm/fmfacade/json/ClientException.java @@ -0,0 +1,20 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.fmfacade.json; + +/** + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class ClientException extends Exception { + + public ClientException(final String msg) { + super(msg); + } + + public ClientException(final String msg, final Exception cause) { + super(msg, cause); + } +} diff --git a/src/net/jesterpm/fmfacade/json/JsonRequestClient.java b/src/net/jesterpm/fmfacade/json/JsonRequestClient.java new file mode 100644 index 0000000..51cf317 --- /dev/null +++ b/src/net/jesterpm/fmfacade/json/JsonRequestClient.java @@ -0,0 +1,109 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.fmfacade.json; + +import java.util.Map; + +import java.io.IOException; + +import org.apache.log4j.Logger; + +import org.restlet.data.Status; +import org.restlet.data.Method; +import org.restlet.representation.Representation; +import org.restlet.Request; +import org.restlet.Response; +import org.restlet.Restlet; + +import org.restlet.ext.jackson.JacksonRepresentation; + +/** + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class JsonRequestClient { + private final Restlet mDispatcher; + + public JsonRequestClient(Restlet dispatcher) { + mDispatcher = dispatcher; + } + + /** + * Perform a GET request for the given URI and parse the response as a + * JSON map. + * + * @return A JsonResponse object which can be used to retrieve the + * response as a JSON map. + */ + public JsonResponse get(final String uri) { + final Request request = new Request(Method.GET, uri); + final Response response = mDispatcher.handle(request); + + return new JsonResponse(response); + } + + /** + * Perform a PUT request for the given URI and parse the response as a + * JSON map. + * + * @return A JsonResponse object which can be used to retrieve the + * response as a JSON map. + */ + public JsonResponse put(final String uri, Representation entity) { + final Request request = new Request(Method.PUT, uri); + request.setEntity(entity); + + final Response response = mDispatcher.handle(request); + return new JsonResponse(response); + } + + /** + * Perform a PUT request for the given URI and parse the response as a + * JSON map. + * + * @return A JsonResponse object which can be used to retrieve the + * response as a JSON map. + */ + public JsonResponse put(final String uri, Map map) { + return put(uri, new JacksonRepresentation<Map>(map)); + } + + /** + * Perform a POST request for the given URI and parse the response as a + * JSON map. + * + * @return A JsonResponse object which can be used to retrieve the + * response as a JSON map. + */ + public JsonResponse post(final String uri, Representation entity) { + final Request request = new Request(Method.POST, uri); + request.setEntity(entity); + + final Response response = mDispatcher.handle(request); + return new JsonResponse(response); + } + + /** + * Perform a POST request for the given URI and parse the response as a + * JSON map. + * + * @return A JsonResponse object which can be used to retrieve the + * response as a JSON map. + */ + public JsonResponse post(final String uri, Map map) { + return post(uri, new JacksonRepresentation<Map>(map)); + } + + /** + * Perform a DELETE request for the given URI. + * + * @return A JsonResponse object with the status of the request. + */ + public JsonResponse delete(final String uri) { + final Request request = new Request(Method.DELETE, uri); + final Response response = mDispatcher.handle(request); + return new JsonResponse(response); + } +} diff --git a/src/net/jesterpm/fmfacade/json/JsonResponse.java b/src/net/jesterpm/fmfacade/json/JsonResponse.java new file mode 100644 index 0000000..f4a9050 --- /dev/null +++ b/src/net/jesterpm/fmfacade/json/JsonResponse.java @@ -0,0 +1,87 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.fmfacade.json; + +import java.util.Map; + +import java.io.IOException; + +import org.restlet.data.Status; +import org.restlet.data.Reference; +import org.restlet.representation.Representation; +import org.restlet.Response; + +import org.restlet.ext.jackson.JacksonRepresentation; + +/** + * JsonResponse wraps a Restlet Response object and parses the entity, if any, + * as a JSON map. + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class JsonResponse { + private final Response mResponse; + private final Representation mRepresentation; + + private Map<String, Object> mMap; + + JsonResponse(Response response) { + mResponse = response; + mRepresentation = response.getEntity(); + mMap = null; + + if (!response.getStatus().isSuccess()) { + if (mRepresentation != null) { + mRepresentation.release(); + } + } + } + + /** + * @return the Status info from the response. + */ + public Status getStatus() { + return mResponse.getStatus(); + } + + /** + * @return the Reference for a redirect. + */ + public Reference getRedirectLocation() { + return mResponse.getLocationRef(); + } + + /** + * Return the parsed json map from the response. + */ + public Map<String, Object> getMap() throws ClientException { + if (mMap == null) { + Representation representation = mRepresentation; + + // Parse response + if (representation == null) { + return null; + } + + JacksonRepresentation<Map> mapRepresentation; + if (representation instanceof JacksonRepresentation) { + mapRepresentation = (JacksonRepresentation<Map>) representation; + } else { + mapRepresentation = new JacksonRepresentation<Map>( + representation, Map.class); + } + + try { + mMap = (Map<String, Object>) mapRepresentation.getObject(); + + } catch (IOException e) { + throw new ClientException("Failed to parse response: " + e.getMessage(), e); + } + } + + return mMap; + } + +} diff --git a/src/net/jesterpm/session/Session.java b/src/net/jesterpm/session/Session.java new file mode 100644 index 0000000..ffb4cd1 --- /dev/null +++ b/src/net/jesterpm/session/Session.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.session; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.restlet.security.User; + +/** + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class Session { + static final long LIFETIME = 86400000; + + private final String mSessionId; + private final User mUser; + private final Map<String, String> mData; + private long mExpires; + + Session(User user) { + mUser = user; + mSessionId = UUID.randomUUID().toString(); + mExpires = System.currentTimeMillis() + LIFETIME; + mData = new HashMap<String, String>(); + } + + void touch() { + mExpires = System.currentTimeMillis() + LIFETIME; + } + + boolean isExpired() { + return System.currentTimeMillis() > mExpires; + } + + public String getId() { + return mSessionId; + } + + public Object get(String key) { + return mData.get(key); + } + + public void put(String key, String value) { + mData.put(key, value); + } + + public User getUser() { + return mUser; + } + + public Map<String, String> getMap() { + return mData; + } +} diff --git a/src/net/jesterpm/session/SessionAuthenticator.java b/src/net/jesterpm/session/SessionAuthenticator.java new file mode 100644 index 0000000..09802e7 --- /dev/null +++ b/src/net/jesterpm/session/SessionAuthenticator.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.session; + +import org.restlet.Context; +import org.restlet.Request; +import org.restlet.Response; +import org.restlet.security.Authenticator; +import org.restlet.security.User; + +/** + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class SessionAuthenticator /*extends Authenticator*/ { + /* + @Override + protected boolean authenticate(Request request, Response response) { + // Check for authentication cookie + final String cookie = request.getCookies().getFirstValue(COOKIE_NAME); + if (cookie != null) { + cLog.debug("Got cookie: " + cookie); + // TODO Decrypt user info + User user = new User(cookie); + request.getClientInfo().setUser(user); + return true; + } + + // Challenge the user if not authenticated + response.redirectSeeOther(mLoginPage); + return false; + } + */ +} diff --git a/src/net/jesterpm/session/SessionCheckingAuthenticator.java b/src/net/jesterpm/session/SessionCheckingAuthenticator.java new file mode 100644 index 0000000..f8db974 --- /dev/null +++ b/src/net/jesterpm/session/SessionCheckingAuthenticator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.session; + +import org.apache.log4j.Logger; + +import org.restlet.Context; +import org.restlet.Request; +import org.restlet.Response; +import org.restlet.security.Authenticator; + +/** + * Authenticator which succeeds if a valid Session exists. + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class SessionCheckingAuthenticator extends Authenticator { + private static final Logger LOG = Logger.getLogger(SessionCheckingAuthenticator.class); + + public SessionCheckingAuthenticator(Context context, boolean optional) { + super(context, optional); + } + + protected boolean authenticate(Request request, Response response) { + Session s = Sessions.getInstance().get(request); + + if (s != null) { + LOG.debug("Found session for user " + s.getUser()); + request.getClientInfo().setUser(s.getUser()); + return true; + + } else { + return false; + } + } + +} diff --git a/src/net/jesterpm/session/SessionCookieAuthenticator.java b/src/net/jesterpm/session/SessionCookieAuthenticator.java new file mode 100644 index 0000000..744c054 --- /dev/null +++ b/src/net/jesterpm/session/SessionCookieAuthenticator.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.session; + +import org.apache.log4j.Logger; + +import org.restlet.Context; +import org.restlet.Request; +import org.restlet.Response; +import org.restlet.security.Authenticator; + +/** + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class SessionCookieAuthenticator extends Authenticator { + private static final Logger LOG = Logger.getLogger(SessionCookieAuthenticator.class); + + private static final String COOKIE_NAME = "S"; + + private final Sessions mSessions; + + public SessionCookieAuthenticator(Context context, boolean optional, Sessions sessions) { + super(context, optional); + + mSessions = sessions; + } + + protected boolean authenticate(Request request, Response response) { + final String cookie = request.getCookies().getFirstValue(COOKIE_NAME); + + if (request.getClientInfo().isAuthenticated()) { + // Request is already authenticated... create session if it doesn't exist. + if (cookie == null) { + Session s = mSessions.create(request.getClientInfo().getUser()); + response.getCookieSettings().add(COOKIE_NAME, s.getId()); + } + + return true; + + } else { + // Check for authentication cookie + if (cookie != null) { + LOG.debug("Got cookie: " + cookie); + + Session s = mSessions.get(cookie); + if (s != null) { + request.getClientInfo().setUser(s.getUser()); + return true; + } + } + + return false; + } + } + +} diff --git a/src/net/jesterpm/session/SessionCreatingAuthenticator.java b/src/net/jesterpm/session/SessionCreatingAuthenticator.java new file mode 100644 index 0000000..4b0bc91 --- /dev/null +++ b/src/net/jesterpm/session/SessionCreatingAuthenticator.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.session; + +import org.apache.log4j.Logger; + +import org.restlet.Context; +import org.restlet.Request; +import org.restlet.Response; +import org.restlet.security.Authenticator; +import org.restlet.security.User; + +/** + * Authenticator which creates a Session for the request and adds a cookie + * to the response. + * + * The Request MUST be Authenticated and MUST have a User object associated. + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class SessionCreatingAuthenticator extends Authenticator { + private static final Logger LOG = Logger.getLogger(SessionCreatingAuthenticator.class); + + public SessionCreatingAuthenticator(Context context) { + super(context, true); + } + + protected boolean authenticate(Request request, Response response) { + if (Sessions.getInstance().get(request) != null) { + return true; + } + + User user = request.getClientInfo().getUser(); + + if (request.getClientInfo().isAuthenticated() && user != null) { + Sessions.getInstance().create(request, response); + LOG.debug(response); + return true; + } + + return false; + } + +} diff --git a/src/net/jesterpm/session/Sessions.java b/src/net/jesterpm/session/Sessions.java new file mode 100644 index 0000000..e225853 --- /dev/null +++ b/src/net/jesterpm/session/Sessions.java @@ -0,0 +1,155 @@ +/* + * Copyright 2013 Jesse Morgan + */ + +package net.jesterpm.session; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; + +import org.restlet.Response; +import org.restlet.Request; +import org.restlet.data.CookieSetting; +import org.restlet.security.User; + +/** + * Singleton Session Manager. + * + * @author Jesse Morgan <jesse@jesterpm.net> + */ +public class Sessions { + private static final String COOKIE_NAME = "S"; + private static final int DELETE = 0; + + private static final Sessions THE = new Sessions(); + public static Sessions getInstance() { + return THE; + } + + private final Map<String, Session> mSessions; + private final Timer mCleanupTimer; + + private Sessions() { + mSessions = new ConcurrentHashMap<String, Session>(); + + mCleanupTimer = new Timer("sessionCleaner", true); + mCleanupTimer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + for (Session s : mSessions.values()) { + if (s.isExpired()) { + mSessions.remove(s.getId()); + } + } + } + }, Session.LIFETIME, Session.LIFETIME); + } + + /** + * Get a session by ID. + * + * @param sessionid + * The Session id + * @return The Session if found and not expired, null otherwise. + */ + public Session get(String sessionid) { + Session s = mSessions.get(sessionid); + + if (s != null && !s.isExpired()) { + s.touch(); + return s; + } + + return null; + } + + /** + * Get the Session associated with the Request. + * + * @param request + * The request to fetch a session for. + * @return A session or null if no session is found. + */ + public Session get(Request request) { + final String cookie = request.getCookies().getFirstValue(COOKIE_NAME); + + if (cookie != null) { + return get(cookie); + } + + return null; + } + + /** + * Create a new Session for the given User object. + * + * @param user + * The User to associate with the Session. + * @return The new Session object. + */ + public Session create(User user) { + if (user == null) { + throw new IllegalArgumentException("Can not create session for null user."); + } + + Session s = new Session(user); + mSessions.put(s.getId(), s); + + return s; + } + + /** + * Delete a Session. + * + * @param sessionid + * The id of the Session to remove. + */ + public void delete(String sessionid) { + mSessions.remove(sessionid); + } + + /** + * Create a new Session and add the Session cookie to the response. + * + * @param request + * The request to create the Session for. + * @param response + * The response to add the session cookie to. + * @return The new Session. + */ + public Session create(Request request, Response response) { + Session s = create(request.getClientInfo().getUser()); + + CookieSetting cookie = new CookieSetting(COOKIE_NAME, s.getId()); + cookie.setPath("/"); + + request.getCookies().add(cookie); + response.getCookieSettings().add(cookie); + + return s; + } + + /** + * Remove a Session and delete the cookies. + * + * @param request + * The request with the session cookie to remove + * @param response + * The response to remove the session cookie from. + */ + public void delete(Request request, Response response) { + final String sessionid = request.getCookies().getFirstValue(COOKIE_NAME); + + delete(sessionid); + + CookieSetting cookie = new CookieSetting(COOKIE_NAME, ""); + cookie.setPath("/"); + cookie.setMaxAge(DELETE); + + request.getCookies().add(cookie); + response.getCookieSettings().add(cookie); + } + +} |