summaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/terminal/gwt/server/ApplicationResourceHandler.java
blob: a5bec1881d6af3441fdffdd262d0662dcd64d738 (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
package com.vaadin.terminal.gwt.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;

import com.vaadin.Application;
import com.vaadin.terminal.ApplicationResource;
import com.vaadin.terminal.DownloadStream;
import com.vaadin.terminal.RequestHandler;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedResponse;

public class ApplicationResourceHandler implements RequestHandler {
    private static final Pattern APP_RESOURCE_PATTERN = Pattern
            .compile("/APP/(\\d+)/.*");

    public boolean handleRequest(Application application,
            WrappedRequest request, WrappedResponse response)
            throws IOException {
        // Check for application resources
        String requestPath = request.getRequestPathInfo();
        Matcher resourceMatcher = APP_RESOURCE_PATTERN.matcher(requestPath);

        if (resourceMatcher.matches()) {
            ApplicationResource resource = application
                    .getResource(resourceMatcher.group(1));
            if (resource != null) {
                DownloadStream stream = resource.getStream();
                if (stream != null) {
                    stream.setCacheTime(resource.getCacheTime());
                    serveResource(stream, response);
                    return true;
                }
            }
        }

        return false;
    }

    protected void serveResource(DownloadStream stream, WrappedResponse response)
            throws IOException {
        if (stream.getParameter("Location") != null) {
            response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
            response.setHeader("Location", stream.getParameter("Location"));
            return;
        }

        // Download from given stream
        final InputStream data = stream.getStream();
        if (data != null) {

            OutputStream out = null;
            try {
                // Sets content type
                response.setContentType(stream.getContentType());

                // Sets cache headers
                response.setCacheTime(stream.getCacheTime());

                // Copy download stream parameters directly
                // to HTTP headers.
                final Iterator<String> i = stream.getParameterNames();
                if (i != null) {
                    while (i.hasNext()) {
                        final String param = i.next();
                        response.setHeader(param, stream.getParameter(param));
                    }
                }

                // suggest local filename from DownloadStream if
                // Content-Disposition
                // not explicitly set
                String contentDispositionValue = stream
                        .getParameter("Content-Disposition");
                if (contentDispositionValue == null) {
                    contentDispositionValue = "filename=\""
                            + stream.getFileName() + "\"";
                    response.setHeader("Content-Disposition",
                            contentDispositionValue);
                }

                int bufferSize = stream.getBufferSize();
                if (bufferSize <= 0 || bufferSize > Constants.MAX_BUFFER_SIZE) {
                    bufferSize = Constants.DEFAULT_BUFFER_SIZE;
                }
                final byte[] buffer = new byte[bufferSize];
                int bytesRead = 0;

                out = response.getOutputStream();

                long totalWritten = 0;
                while ((bytesRead = data.read(buffer)) > 0) {
                    out.write(buffer, 0, bytesRead);

                    totalWritten += bytesRead;
                    if (totalWritten >= buffer.length) {
                        // Avoid chunked encoding for small resources
                        out.flush();
                    }
                }
            } finally {
                AbstractCommunicationManager.tryToCloseStream(out);
                AbstractCommunicationManager.tryToCloseStream(data);
            }
        }
    }
}