package org.ovirt.engine.core.utils.servlet;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.utils.EngineLocalConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is a very simple servlet that receives a mime type and a file name as
* parameters and serves the content of that file. It is intended to use in the
* web application descriptor as follows:
*
* <pre>
* <servlet>
* <servlet-name>web-conf.js</servlet-name>
* <servlet-class>org.ovirt.engine.core.FileServlet</servlet-class>
* <init-param>
* <param-name>type</param-name>
* <param-value>text/javascript</param-value>
* </init-param>
* <init-param>
* <param-name>name</param-name>
* <param-value>/etc/ovirt-engine/web-conf.js</param-value>
* </init-param>
* </servlet>
* <servlet-mapping>
* <servlet-name>web-conf.js</servlet-name>
* <url-pattern>/web-conf.js</url-pattern>
* </servlet-mapping>
* <servlet>
* </pre>
*
* This can be useful when the web application has to serve files that are
* contained in external directories.
*
* If the file given in the <code>file</code> is a directory the servlet will
* serve any file inside that directory, taking the relative path from the
* request URL and appending it to the value of the <code>file</code> parameter.
*
* If the <code>type</code> parameter is not given the content type will be
* calculated according to the system MIME types configuration file
* <code>/etc/mime.types</code>.
*/
public class FileServlet extends HttpServlet {
// Serialization id:
private static final long serialVersionUID = -1794616863361641804L;
// The log:
private static final Logger log = LoggerFactory.getLogger(FileServlet.class);
// The names of the parameters:
private static final String CACHE = "cache";
private static final String TYPE = "type";
private static final String FILE = "file";
private static final String REQUIRED = "required";
// The name of the index page:
private static final String INDEX = "index.html";
// The values of the parameters:
protected boolean cache;
protected String type;
protected File base;
protected boolean required = true;
@Override
public void init(ServletConfig config) throws ServletException {
// Let the parent do its work:
super.init(config);
final String cacheString = config.getInitParameter(CACHE);
if (cacheString == null) {
cache = true;
}
else {
cache = Boolean.parseBoolean(cacheString);
}
// Get the content type of the file (it can be null, in which case the
// global system MIME types map will be used to figure it out):
type = config.getInitParameter(TYPE);
// Get the name of the file or base directory:
final String name = config.getInitParameter(FILE);
if (name == null) {
final String message = "Can't get base name from parameter \"" + FILE + "\".";
log.error(message);
throw new ServletException(message);
}
// Create the base file object:
// we use %{x} convention to avoid conflict with jboss properties
final String expanded = EngineLocalConfig.getInstance().expandString(name.replaceAll("%\\{", "\\${"));
if (StringUtils.isEmpty(expanded)) {
final String message = "Refusing to serve empty location";
log.debug(message);
throw new ServletException(message);
}
// is the base file required
final String isBaseRequired = config.getInitParameter(REQUIRED);
if (isBaseRequired != null) {
required = Boolean.parseBoolean(isBaseRequired);
}
base = new File(expanded);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Locate the requested file:
File file = ServletUtils.makeFileFromSanePath(request.getPathInfo(), base);
file = checkForIndex(request, response, file, request.getPathInfo());
// Send the content of the file:
// type is the default MIME type of the Servlet.
ServletUtils.sendFile(request, response, file, type, cache, required);
}
protected File checkForIndex(HttpServletRequest request, HttpServletResponse response, File file, String path) throws IOException {
// If the requested file is a directory then try to replace it with the
// corresponding index page (if it exists):
if (file != null && file.isDirectory()) {
File index = new File(file, INDEX);
log.info("Index is '{}'.", index.getAbsolutePath());
if (index.isFile()) {
String redirect = null;
if (path == null) {
redirect = request.getServletPath() + "/" + INDEX;
}
else {
redirect = request.getServletPath() + path + "/" + INDEX;
}
response.sendRedirect(redirect);
file = new File(file, INDEX);
}
else {
log.error("There is no index page for directory '{}', will send a 404 error response.",
file.getAbsolutePath());
file = null;
}
}
return file;
}
}