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