// 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; import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import java.util.Properties; import fitnesse.authentication.Authenticator; import fitnesse.responders.PageFactory; import fitnesse.responders.ResponderFactory; import fitnesse.responders.editing.ContentFilter; import fitnesse.responders.editing.SaveResponder; import fitnesse.wiki.VersionsController; import fitnesse.wiki.zip.ZipFileVersionsController; import fitnesse.wikitext.parser.SymbolProvider; import fitnesse.wikitext.parser.SymbolType; public class ComponentFactory { private final String endl = System.getProperty("line.separator"); public static final String PROPERTIES_FILE = "plugins.properties"; public static final String WIKI_PAGE_CLASS = "WikiPage"; public static final String PLUGINS = "Plugins"; public static final String RESPONDERS = "Responders"; public static final String SYMBOL_TYPES = "SymbolTypes"; public static final String AUTHENTICATOR = "Authenticator"; public static final String CONTENT_FILTER = "ContentFilter"; public static final String VERSIONS_CONTROLLER = "VersionsController"; public static final String DEFAULT_NEWPAGE_CONTENT = "newpage.default.content"; public static final String THEME = "Theme"; private final Properties loadedProperties; private final String propertiesLocation; private boolean propertiesAreLoaded = false; private SymbolProvider symbolProvider; public ComponentFactory() { this(new Properties()); } public ComponentFactory(String propertiesLocation) { this(propertiesLocation, new Properties(), SymbolProvider.wikiParsingProvider); } public ComponentFactory(Properties properties) { this(properties, SymbolProvider.wikiParsingProvider); } public ComponentFactory(Properties properties, SymbolProvider symbolProvider) { this.propertiesLocation = null; this.loadedProperties = properties; propertiesAreLoaded = true; this.symbolProvider = symbolProvider; } public ComponentFactory(String propertiesLocation, Properties properties, SymbolProvider symbolProvider) { this.propertiesLocation = propertiesLocation; this.loadedProperties = properties; loadProperties(propertiesLocation); this.symbolProvider = symbolProvider; } protected void loadProperties(String propertiesLocation) { try { String propertiesPath = propertiesLocation + "/" + PROPERTIES_FILE; FileInputStream propertiesStream = new FileInputStream(propertiesPath); loadedProperties.load(propertiesStream); } catch (IOException e) { // No properties files means all defaults are loaded } } Properties getProperties() { if (!propertiesAreLoaded) { loadProperties(propertiesLocation); propertiesAreLoaded = true; } return loadedProperties; } public String getProperty(String propertyName) { return getProperties().getProperty(propertyName); } public Object createComponent(String componentType, Class<?> defaultComponent) { String componentClassName = loadedProperties.getProperty(componentType); Class<?> componentClass; try { if (componentClassName != null) componentClass = Class.forName(componentClassName); else componentClass = defaultComponent; if (componentClass != null) { Constructor<?> constructor = componentClass.getConstructor(Properties.class); return constructor.newInstance(loadedProperties); } } catch (Exception e) { throw new RuntimeException("Unable to instantiate component for type " + componentType, e); } return null; } public Object createComponent(String componentType) { return createComponent(componentType, null); } public String loadWikiPage(WikiPageFactory factory) throws ClassNotFoundException { StringBuffer buffer = new StringBuffer(); String rootPageClassName = loadedProperties.getProperty(WIKI_PAGE_CLASS); if (rootPageClassName != null) { factory.setWikiPageClass(Class.forName(rootPageClassName)); buffer.append("\tCustom wiki page plugin loaded: ").append(rootPageClassName).append(endl); } return buffer.toString(); } public String loadPlugins(ResponderFactory responderFactory, WikiPageFactory wikiPageFactory) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException { StringBuffer buffer = new StringBuffer(); String[] responderPlugins = getListFromProperties(PLUGINS); if (responderPlugins != null) { buffer.append("\tCustom plugins loaded:").append(endl); for (String responderPlugin : responderPlugins) { Class<?> pluginClass = Class.forName(responderPlugin); loadWikiPageFromPlugin(pluginClass, wikiPageFactory, buffer); loadRespondersFromPlugin(pluginClass, responderFactory, buffer); loadSymbolTypesFromPlugin(pluginClass, symbolProvider, buffer); } } return buffer.toString(); } private void loadWikiPageFromPlugin(Class<?> pluginClass, WikiPageFactory wikiPageFactory, StringBuffer buffer) throws IllegalAccessException, InvocationTargetException { try { Method method = pluginClass.getMethod("registerWikiPage", WikiPageFactory.class); method.invoke(pluginClass, wikiPageFactory); buffer.append("\t\t").append("wikiPage:").append(pluginClass.getName()).append(endl); } catch (NoSuchMethodException e) { // ok, no wiki page to register in this plugin } } private void loadRespondersFromPlugin(Class<?> pluginClass, ResponderFactory responderFactory, StringBuffer buffer) throws IllegalAccessException, InvocationTargetException { try { Method method = pluginClass.getMethod("registerResponders", ResponderFactory.class); method.invoke(pluginClass, responderFactory); buffer.append("\t\t").append("responders:").append(pluginClass.getName()).append(endl); } catch (NoSuchMethodException e) { // ok, no responders to register in this plugin } } private void loadSymbolTypesFromPlugin(Class<?> pluginClass, SymbolProvider symbolProvider, StringBuffer buffer) throws IllegalAccessException, InvocationTargetException { try { Method method = pluginClass.getMethod("registerSymbolTypes", SymbolProvider.class); method.invoke(pluginClass, symbolProvider); buffer.append("\t\t").append("widgets:").append(pluginClass.getName()).append(endl); } catch (NoSuchMethodException e) { // ok, no widgets to register in this plugin } } public String loadResponders(ResponderFactory responderFactory) throws ClassNotFoundException { StringBuffer buffer = new StringBuffer(); String[] responderList = getListFromProperties(RESPONDERS); if (responderList != null) { buffer.append("\tCustom responders loaded:").append(endl); for (String responder : responderList) { String[] values = responder.trim().split(":"); String key = values[0]; String className = values[1]; responderFactory.addResponder(key, className); buffer.append("\t\t").append(key).append(":").append(className).append(endl); } } return buffer.toString(); } private String[] getListFromProperties(String propertyName) { String value = loadedProperties.getProperty(propertyName); if (value == null) return null; else return value.split(","); } public Authenticator getAuthenticator(Authenticator defaultAuthenticator) { Authenticator authenticator = (Authenticator) createComponent(AUTHENTICATOR); return authenticator == null ? defaultAuthenticator : authenticator; } public String loadSymbolTypes() throws ClassNotFoundException, InstantiationException, IllegalAccessException { StringBuffer buffer = new StringBuffer(); String[] symbolTypeNames = getListFromProperties(SYMBOL_TYPES); if (symbolTypeNames != null) { buffer.append("\tCustom symbol types loaded:").append(endl); for (String symbolTypeName : symbolTypeNames) { Class<?> symbolTypeClass = Class.forName(symbolTypeName.trim()); symbolProvider.add((SymbolType)symbolTypeClass.newInstance()); buffer.append("\t\t").append(symbolTypeClass.getName()).append(endl); } } return buffer.toString(); } public String loadContentFilter() { ContentFilter filter = (ContentFilter) createComponent(CONTENT_FILTER); if (filter != null) { SaveResponder.contentFilter = filter; return "\tContent filter installed: " + filter.getClass().getName() + "\n"; } return ""; } public VersionsController loadVersionsController() { VersionsController versionsController = (VersionsController) createComponent(VERSIONS_CONTROLLER); if (versionsController == null) { versionsController = new ZipFileVersionsController(); } return versionsController; } }