001 package org.apache.myfaces.tobago.servlet;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one or more
005 * contributor license agreements. See the NOTICE file distributed with
006 * this work for additional information regarding copyright ownership.
007 * The ASF licenses this file to You under the Apache License, Version 2.0
008 * (the "License"); you may not use this file except in compliance with
009 * the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020 import org.apache.commons.io.IOUtils;
021 import org.apache.commons.logging.Log;
022 import org.apache.commons.logging.LogFactory;
023 import org.apache.myfaces.tobago.util.MimeTypeUtils;
024
025 import javax.servlet.ServletConfig;
026 import javax.servlet.ServletException;
027 import javax.servlet.http.HttpServlet;
028 import javax.servlet.http.HttpServletRequest;
029 import javax.servlet.http.HttpServletResponse;
030 import java.io.IOException;
031 import java.io.InputStream;
032 import java.util.Date;
033
034 /**
035 * <p><pre>
036 * <servlet>
037 * <servlet-name>ResourceServlet</servlet-name>
038 * <servlet-class>org.apache.myfaces.tobago.servlet.ResourceServlet</servlet-class>
039 * <init-param>
040 * <description>The value for the expires header in seconds.
041 * Default is no expires header.</description>
042 * <param-name>expires</param-name>
043 * <param-value>14400</param-value>
044 * </init-param>
045 * </servlet>
046 * <servlet-mapping>
047 * <servlet-name>ResourceServlet</servlet-name>
048 * <url-pattern>/org/apache/myfaces/tobago/renderkit/*</url-pattern>
049 * </servlet-mapping>
050 * </pre><p>
051 *
052 * @since 1.0.7
053 */
054 public class ResourceServlet extends HttpServlet {
055
056 private static final long serialVersionUID = -4491419290205206466L;
057
058 private static final Log LOG = LogFactory.getLog(ResourceServlet.class);
059
060 private Long expires;
061
062 @Override
063 public void init(ServletConfig servletConfig) throws ServletException {
064 super.init(servletConfig);
065 String expiresString = servletConfig.getInitParameter("expires");
066
067 expires = null;
068 if (expiresString != null) {
069 try {
070 expires = new Long(expiresString);
071 } catch (NumberFormatException e) {
072 LOG.error("Caught: " + e.getMessage(), e);
073 }
074 }
075 }
076
077 @Override
078 protected void service(
079 HttpServletRequest request, HttpServletResponse response)
080 throws ServletException, IOException {
081
082 String requestURI = request.getRequestURI();
083 String resource = requestURI.substring(request.getContextPath().length() + 1);
084
085 if (expires != null) {
086 response.setHeader("Cache-Control", "max-age=" + expires);
087 response.setDateHeader("Expires", new Date().getTime() + (expires * 1000));
088 }
089 String contentType = MimeTypeUtils.getMimeTypeForFile(requestURI);
090 if (contentType != null) {
091 response.setContentType(contentType);
092 } else {
093 String message = "Unsupported mime type of resource='" + resource + "'";
094 LOG.warn(message + " (because of security reasons)");
095 response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
096 return;
097 }
098
099 InputStream inputStream = null;
100 try {
101 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
102
103 // meta inf (like in servlet 3.0)
104 inputStream = classLoader.getResourceAsStream("META-INF/resources/" + resource);
105
106 // "normal" classpath
107 if (inputStream == null) {
108 inputStream = classLoader.getResourceAsStream(resource);
109 }
110
111 if (inputStream != null) {
112 IOUtils.copy(inputStream, response.getOutputStream());
113 } else {
114 String message = "Resource '" + resource + "' not found!";
115 LOG.warn(message);
116 response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
117 }
118 } finally {
119 IOUtils.closeQuietly(inputStream);
120 }
121 }
122 }