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, boolean spaRedirect) {
93 this.classpath = classpath;
94 this.alias = alias;
95 this.welcomeFile = welcomeFile;
96 this.classloader = classloader;
97 this.spaRedirect = spaRedirect;
98 }
99
100
101
102
103
104
105
106 @SuppressWarnings("unchecked")
107 public void activate(Map componentProperties) {
108 if (welcomeFile == null)
109 welcomeFile = (String) componentProperties.get("welcome.file");
110 boolean welcomeFileSpecified = true;
111 if (welcomeFile == null) {
112 welcomeFileSpecified = false;
113 welcomeFile = "index.html";
114 }
115 if (alias == null)
116 alias = (String) componentProperties.get("alias");
117 if (classpath == null)
118 classpath = (String) componentProperties.get("classpath");
119 logger.info("registering classpath:{} at {} with welcome file {} {}", classpath, alias, welcomeFile,
120 welcomeFileSpecified ? "" : "(via default)");
121 }
122
123 public String getDefaultUrl() {
124 return alias;
125 }
126
127 @Override
128 public String toString() {
129 return "StaticResource [alias=" + alias + ", classpath=" + classpath + ", welcome file=" + welcomeFile + "]";
130 }
131
132 @Override
133 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
134 String pathInfo = req.getPathInfo();
135 String servletPath = req.getServletPath();
136 String path = pathInfo == null ? servletPath : servletPath + pathInfo;
137 logger.debug("handling path {}, pathInfo={}, servletPath={}", path, pathInfo, servletPath);
138
139
140 if ("/".equals(path) || alias.equals(path) || (alias + "/").equals(path)) {
141 String redirectPath;
142 if ("/".equals(alias)) {
143 redirectPath = "/" + welcomeFile;
144 } else {
145 redirectPath = alias + "/" + welcomeFile;
146 }
147 String queryString = req.getQueryString();
148 redirectPath += queryString != null ? "?" + queryString : "";
149 logger.debug("redirecting {} to {}", path, redirectPath);
150 resp.sendRedirect(redirectPath);
151 return;
152 }
153
154
155 String classpathToResource;
156 if (pathInfo == null) {
157 if (!servletPath.equals(alias)) {
158 classpathToResource = classpath + servletPath;
159 } else {
160 classpathToResource = classpath + "/" + welcomeFile;
161 }
162 } else {
163 classpathToResource = classpath + pathInfo;
164 }
165
166
167 if (!classpathToResource.startsWith("/"))
168 classpathToResource = "/" + classpathToResource;
169
170
171 URL url = classloader.getResource(classpathToResource);
172
173
174 if (spaRedirect && url == null) {
175 String spaRedirect = classpath + "/" + welcomeFile;
176 logger.trace("using fallback {}", spaRedirect);
177 url = classloader.getResource(spaRedirect);
178 }
179
180 if (url == null) {
181 resp.sendError(404);
182 return;
183 }
184
185 logger.debug("opening url {} {}", classpathToResource, url);
186 try (InputStream in = url.openStream()) {
187 String md5 = DigestUtils.md5Hex(in);
188 if (md5.equals(req.getHeader("If-None-Match"))) {
189 resp.setStatus(304);
190 return;
191 }
192 resp.setHeader("ETag", md5);
193 }
194
195 String contentType = MimeTypes.getMimeType(url.getPath());
196 if (!MimeTypes.DEFAULT_TYPE.equals(contentType)) {
197 resp.setHeader("Content-Type", contentType);
198 }
199
200 try (InputStream in = url.openStream()) {
201 IOUtils.copy(in, resp.getOutputStream());
202 }
203 }
204 }