/*
Copyright 2012 Christian Prause and Fraunhofer FIT
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 net.sf.collabreview.web;
import net.sf.collabreview.core.CollabReviewSingleton;
import net.sf.collabreview.core.configuration.ConfigurationData;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
* A Servlet that allows other Servlets to register through the host config file.
* The advantage is that different extension servlets can be used depending on the host on which CollabReview runs.
* <p/>
* This extension mechanism is first needed for Silviya's Wiki-Level Servlet, which is not needed on a default system.
*
* @author Christian Prause (chris)
* @date 2009-10-26 15:48:45
*/
public class ExtensionDispatcherServlet extends HttpServlet {
/**
* Apache commons logging logger for class ExtensionDispatcherServlet.
*/
private static final Log logger = LogFactory.getLog(ExtensionDispatcherServlet.class);
/**
* All the ExtensionServlets that are registered.
*/
private List<ExtensionServlet> registeredExtensions = new ArrayList<ExtensionServlet>();
@Override
public void init(ServletConfig servletConfig) throws ServletException {
logger.debug("Configuring...");
super.init(servletConfig);
//Document document = Configuration.get().getDom4JSubTree("extensions");
ConfigurationData extensionDispatcherConfig = CollabReviewSingleton.get().getExtensionDispatcherConfiguration();
if (extensionDispatcherConfig == null) {
logger.info("No extensions defined. Add an <extensions id=\"extensions\"/> element to your configuration");
} else {
for (ConfigurationData extensionConfig : extensionDispatcherConfig.getSubElements("extension")) {
initExtension(extensionConfig);
}
}
}
/**
* Create and configure an ExtensionServlet according to the global configuration.
*
* @param extensionElement XML describing the extension to add
*/
private void initExtension(ConfigurationData extensionElement) {
String name = null;
try {
name = extensionElement.getValue("id");
String className = extensionElement.getValue("class");
ExtensionServlet extension = (ExtensionServlet) getClass().getClassLoader().loadClass(className).newInstance();
extension.setExtensionName(name);
extension.setServedUrlPattern(".*/extension/(" + extensionElement.getValue("uri") + ")");
extension.configure(CollabReviewSingleton.get(), extensionElement);
registeredExtensions.add(extension);
} catch (Exception e) {
logger.error("Failed to load extension: " + name + " Please check your host config file!", e);
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
assert request != null;
assert response != null;
if (request.getRequestURI().endsWith("/extension/")) {
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
response.setCharacterEncoding("utf-8");
PrintWriter writer = response.getWriter();
writer.format("The following extensions are available on this server:\n");
for (ExtensionServlet extensionServlet : registeredExtensions) {
writer.format("%30s at %s\n", extensionServlet.getExtensionName(), extensionServlet.getServedUrlPattern());
}
return;
}
ExtensionServlet extension = getTargetServlet(request);
if (extension == null) {
sendUnknownExtension(request, response);
return;
}
extension.doGet(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ExtensionServlet extension = getTargetServlet(request);
if (extension == null) {
sendUnknownExtension(request, response);
return;
}
extension.doPost(request, response);
}
/**
* Determine the ExtensionServlet to which the request is directed.
*
* @param request the incoming request
* @return the target ExtensionServlet for the request
*/
private ExtensionServlet getTargetServlet(HttpServletRequest request) {
for (ExtensionServlet extension : registeredExtensions) {
if (extension.getServedUrlPattern().matcher(request.getRequestURI()).matches()) {
logger.debug("Requested extension: " + extension.getExtensionName());
return extension;
}
}
return null;
}
/**
* Send an error response because the target ExtensionServlet could not be determined.
*
* @param request the incoming request
* @param response the outgoing response
* @throws IOException if sending the error message fails
*/
private void sendUnknownExtension(HttpServletRequest request, HttpServletResponse response) throws IOException {
logger.warn("A client requested an unknown extension: " + request.getRequestURI());
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Illegal resource");
}
}