0001: /*
0002: JSPWiki - a JSP-based WikiWiki clone.
0003:
0004: Copyright (C) 2001-2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)
0005:
0006: This program is free software; you can redistribute it and/or modify
0007: it under the terms of the GNU Lesser General Public License as published by
0008: the Free Software Foundation; either version 2.1 of the License, or
0009: (at your option) any later version.
0010:
0011: This program is distributed in the hope that it will be useful,
0012: but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0014: GNU Lesser General Public License for more details.
0015:
0016: You should have received a copy of the GNU Lesser General Public License
0017: along with this program; if not, write to the Free Software
0018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0019: */
0020: package com.ecyrd.jspwiki;
0021:
0022: import java.io.File;
0023: import java.io.IOException;
0024: import java.io.UnsupportedEncodingException;
0025: import java.net.URLDecoder;
0026: import java.net.URLEncoder;
0027: import java.security.Principal;
0028: import java.util.*;
0029:
0030: import javax.servlet.ServletConfig;
0031: import javax.servlet.ServletContext;
0032: import javax.servlet.ServletRequest;
0033: import javax.servlet.http.HttpServletRequest;
0034:
0035: import org.apache.commons.lang.time.StopWatch;
0036: import org.apache.log4j.Logger;
0037: import org.apache.log4j.PropertyConfigurator;
0038:
0039: import com.ecyrd.jspwiki.attachment.Attachment;
0040: import com.ecyrd.jspwiki.attachment.AttachmentManager;
0041: import com.ecyrd.jspwiki.auth.AuthenticationManager;
0042: import com.ecyrd.jspwiki.auth.AuthorizationManager;
0043: import com.ecyrd.jspwiki.auth.UserManager;
0044: import com.ecyrd.jspwiki.auth.acl.AclManager;
0045: import com.ecyrd.jspwiki.auth.acl.DefaultAclManager;
0046: import com.ecyrd.jspwiki.auth.authorize.GroupManager;
0047: import com.ecyrd.jspwiki.diff.DifferenceManager;
0048: import com.ecyrd.jspwiki.event.WikiEngineEvent;
0049: import com.ecyrd.jspwiki.event.WikiEventListener;
0050: import com.ecyrd.jspwiki.event.WikiEventManager;
0051: import com.ecyrd.jspwiki.filters.FilterException;
0052: import com.ecyrd.jspwiki.filters.FilterManager;
0053: import com.ecyrd.jspwiki.i18n.InternationalizationManager;
0054: import com.ecyrd.jspwiki.parser.JSPWikiMarkupParser;
0055: import com.ecyrd.jspwiki.parser.MarkupParser;
0056: import com.ecyrd.jspwiki.parser.WikiDocument;
0057: import com.ecyrd.jspwiki.plugin.PluginManager;
0058: import com.ecyrd.jspwiki.providers.ProviderException;
0059: import com.ecyrd.jspwiki.providers.WikiPageProvider;
0060: import com.ecyrd.jspwiki.render.RenderingManager;
0061: import com.ecyrd.jspwiki.rss.RSSGenerator;
0062: import com.ecyrd.jspwiki.rss.RSSThread;
0063: import com.ecyrd.jspwiki.search.SearchManager;
0064: import com.ecyrd.jspwiki.ui.Command;
0065: import com.ecyrd.jspwiki.ui.CommandResolver;
0066: import com.ecyrd.jspwiki.ui.EditorManager;
0067: import com.ecyrd.jspwiki.ui.TemplateManager;
0068: import com.ecyrd.jspwiki.ui.admin.AdminBeanManager;
0069: import com.ecyrd.jspwiki.ui.progress.ProgressManager;
0070: import com.ecyrd.jspwiki.url.URLConstructor;
0071: import com.ecyrd.jspwiki.util.ClassUtil;
0072: import com.ecyrd.jspwiki.util.WatchDog;
0073: import com.ecyrd.jspwiki.workflow.*;
0074:
0075: /**
0076: * Provides Wiki services to the JSP page.
0077: *
0078: * <P>
0079: * This is the main interface through which everything should go.
0080: *
0081: * <P>
0082: * Using this class: Always get yourself an instance from JSP page
0083: * by using the WikiEngine.getInstance() method. Never create a new
0084: * WikiEngine() from scratch, unless you're writing tests.
0085: * <p>
0086: * There's basically only a single WikiEngine for each web application, and
0087: * you should always get it using the WikiEngine.getInstance() method.
0088: *
0089: * @author Janne Jalkanen
0090: */
0091: public class WikiEngine {
0092: private static final String ATTR_WIKIENGINE = "com.ecyrd.jspwiki.WikiEngine";
0093:
0094: private static final Logger log = Logger
0095: .getLogger(WikiEngine.class);
0096:
0097: /** True, if log4j has been configured. */
0098: // FIXME: If you run multiple applications, the first application
0099: // to run defines where the log goes. Not what we want.
0100: private static boolean c_configured = false;
0101:
0102: /** Stores properties. */
0103: private Properties m_properties;
0104:
0105: /** Property for application name */
0106: public static final String PROP_APPNAME = "jspwiki.applicationName";
0107:
0108: /** Property start for any interwiki reference. */
0109: public static final String PROP_INTERWIKIREF = "jspwiki.interWikiRef.";
0110:
0111: /** If true, then the user name will be stored with the page data.*/
0112: public static final String PROP_STOREUSERNAME = "jspwiki.storeUserName";
0113:
0114: /** Define the used encoding. Currently supported are ISO-8859-1 and UTF-8 */
0115: public static final String PROP_ENCODING = "jspwiki.encoding";
0116:
0117: /** The name for the base URL to use in all references. */
0118: public static final String PROP_BASEURL = "jspwiki.baseURL";
0119:
0120: /** The name for the property which allows you to set the current reference
0121: * style. The value is {@value}.
0122: */
0123: public static final String PROP_REFSTYLE = "jspwiki.referenceStyle";
0124:
0125: /** Property name for the "spaces in titles" -hack. */
0126: public static final String PROP_BEAUTIFYTITLE = "jspwiki.breakTitleWithSpaces";
0127:
0128: /** Property name for where the jspwiki work directory should be.
0129: If not specified, reverts to ${java.tmpdir}. */
0130: public static final String PROP_WORKDIR = "jspwiki.workDir";
0131:
0132: /** The name of the cookie that gets stored to the user browser. */
0133: public static final String PREFS_COOKIE_NAME = "JSPWikiUserProfile";
0134:
0135: /** Property name for the "match english plurals" -hack. */
0136: public static final String PROP_MATCHPLURALS = "jspwiki.translatorReader.matchEnglishPlurals";
0137:
0138: /** Property name for the template that is used. */
0139: public static final String PROP_TEMPLATEDIR = "jspwiki.templateDir";
0140:
0141: /** Property name for the default front page. */
0142: public static final String PROP_FRONTPAGE = "jspwiki.frontPage";
0143:
0144: /** Property name for setting the url generator instance */
0145:
0146: public static final String PROP_URLCONSTRUCTOR = "jspwiki.urlConstructor";
0147:
0148: /** If this property is set to false, all filters are disabled when translating. */
0149: public static final String PROP_RUNFILTERS = "jspwiki.runFilters";
0150:
0151: /** Does the work in renaming pages. */
0152: private PageRenamer m_pageRenamer = null;
0153:
0154: /** The name of the property containing the ACLManager implementing class.
0155: * The value is {@value}. */
0156: public static final String PROP_ACL_MANAGER_IMPL = "jspwiki.aclManager";
0157:
0158: /** Should the user info be saved with the page data as well? */
0159: private boolean m_saveUserInfo = true;
0160:
0161: /** If true, uses UTF8 encoding for all data */
0162: private boolean m_useUTF8 = true;
0163:
0164: /** Stores the base URL. */
0165: private String m_baseURL;
0166:
0167: /** Store the file path to the basic URL. When we're not running as
0168: a servlet, it defaults to the user's current directory. */
0169: private String m_rootPath = System.getProperty("user.dir");
0170:
0171: /** Stores references between wikipages. */
0172: private ReferenceManager m_referenceManager = null;
0173:
0174: /** Stores the Plugin manager */
0175: private PluginManager m_pluginManager;
0176:
0177: /** Stores the Variable manager */
0178: private VariableManager m_variableManager;
0179:
0180: /** Stores the Attachment manager */
0181: private AttachmentManager m_attachmentManager = null;
0182:
0183: /** Stores the Page manager */
0184: private PageManager m_pageManager = null;
0185:
0186: /** Stores the authorization manager */
0187: private AuthorizationManager m_authorizationManager = null;
0188:
0189: /** Stores the authentication manager.*/
0190: private AuthenticationManager m_authenticationManager = null;
0191:
0192: /** Stores the ACL manager. */
0193: private AclManager m_aclManager = null;
0194:
0195: /** Resolves wiki actions, JSPs and special pages. */
0196: private CommandResolver m_commandResolver = null;
0197:
0198: private TemplateManager m_templateManager = null;
0199:
0200: /** Does all our diffs for us. */
0201: private DifferenceManager m_differenceManager;
0202:
0203: /** Handlers page filters. */
0204: private FilterManager m_filterManager;
0205:
0206: /** Stores the Search manager */
0207: private SearchManager m_searchManager = null;
0208:
0209: /** Facade for managing users */
0210: private UserManager m_userManager = null;
0211:
0212: /** Facade for managing users */
0213: private GroupManager m_groupManager = null;
0214:
0215: private RenderingManager m_renderingManager;
0216:
0217: private EditorManager m_editorManager;
0218:
0219: private InternationalizationManager m_internationalizationManager;
0220:
0221: private ProgressManager m_progressManager;
0222:
0223: /** Constructs URLs */
0224: private URLConstructor m_urlConstructor;
0225:
0226: /** Generates RSS feed when requested. */
0227: private RSSGenerator m_rssGenerator;
0228:
0229: /** The RSS file to generate. */
0230: private String m_rssFile;
0231:
0232: /** Store the ServletContext that we're in. This may be null if WikiEngine
0233: is not running inside a servlet container (i.e. when testing). */
0234: private ServletContext m_servletContext = null;
0235:
0236: /** If true, all titles will be cleaned. */
0237: private boolean m_beautifyTitle = false;
0238:
0239: /** Stores the template path. This is relative to "templates". */
0240: private String m_templateDir;
0241:
0242: /** The default front page name. Defaults to "Main". */
0243: private String m_frontPage;
0244:
0245: /** The time when this engine was started. */
0246: private Date m_startTime;
0247:
0248: /** The location where the work directory is. */
0249: private String m_workDir;
0250:
0251: /** Each engine has their own application id. */
0252: private String m_appid = "";
0253:
0254: private boolean m_isConfigured = false; // Flag.
0255:
0256: /** Each engine has its own workflow manager. */
0257: private WorkflowManager m_workflowMgr = null;
0258:
0259: private AdminBeanManager m_adminBeanManager;
0260:
0261: /**
0262: * Gets a WikiEngine related to this servlet. Since this method
0263: * is only called from JSP pages (and JspInit()) to be specific,
0264: * we throw a RuntimeException if things don't work.
0265: *
0266: * @param config The ServletConfig object for this servlet.
0267: *
0268: * @return A WikiEngine instance.
0269: * @throws InternalWikiException in case something fails. This
0270: * is a RuntimeException, so be prepared for it.
0271: */
0272:
0273: // FIXME: It seems that this does not work too well, jspInit()
0274: // does not react to RuntimeExceptions, or something...
0275: public static synchronized WikiEngine getInstance(
0276: ServletConfig config) throws InternalWikiException {
0277: return getInstance(config.getServletContext(), null);
0278: }
0279:
0280: /**
0281: * Gets a WikiEngine related to the servlet. Works like getInstance(ServletConfig),
0282: * but does not force the Properties object. This method is just an optional way
0283: * of initializing a WikiEngine for embedded JSPWiki applications; normally, you
0284: * should use getInstance(ServletConfig).
0285: *
0286: * @param config The ServletConfig of the webapp servlet/JSP calling this method.
0287: * @param props A set of properties, or null, if we are to load JSPWiki's default
0288: * jspwiki.properties (this is the usual case).
0289: *
0290: * @return One well-behaving WikiEngine instance.
0291: */
0292: public static synchronized WikiEngine getInstance(
0293: ServletConfig config, Properties props) {
0294: return getInstance(config.getServletContext(), props);
0295: }
0296:
0297: /**
0298: * Gets a WikiEngine related to the servlet. Works just like getInstance( ServletConfig )
0299: *
0300: * @param context The ServletContext of the webapp servlet/JSP calling this method.
0301: * @param props A set of properties, or null, if we are to load JSPWiki's default
0302: * jspwiki.properties (this is the usual case).
0303: *
0304: * @return One fully functional, properly behaving WikiEngine.
0305: * @throws InternalWikiException If the WikiEngine instantiation fails.
0306: */
0307:
0308: // FIXME: Potential make-things-easier thingy here: no need to fetch the wikiengine anymore
0309: // Wiki.jsp.jspInit() [really old code]; it's probably even faster to fetch it
0310: // using this method every time than go to pageContext.getAttribute().
0311: public static synchronized WikiEngine getInstance(
0312: ServletContext context, Properties props)
0313: throws InternalWikiException {
0314: WikiEngine engine = (WikiEngine) context
0315: .getAttribute(ATTR_WIKIENGINE);
0316:
0317: if (engine == null) {
0318: String appid = Integer.toString(context.hashCode()); //FIXME: Kludge, use real type.
0319:
0320: context.log(" Assigning new engine to " + appid);
0321: try {
0322: if (props == null) {
0323: props = PropertyReader.loadWebAppProps(context);
0324: }
0325:
0326: engine = new WikiEngine(context, appid, props);
0327: context.setAttribute(ATTR_WIKIENGINE, engine);
0328: } catch (Exception e) {
0329: context.log("ERROR: Failed to create a Wiki engine: "
0330: + e.getMessage());
0331: throw new InternalWikiException(
0332: "No wiki engine, check logs.");
0333: }
0334:
0335: }
0336:
0337: return engine;
0338: }
0339:
0340: /**
0341: * Instantiate the WikiEngine using a given set of properties.
0342: * Use this constructor for testing purposes only.
0343: *
0344: * @param properties A set of properties to use to initialize this WikiEngine.
0345: * @throws WikiException If the initialization fails.
0346: */
0347: public WikiEngine(Properties properties) throws WikiException {
0348: initialize(properties);
0349: }
0350:
0351: /**
0352: * Instantiate using this method when you're running as a servlet and
0353: * WikiEngine will figure out where to look for the property
0354: * file.
0355: * Do not use this method - use WikiEngine.getInstance() instead.
0356: *
0357: * @param context A ServletContext.
0358: * @param appid An Application ID. This application is an unique random string which
0359: * is used to recognize this WikiEngine.
0360: * @param props The WikiEngine configuration.
0361: * @throws WikiException If the WikiEngine construction fails.
0362: */
0363: protected WikiEngine(ServletContext context, String appid,
0364: Properties props) throws WikiException {
0365: m_servletContext = context;
0366: m_appid = appid;
0367:
0368: try {
0369: //
0370: // Note: May be null, if JSPWiki has been deployed in a WAR file.
0371: //
0372: m_rootPath = context.getRealPath("/");
0373: initialize(props);
0374: log
0375: .info("Root path for this Wiki is: '" + m_rootPath
0376: + "'");
0377: } catch (Exception e) {
0378: String msg = Release.APPNAME
0379: + ": Unable to load and setup properties from jspwiki.properties. "
0380: + e.getMessage();
0381: context.log(msg);
0382: throw new WikiException(msg);
0383: }
0384: }
0385:
0386: /**
0387: * Does all the real initialization.
0388: */
0389: private void initialize(Properties props) throws WikiException {
0390: m_startTime = new Date();
0391: m_properties = props;
0392:
0393: //
0394: // Initialized log4j. However, make sure that
0395: // we don't initialize it multiple times. Also, if
0396: // all of the log4j statements have been removed from
0397: // the property file, we do not do any property setting
0398: // either.q
0399: //
0400: if (!c_configured) {
0401: if (props.getProperty("log4j.rootCategory") != null) {
0402: PropertyConfigurator.configure(props);
0403: }
0404: c_configured = true;
0405: }
0406:
0407: log.info("*******************************************");
0408: log.info(Release.APPNAME + " " + Release.getVersionString()
0409: + " starting. Whee!");
0410:
0411: fireEvent(WikiEngineEvent.INITIALIZING); // begin initialization
0412:
0413: log.debug("Java version: "
0414: + System.getProperty("java.runtime.version"));
0415: log.debug("Java vendor: "
0416: + System.getProperty("java.vm.vendor"));
0417: log.debug("OS: " + System.getProperty("os.name") + " "
0418: + System.getProperty("os.version") + " "
0419: + System.getProperty("os.arch"));
0420: log.debug("Default server locale: " + Locale.getDefault());
0421: log.debug("Default server timezone: "
0422: + TimeZone.getDefault().getDisplayName(true,
0423: TimeZone.LONG));
0424:
0425: if (m_servletContext != null) {
0426: log.info("Servlet container: "
0427: + m_servletContext.getServerInfo());
0428: if (m_servletContext.getMajorVersion() < 2
0429: || (m_servletContext.getMajorVersion() == 2 && m_servletContext
0430: .getMinorVersion() < 4)) {
0431: throw new InternalWikiException(
0432: "I require a container which supports at least version 2.4 of Servlet specification");
0433: }
0434: }
0435:
0436: log.debug("Configuring WikiEngine...");
0437:
0438: // Initializes the CommandResolver
0439: m_commandResolver = new CommandResolver(this , props);
0440:
0441: //
0442: // Create and find the default working directory.
0443: //
0444: m_workDir = TextUtil.getStringProperty(props, PROP_WORKDIR,
0445: null);
0446:
0447: if (m_workDir == null) {
0448: m_workDir = System.getProperty("java.io.tmpdir", ".");
0449: m_workDir += File.separator + Release.APPNAME + "-"
0450: + m_appid;
0451: }
0452:
0453: try {
0454: File f = new File(m_workDir);
0455: f.mkdirs();
0456:
0457: //
0458: // A bunch of sanity checks
0459: //
0460: if (!f.exists())
0461: throw new WikiException(
0462: "Work directory does not exist: " + m_workDir);
0463: if (!f.canRead())
0464: throw new WikiException(
0465: "No permission to read work directory: "
0466: + m_workDir);
0467: if (!f.canWrite())
0468: throw new WikiException(
0469: "No permission to write to work directory: "
0470: + m_workDir);
0471: if (!f.isDirectory())
0472: throw new WikiException(
0473: "jspwiki.workDir does not point to a directory: "
0474: + m_workDir);
0475: } catch (SecurityException e) {
0476: log.fatal(
0477: "Unable to find or create the working directory: "
0478: + m_workDir, e);
0479: throw new IllegalArgumentException(
0480: "Unable to find or create the working dir: "
0481: + m_workDir);
0482: }
0483:
0484: log.info("JSPWiki working directory is '" + m_workDir + "'");
0485:
0486: m_saveUserInfo = TextUtil.getBooleanProperty(props,
0487: PROP_STOREUSERNAME, m_saveUserInfo);
0488:
0489: m_useUTF8 = "UTF-8".equals(TextUtil.getStringProperty(props,
0490: PROP_ENCODING, "ISO-8859-1"));
0491: m_baseURL = TextUtil.getStringProperty(props, PROP_BASEURL, "");
0492:
0493: m_beautifyTitle = TextUtil.getBooleanProperty(props,
0494: PROP_BEAUTIFYTITLE, m_beautifyTitle);
0495:
0496: m_templateDir = TextUtil.getStringProperty(props,
0497: PROP_TEMPLATEDIR, "default");
0498: m_frontPage = TextUtil.getStringProperty(props, PROP_FRONTPAGE,
0499: "Main");
0500:
0501: //
0502: // Initialize the important modules. Any exception thrown by the
0503: // managers means that we will not start up.
0504: //
0505:
0506: // FIXME: This part of the code is getting unwieldy. We must think
0507: // of a better way to do the startup-sequence.
0508: try {
0509: Class urlclass = ClassUtil.findClass(
0510: "com.ecyrd.jspwiki.url", TextUtil
0511: .getStringProperty(props,
0512: PROP_URLCONSTRUCTOR,
0513: "DefaultURLConstructor"));
0514: m_urlConstructor = (URLConstructor) urlclass.newInstance();
0515: m_urlConstructor.initialize(this , props);
0516:
0517: m_pageManager = (PageManager) ClassUtil.getMappedObject(
0518: PageManager.class.getName(), this , props);
0519: m_pluginManager = (PluginManager) ClassUtil
0520: .getMappedObject(PluginManager.class.getName(),
0521: this , props);
0522: m_differenceManager = (DifferenceManager) ClassUtil
0523: .getMappedObject(DifferenceManager.class.getName(),
0524: this , props);
0525: m_attachmentManager = (AttachmentManager) ClassUtil
0526: .getMappedObject(AttachmentManager.class.getName(),
0527: this , props);
0528: m_variableManager = (VariableManager) ClassUtil
0529: .getMappedObject(VariableManager.class.getName(),
0530: props);
0531: // m_filterManager = (FilterManager)ClassUtil.getMappedObject(FilterManager.class.getName(), this, props );
0532: m_renderingManager = (RenderingManager) ClassUtil
0533: .getMappedObject(RenderingManager.class.getName());
0534:
0535: m_searchManager = (SearchManager) ClassUtil
0536: .getMappedObject(SearchManager.class.getName(),
0537: this , props);
0538:
0539: m_authenticationManager = (AuthenticationManager) ClassUtil
0540: .getMappedObject(AuthenticationManager.class
0541: .getName());
0542: m_authorizationManager = (AuthorizationManager) ClassUtil
0543: .getMappedObject(AuthorizationManager.class
0544: .getName());
0545: m_userManager = (UserManager) ClassUtil
0546: .getMappedObject(UserManager.class.getName());
0547: m_groupManager = (GroupManager) ClassUtil
0548: .getMappedObject(GroupManager.class.getName());
0549:
0550: m_editorManager = (EditorManager) ClassUtil
0551: .getMappedObject(EditorManager.class.getName(),
0552: this );
0553: m_editorManager.initialize(props);
0554:
0555: m_progressManager = new ProgressManager();
0556:
0557: // Initialize the authentication, authorization, user and acl managers
0558:
0559: m_authenticationManager.initialize(this , props);
0560: m_authorizationManager.initialize(this , props);
0561: m_userManager.initialize(this , props);
0562: m_groupManager.initialize(this , props);
0563: m_aclManager = getAclManager();
0564:
0565: // Start the Workflow manager
0566: m_workflowMgr = (WorkflowManager) ClassUtil
0567: .getMappedObject(WorkflowManager.class.getName());
0568: m_workflowMgr.initialize(this , props);
0569:
0570: m_internationalizationManager = (InternationalizationManager) ClassUtil
0571: .getMappedObject(InternationalizationManager.class
0572: .getName(), this );
0573:
0574: m_templateManager = (TemplateManager) ClassUtil
0575: .getMappedObject(TemplateManager.class.getName(),
0576: this , props);
0577:
0578: m_adminBeanManager = (AdminBeanManager) ClassUtil
0579: .getMappedObject(AdminBeanManager.class.getName(),
0580: this );
0581:
0582: // Since we want to use a page filters initilize() method
0583: // as a engine startup listener where we can initialize global event listeners,
0584: // it must be called lastly, so that all object references in the engine
0585: // are availabe to the initialize() method
0586: m_filterManager = (FilterManager) ClassUtil
0587: .getMappedObject(FilterManager.class.getName(),
0588: this , props);
0589:
0590: // RenderingManager depends on FilterManager events.
0591:
0592: m_renderingManager.initialize(this , props);
0593:
0594: //
0595: // ReferenceManager has the side effect of loading all
0596: // pages. Therefore after this point, all page attributes
0597: // are available.
0598: //
0599: // initReferenceManager is indirectly using m_filterManager, therefore
0600: // it has to be called after it was initialized.
0601: //
0602: initReferenceManager();
0603:
0604: //
0605: // Hook the different manager routines into the system.
0606: //
0607: getFilterManager().addPageFilter(m_referenceManager, -1001);
0608: getFilterManager().addPageFilter(m_searchManager, -1002);
0609: }
0610:
0611: catch (RuntimeException e) {
0612: // RuntimeExceptions may occur here, even if they shouldn't.
0613: log.fatal("Failed to start managers.", e);
0614: throw new WikiException("Failed to start managers: "
0615: + e.getMessage());
0616: } catch (ClassNotFoundException e) {
0617: log
0618: .fatal(
0619: "JSPWiki could not start, URLConstructor was not found: ",
0620: e);
0621: throw new WikiException(e.getMessage());
0622: } catch (InstantiationException e) {
0623: log
0624: .fatal(
0625: "JSPWiki could not start, URLConstructor could not be instantiated: ",
0626: e);
0627: throw new WikiException(e.getMessage());
0628: } catch (IllegalAccessException e) {
0629: log
0630: .fatal(
0631: "JSPWiki could not start, URLConstructor cannot be accessed: ",
0632: e);
0633: throw new WikiException(e.getMessage());
0634: }
0635:
0636: //
0637: // Initialize the good-to-have-but-not-fatal modules.
0638: //
0639: try {
0640: if (TextUtil.getBooleanProperty(props,
0641: RSSGenerator.PROP_GENERATE_RSS, false)) {
0642: m_rssGenerator = (RSSGenerator) ClassUtil
0643: .getMappedObject(RSSGenerator.class.getName(),
0644: this , props);
0645: }
0646:
0647: m_pageRenamer = (PageRenamer) ClassUtil.getMappedObject(
0648: PageRenamer.class.getName(), this , props);
0649: } catch (Exception e) {
0650: log.error(
0651: "Unable to start RSS generator - JSPWiki will still work, "
0652: + "but there will be no RSS feed.", e);
0653: }
0654:
0655: // Start the RSS generator & generator thread
0656: if (m_rssGenerator != null) {
0657: m_rssFile = TextUtil.getStringProperty(props,
0658: RSSGenerator.PROP_RSSFILE, "rss.rdf");
0659: File rssFile = null;
0660: if (m_rssFile.startsWith(File.separator)) {
0661: // honor absolute pathnames:
0662: rssFile = new File(m_rssFile);
0663: } else {
0664: // relative path names are anchored from the webapp root path:
0665: rssFile = new File(getRootPath(), m_rssFile);
0666: }
0667: int rssInterval = TextUtil.getIntegerProperty(props,
0668: RSSGenerator.PROP_INTERVAL, 3600);
0669: RSSThread rssThread = new RSSThread(this , rssFile,
0670: rssInterval);
0671: rssThread.start();
0672: }
0673:
0674: fireEvent(WikiEngineEvent.INITIALIZED); // initialization complete
0675:
0676: log.info("WikiEngine configured.");
0677: m_isConfigured = true;
0678: }
0679:
0680: /**
0681: * Initializes the reference manager. Scans all existing WikiPages for
0682: * internal links and adds them to the ReferenceManager object.
0683: *
0684: * @throws WikiException If the reference manager initialization fails.
0685: */
0686: public void initReferenceManager() throws WikiException {
0687: try {
0688: ArrayList pages = new ArrayList();
0689: pages.addAll(m_pageManager.getAllPages());
0690: pages.addAll(m_attachmentManager.getAllAttachments());
0691:
0692: // Build a new manager with default key lists.
0693: if (m_referenceManager == null) {
0694: m_referenceManager = (ReferenceManager) ClassUtil
0695: .getMappedObject(ReferenceManager.class
0696: .getName(), this );
0697: m_referenceManager.initialize(pages);
0698: }
0699:
0700: } catch (ProviderException e) {
0701: log.fatal("PageProvider is unable to list pages: ", e);
0702: }
0703: }
0704:
0705: /**
0706: * Throws an exception if a property is not found.
0707: *
0708: * @param props A set of properties to search the key in.
0709: * @param key The key to look for.
0710: * @return The required property
0711: *
0712: * @throws NoRequiredPropertyException If the search key is not
0713: * in the property set.
0714: */
0715:
0716: // FIXME: Should really be in some util file.
0717: public static String getRequiredProperty(Properties props,
0718: String key) throws NoRequiredPropertyException {
0719: String value = TextUtil.getStringProperty(props, key, null);
0720:
0721: if (value == null) {
0722: throw new NoRequiredPropertyException(
0723: "Required property not found", key);
0724: }
0725:
0726: return value;
0727: }
0728:
0729: /**
0730: * Returns the set of properties that the WikiEngine was initialized
0731: * with. Note that this method returns a direct reference, so it's possible
0732: * to manipulate the properties. However, this is not advised unless you
0733: * really know what you're doing.
0734: *
0735: * @return The wiki properties
0736: */
0737:
0738: public Properties getWikiProperties() {
0739: return m_properties;
0740: }
0741:
0742: /**
0743: * Returns the JSPWiki working directory set with "jspwiki.workDir".
0744: *
0745: * @since 2.1.100
0746: * @return The working directory.
0747: */
0748: public String getWorkDir() {
0749: return m_workDir;
0750: }
0751:
0752: /**
0753: * Don't use.
0754: * @since 1.8.0
0755: * @deprecated
0756: */
0757: public String getPluginSearchPath() {
0758: // FIXME: This method should not be here, probably.
0759: return TextUtil.getStringProperty(m_properties,
0760: PluginManager.PROP_SEARCHPATH, null);
0761: }
0762:
0763: /**
0764: * Returns the current template directory.
0765: *
0766: * @since 1.9.20
0767: * @return The template directory as initialized by the engine.
0768: */
0769: public String getTemplateDir() {
0770: return m_templateDir;
0771: }
0772:
0773: /**
0774: * Returns the current TemplateManager.
0775: *
0776: * @return A TemplateManager instance.
0777: */
0778: public TemplateManager getTemplateManager() {
0779: return m_templateManager;
0780: }
0781:
0782: /**
0783: * Returns the base URL, telling where this Wiki actually lives.
0784: *
0785: * @since 1.6.1
0786: * @return The Base URL.
0787: */
0788:
0789: public String getBaseURL() {
0790: return m_baseURL;
0791: }
0792:
0793: /**
0794: * Returns the moment when this engine was started.
0795: *
0796: * @since 2.0.15.
0797: * @return The start time of this wiki.
0798: */
0799:
0800: public Date getStartTime() {
0801: return (Date) m_startTime.clone();
0802: }
0803:
0804: /**
0805: * <p>
0806: * Returns the basic absolute URL to a page, without any modifications. You
0807: * may add any parameters to this.
0808: * </p>
0809: * <p>
0810: * Since 2.3.90 it is safe to call this method with <code>null</code>
0811: * pageName, in which case it will default to the front page.
0812: * </p>
0813: * @since 2.0.3
0814: * @param pageName The name of the page. May be null, in which case defaults to the front page.
0815: * @return An absolute URL to the page.
0816: */
0817: public String getViewURL(String pageName) {
0818: if (pageName == null) {
0819: pageName = getFrontPage();
0820: }
0821: return getURLConstructor().makeURL(WikiContext.VIEW, pageName,
0822: true, null);
0823: }
0824:
0825: /**
0826: * Returns the basic URL to an editor. Please use WikiContext.getURL() or
0827: * WikiEngine.getURL() instead.
0828: *
0829: * @see #getURL(String, String, String, boolean)
0830: * @see WikiContext#getURL(String, String)
0831: * @deprecated
0832: *
0833: * @since 2.0.3
0834: */
0835: public String getEditURL(String pageName) {
0836: return m_urlConstructor.makeURL(WikiContext.EDIT, pageName,
0837: false, null);
0838: }
0839:
0840: /**
0841: * Returns the basic attachment URL.Please use WikiContext.getURL() or
0842: * WikiEngine.getURL() instead.
0843: *
0844: * @see #getURL(String, String, String, boolean)
0845: * @see WikiContext#getURL(String, String)
0846: * @since 2.0.42.
0847: * @param attName Attachment name
0848: * @deprecated
0849: */
0850: public String getAttachmentURL(String attName) {
0851: return m_urlConstructor.makeURL(WikiContext.ATTACH, attName,
0852: false, null);
0853: }
0854:
0855: /**
0856: * Returns an URL if a WikiContext is not available.
0857: *
0858: * @param context The WikiContext (VIEW, EDIT, etc...)
0859: * @param pageName Name of the page, as usual
0860: * @param params List of parameters. May be null, if no parameters.
0861: * @param absolute If true, will generate an absolute URL regardless of properties setting.
0862: * @return An URL (absolute or relative).
0863: */
0864: public String getURL(String context, String pageName,
0865: String params, boolean absolute) {
0866: if (pageName == null)
0867: pageName = getFrontPage();
0868: return m_urlConstructor.makeURL(context, pageName, absolute,
0869: params);
0870: }
0871:
0872: /**
0873: * Returns the default front page, if no page is used.
0874: *
0875: * @return The front page name.
0876: */
0877:
0878: public String getFrontPage() {
0879: return m_frontPage;
0880: }
0881:
0882: /**
0883: * Returns the ServletContext that this particular WikiEngine was
0884: * initialized with. <B>It may return null</B>, if the WikiEngine is not
0885: * running inside a servlet container!
0886: *
0887: * @since 1.7.10
0888: * @return ServletContext of the WikiEngine, or null.
0889: */
0890:
0891: public ServletContext getServletContext() {
0892: return m_servletContext;
0893: }
0894:
0895: /**
0896: * This is a safe version of the Servlet.Request.getParameter() routine.
0897: * Unfortunately, the default version always assumes that the incoming
0898: * character set is ISO-8859-1, even though it was something else.
0899: * This means that we need to make a new string using the correct
0900: * encoding.
0901: * <P>
0902: * For more information, see:
0903: * <A HREF="http://www.jguru.com/faq/view.jsp?EID=137049">JGuru FAQ</A>.
0904: * <P>
0905: * Incidentally, this is almost the same as encodeName(), below.
0906: * I am not yet entirely sure if it's safe to merge the code.
0907: *
0908: * @since 1.5.3
0909: * @deprecated JSPWiki now requires servlet API 2.3, which has a better
0910: * way of dealing with this stuff. This will be removed in
0911: * the near future.
0912: */
0913:
0914: public String safeGetParameter(ServletRequest request, String name) {
0915: try {
0916: String res = request.getParameter(name);
0917: if (res != null) {
0918: res = new String(res.getBytes("ISO-8859-1"),
0919: getContentEncoding());
0920: }
0921:
0922: return res;
0923: } catch (UnsupportedEncodingException e) {
0924: log.fatal("Unsupported encoding", e);
0925: return "";
0926: }
0927:
0928: }
0929:
0930: /**
0931: * Returns the query string (the portion after the question mark).
0932: *
0933: * @param request The HTTP request to parse.
0934: * @return The query string. If the query string is null,
0935: * returns an empty string.
0936: *
0937: * @since 2.1.3
0938: */
0939: public String safeGetQueryString(HttpServletRequest request) {
0940: if (request == null) {
0941: return "";
0942: }
0943:
0944: try {
0945: String res = request.getQueryString();
0946: if (res != null) {
0947: res = new String(res.getBytes("ISO-8859-1"),
0948: getContentEncoding());
0949:
0950: //
0951: // Ensure that the 'page=xyz' attribute is removed
0952: // FIXME: Is it really the mandate of this routine to
0953: // do that?
0954: //
0955: int pos1 = res.indexOf("page=");
0956: if (pos1 >= 0) {
0957: String tmpRes = res.substring(0, pos1);
0958: int pos2 = res.indexOf("&", pos1) + 1;
0959: if ((pos2 > 0) && (pos2 < res.length())) {
0960: tmpRes = tmpRes + res.substring(pos2);
0961: }
0962: res = tmpRes;
0963: }
0964: }
0965:
0966: return res;
0967: } catch (UnsupportedEncodingException e) {
0968: log.fatal("Unsupported encoding", e);
0969: return "";
0970: }
0971: }
0972:
0973: /**
0974: * Returns an URL to some other Wiki that we know.
0975: *
0976: * @param wikiName The name of the other wiki.
0977: * @return null, if no such reference was found.
0978: */
0979: public String getInterWikiURL(String wikiName) {
0980: return TextUtil.getStringProperty(m_properties,
0981: PROP_INTERWIKIREF + wikiName, null);
0982: }
0983:
0984: /**
0985: * Returns a collection of all supported InterWiki links.
0986: *
0987: * @return A Collection of Strings.
0988: */
0989: public Collection getAllInterWikiLinks() {
0990: Vector v = new Vector();
0991:
0992: for (Enumeration i = m_properties.propertyNames(); i
0993: .hasMoreElements();) {
0994: String prop = (String) i.nextElement();
0995:
0996: if (prop.startsWith(PROP_INTERWIKIREF)) {
0997: v.add(prop.substring(prop.lastIndexOf(".") + 1));
0998: }
0999: }
1000:
1001: return v;
1002: }
1003:
1004: /**
1005: * Returns a collection of all image types that get inlined.
1006: *
1007: * @return A Collection of Strings with a regexp pattern.
1008: */
1009:
1010: public Collection getAllInlinedImagePatterns() {
1011: return JSPWikiMarkupParser.getImagePatterns(this );
1012: }
1013:
1014: /**
1015: * <p>If the page is a special page, then returns a direct URL
1016: * to that page. Otherwise returns <code>null</code>.
1017: * This method delegates requests to
1018: * {@link com.ecyrd.jspwiki.ui.CommandResolver#getSpecialPageReference(String)}.
1019: * </p>
1020: * <p>
1021: * Special pages are defined in jspwiki.properties using the jspwiki.specialPage
1022: * setting. They're typically used to give Wiki page names to e.g. custom JSP
1023: * pages.
1024: * </p>
1025: *
1026: * @param original The page to check
1027: * @return A reference to the page, or null, if there's no special page.
1028: */
1029: public String getSpecialPageReference(String original) {
1030: return m_commandResolver.getSpecialPageReference(original);
1031: }
1032:
1033: /**
1034: * Returns the name of the application.
1035: *
1036: * @return A string describing the name of this application.
1037: */
1038:
1039: // FIXME: Should use servlet context as a default instead of a constant.
1040: public String getApplicationName() {
1041: String appName = TextUtil.getStringProperty(m_properties,
1042: PROP_APPNAME, Release.APPNAME);
1043:
1044: return appName;
1045: }
1046:
1047: /**
1048: * Beautifies the title of the page by appending spaces in suitable
1049: * places, if the user has so decreed in the properties when constructing
1050: * this WikiEngine. However, attachment names are only beautified by
1051: * the name.
1052: *
1053: * @param title The title to beautify
1054: * @return A beautified title (or, if beautification is off,
1055: * returns the title without modification)
1056: * @since 1.7.11
1057: */
1058: public String beautifyTitle(String title) {
1059: if (m_beautifyTitle) {
1060: try {
1061: Attachment att = m_attachmentManager
1062: .getAttachmentInfo(title);
1063:
1064: if (att == null) {
1065: return TextUtil.beautifyString(title);
1066: }
1067:
1068: String parent = TextUtil.beautifyString(att
1069: .getParentName());
1070:
1071: return parent + "/" + att.getFileName();
1072: } catch (ProviderException e) {
1073: return title;
1074: }
1075: }
1076:
1077: return title;
1078: }
1079:
1080: /**
1081: * Beautifies the title of the page by appending non-breaking spaces
1082: * in suitable places. This is really suitable only for HTML output,
1083: * as it uses the &nbsp; -character.
1084: *
1085: * @param title The title to beautify
1086: * @return A beautified title.
1087: * @since 2.1.127
1088: */
1089: public String beautifyTitleNoBreak(String title) {
1090: if (m_beautifyTitle) {
1091: return TextUtil.beautifyString(title, " ");
1092: }
1093:
1094: return title;
1095: }
1096:
1097: /**
1098: * Returns true, if the requested page (or an alias) exists. Will consider
1099: * any version as existing. Will also consider attachments.
1100: *
1101: * @param page WikiName of the page.
1102: * @return true, if page (or attachment) exists.
1103: */
1104: public boolean pageExists(String page) {
1105: Attachment att = null;
1106:
1107: try {
1108: if (m_commandResolver.getSpecialPageReference(page) != null)
1109: return true;
1110:
1111: if (getFinalPageName(page) != null) {
1112: return true;
1113: }
1114:
1115: att = getAttachmentManager().getAttachmentInfo(
1116: (WikiContext) null, page);
1117: } catch (ProviderException e) {
1118: log.debug("pageExists() failed to find attachments", e);
1119: }
1120:
1121: return att != null;
1122: }
1123:
1124: /**
1125: * Returns true, if the requested page (or an alias) exists with the
1126: * requested version.
1127: *
1128: * @param page Page name
1129: * @param version Page version
1130: * @return True, if page (or alias, or attachment) exists
1131: * @throws ProviderException If the provider fails.
1132: */
1133: public boolean pageExists(String page, int version)
1134: throws ProviderException {
1135: if (m_commandResolver.getSpecialPageReference(page) != null)
1136: return true;
1137:
1138: String finalName = getFinalPageName(page);
1139:
1140: boolean isThere = false;
1141:
1142: if (finalName != null) {
1143: //
1144: // Go and check if this particular version of this page
1145: // exists.
1146: //
1147: isThere = m_pageManager.pageExists(finalName, version);
1148: }
1149:
1150: if (isThere == false) {
1151: //
1152: // Go check if such an attachment exists.
1153: //
1154: try {
1155: isThere = getAttachmentManager().getAttachmentInfo(
1156: (WikiContext) null, page, version) != null;
1157: } catch (ProviderException e) {
1158: log.debug("pageExists() failed to find attachments", e);
1159: }
1160: }
1161:
1162: return isThere;
1163: }
1164:
1165: /**
1166: * Returns true, if the requested page (or an alias) exists, with the
1167: * specified version in the WikiPage.
1168: *
1169: * @param page A WikiPage object describing the name and version.
1170: * @return true, if the page (or alias, or attachment) exists.
1171: * @throws ProviderException If something goes badly wrong.
1172: * @since 2.0
1173: */
1174: public boolean pageExists(WikiPage page) throws ProviderException {
1175: if (page != null) {
1176: return pageExists(page.getName(), page.getVersion());
1177: }
1178: return false;
1179: }
1180:
1181: /**
1182: * Returns the correct page name, or null, if no such
1183: * page can be found. Aliases are considered. This
1184: * method simply delegates to
1185: * {@link com.ecyrd.jspwiki.ui.CommandResolver#getFinalPageName(String)}.
1186: * @since 2.0
1187: * @param page Page name.
1188: * @return The rewritten page name, or null, if the page does not exist.
1189: * @throws ProviderException If something goes wrong in the backend.
1190: */
1191: public String getFinalPageName(String page)
1192: throws ProviderException {
1193: return m_commandResolver.getFinalPageName(page);
1194: }
1195:
1196: /**
1197: * Turns a WikiName into something that can be
1198: * called through using an URL.
1199: *
1200: * @since 1.4.1
1201: * @param pagename A name. Can be actually any string.
1202: * @return A properly encoded name.
1203: * @see #decodeName(String)
1204: */
1205: public String encodeName(String pagename) {
1206: try {
1207: return URLEncoder.encode(pagename, m_useUTF8 ? "UTF-8"
1208: : "ISO-8859-1");
1209: } catch (UnsupportedEncodingException e) {
1210: throw new InternalWikiException(
1211: "ISO-8859-1 not a supported encoding!?! Your platform is borked.");
1212: }
1213: }
1214:
1215: /**
1216: * Decodes a URL-encoded request back to regular life. This properly heeds
1217: * the encoding as defined in the settings file.
1218: *
1219: * @param pagerequest The URL-encoded string to decode
1220: * @return A decoded string.
1221: * @see #encodeName(String)
1222: */
1223: public String decodeName(String pagerequest) {
1224: try {
1225: return URLDecoder.decode(pagerequest, m_useUTF8 ? "UTF-8"
1226: : "ISO-8859-1");
1227: } catch (UnsupportedEncodingException e) {
1228: throw new InternalWikiException(
1229: "ISO-8859-1 not a supported encoding!?! Your platform is borked.");
1230: }
1231: }
1232:
1233: /**
1234: * Returns the IANA name of the character set encoding we're
1235: * supposed to be using right now.
1236: *
1237: * @since 1.5.3
1238: * @return The content encoding (either UTF-8 or ISO-8859-1).
1239: */
1240: public String getContentEncoding() {
1241: if (m_useUTF8)
1242: return "UTF-8";
1243:
1244: return "ISO-8859-1";
1245: }
1246:
1247: /**
1248: * Returns the {@link com.ecyrd.jspwiki.workflow.WorkflowManager} associated with this
1249: * WikiEngine. If the WIkiEngine has not been initialized, this method will return
1250: * <code>null</code>.
1251: * @return the task queue
1252: */
1253: public WorkflowManager getWorkflowManager() {
1254: return m_workflowMgr;
1255: }
1256:
1257: /**
1258: * Returns the un-HTMLized text of the latest version of a page.
1259: * This method also replaces the < and & -characters with
1260: * their respective HTML entities, thus making it suitable
1261: * for inclusion on an HTML page. If you want to have the
1262: * page text without any conversions, use getPureText().
1263: *
1264: * @param page WikiName of the page to fetch.
1265: * @return WikiText.
1266: */
1267: public String getText(String page) {
1268: return getText(page, WikiPageProvider.LATEST_VERSION);
1269: }
1270:
1271: /**
1272: * Returns the un-HTMLized text of the given version of a page.
1273: * This method also replaces the < and & -characters with
1274: * their respective HTML entities, thus making it suitable
1275: * for inclusion on an HTML page. If you want to have the
1276: * page text without any conversions, use getPureText().
1277: *
1278: *
1279: * @param page WikiName of the page to fetch
1280: * @param version Version of the page to fetch
1281: * @return WikiText.
1282: */
1283: public String getText(String page, int version) {
1284: String result = getPureText(page, version);
1285:
1286: //
1287: // Replace ampersand first, or else all quotes and stuff
1288: // get replaced as well with " etc.
1289: //
1290: /*
1291: result = TextUtil.replaceString( result, "&", "&" );
1292: */
1293:
1294: result = TextUtil.replaceEntities(result);
1295:
1296: return result;
1297: }
1298:
1299: /**
1300: * Returns the un-HTMLized text of the given version of a page in
1301: * the given context. USE THIS METHOD if you don't know what
1302: * doing.
1303: * <p>
1304: * This method also replaces the < and & -characters with
1305: * their respective HTML entities, thus making it suitable
1306: * for inclusion on an HTML page. If you want to have the
1307: * page text without any conversions, use getPureText().
1308: *
1309: * @since 1.9.15.
1310: * @param context The WikiContext
1311: * @param page A page reference (not an attachment)
1312: * @return The page content as HTMLized String.
1313: * @see #getPureText(WikiPage)
1314: */
1315: public String getText(WikiContext context, WikiPage page) {
1316: return getText(page.getName(), page.getVersion());
1317: }
1318:
1319: /**
1320: * Returns the pure text of a page, no conversions. Use this
1321: * if you are writing something that depends on the parsing
1322: * of the page. Note that you should always check for page
1323: * existence through pageExists() before attempting to fetch
1324: * the page contents.
1325: *
1326: * @param page The name of the page to fetch.
1327: * @param version If WikiPageProvider.LATEST_VERSION, then uses the
1328: * latest version.
1329: * @return The page contents. If the page does not exist,
1330: * returns an empty string.
1331: */
1332: // FIXME: Should throw an exception on unknown page/version?
1333: public String getPureText(String page, int version) {
1334: String result = null;
1335:
1336: try {
1337: result = m_pageManager.getPageText(page, version);
1338: } catch (ProviderException e) {
1339: // FIXME
1340: } finally {
1341: if (result == null)
1342: result = "";
1343: }
1344:
1345: return result;
1346: }
1347:
1348: /**
1349: * Returns the pure text of a page, no conversions. Use this
1350: * if you are writing something that depends on the parsing
1351: * the page. Note that you should always check for page
1352: * existence through pageExists() before attempting to fetch
1353: * the page contents.
1354: *
1355: * @param page A handle to the WikiPage
1356: * @return String of WikiText.
1357: * @since 2.1.13.
1358: */
1359: public String getPureText(WikiPage page) {
1360: return getPureText(page.getName(), page.getVersion());
1361: }
1362:
1363: /**
1364: * Returns the converted HTML of the page using a different
1365: * context than the default context.
1366: *
1367: * @param context A WikiContext in which you wish to render this page in.
1368: * @param page WikiPage reference.
1369: * @return HTML-rendered version of the page.
1370: */
1371:
1372: public String getHTML(WikiContext context, WikiPage page) {
1373: String pagedata = null;
1374:
1375: pagedata = getPureText(page.getName(), page.getVersion());
1376:
1377: String res = textToHTML(context, pagedata);
1378:
1379: return res;
1380: }
1381:
1382: /**
1383: * Returns the converted HTML of the page.
1384: *
1385: * @param page WikiName of the page to convert.
1386: * @return HTML-rendered version of the page.
1387: */
1388: public String getHTML(String page) {
1389: return getHTML(page, WikiPageProvider.LATEST_VERSION);
1390: }
1391:
1392: /**
1393: * Returns the converted HTML of the page's specific version.
1394: * The version must be a positive integer, otherwise the current
1395: * version is returned.
1396: *
1397: * @param pagename WikiName of the page to convert.
1398: * @param version Version number to fetch
1399: * @return HTML-rendered page text.
1400: */
1401: public String getHTML(String pagename, int version) {
1402: WikiPage page = getPage(pagename, version);
1403:
1404: WikiContext context = new WikiContext(this , page);
1405: context.setRequestContext(WikiContext.NONE);
1406:
1407: String res = getHTML(context, page);
1408:
1409: return res;
1410: }
1411:
1412: /**
1413: * Converts raw page data to HTML.
1414: *
1415: * @param pagedata Raw page data to convert to HTML
1416: * @param context The WikiContext in which the page is to be rendered
1417: * @return Rendered page text
1418: */
1419: public String textToHTML(WikiContext context, String pagedata) {
1420: String result = "";
1421:
1422: boolean runFilters = "true".equals(m_variableManager.getValue(
1423: context, PROP_RUNFILTERS, "true"));
1424:
1425: StopWatch sw = new StopWatch();
1426: sw.start();
1427: try {
1428: if (runFilters)
1429: pagedata = m_filterManager.doPreTranslateFiltering(
1430: context, pagedata);
1431:
1432: result = m_renderingManager.getHTML(context, pagedata);
1433:
1434: if (runFilters)
1435: result = m_filterManager.doPostTranslateFiltering(
1436: context, result);
1437: } catch (FilterException e) {
1438: // FIXME: Don't yet know what to do
1439: }
1440: sw.stop();
1441: if (log.isDebugEnabled())
1442: log.debug("Page " + context.getRealPage().getName()
1443: + " rendered, took " + sw);
1444:
1445: return result;
1446: }
1447:
1448: /**
1449: * Protected method that signals that the WikiEngine will be
1450: * shut down by the servlet container. It is called by
1451: * {@link WikiServlet#destroy()}. When this method is called,
1452: * it fires a "shutdown" WikiEngineEvent to all registered
1453: * listeners.
1454: */
1455: protected void shutdown() {
1456: fireEvent(WikiEngineEvent.SHUTDOWN);
1457: m_filterManager.destroy();
1458: }
1459:
1460: /**
1461: * Reads a WikiPageful of data from a String and returns all links
1462: * internal to this Wiki in a Collection.
1463: *
1464: * @param page The WikiPage to scan
1465: * @param pagedata The page contents
1466: * @return a Collection of Strings
1467: */
1468: protected Collection scanWikiLinks(WikiPage page, String pagedata) {
1469: LinkCollector localCollector = new LinkCollector();
1470:
1471: textToHTML(new WikiContext(this , page), pagedata,
1472: localCollector, null, localCollector, false, true);
1473:
1474: return localCollector.getLinks();
1475: }
1476:
1477: /**
1478: * Just convert WikiText to HTML.
1479: *
1480: * @param context The WikiContext in which to do the conversion
1481: * @param pagedata The data to render
1482: * @param localLinkHook Is called whenever a wiki link is found
1483: * @param extLinkHook Is called whenever an external link is found
1484: *
1485: * @return HTML-rendered page text.
1486: */
1487:
1488: public String textToHTML(WikiContext context, String pagedata,
1489: StringTransmutator localLinkHook,
1490: StringTransmutator extLinkHook) {
1491: return textToHTML(context, pagedata, localLinkHook,
1492: extLinkHook, null, true, false);
1493: }
1494:
1495: /**
1496: * Just convert WikiText to HTML.
1497: *
1498: * @param context The WikiContext in which to do the conversion
1499: * @param pagedata The data to render
1500: * @param localLinkHook Is called whenever a wiki link is found
1501: * @param extLinkHook Is called whenever an external link is found
1502: * @param attLinkHook Is called whenever an attachment link is found
1503: * @return HTML-rendered page text.
1504: */
1505:
1506: public String textToHTML(WikiContext context, String pagedata,
1507: StringTransmutator localLinkHook,
1508: StringTransmutator extLinkHook,
1509: StringTransmutator attLinkHook) {
1510: return textToHTML(context, pagedata, localLinkHook,
1511: extLinkHook, attLinkHook, true, false);
1512: }
1513:
1514: /**
1515: * Helper method for doing the HTML translation.
1516: *
1517: * @param context The WikiContext in which to do the conversion
1518: * @param pagedata The data to render
1519: * @param localLinkHook Is called whenever a wiki link is found
1520: * @param extLinkHook Is called whenever an external link is found
1521: * @param parseAccessRules Parse the access rules if we encounter them
1522: * @param justParse Just parses the pagedata, does not actually render. In this case,
1523: * this methods an empty string.
1524: * @return HTML-rendered page text.
1525:
1526: */
1527: private String textToHTML(WikiContext context, String pagedata,
1528: StringTransmutator localLinkHook,
1529: StringTransmutator extLinkHook,
1530: StringTransmutator attLinkHook, boolean parseAccessRules,
1531: boolean justParse) {
1532: String result = "";
1533:
1534: if (pagedata == null) {
1535: log.error("NULL pagedata to textToHTML()");
1536: return null;
1537: }
1538:
1539: boolean runFilters = "true".equals(m_variableManager.getValue(
1540: context, PROP_RUNFILTERS, "true"));
1541:
1542: try {
1543: StopWatch sw = new StopWatch();
1544: sw.start();
1545:
1546: if (runFilters)
1547: pagedata = m_filterManager.doPreTranslateFiltering(
1548: context, pagedata);
1549:
1550: MarkupParser mp = m_renderingManager.getParser(context,
1551: pagedata);
1552: mp.addLocalLinkHook(localLinkHook);
1553: mp.addExternalLinkHook(extLinkHook);
1554: mp.addAttachmentLinkHook(attLinkHook);
1555:
1556: if (!parseAccessRules)
1557: mp.disableAccessRules();
1558:
1559: WikiDocument doc = mp.parse();
1560:
1561: //
1562: // In some cases it's better just to parse, not to render
1563: //
1564: if (!justParse) {
1565: result = m_renderingManager.getHTML(context, doc);
1566:
1567: if (runFilters)
1568: result = m_filterManager.doPostTranslateFiltering(
1569: context, result);
1570: }
1571:
1572: sw.stop();
1573:
1574: if (log.isDebugEnabled())
1575: log.debug("Page " + context.getRealPage().getName()
1576: + " rendered, took " + sw);
1577: } catch (IOException e) {
1578: log.error("Failed to scan page data: ", e);
1579: } catch (FilterException e) {
1580: // FIXME: Don't yet know what to do
1581: }
1582:
1583: return result;
1584: }
1585:
1586: /**
1587: * Updates all references for the given page.
1588: *
1589: * @param page wiki page for which references should be updated
1590: */
1591: public void updateReferences(WikiPage page) {
1592: String pageData = getPureText(page.getName(),
1593: WikiProvider.LATEST_VERSION);
1594:
1595: m_referenceManager.updateReferences(page.getName(),
1596: scanWikiLinks(page, pageData));
1597: }
1598:
1599: /**
1600: * Writes the WikiText of a page into the
1601: * page repository. If the <code>jspwiki.properties</code> file contains
1602: * the property <code>jspwiki.approver.workflow.saveWikiPage</code> and
1603: * its value resolves to a valid user, {@link com.ecyrd.jspwiki.auth.authorize.Group}
1604: * or {@link com.ecyrd.jspwiki.auth.authorize.Role}, this method will
1605: * place a {@link com.ecyrd.jspwiki.workflow.Decision} in the approver's
1606: * workflow inbox and throw a {@link com.ecyrd.jspwiki.workflow.DecisionRequiredException}.
1607: * If the submitting user is authenticated and the page save is rejected,
1608: * a notification will be placed in the user's decision queue.
1609: *
1610: * @since 2.1.28
1611: * @param context The current WikiContext
1612: * @param text The Wiki markup for the page.
1613: * @throws WikiException if the save operation encounters an error during the
1614: * save operation. If the page-save operation requires approval, the exception will
1615: * be of type {@link com.ecyrd.jspwiki.workflow.DecisionRequiredException}. Individual
1616: * PageFilters, such as the {@link com.ecyrd.jspwiki.filters.SpamFilter} may also
1617: * throw a {@link com.ecyrd.jspwiki.filters.RedirectException}.
1618: */
1619: public void saveText(WikiContext context, String text)
1620: throws WikiException {
1621: // Check if page data actually changed; bail if not
1622: WikiPage page = context.getPage();
1623: String oldText = getPureText(page);
1624: String proposedText = TextUtil.normalizePostData(text);
1625: if (oldText != null && oldText.equals(proposedText)) {
1626: return;
1627: }
1628:
1629: // Create approval workflow for page save; add the diffed, proposed
1630: // and old text versions as Facts for the approver (if approval is required)
1631: // If submitter is authenticated, any reject messages will appear in his/her workflow inbox.
1632: WorkflowBuilder builder = WorkflowBuilder.getBuilder(this );
1633: Principal submitter = context.getCurrentUser();
1634: Task prepTask = new PageManager.PreSaveWikiPageTask(context,
1635: proposedText);
1636: Task completionTask = new PageManager.SaveWikiPageTask();
1637: String diffText = m_differenceManager.makeDiff(context,
1638: oldText, proposedText);
1639: boolean isAuthenticated = context.getWikiSession()
1640: .isAuthenticated();
1641: Fact[] facts = new Fact[5];
1642: facts[0] = new Fact(PageManager.FACT_PAGE_NAME, page.getName());
1643: facts[1] = new Fact(PageManager.FACT_DIFF_TEXT, diffText);
1644: facts[2] = new Fact(PageManager.FACT_PROPOSED_TEXT,
1645: proposedText);
1646: facts[3] = new Fact(PageManager.FACT_CURRENT_TEXT, oldText);
1647: facts[4] = new Fact(PageManager.FACT_IS_AUTHENTICATED, Boolean
1648: .valueOf(isAuthenticated));
1649: String rejectKey = isAuthenticated ? PageManager.SAVE_REJECT_MESSAGE_KEY
1650: : null;
1651: Workflow workflow = builder.buildApprovalWorkflow(submitter,
1652: PageManager.SAVE_APPROVER, prepTask,
1653: PageManager.SAVE_DECISION_MESSAGE_KEY, facts,
1654: completionTask, rejectKey);
1655: m_workflowMgr.start(workflow);
1656:
1657: // Let callers know if the page-save requires approval
1658: if (workflow.getCurrentStep() instanceof Decision) {
1659: throw new DecisionRequiredException(
1660: "The page contents must be approved before they become active.");
1661: }
1662: }
1663:
1664: /**
1665: * Returns the number of pages in this Wiki
1666: * @return The total number of pages.
1667: */
1668: public int getPageCount() {
1669: return m_pageManager.getTotalPageCount();
1670: }
1671:
1672: /**
1673: * Returns the provider name.
1674: * @return The full class name of the current page provider.
1675: */
1676:
1677: public String getCurrentProvider() {
1678: return m_pageManager.getProvider().getClass().getName();
1679: }
1680:
1681: /**
1682: * Return information about current provider. This method just calls
1683: * the corresponding PageManager method, which in turn calls the
1684: * provider method.
1685: *
1686: * @return A textual description of the current provider.
1687: * @since 1.6.4
1688: */
1689: public String getCurrentProviderInfo() {
1690: return m_pageManager.getProviderDescription();
1691: }
1692:
1693: /**
1694: * Returns a Collection of WikiPages, sorted in time
1695: * order of last change (i.e. first object is the most
1696: * recently changed). This method also includes attachments.
1697: *
1698: * @return Collection of WikiPage objects. In reality, the returned
1699: * collection is a Set, but due to API compatibility reasons,
1700: * we're not changing the signature soon...
1701: */
1702:
1703: // FIXME: Should really get a Date object and do proper comparisons.
1704: // This is terribly wasteful.
1705: public Collection getRecentChanges() {
1706: try {
1707: Collection pages = m_pageManager.getAllPages();
1708: Collection atts = m_attachmentManager.getAllAttachments();
1709:
1710: TreeSet sortedPages = new TreeSet(new PageTimeComparator());
1711:
1712: sortedPages.addAll(pages);
1713: sortedPages.addAll(atts);
1714:
1715: return sortedPages;
1716: } catch (ProviderException e) {
1717: log.error("Unable to fetch all pages: ", e);
1718: return null;
1719: }
1720: }
1721:
1722: /**
1723: * Parses an incoming search request, then
1724: * does a search.
1725: * <P>
1726: * The query is dependent on the actual chosen search provider - each one of them has
1727: * a language of its own.
1728: *
1729: * @param query The query string
1730: * @return A Collection of SearchResult objects.
1731: * @throws ProviderException If the searching failed
1732: * @throws IOException If the searching failed
1733: */
1734:
1735: //
1736: // FIXME: Should also have attributes attached.
1737: //
1738: public Collection findPages(String query) throws ProviderException,
1739: IOException {
1740: Collection results = m_searchManager.findPages(query);
1741:
1742: return results;
1743: }
1744:
1745: /**
1746: * Finds the corresponding WikiPage object based on the page name. It always finds
1747: * the latest version of a page.
1748: *
1749: * @param pagereq The name of the page to look for.
1750: * @return A WikiPage object, or null, if the page by the name could not be found.
1751: */
1752:
1753: public WikiPage getPage(String pagereq) {
1754: return getPage(pagereq, WikiProvider.LATEST_VERSION);
1755: }
1756:
1757: /**
1758: * Finds the corresponding WikiPage object base on the page name and version.
1759: *
1760: * @param pagereq The name of the page to look for.
1761: * @param version The version number to look for. May be WikiProvider.LATEST_VERSION,
1762: * in which case it will look for the latest version (and this method then becomes
1763: * the equivalent of getPage(String).
1764: *
1765: * @return A WikiPage object, or null, if the page could not be found; or if there
1766: * is no such version of the page.
1767: * @since 1.6.7.
1768: */
1769:
1770: public WikiPage getPage(String pagereq, int version) {
1771: try {
1772: WikiPage p = m_pageManager.getPageInfo(pagereq, version);
1773:
1774: if (p == null) {
1775: p = m_attachmentManager.getAttachmentInfo(
1776: (WikiContext) null, pagereq);
1777: }
1778:
1779: return p;
1780: } catch (ProviderException e) {
1781: log.error("Unable to fetch page info", e);
1782: return null;
1783: }
1784: }
1785:
1786: /**
1787: * Returns a Collection of WikiPages containing the
1788: * version history of a page.
1789: *
1790: * @param page Name of the page to look for
1791: * @return an ordered List of WikiPages, each corresponding to a different
1792: * revision of the page.
1793: */
1794:
1795: public List getVersionHistory(String page) {
1796: List c = null;
1797:
1798: try {
1799: c = m_pageManager.getVersionHistory(page);
1800:
1801: if (c == null) {
1802: c = m_attachmentManager.getVersionHistory(page);
1803: }
1804: } catch (ProviderException e) {
1805: log.error("FIXME");
1806: }
1807:
1808: return c;
1809: }
1810:
1811: /**
1812: * Returns a diff of two versions of a page.
1813: * <p>
1814: * Note that the API was changed in 2.6 to provide a WikiContext object!
1815: *
1816: * @param context The WikiContext of the page you wish to get a diff from
1817: * @param version1 Version number of the old page. If
1818: * WikiPageProvider.LATEST_VERSION (-1), then uses current page.
1819: * @param version2 Version number of the new page. If
1820: * WikiPageProvider.LATEST_VERSION (-1), then uses current page.
1821: *
1822: * @return A HTML-ized difference between two pages. If there is no difference,
1823: * returns an empty string.
1824: */
1825: public String getDiff(WikiContext context, int version1,
1826: int version2) {
1827: String page = context.getPage().getName();
1828: String page1 = getPureText(page, version1);
1829: String page2 = getPureText(page, version2);
1830:
1831: // Kludge to make diffs for new pages to work this way.
1832:
1833: if (version1 == WikiPageProvider.LATEST_VERSION) {
1834: page1 = "";
1835: }
1836:
1837: String diff = m_differenceManager.makeDiff(context, page1,
1838: page2);
1839:
1840: return diff;
1841: }
1842:
1843: /**
1844: * Returns this object's ReferenceManager.
1845: * @return The current ReferenceManager instance.
1846: *
1847: * @since 1.6.1
1848: */
1849: public ReferenceManager getReferenceManager() {
1850: return m_referenceManager;
1851: }
1852:
1853: /**
1854: * Returns the current rendering manager for this wiki application.
1855: *
1856: * @since 2.3.27
1857: * @return A RenderingManager object.
1858: */
1859: public RenderingManager getRenderingManager() {
1860: return m_renderingManager;
1861: }
1862:
1863: /**
1864: * Returns the current plugin manager.
1865: * @since 1.6.1
1866: * @return The current PluginManager instance
1867: */
1868:
1869: public PluginManager getPluginManager() {
1870: return m_pluginManager;
1871: }
1872:
1873: /**
1874: * Returns the current variable manager.
1875: * @return The current VariableManager.
1876: */
1877:
1878: public VariableManager getVariableManager() {
1879: return m_variableManager;
1880: }
1881:
1882: /**
1883: * Shortcut to getVariableManager().getValue(). However, this method does not
1884: * throw a NoSuchVariableException, but returns null in case the variable does
1885: * not exist.
1886: *
1887: * @param context WikiContext to look the variable in
1888: * @param name Name of the variable to look for
1889: * @return Variable value, or null, if there is no such variable.
1890: * @since 2.2
1891: */
1892: public String getVariable(WikiContext context, String name) {
1893: try {
1894: return m_variableManager.getValue(context, name);
1895: } catch (NoSuchVariableException e) {
1896: return null;
1897: }
1898: }
1899:
1900: /**
1901: * Returns the current PageManager which is responsible for storing
1902: * and managing WikiPages.
1903: *
1904: * @return The current PageManager instance.
1905: */
1906: public PageManager getPageManager() {
1907: return m_pageManager;
1908: }
1909:
1910: /**
1911: * Returns the CommandResolver for this wiki engine.
1912: * @return the resolver
1913: */
1914: public CommandResolver getCommandResolver() {
1915: return m_commandResolver;
1916: }
1917:
1918: /**
1919: * Returns the current AttachmentManager, which is responsible for
1920: * storing and managing attachments.
1921: *
1922: * @since 1.9.31.
1923: * @return The current AttachmentManager instance
1924: */
1925: public AttachmentManager getAttachmentManager() {
1926: return m_attachmentManager;
1927: }
1928:
1929: /**
1930: * Returns the currently used authorization manager.
1931: *
1932: * @return The current AuthorizationManager instance
1933: */
1934: public AuthorizationManager getAuthorizationManager() {
1935: return m_authorizationManager;
1936: }
1937:
1938: /**
1939: * Returns the currently used authentication manager.
1940: *
1941: * @return The current AuthenticationManager instance.
1942: */
1943: public AuthenticationManager getAuthenticationManager() {
1944: return m_authenticationManager;
1945: }
1946:
1947: /**
1948: * Returns the manager responsible for the filters.
1949: * @since 2.1.88
1950: * @return The current FilterManager instance
1951: */
1952: public FilterManager getFilterManager() {
1953: return m_filterManager;
1954: }
1955:
1956: /**
1957: * Returns the manager responsible for searching the Wiki.
1958: * @since 2.2.21
1959: * @return The current SearchManager instance
1960: */
1961: public SearchManager getSearchManager() {
1962: return m_searchManager;
1963: }
1964:
1965: /**
1966: * Returns the progress manager we're using
1967: * @return A ProgressManager
1968: * @since 2.6
1969: */
1970: public ProgressManager getProgressManager() {
1971: return m_progressManager;
1972: }
1973:
1974: /**
1975: * Figure out to which page we are really going to. Considers
1976: * special page names from the jspwiki.properties, and possible aliases.
1977: * This method delgates requests to
1978: * {@link com.ecyrd.jspwiki.WikiContext#getRedirectURL()}.
1979: * @param context The Wiki Context in which the request is being made.
1980: * @return A complete URL to the new page to redirect to
1981: * @since 2.2
1982: */
1983:
1984: public String getRedirectURL(WikiContext context) {
1985: return context.getRedirectURL();
1986: }
1987:
1988: /**
1989: * Shortcut to create a WikiContext from a supplied HTTP request,
1990: * using a default wiki context.
1991: * @param request the HTTP request
1992: * @param requestContext the default context to use
1993: * @return a new WikiContext object.
1994: *
1995: * @see com.ecyrd.jspwiki.ui.CommandResolver
1996: * @see com.ecyrd.jspwiki.ui.Command
1997: * @since 2.1.15.
1998: */
1999: // FIXME: We need to have a version which takes a fixed page
2000: // name as well, or check it elsewhere.
2001: public WikiContext createContext(HttpServletRequest request,
2002: String requestContext) {
2003: if (!m_isConfigured) {
2004: throw new InternalWikiException(
2005: "WikiEngine has not been properly started. It is likely that the configuration is faulty. Please check all logs for the possible reason.");
2006: }
2007:
2008: // Build the wiki context
2009: Command command = m_commandResolver.findCommand(request,
2010: requestContext);
2011: return new WikiContext(this , request, command);
2012: }
2013:
2014: /**
2015: * Deletes a page or an attachment completely, including all versions. If the page
2016: * does not exist, does nothing.
2017: *
2018: * @param pageName The name of the page.
2019: * @throws ProviderException If something goes wrong.
2020: */
2021: public void deletePage(String pageName) throws ProviderException {
2022: WikiPage p = getPage(pageName);
2023:
2024: if (p != null) {
2025: if (p instanceof Attachment) {
2026: m_attachmentManager.deleteAttachment((Attachment) p);
2027: } else {
2028: if (m_attachmentManager.hasAttachments(p)) {
2029: Collection attachments = m_attachmentManager
2030: .listAttachments(p);
2031: for (Iterator atti = attachments.iterator(); atti
2032: .hasNext();) {
2033: m_attachmentManager
2034: .deleteAttachment((Attachment) (atti
2035: .next()));
2036: }
2037: }
2038: m_pageManager.deletePage(p);
2039: }
2040: }
2041: }
2042:
2043: /**
2044: * Deletes a specific version of a page or an attachment.
2045: *
2046: * @param page The page object.
2047: * @throws ProviderException If something goes wrong.
2048: */
2049: public void deleteVersion(WikiPage page) throws ProviderException {
2050: if (page instanceof Attachment) {
2051: m_attachmentManager.deleteVersion((Attachment) page);
2052: } else {
2053: m_pageManager.deleteVersion(page);
2054: }
2055: }
2056:
2057: /**
2058: * Returns the URL of the global RSS file. May be null, if the
2059: * RSS file generation is not operational.
2060: * @since 1.7.10
2061: * @return The global RSS url
2062: */
2063: public String getGlobalRSSURL() {
2064: if (m_rssGenerator != null && m_rssGenerator.isEnabled()) {
2065: return getBaseURL() + m_rssFile;
2066: }
2067:
2068: return null;
2069: }
2070:
2071: /**
2072: * Returns the root path. The root path is where the WikiEngine is
2073: * located in the file system.
2074: *
2075: * @since 2.2
2076: * @return A path to where the Wiki is installed in the local filesystem.
2077: */
2078: public String getRootPath() {
2079: return m_rootPath;
2080: }
2081:
2082: /**
2083: * @since 2.2.6
2084: * @return the URL constructor
2085: */
2086: public URLConstructor getURLConstructor() {
2087: return m_urlConstructor;
2088: }
2089:
2090: /**
2091: * @since 2.1.165
2092: * @return the RSS generator
2093: */
2094: public RSSGenerator getRSSGenerator() {
2095: return m_rssGenerator;
2096: }
2097:
2098: /**
2099: * Renames, or moves, a wiki page. Can also alter referring wiki
2100: * links to point to the renamed page.
2101: *
2102: * @param context The context during which this rename takes
2103: * place.
2104: * @param renameFrom Name of the source page.
2105: * @param renameTo Name of the destination page.
2106: * @param changeReferrers If true, then changes any referring links
2107: * to point to the renamed page.
2108: *
2109: * @return The name of the page that the source was renamed to.
2110: *
2111: * @throws WikiException In the case of an error, such as the destination
2112: * page already existing.
2113: */
2114: public String renamePage(WikiContext context, String renameFrom,
2115: String renameTo, boolean changeReferrers)
2116: throws WikiException {
2117: return m_pageRenamer.renamePage(context, renameFrom, renameTo,
2118: changeReferrers);
2119: }
2120:
2121: /**
2122: * Returns the PageRenamer employed by this WikiEngine.
2123: * @since 2.5.141
2124: * @return The current PageRenamer instance.
2125: */
2126: public PageRenamer getPageRenamer() {
2127: return m_pageRenamer;
2128: }
2129:
2130: /**
2131: * Returns the UserManager employed by this WikiEngine.
2132: * @since 2.3
2133: * @return The current UserManager instance.
2134: */
2135: public UserManager getUserManager() {
2136: return m_userManager;
2137: }
2138:
2139: /**
2140: * Returns the GroupManager employed by this WikiEngine.
2141: * @since 2.3
2142: * @return The current GroupManager instance
2143: */
2144: public GroupManager getGroupManager() {
2145: return m_groupManager;
2146: }
2147:
2148: /**
2149: * Returns the current AdminBeanManager.
2150: *
2151: * @return The current AdminBeanManager
2152: * @since 2.6
2153: */
2154: public AdminBeanManager getAdminBeanManager() {
2155: return m_adminBeanManager;
2156: }
2157:
2158: /**
2159: * Returns the AclManager employed by this WikiEngine.
2160: * The AclManager is lazily initialized.
2161: * <p>
2162: * The AclManager implementing class may be set by the
2163: * System property {@link #PROP_ACL_MANAGER_IMPL}.
2164: * </p>
2165: *
2166: * @since 2.3
2167: * @return The current AclManager.
2168: */
2169: public AclManager getAclManager() {
2170: if (m_aclManager == null) {
2171: try {
2172: String s = m_properties.getProperty(
2173: PROP_ACL_MANAGER_IMPL, DefaultAclManager.class
2174: .getName());
2175: m_aclManager = (AclManager) ClassUtil
2176: .getMappedObject(s); // TODO: I am not sure whether this is the right call
2177: m_aclManager.initialize(this , m_properties);
2178: } catch (WikiException we) {
2179: log
2180: .fatal("unable to instantiate class for AclManager: "
2181: + we.getMessage());
2182: throw new InternalWikiException(
2183: "Cannot instantiate AclManager, please check logs.");
2184: }
2185: }
2186: return m_aclManager;
2187: }
2188:
2189: /**
2190: * Returns the DifferenceManager so that texts can be compared.
2191: * @return the difference manager
2192: */
2193: public DifferenceManager getDifferenceManager() {
2194: return m_differenceManager;
2195: }
2196:
2197: /**
2198: * Returns the current EditorManager instance.
2199: *
2200: * @return The current EditorManager.
2201: */
2202: public EditorManager getEditorManager() {
2203: return m_editorManager;
2204: }
2205:
2206: /**
2207: * Returns the current i18n manager.
2208: *
2209: * @return The current Intertan... Interante... Internatatializ... Whatever.
2210: */
2211: public InternationalizationManager getInternationalizationManager() {
2212: return m_internationalizationManager;
2213: }
2214:
2215: /**
2216: * Registers a WikiEventListener with this instance.
2217: * @param listener the event listener
2218: */
2219: public final synchronized void addWikiEventListener(
2220: WikiEventListener listener) {
2221: WikiEventManager.addWikiEventListener(this , listener);
2222: }
2223:
2224: /**
2225: * Un-registers a WikiEventListener with this instance.
2226: * @param listener the event listener
2227: */
2228: public final synchronized void removeWikiEventListener(
2229: WikiEventListener listener) {
2230: WikiEventManager.removeWikiEventListener(this , listener);
2231: }
2232:
2233: /**
2234: * Fires a WikiEngineEvent to all registered listeners.
2235: * @param type the event type
2236: */
2237: protected final void fireEvent(int type) {
2238: if (WikiEventManager.isListening(this )) {
2239: WikiEventManager.fireEvent(this , new WikiEngineEvent(this ,
2240: type));
2241: }
2242: }
2243:
2244: private Map m_attributes = Collections
2245: .synchronizedMap(new HashMap());
2246:
2247: /**
2248: * Adds an attribute to the engine for the duration of this engine. The
2249: * value is not persisted.
2250: *
2251: * @since 2.4.91
2252: * @param key the attribute name
2253: * @param value the value
2254: */
2255: public void setAttribute(String key, Object value) {
2256: m_attributes.put(key, value);
2257: }
2258:
2259: /**
2260: * Gets an attribute from the engine.
2261: *
2262: * @param key the attribute name
2263: * @return the value
2264: */
2265: public Object getAttribute(String key) {
2266: return m_attributes.get(key);
2267: }
2268:
2269: /**
2270: * Removes an attribute.
2271: *
2272: * @param key The key of the attribute to remove.
2273: * @return The previous attribute, if it existed.
2274: */
2275: public Object removeAttribute(String key) {
2276: return m_attributes.remove(key);
2277: }
2278:
2279: /**
2280: * Returns a WatchDog for current thread.
2281: *
2282: * @return The current thread WatchDog.
2283: * @since 2.4.92
2284: */
2285: public WatchDog getCurrentWatchDog() {
2286: return WatchDog.getCurrentWatchDog(this);
2287: }
2288: }
|