/******************************************************************************* * Copyright 2015 xWic group (http://www.xwic.de) * * Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package de.jwic.web; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Returns a file resource from the classpath. The servlet must be * mapped to the path /cp/ to function properly. * @author Florian Lippisch * @version $Revision: 1.3 $ */ public class ClasspathResourceServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected final Log log = LogFactory.getLog(getClass()); private String[] allowedTypes = { ".gif", ".jpeg", ".js", ".css", ".png", ".vtl", ".html"}; private String servletId = "/cp/"; private long startup = 0; private boolean isClassResource = false; /** * Default constructor. * */ public ClasspathResourceServlet() { startup = System.currentTimeMillis(); } protected long getLastModified(HttpServletRequest arg0) { return startup; } @Override public void init(ServletConfig config) throws ServletException { super.init(config); isClassResource = Boolean.parseBoolean(config.getInitParameter("classresource")); } /* (non-Javadoc) * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @SuppressWarnings("unused") protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String ctxPath = req.getContextPath(); String fileLocation = getFileLocation(req); String fileName; if (fileLocation != null) { fileName = getFileName(fileLocation); } else { fileName = null; } if (fileName == null) { res.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } if (!isClassResource && !isAllowedType(fileName)) { res.sendError(HttpServletResponse.SC_FORBIDDEN); return; } // prepare the dowload InputStream in = null; try{ // get the file data as an InputStream in = getClass().getClassLoader().getResourceAsStream(fileLocation); }catch(Exception e){ in = null; log.error("Error reading resource " + fileLocation, e); res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString()); return; } if (in == null) { res.sendError(HttpServletResponse.SC_NOT_FOUND); return; } String mimeType = getServletContext().getMimeType(fileName); if (mimeType == null) { mimeType = "application/x-msdownload"; } // set the response header res.setContentType(mimeType); res.setHeader ("Content-Disposition","filename="+fileName+";"); res.setHeader ("Cache-Control", "max-age=" + (60*60*24)); // 24 hours res.setContentLength(in != null ? in.available() : 0); ServletOutputStream out = res.getOutputStream(); //send the file as a stream of bytes int transfered = 0; try { byte[] buf = new byte[1024]; int length = 0; while ((length = in.read(buf)) != -1) { try { out.write(buf,0,length); } catch (Exception e1) { // error with client log.error("Error sending data to client", e1); return; } transfered += length; // for debugging !!! //long start = System.currentTimeMillis(); //while (System.currentTimeMillis()-start<1000) {} } } catch (Exception e2) { // error with server log.error("Error reading data", e2); return; } finally { in.close(); out.flush(); out.close(); } log.debug("Access to ClasspathResource '" + fileLocation + "'"); } /** * @param fileName * @return */ private boolean isAllowedType(String fileName) { int pos = fileName.lastIndexOf('.'); String suffix = "."; if (pos != -1) { suffix = fileName.substring(pos); } for (int i = 0; i < allowedTypes.length; i++) { if (allowedTypes[i].equals(suffix)) { return true; } } return false; } /** * @param req * @return */ private String getFileLocation(HttpServletRequest req) { String uri = req.getRequestURI(); if (isClassResource) { return uri.substring(req.getContextPath().length() + 1); } else { return uri.substring(req.getContextPath().length() + servletId.length()); } } /** * Returns the filename in the filePath. * @param filePath * @return */ private String getFileName(String filePath) { int i = filePath.lastIndexOf('/'); if (i != -1) { return filePath.substring(i + 1); } return null; } }