diff --git a/src/java/DmWebPortal/src/java/gov/anl/aps/dm/api/DmRestApi.java b/src/java/DmWebPortal/src/java/gov/anl/aps/dm/api/DmRestApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..484c39a77ed7eb1d6803bee65736b914df0e84ba
--- /dev/null
+++ b/src/java/DmWebPortal/src/java/gov/anl/aps/dm/api/DmRestApi.java
@@ -0,0 +1,675 @@
+package gov.anl.aps.dm.api;
+
+import gov.anl.aps.dm.common.constants.DmHttpHeader;
+import gov.anl.aps.dm.common.constants.DmProperty;
+import gov.anl.aps.dm.common.constants.DmRole;
+import gov.anl.aps.dm.common.constants.DmServiceProtocol;
+import gov.anl.aps.dm.common.exceptions.AuthorizationError;
+import gov.anl.aps.dm.common.exceptions.CommunicationError;
+import gov.anl.aps.dm.common.exceptions.ConfigurationError;
+import gov.anl.aps.dm.common.exceptions.InvalidArgument;
+import gov.anl.aps.dm.common.exceptions.InvalidSession;
+import gov.anl.aps.dm.common.exceptions.DmException;
+import gov.anl.aps.dm.common.exceptions.DmExceptionFactory;
+import gov.anl.aps.dm.common.utilities.NoServerVerificationSSLSocketFactory;
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.ConnectException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.net.ssl.HttpsURLConnection;
+import org.apache.log4j.Logger;
+
+/**
+ * DM REST Web Service API class.
+ *
+ * This class serves as superclass for all DM web service interface classes. It
+ * handles basic communication with web service (establishing sessions, sending
+ * requests, receiving responses, generating exceptions, etc.).
+ */
+public class DmRestApi {
+
+    /**
+     * Relative path for login requests.
+     */
+    public static final String LOGIN_REQUEST_URL = "/login";
+
+    private static final String DefaultSessionId = "defaultSession";
+
+    private static final boolean httpsInitialized = initializeHttpsConnection();    
+    private static final Logger logger = Logger.getLogger(DmRestApi.class.getName());
+
+    private static boolean initializeHttpsConnection() {
+        HttpsURLConnection.setDefaultSSLSocketFactory(new NoServerVerificationSSLSocketFactory());
+        return true;
+    }
+
+    private URL serviceUrl;
+    private DmSession session = new DmSession();
+
+    /**
+     * Constructor.
+     *
+     * Initializes web service URL from system properties.
+     *
+     * @throws ConfigurationError if web service URL property is malformed or
+     * null
+     */
+    public DmRestApi() throws ConfigurationError {
+        configureFromProperties();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param webServiceUrl web service URL
+     * @throws ConfigurationError if web service URL is malformed or null
+     */
+    public DmRestApi(String webServiceUrl) throws ConfigurationError {
+        configureFromString(webServiceUrl);
+    }
+
+    /**
+     * Configure web service URL from Java VM properties.
+     *
+     * @throws ConfigurationError if web service URL property is malformed or
+     * null
+     */
+    public final void configureFromProperties() throws ConfigurationError {
+        String webServiceUrl = System.getProperty(DmProperty.WEB_SERVICE_URL_PROPERTY_NAME);
+        configureFromString(webServiceUrl);
+    }
+
+    /**
+     * Configure web service URL from string.
+     *
+     * @param webServiceUrl web service URL
+     * @throws ConfigurationError if web service URL property is malformed or
+     * null
+     */
+    public final void configureFromString(String webServiceUrl) throws ConfigurationError {
+        if (webServiceUrl == null) {
+            throw new ConfigurationError("DM web service url is not specified.");
+        }
+        try {
+            serviceUrl = new URL(webServiceUrl);
+        } catch (MalformedURLException ex) {
+            throw new ConfigurationError("Malformed DM web service url: " + webServiceUrl);
+        }
+
+        DmServiceProtocol protocol = DmServiceProtocol.fromString(serviceUrl.getProtocol());
+        if (protocol == null) {
+            throw new ConfigurationError("Unsupported service protocol specified in " + webServiceUrl);
+        }
+    }
+
+    public URL getServiceUrl() {
+        return serviceUrl;
+    }
+
+    public DmSession getSession() {
+        return session;
+    }
+
+    public void setSession(DmSession session) {
+        this.session = session;
+    }
+
+    /**
+     * Check HTTP response for exceptions.
+     *
+     * @param connection HTTP connection
+     * @throws DmException when DM error is detected
+     */
+    public static void checkHttpResponseForDmException(HttpURLConnection connection) throws DmException {
+        String exceptionType = connection.getHeaderField(DmHttpHeader.DM_EXCEPTION_TYPE_HEADER);
+        if (exceptionType != null) {
+            String statusMessage = connection.getHeaderField(DmHttpHeader.DM_STATUS_MESSAGE_HEADER);
+            String statusCode = connection.getHeaderField(DmHttpHeader.DM_STATUS_CODE_HEADER);
+            int code = Integer.parseInt(statusCode);
+            DmExceptionFactory.throwDmException(exceptionType, code, statusMessage);
+        }
+    }
+
+    /**
+     * Convert HTTP error for exceptions.
+     *
+     * @param httpError HTTP error
+     * @param connection HTTP connection
+     * @return generated DM exception
+     */
+    public static DmException convertHttpErrorToDmException(Exception httpError, HttpURLConnection connection) {
+        String exceptionType = connection.getHeaderField(DmHttpHeader.DM_EXCEPTION_TYPE_HEADER);
+        if (exceptionType != null) {
+            String statusMessage = connection.getHeaderField(DmHttpHeader.DM_STATUS_MESSAGE_HEADER);
+            String statusCode = connection.getHeaderField(DmHttpHeader.DM_STATUS_CODE_HEADER);
+            int code = Integer.parseInt(statusCode);
+            return DmExceptionFactory.generateDmException(exceptionType, code, statusMessage);
+        } else {
+            return new DmException(httpError);
+        }
+    }
+
+    /**
+     * Get full request URL.
+     *
+     * @param requestUrl relative request path, e.g. /object
+     * @return full request URL string, e.g. http://localhost:17524/dm/object
+     */
+    public String getFullRequestUrl(String requestUrl) {
+        String url = serviceUrl + requestUrl;
+        return url;
+    }
+
+    /**
+     * Verify session cookie.
+     *
+     * @return session cookie
+     * @throws InvalidSession if session cookie is expired or null
+     */
+    public String verifySessionCookie() throws InvalidSession {
+        return session.verifyCookie();
+    }
+
+    /*
+     * Get all response headers in a single string.
+     *
+     * @param connection HTTP connection 
+     * @return string containing response headers
+     */
+    private static String getResponseHeaders(HttpURLConnection connection) {
+        String headerString = "";
+        Map<String, List<String>> headerMap = connection.getHeaderFields();
+        for (String key : headerMap.keySet()) {
+            List<String> values = headerMap.get(key);
+            headerString += key + ": " + values + "\n";
+        }
+        return headerString;
+    }
+
+    /**
+     * Prepare post data.
+     *
+     * @param data key/value data map
+     * @return string suitable for HTTP post request
+     * @throws InvalidArgument in case of invalid input data
+     */
+    public static String preparePostData(Map<String, String> data) throws InvalidArgument {
+        try {
+            String postData = "";
+            String separator = "";
+            for (String key : data.keySet()) {
+                postData += separator + key + "=" + URLEncoder.encode(data.get(key), "UTF8");
+                separator = "&";
+            }
+            return postData;
+        } catch (UnsupportedEncodingException ex) {
+            logger.error("Invalid argument: " + ex);
+            throw new InvalidArgument(ex);
+        }
+    }
+
+    /**
+     * Update session cookie from connection's HTTP headers.
+     *
+     * @param connection HTTP connection
+     */
+    private void updateSessionCookie(HttpURLConnection connection) {
+        String cookie = connection.getHeaderField(DmHttpHeader.DM_SET_COOKIE_HEADER);
+        if (cookie != null) {
+            session.setCookie(cookie);
+            logger.debug("Updated session cookie: " + cookie);
+        }
+        String sessionRole = connection.getHeaderField(DmHttpHeader.DM_SESSION_ROLE_HEADER);
+        if (sessionRole != null) {
+            session.setRole(DmRole.fromString(sessionRole));
+            logger.debug("Updated session role: " + sessionRole);
+        }
+    }
+
+    /**
+     * Send post data.
+     *
+     * @param data key/value data map
+     * @param connection HTTP connection
+     * @throws InvalidArgument in case there is a problem with post data
+     * @throws DmException in case of any other error
+     */
+    private static void sendPostData(Map<String, String> data, HttpURLConnection connection) throws InvalidArgument, DmException {
+        String postData = preparePostData(data);
+        try (DataOutputStream dos = new DataOutputStream(connection.getOutputStream())) {
+            dos.writeBytes(postData);
+            dos.flush();
+        } catch (IOException ex) {
+            logger.error(ex);
+            throw new DmException(ex);
+        }
+    }
+
+    /**
+     * Read HTTP response.
+     *
+     * @param connection HTTP connection
+     * @return HTTP response as a string
+     * @throws DmException in case of any errors
+     */
+    private static String readHttpResponse(HttpURLConnection connection) throws DmException {
+        try {
+            BufferedReader br = new BufferedReader(new InputStreamReader(
+                    (connection.getInputStream())));
+            StringBuilder sb = new StringBuilder();
+            String output;
+            while ((output = br.readLine()) != null) {
+                sb.append(output);
+                sb.append('\n');
+            }
+            return sb.toString();
+        } catch (IOException ex) {
+            logger.error(ex);
+            throw new DmException(ex);
+        }
+    }
+
+    /**
+     * Set session cookie in the request headers.
+     *
+     * @param connection HTTP connection
+     * @param sessionCookie session cookie (may be null)
+     */
+    private static void setCookieRequestHeader(HttpURLConnection connection, String sessionCookie) {
+        if (sessionCookie != null) {
+            connection.setRequestProperty("Cookie", sessionCookie);
+            logger.debug("Setting session cookie to: " + sessionCookie);
+        }
+    }
+
+    /**
+     * Set common POST request headers plus session cookie.
+     *
+     * @param connection HTTP connection
+     * @param sessionCookie session cookie (may be null)
+     * @throws DmException in case of any errors
+     */
+    private static void setPostRequestHeaders(HttpURLConnection connection, String sessionCookie) throws DmException {
+        setPostRequestHeaders(connection);
+        setCookieRequestHeader(connection, sessionCookie);
+    }
+
+    /**
+     * Set common POST request headers.
+     *
+     * @param connection HTTP connection
+     * @throws DmException in case of any errors
+     */
+    private static void setPostRequestHeaders(HttpURLConnection connection) throws DmException {
+        try {
+            connection.setDoOutput(true);
+            connection.setRequestMethod("POST");
+            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+        } catch (ProtocolException ex) {
+            logger.error(ex);
+            throw new DmException(ex);
+        }
+    }
+
+    /**
+     * Set common GET request headers plus session cookie.
+     *
+     * @param connection HTTP connection
+     * @param sessionCookie session cookie (may be null)
+     * @throws DmException in case of any errors
+     */
+    private static void setGetRequestHeaders(HttpURLConnection connection, String sessionCookie) throws DmException {
+        setGetRequestHeaders(connection);
+        setCookieRequestHeader(connection, sessionCookie);
+    }
+
+    /**
+     * Set common GET request headers.
+     *
+     * @param connection HTTP connection
+     * @throws DmException in case of any errors
+     */
+    private static void setGetRequestHeaders(HttpURLConnection connection) throws DmException {
+        try {
+            connection.setRequestMethod("GET");
+        } catch (ProtocolException ex) {
+            logger.error(ex);
+            throw new DmException(ex);
+        }
+    }
+
+    /**
+     * Set common PUT request headers plus session cookie.
+     *
+     * @param connection HTTP connection
+     * @param sessionCookie session cookie (may be null)
+     * @throws DmException in case of any errors
+     */
+    private static void setPutRequestHeaders(HttpURLConnection connection, String sessionCookie) throws DmException {
+        setPutRequestHeaders(connection);
+        setCookieRequestHeader(connection, sessionCookie);
+    }
+
+    /**
+     * Set common PUT request headers.
+     *
+     * @param connection HTTP connection
+     * @throws DmException in case of any errors
+     */
+    private static void setPutRequestHeaders(HttpURLConnection connection) throws DmException {
+        try {
+            connection.setDoOutput(true);
+            connection.setRequestMethod("PUT");
+            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+        } catch (ProtocolException ex) {
+            logger.error(ex);
+            throw new DmException(ex);
+        }
+    }
+
+    /**
+     * Set common DELETE request headers plus session cookie.
+     *
+     * @param connection HTTP connection
+     * @param sessionCookie session cookie (may be null)
+     * @throws DmException in case of any errors
+     */
+    private static void setDeleteRequestHeaders(HttpURLConnection connection, String sessionCookie) throws DmException {
+        setDeleteRequestHeaders(connection);
+        setCookieRequestHeader(connection, sessionCookie);
+    }
+
+    /**
+     * Set common DELETE request headers.
+     *
+     * @param connection HTTP connection
+     * @throws DmException in case of any errors
+     */
+    private static void setDeleteRequestHeaders(HttpURLConnection connection) throws DmException {
+        try {
+            connection.setRequestMethod("DELETE");
+        } catch (ProtocolException ex) {
+            logger.error(ex);
+            throw new DmException(ex);
+        }
+    }
+
+    /**
+     * Login with a given username and password, and with specified session id.
+     *
+     * @param username username
+     * @param password password
+     * @param sessionId session id, can be null
+     * @throws AuthorizationError in case of incorrect username or password
+     * @throws CommunicationError in case service cannot be contacted
+     * @throws DmException in case of any other errors
+     */
+    public void login(String username, String password, String sessionId) throws DmException {
+        HttpURLConnection connection = null;
+        try {
+            String urlString = getFullRequestUrl(LOGIN_REQUEST_URL);
+            URL url = new URL(urlString);
+            connection = (HttpURLConnection) url.openConnection();
+            setPostRequestHeaders(connection);
+            HashMap<String, String> loginData = new HashMap<>();
+            loginData.put("username", username);
+            loginData.put("password", password);
+
+            logger.debug("Establishing session for user: " + username);
+            logger.debug("Service URL: " + serviceUrl);
+            sendPostData(loginData, connection);
+            checkHttpResponseForDmException(connection);
+            session.setUsername(username);
+            session.setId(sessionId);
+            updateSessionCookie(connection);
+        } catch (ConnectException ex) {
+            String errorMsg = "Cannot connect to " + getServiceUrl();
+            logger.error(errorMsg);
+            throw new CommunicationError(errorMsg, ex);
+        } catch (DmException ex) {
+            logger.error(ex);
+            throw ex;
+        } catch (IOException ex) {
+            logger.error(ex);
+            throw new DmException(ex);
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+
+    }
+
+    /**
+     * Login with a given username and password.
+     *
+     * @param username username
+     * @param password password
+     * @throws AuthorizationError in case of incorrect username or password
+     * @throws CommunicationError in case service cannot be contacted
+     * @throws DmException in case of any other errors
+     */
+    public void login(String username, String password) throws DmException {
+        login(username, password, DefaultSessionId);
+    }
+
+    /**
+     * Invoke GET request.
+     *
+     * @param requestUrl relative request path, e.g. /object
+     * @return service response string
+     * @throws DmException in case of any errors
+     */
+    public String invokeSessionGetRequest(String requestUrl) throws DmException {
+        String urlString = getFullRequestUrl(requestUrl);
+        HttpURLConnection connection = null;
+        try {
+            logger.debug("Invoking session get request for URL: " + requestUrl);
+            String sessionCookie = session.verifyCookie();
+            URL url = new URL(urlString);
+            connection = (HttpURLConnection) url.openConnection();
+
+            setGetRequestHeaders(connection, sessionCookie);
+            updateSessionCookie(connection);
+            checkHttpResponseForDmException(connection);
+            logger.debug("Response message:\n" + connection.getResponseMessage());
+            return readHttpResponse(connection);
+        } catch (DmException ex) {
+            throw ex;
+        } catch (ConnectException ex) {
+            String errorMsg = "Cannot connect to " + getServiceUrl();
+            logger.error(errorMsg);
+            throw new CommunicationError(errorMsg, ex);
+        } catch (IOException ex) {
+            DmException dmException = convertHttpErrorToDmException(ex, connection);
+            logger.error(ex.getMessage());
+            throw dmException;
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+    /**
+     * Invoke GET request.
+     *
+     * @param requestUrl relative request path, e.g. /object
+     * @return service response string
+     * @throws DmException in case of any errors
+     */
+    public String invokeGetRequest(String requestUrl) throws DmException {
+        String urlString = getFullRequestUrl(requestUrl);
+        HttpURLConnection connection = null;
+        try {
+            logger.debug("Invoking get request for URL: " + requestUrl);
+            URL url = new URL(urlString);
+            connection = (HttpURLConnection) url.openConnection();
+            updateSessionCookie(connection);
+            checkHttpResponseForDmException(connection);
+            logger.debug("Response message:\n" + connection.getResponseMessage());
+            return readHttpResponse(connection);
+        } catch (DmException ex) {
+            throw ex;
+        } catch (ConnectException ex) {
+            String errorMsg = "Cannot connect to " + getServiceUrl();
+            logger.error(errorMsg);
+            throw new CommunicationError(errorMsg, ex);
+        } catch (IOException ex) {
+            DmException dmException = convertHttpErrorToDmException(ex, connection);
+            logger.error(ex.getMessage());
+            throw dmException;
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+    /**
+     * Invoke POST request.
+     *
+     * @param requestUrl relative request path, e.g. /object
+     * @param data request data
+     * @return service response string
+     * @throws DmException in case of any errors
+     */
+    public String invokeSessionPostRequest(String requestUrl, Map<String, String> data) throws DmException {
+        String urlString = getFullRequestUrl(requestUrl);
+        HttpURLConnection connection = null;
+        try {
+            logger.debug("Invoking session post request for URL: " + requestUrl);
+            String sessionCookie = session.verifyCookie();
+            URL url = new URL(urlString);
+            connection = (HttpURLConnection) url.openConnection();
+
+            setPostRequestHeaders(connection, sessionCookie);
+            sendPostData(data, connection);
+            updateSessionCookie(connection);
+            checkHttpResponseForDmException(connection);
+            logger.debug("Response message:\n" + connection.getResponseMessage());
+            return readHttpResponse(connection);
+        } catch (DmException ex) {
+            throw ex;
+        } catch (ConnectException ex) {
+            String errorMsg = "Cannot connect to " + getServiceUrl();
+            logger.error(errorMsg);
+            throw new CommunicationError(errorMsg, ex);
+        } catch (IOException ex) {
+            DmException dmException = convertHttpErrorToDmException(ex, connection);
+            logger.error(ex.getMessage());
+            throw dmException;
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+    /**
+     * Invoke PUT request.
+     *
+     * @param requestUrl relative request path, e.g. /object
+     * @param data request data
+     * @return service response string
+     * @throws DmException in case of any errors
+     */
+    public String invokeSessionPutRequest(String requestUrl, Map<String, String> data) throws DmException {
+        String urlString = getFullRequestUrl(requestUrl);
+        HttpURLConnection connection = null;
+        try {
+            logger.debug("Invoking session put request for URL: " + requestUrl);
+            String sessionCookie = session.verifyCookie();
+            URL url = new URL(urlString);
+            connection = (HttpURLConnection) url.openConnection();
+
+            setPutRequestHeaders(connection, sessionCookie);
+            sendPostData(data, connection);
+            updateSessionCookie(connection);
+            checkHttpResponseForDmException(connection);
+            logger.debug("Response message:\n" + connection.getResponseMessage());
+            return readHttpResponse(connection);
+        } catch (DmException ex) {
+            throw ex;
+        } catch (ConnectException ex) {
+            String errorMsg = "Cannot connect to " + getServiceUrl();
+            logger.error(errorMsg);
+            throw new CommunicationError(errorMsg, ex);
+        } catch (IOException ex) {
+            DmException dmException = convertHttpErrorToDmException(ex, connection);
+            logger.error(ex.getMessage());
+            throw dmException;
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+    /**
+     * Invoke DELETE request.
+     *
+     * @param requestUrl relative request path, e.g. /dm/object
+     * @return service response string
+     * @throws DmException in case of any errors
+     */
+    public String invokeSessionDeleteRequest(String requestUrl) throws DmException {
+        String urlString = getFullRequestUrl(requestUrl);
+        HttpURLConnection connection = null;
+        try {
+            logger.debug("Invoking session post request for URL: " + requestUrl);
+            String sessionCookie = session.verifyCookie();
+            URL url = new URL(urlString);
+            connection = (HttpURLConnection) url.openConnection();
+
+            setDeleteRequestHeaders(connection, sessionCookie);
+            updateSessionCookie(connection);
+            checkHttpResponseForDmException(connection);
+            logger.debug("Response message:\n" + connection.getResponseMessage());
+            return readHttpResponse(connection);
+        } catch (DmException ex) {
+            throw ex;
+        } catch (ConnectException ex) {
+            String errorMsg = "Cannot connect to " + getServiceUrl();
+            logger.error(errorMsg);
+            throw new CommunicationError(errorMsg, ex);
+        } catch (IOException ex) {
+            DmException dmException = convertHttpErrorToDmException(ex, connection);
+            logger.error(ex.getMessage());
+            throw dmException;
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+
+    /*
+     * Main method, used for simple testing.
+     *
+     * @param args main arguments
+     */
+    public static void main(String[] args) {
+        try {
+            DmRestApi client = new DmRestApi("http://zagreb.svdev.net:10232/dm");
+            //client.login("sveseli", "sveseli");
+            HashMap<String, String> data = new HashMap<>();
+            //data.put("parentDirectory", "/");
+            String drawing = client.invokeGetRequest("/pdmLink/drawings/D14100201-113160.asm");
+            System.out.println("Drawing: \n" + drawing);
+        } catch (DmException ex) {
+            System.out.println("Sorry: " + ex);
+        }
+    }
+}
diff --git a/src/java/DmWebPortal/src/java/gov/anl/aps/dm/api/DmSession.java b/src/java/DmWebPortal/src/java/gov/anl/aps/dm/api/DmSession.java
new file mode 100644
index 0000000000000000000000000000000000000000..41e294838c872d7d6239960aba805cf926cd3b73
--- /dev/null
+++ b/src/java/DmWebPortal/src/java/gov/anl/aps/dm/api/DmSession.java
@@ -0,0 +1,100 @@
+package gov.anl.aps.dm.api;
+
+import gov.anl.aps.dm.common.constants.DmRole;
+import gov.anl.aps.dm.common.exceptions.InvalidSession;
+import java.io.Serializable;
+import java.net.HttpCookie;
+
+/**
+ * DM session class, used for keeping all session-related information (session
+ * id, username, role, etc.).
+ */
+public class DmSession implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String id = null;
+    private String username = null;
+    private String cookie = null;
+    private DmRole role = null;
+
+    public DmSession() {
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getCookie() {
+        return cookie;
+    }
+
+    public void setCookie(String cookie) {
+        this.cookie = cookie;
+    }
+
+    public String verifyCookie() throws InvalidSession {
+        if (cookie == null) {
+            throw new InvalidSession("Valid session has not been established.");
+        } else {
+            HttpCookie httpCookie = HttpCookie.parse(cookie).get(0);
+            if (httpCookie.hasExpired()) {
+                throw new InvalidSession("Session id " + id + " has expired.");
+            }
+        }
+        return cookie;
+    }
+
+    public DmRole getRole() {
+        return role;
+    }
+
+    public void setRole(DmRole role) {
+        this.role = role;
+    }
+
+    public boolean isAdminRole() {
+        if (role != null) {
+            return role.equals(DmRole.ADMIN);
+        }
+        return false;
+    }
+
+    public boolean isUserRole() {
+        if (role != null) {
+            return role.equals(DmRole.USER);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        String result = "{ ";
+        String delimiter = "";
+        if (username != null) {
+            result += "username :" + username;
+            delimiter = "; ";
+        }
+        if (id != null) {
+            result += delimiter + "id : " + id;
+            delimiter = "; ";
+        }
+        if (cookie != null) {
+            result += delimiter + "cookie : " + cookie;
+        }
+        result += " }";
+        return result;
+    }
+}