summaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/terminal/gwt/server/RequestTimer.java
blob: 1df65d6c58de99f4bbaab5bef1f01fbeae3a5838 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
@VaadinApache2LicenseForJavaFiles@
 */

package com.vaadin.terminal.gwt.server;

import java.io.Serializable;

import javax.portlet.PortletRequest;
import javax.portlet.PortletSession;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * Times the handling of requests and stores the information as an attribute in
 * the request. The timing info is later passed on to the client in the UIDL and
 * the client provides JavaScript API for accessing this data from e.g.
 * TestBench.
 * 
 * @author Jonatan Kronqvist / Vaadin Ltd
 */
public class RequestTimer implements Serializable {
    public static final String SESSION_ATTR_ID = "REQUESTTIMER";

    private long requestStartTime = 0;
    private long totalSessionTime = 0;
    private long lastRequestTime = -1;

    /**
     * This class acts as a proxy for setting and getting session and request
     * attributes on HttpServletRequests and PortletRequests. Using this class
     * we don't need to duplicate code everywhere.
     */
    static class RequestWrapper implements Serializable {
        private final HttpServletRequest servletRequest;
        private final PortletRequest portletRequest;

        public RequestWrapper(HttpServletRequest servletRequest) {
            this.servletRequest = servletRequest;
            portletRequest = null;
        }

        public RequestWrapper(PortletRequest portletRequest) {
            this.portletRequest = portletRequest;
            servletRequest = null;
        }

        public void setAttribute(String name, Object value) {
            if (servletRequest != null) {
                servletRequest.setAttribute(name, value);
            } else {
                portletRequest.setAttribute(name, value);
            }
        }

        public void setSessionAttribute(String name, Object value) {
            if (servletRequest != null) {
                HttpSession session = servletRequest.getSession();
                if (session != null) {
                    session.setAttribute(name, value);
                }
            } else {
                PortletSession portletSession = portletRequest
                        .getPortletSession();
                if (portletSession != null) {
                    portletSession.setAttribute(name, value);
                }
            }
        }

        public Object getSessionAttribute(String name) {
            if (servletRequest != null) {
                HttpSession session = servletRequest.getSession();
                if (session != null) {
                    return session.getAttribute(name);
                }
            } else {
                PortletSession portletSession = portletRequest
                        .getPortletSession();
                if (portletSession != null) {
                    return portletSession.getAttribute(name);
                }
            }
            return null;
        }
    }

    /**
     * Starts the timing of a request. This should be called before any
     * processing of the request.
     * 
     * @param request
     *            the request.
     */
    public void start(RequestWrapper request) {
        requestStartTime = System.nanoTime();
        request.setAttribute("TOTAL", totalSessionTime);
        request.setAttribute("LASTREQUEST", lastRequestTime);
    }

    /**
     * Stops the timing of a request. This should be called when all processing
     * of a request has finished.
     */
    public void stop() {
        // Measure and store the total handling time. This data can be
        // used in TestBench 3 tests.
        long time = (System.nanoTime() - requestStartTime) / 1000000;
        lastRequestTime = time;
        totalSessionTime += time;
    }

    /**
     * Returns a valid request timer for the specified request. Timers are
     * session bound.
     * 
     * @param request
     *            the request for which to get a valid timer.
     * @return a valid timer.
     */
    public static RequestTimer get(RequestWrapper request) {
        RequestTimer timer = (RequestTimer) request
                .getSessionAttribute(SESSION_ATTR_ID);
        if (timer == null) {
            timer = new RequestTimer();
        }
        return timer;
    }

    /**
     * Associates the specified request timer with the specified request. Since
     * {@link #get(RequestWrapper)} will, at one point or another, return a new
     * instance, this method should be called to keep the request <-> timer
     * association updated.
     * 
     * @param request
     *            the request for which to set the timer.
     * @param requestTimer
     *            the timer.
     */
    public static void set(RequestWrapper request, RequestTimer requestTimer) {
        request.setSessionAttribute(RequestTimer.SESSION_ATTR_ID, requestTimer);
    }
}