001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2011 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.server.plugins;
021
022 import org.apache.commons.io.IOUtils;
023 import org.apache.commons.lang.StringUtils;
024 import org.slf4j.Logger;
025 import org.slf4j.LoggerFactory;
026 import org.sonar.server.platform.Platform;
027
028 import java.io.IOException;
029 import java.io.InputStream;
030 import java.io.OutputStream;
031
032 import javax.servlet.ServletException;
033 import javax.servlet.http.HttpServlet;
034 import javax.servlet.http.HttpServletRequest;
035 import javax.servlet.http.HttpServletResponse;
036
037 public class StaticResourcesServlet extends HttpServlet {
038
039 private static final Logger LOG = LoggerFactory.getLogger(StaticResourcesServlet.class);
040 private static final long serialVersionUID = -2577454614650178426L;
041
042 @Override
043 public void doGet(HttpServletRequest request, HttpServletResponse response)
044 throws ServletException, IOException {
045 String pluginKey = getPluginKey(request);
046 String resource = getResourcePath(request);
047
048 DefaultServerPluginRepository pluginRepository = Platform.getInstance().getContainer().getComponentByType(DefaultServerPluginRepository.class);
049 ClassLoader classLoader = pluginRepository.getClassloader(pluginKey);
050 if (classLoader == null) {
051 LOG.error("Plugin not found: " + pluginKey);
052 response.sendError(HttpServletResponse.SC_NOT_FOUND);
053 return;
054 }
055 InputStream in = null;
056 OutputStream out = null;
057 try {
058 in = classLoader.getResourceAsStream(resource);
059 if (in != null) {
060 out = response.getOutputStream();
061 IOUtils.copy(in, out);
062 } else {
063 LOG.error("Unable to find resource '" + resource + "' in plugin '" + pluginKey + "'");
064 response.sendError(HttpServletResponse.SC_NOT_FOUND);
065 }
066 } catch (Exception e) {
067 LOG.error("Unable to load static resource '" + resource + "' from plugin '" + pluginKey + "'", e);
068 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
069 } finally {
070 IOUtils.closeQuietly(in);
071 IOUtils.closeQuietly(out);
072 }
073 }
074
075 /**
076 * @return part of request URL after servlet path
077 */
078 protected String getPluginKeyAndResourcePath(HttpServletRequest request) {
079 return StringUtils.substringAfter(request.getRequestURI(), request.getContextPath() + request.getServletPath() + "/");
080 }
081
082 protected String getPluginKey(HttpServletRequest request) {
083 return StringUtils.substringBefore(getPluginKeyAndResourcePath(request), "/");
084 }
085
086 /**
087 * Note that returned value should not have a leading "/" - see {@link Class#resolveName(String)}.
088 */
089 protected String getResourcePath(HttpServletRequest request) {
090 return "static/" + StringUtils.substringAfter(getPluginKeyAndResourcePath(request), "/");
091 }
092 }