1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.servlet;
21
22 import org.apache.commons.io.IOUtils;
23 import org.apache.myfaces.tobago.application.ProjectStage;
24 import org.apache.myfaces.tobago.config.TobagoConfig;
25 import org.apache.myfaces.tobago.context.Theme;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 import org.apache.myfaces.tobago.internal.util.MimeTypeUtils;
29
30 import javax.servlet.ServletConfig;
31 import javax.servlet.ServletException;
32 import javax.servlet.http.HttpServlet;
33 import javax.servlet.http.HttpServletRequest;
34 import javax.servlet.http.HttpServletResponse;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.OutputStream;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Set;
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 public class ResourceServlet extends HttpServlet {
69
70 private static final long serialVersionUID = -4491419290205206466L;
71
72 private static final Logger LOG = LoggerFactory.getLogger(ResourceServlet.class);
73
74 private Long expires;
75 private int bufferSize;
76 private Set<String> resourceDirs = new HashSet<String>();
77
78 @Override
79 public void init(ServletConfig servletConfig) throws ServletException {
80 super.init(servletConfig);
81 TobagoConfig tobagoConfig = TobagoConfig.getInstance(servletConfig.getServletContext());
82 if (tobagoConfig != null && tobagoConfig.getProjectStage() == ProjectStage.Production) {
83 expires = 24 * 60 * 60 * 1000L;
84 }
85 Theme defaultTheme = tobagoConfig.getDefaultTheme();
86 addResourceDir(defaultTheme.getFallbackList());
87 addResourceDir(tobagoConfig.getSupportedThemes());
88
89 String expiresString = servletConfig.getInitParameter("expires");
90 if (expiresString != null) {
91 try {
92 expires = new Long(expiresString) * 1000;
93 } catch (NumberFormatException e) {
94 LOG.error("Caught: " + e.getMessage(), e);
95 }
96 }
97 String bufferSizeString = servletConfig.getInitParameter("bufferSize");
98 bufferSize = 1024 * 4;
99 if (bufferSizeString != null) {
100 try {
101 bufferSize = Integer.parseInt(bufferSizeString);
102 } catch (NumberFormatException e) {
103 LOG.error("Caught: " + e.getMessage(), e);
104 }
105 }
106 }
107
108 private void addResourceDir(List<Theme> themes) {
109 for (Theme theme : themes) {
110 addResourceDir(theme);
111 }
112 }
113
114 private void addResourceDir(Theme theme) {
115 String dir = theme.getResourcePath();
116 if (dir.startsWith("/")) {
117 resourceDirs.add(dir.substring(1));
118 } else {
119 resourceDirs.add(dir);
120 }
121 }
122
123 @Override
124 protected void doGet(
125 HttpServletRequest request, HttpServletResponse response)
126 throws ServletException, IOException {
127
128 String requestURI = request.getRequestURI();
129 String resource = requestURI.substring(request.getContextPath().length() + 1);
130 for (String resourceDir : resourceDirs) {
131 if (resource.startsWith(resourceDir)) {
132 if (Character.isDigit(resource.charAt(resourceDir.length()+1))) {
133 resource = resourceDir + resource.substring(resource.indexOf('/', resourceDir.length() + 1));
134 }
135 break;
136 }
137 }
138 if (expires != null) {
139 response.setDateHeader("Last-Modified", 0);
140 response.setHeader("Cache-Control", "Public, max-age=" + expires);
141 response.setDateHeader("Expires", System.currentTimeMillis() + expires);
142 }
143 String contentType = MimeTypeUtils.getMimeTypeForFile(requestURI);
144 if (contentType != null) {
145 response.setContentType(contentType);
146 } else {
147 String message = "Unsupported mime type of resource='" + resource + "'";
148 LOG.warn(message + " (because of security reasons)");
149 response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
150 return;
151 }
152
153 InputStream inputStream = null;
154 try {
155 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
156
157
158 inputStream = classLoader.getResourceAsStream("META-INF/resources/" + resource);
159
160
161 if (inputStream == null) {
162 inputStream = classLoader.getResourceAsStream(resource);
163 }
164
165 if (inputStream != null) {
166 copy(inputStream, response.getOutputStream());
167 } else {
168 String message = "Resource '" + resource + "' not found!";
169 LOG.warn(message);
170 response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
171 }
172 } finally {
173 IOUtils.closeQuietly(inputStream);
174 }
175 }
176
177 @Override
178 protected long getLastModified(HttpServletRequest request) {
179 if (expires != null) {
180 return 0;
181 } else {
182 return super.getLastModified(request);
183 }
184 }
185
186 private void copy(InputStream inputStream, OutputStream outputStream) throws IOException {
187 byte[] buffer = new byte[bufferSize];
188 int count;
189 while (-1 != (count = inputStream.read(buffer))) {
190 outputStream.write(buffer, 0, count);
191 }
192 }
193 }