1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.rest;
23
24 import org.opencastproject.util.MimeTypes;
25
26 import org.apache.commons.codec.digest.DigestUtils;
27 import org.apache.commons.io.IOUtils;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.net.URL;
34 import java.util.Map;
35
36 import javax.servlet.ServletException;
37 import javax.servlet.http.HttpServlet;
38 import javax.servlet.http.HttpServletRequest;
39 import javax.servlet.http.HttpServletResponse;
40
41
42
43
44 public class StaticResource extends HttpServlet {
45
46 private static final long serialVersionUID = 1L;
47
48
49 private static final Logger logger = LoggerFactory.getLogger(StaticResource.class);
50
51
52 protected String classpath = null;
53
54
55 protected String alias = null;
56
57
58 protected String welcomeFile = null;
59
60
61 protected boolean spaRedirect = false;
62
63
64 protected ClassLoader classloader = null;
65
66
67
68
69
70
71
72
73
74
75
76 public StaticResource(ClassLoader classloader, String classpath, String alias, String welcomeFile) {
77 this(classloader, classpath, alias, welcomeFile, false);
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91
92 public StaticResource(ClassLoader classloader, String classpath, String alias, String welcomeFile,
93 boolean spaRedirect) {
94 this.classpath = classpath;
95 this.alias = alias;
96 this.welcomeFile = welcomeFile;
97 this.classloader = classloader;
98 this.spaRedirect = spaRedirect;
99 }
100
101
102
103
104
105
106
107 @SuppressWarnings("unchecked")
108 public void activate(Map componentProperties) {
109 if (welcomeFile == null) {
110 welcomeFile = (String) componentProperties.get("welcome.file");
111 }
112 boolean welcomeFileSpecified = true;
113 if (welcomeFile == null) {
114 welcomeFileSpecified = false;
115 welcomeFile = "index.html";
116 }
117 if (alias == null) {
118 alias = (String) componentProperties.get("alias");
119 }
120 if (classpath == null) {
121 classpath = (String) componentProperties.get("classpath");
122 }
123 logger.info("registering classpath:{} at {} with welcome file {} {}", classpath, alias, welcomeFile,
124 welcomeFileSpecified ? "" : "(via default)");
125 }
126
127 public String getDefaultUrl() {
128 return alias;
129 }
130
131 @Override
132 public String toString() {
133 return "StaticResource [alias=" + alias + ", classpath=" + classpath + ", welcome file=" + welcomeFile + "]";
134 }
135
136 @Override
137 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
138 String pathInfo = req.getPathInfo();
139 String servletPath = req.getServletPath();
140 String path = pathInfo == null ? servletPath : servletPath + pathInfo;
141 logger.debug("handling path {}, pathInfo={}, servletPath={}", path, pathInfo, servletPath);
142
143
144 if ("/".equals(path) || alias.equals(path) || (alias + "/").equals(path)) {
145 String redirectPath;
146 if ("/".equals(alias)) {
147 redirectPath = "/" + welcomeFile;
148 } else {
149 redirectPath = alias + "/" + welcomeFile;
150 }
151 String queryString = req.getQueryString();
152 redirectPath += queryString != null ? "?" + queryString : "";
153 logger.debug("redirecting {} to {}", path, redirectPath);
154 resp.sendRedirect(redirectPath);
155 return;
156 }
157
158
159 String classpathToResource;
160 if (pathInfo == null) {
161 if (!servletPath.equals(alias)) {
162 classpathToResource = classpath + servletPath;
163 } else {
164 classpathToResource = classpath + "/" + welcomeFile;
165 }
166 } else {
167 classpathToResource = classpath + pathInfo;
168 }
169
170
171 if (!classpathToResource.startsWith("/")) {
172 classpathToResource = "/" + classpathToResource;
173 }
174
175
176 URL url = classloader.getResource(classpathToResource);
177
178
179 if (spaRedirect && url == null) {
180 String spaRedirect = classpath + "/" + welcomeFile;
181 logger.trace("using fallback {}", spaRedirect);
182 url = classloader.getResource(spaRedirect);
183 }
184
185 if (url == null) {
186 resp.sendError(404);
187 return;
188 }
189
190 logger.debug("opening url {} {}", classpathToResource, url);
191 try (InputStream in = url.openStream()) {
192 String md5 = DigestUtils.md5Hex(in);
193 if (md5.equals(req.getHeader("If-None-Match"))) {
194 resp.setStatus(304);
195 return;
196 }
197 resp.setHeader("ETag", md5);
198 }
199
200 String contentType = MimeTypes.getMimeType(url.getPath());
201 if (!MimeTypes.DEFAULT_TYPE.equals(contentType)) {
202 resp.setHeader("Content-Type", contentType);
203 }
204
205 try (InputStream in = url.openStream()) {
206 IOUtils.copy(in, resp.getOutputStream());
207 }
208 }
209 }