// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the CPL Common Public License version 1.0.
package fitnesse.responders;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import fitnesse.responders.run.SuiteResponder;
import fitnesse.responders.run.TestResponder;
import fitnesse.wiki.PathParser;
import org.apache.commons.lang.StringUtils;
import fitnesse.Responder;
import fitnesse.http.Request;
import fitnesse.responders.editing.AddChildPageResponder;
import fitnesse.responders.editing.EditResponder;
import fitnesse.responders.editing.NewPageResponder;
import fitnesse.responders.editing.PropertiesResponder;
import fitnesse.responders.editing.SavePropertiesResponder;
import fitnesse.responders.editing.SaveResponder;
import fitnesse.responders.editing.SymbolicLinkResponder;
import fitnesse.responders.files.CreateDirectoryResponder;
import fitnesse.responders.files.DeleteConfirmationResponder;
import fitnesse.responders.files.DeleteFileResponder;
import fitnesse.responders.files.FileResponder;
import fitnesse.responders.files.RenameFileConfirmationResponder;
import fitnesse.responders.files.RenameFileResponder;
import fitnesse.responders.files.UploadResponder;
import fitnesse.responders.refactoring.*;
import fitnesse.responders.run.StopTestResponder;
import fitnesse.responders.search.*;
import fitnesse.responders.testHistory.HistoryComparerResponder;
import fitnesse.responders.testHistory.PageHistoryResponder;
import fitnesse.responders.testHistory.PurgeHistoryResponder;
import fitnesse.responders.testHistory.SuiteOverviewResponder;
import fitnesse.responders.testHistory.TestHistoryResponder;
import fitnesse.responders.versions.RollbackResponder;
import fitnesse.responders.versions.VersionComparerResponder;
import fitnesse.responders.versions.VersionResponder;
import fitnesse.responders.versions.VersionSelectionResponder;
public class ResponderFactory {
private final static Logger LOG = Logger.getLogger(ResponderFactory.class.getName());
private final String rootPath;
private final Map<String, Class<? extends Responder>> responderMap;
private final Map<String, List<Responder>> filterMap;
public ResponderFactory(String rootPath) {
this.rootPath = rootPath;
responderMap = new HashMap<String, Class<? extends Responder>>();
addResponder("new", NewPageResponder.class);
addResponder("edit", EditResponder.class);
addResponder("saveData", SaveResponder.class);
addResponder("search", SearchResponder.class);
addResponder("searchForm", SearchFormResponder.class);
addResponder("stoptest", StopTestResponder.class);
addResponder("test", TestResponder.class);
addResponder("suite", SuiteResponder.class);
addResponder("proxy", SerializedPageResponder.class);
addResponder("versions", VersionSelectionResponder.class);
addResponder("viewVersion", VersionResponder.class);
addResponder("rollback", RollbackResponder.class);
addResponder("names", NameWikiPageResponder.class);
addResponder("properties", PropertiesResponder.class);
addResponder("saveProperties", SavePropertiesResponder.class);
addResponder("executeSearchProperties", ExecuteSearchPropertiesResponder.class);
addResponder("whereUsed", WhereUsedResponder.class);
addResponder("refactor", RefactorPageResponder.class);
addResponder("deletePage", DeletePageResponder.class);
addResponder("renamePage", RenamePageResponder.class);
addResponder("movePage", MovePageResponder.class);
addResponder("pageData", PageDataWikiPageResponder.class);
addResponder("createDir", CreateDirectoryResponder.class);
addResponder("upload", UploadResponder.class);
addResponder("deleteFile", DeleteFileResponder.class);
addResponder("renameFile", RenameFileResponder.class);
addResponder("deleteConfirmation", DeleteConfirmationResponder.class);
addResponder("renameConfirmation", RenameFileConfirmationResponder.class);
addResponder("raw", RawContentResponder.class);
addResponder("rss", RssResponder.class);
addResponder("import", WikiImportingResponder.class);
addResponder("files", FileResponder.class);
addResponder("shutdown", ShutdownResponder.class);
addResponder("symlink", SymbolicLinkResponder.class);
addResponder("importAndView", ImportAndViewResponder.class);
addResponder("getPage", WikiPageResponder.class);
addResponder("packet", PacketResponder.class);
addResponder("testHistory", TestHistoryResponder.class);
addResponder("pageHistory", PageHistoryResponder.class);
addResponder("addChild", AddChildPageResponder.class);
addResponder("purgeHistory", PurgeHistoryResponder.class);
addResponder("compareHistory", HistoryComparerResponder.class);
addResponder("replace", SearchReplaceResponder.class);
addResponder("overview", SuiteOverviewResponder.class);
addResponder("compareVersions", VersionComparerResponder.class);
filterMap = new HashMap<String, List<Responder>>();
}
public final void addResponder(String key, Class<? extends Responder> responderClass) {
responderMap.put(key, responderClass);
}
public void addFilter(String key, Responder filterClass) {
List<Responder> filters = filterMap.get(key);
if (filters == null) {
filters = new LinkedList<Responder>();
filterMap.put(key, filters);
}
filters.add(filterClass);
}
public String getResponderKey(Request request) {
String fullQuery;
if (request.hasInput("responder"))
fullQuery = (String) request.getInput("responder");
else
fullQuery = request.getQueryString();
if (fullQuery == null)
return null;
int argStart = fullQuery.indexOf('&');
return (argStart <= 0) ? fullQuery : fullQuery.substring(0, argStart);
}
public Responder makeResponder(Request request) throws InstantiationException, IOException {
String resource = request.getResource();
String responderKey = getResponderKey(request);
final Responder responder;
if (usingResponderKey(responderKey)) {
responder = wrapWithFilters(responderKey, lookupResponder(responderKey));
} else if (resource.startsWith("files/") || resource.equals("files")) {
responder = wrapWithFilters("files", FileResponder.makeResponder(request, rootPath));
} else if (StringUtils.isBlank(resource) || PathParser.parse(resource) != null) {
responder = wrapWithFilters("wiki", new WikiPageResponder());
} else {
responder = new NotFoundResponder();
}
return responder;
}
private Responder lookupResponder(String responderKey)
throws InstantiationException {
Class<?> responderClass = getResponderClass(responderKey);
if (responderClass != null) {
try {
return newResponderInstance(responderClass);
} catch (Exception e) {
LOG.log(Level.WARNING, "Unable to instantiate responder " + responderKey, e);
throw new InstantiationException("Unable to instantiate responder " + responderKey);
}
}
throw new InstantiationException("No responder for " + responderKey);
}
private Responder newResponderInstance(Class<?> responderClass)
throws InstantiationException, IllegalAccessException, InvocationTargetException,
NoSuchMethodException {
try {
Constructor<?> constructor = responderClass.getConstructor(String.class);
return (Responder) constructor.newInstance(rootPath);
} catch (NoSuchMethodException e) {
Constructor<?> constructor = responderClass.getConstructor();
return (Responder) constructor.newInstance();
}
}
private Responder wrapWithFilters(String key, Responder responder) throws InstantiationException {
List<Responder> filters = filterMap.get(key);
if (filters == null || filters.isEmpty()) {
return responder;
}
return new FilteringResponder(filters, responder);
}
public Class<?> getResponderClass(String responderKey) {
return responderMap.get(responderKey);
}
private boolean usingResponderKey(String responderKey) {
return !("".equals(responderKey) || responderKey == null);
}
}