/*
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.  
 */

package org.apache.wiki.plugin;

import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.MatchResult;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternCompiler;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.apache.wiki.InternalWikiException;
import org.apache.wiki.WikiContext;
import org.apache.wiki.WikiEngine;
import org.apache.wiki.ajax.WikiAjaxDispatcherServlet;
import org.apache.wiki.ajax.WikiAjaxServlet;
import org.apache.wiki.api.engine.PluginManager;
import org.apache.wiki.api.exceptions.PluginException;
import org.apache.wiki.api.plugin.InitializablePlugin;
import org.apache.wiki.api.plugin.WikiPlugin;
import org.apache.wiki.modules.ModuleManager;
import org.apache.wiki.modules.WikiModuleInfo;
import org.apache.wiki.preferences.Preferences;
import org.apache.wiki.util.ClassUtil;
import org.apache.wiki.util.FileUtil;
import org.apache.wiki.util.TextUtil;
import org.apache.wiki.util.XHTML;
import org.apache.wiki.util.XhtmlUtil;
import org.apache.wiki.util.XmlUtil;
import org.jdom2.Element;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

import javax.servlet.http.HttpServlet;

/**
 *  Manages plugin classes.  There exists a single instance of PluginManager
 *  per each instance of WikiEngine, that is, each JSPWiki instance.
 *  <P>
 *  A plugin is defined to have three parts:
 *  <OL>
 *    <li>The plugin class
 *    <li>The plugin parameters
 *    <li>The plugin body
 *  </ol>
 *
 *  For example, in the following line of code:
 *  <pre>
 *  [{INSERT org.apache.wiki.plugin.FunnyPlugin  foo='bar'
 *  blob='goo'
 *
 *  abcdefghijklmnopqrstuvw
 *  01234567890}]
 *  </pre>
 *
 *  The plugin class is "org.apache.wiki.plugin.FunnyPlugin", the
 *  parameters are "foo" and "blob" (having values "bar" and "goo",
 *  respectively), and the plugin body is then
 *  "abcdefghijklmnopqrstuvw\n01234567890".   The plugin body is
 *  accessible via a special parameter called "_body".
 *  <p>
 *  If the parameter "debug" is set to "true" for the plugin,
 *  JSPWiki will output debugging information directly to the page if there
 *  is an exception.
 *  <P>
 *  The class name can be shortened, and marked without the package.
 *  For example, "FunnyPlugin" would be expanded to
 *  "org.apache.wiki.plugin.FunnyPlugin" automatically.  It is also
 *  possible to define other packages, by setting the
 *  "jspwiki.plugin.searchPath" property.  See the included
 *  jspwiki.properties file for examples.
 *  <P>
 *  Even though the nominal way of writing the plugin is
 *  <pre>
 *  [{INSERT pluginclass WHERE param1=value1...}],
 *  </pre>
 *  it is possible to shorten this quite a lot, by skipping the
 *  INSERT, and WHERE words, and dropping the package name.  For
 *  example:
 *
 *  <pre>
 *  [{INSERT org.apache.wiki.plugin.Counter WHERE name='foo'}]
 *  </pre>
 *
 *  is the same as
 *  <pre>
 *  [{Counter name='foo'}]
 *  </pre>
 *  <h3>Plugin property files</h3>
 *  <p>
 *  Since 2.3.25 you can also define a generic plugin XML properties file per
 *  each JAR file.
 *  <pre>
 *  <modules>
 *   <plugin class="org.apache.wiki.foo.TestPlugin">
 *       <author>Janne Jalkanen</author>
 *       <script>foo.js</script>
 *       <stylesheet>foo.css</stylesheet>
 *       <alias>code</alias>
 *   </plugin>
 *   <plugin class="org.apache.wiki.foo.TestPlugin2">
 *       <author>Janne Jalkanen</author>
 *   </plugin>
 *   </modules>
 *  </pre>
 *  <h3>Plugin lifecycle</h3>
 *
 *  <p>Plugin can implement multiple interfaces to let JSPWiki know at which stages they should
 *  be invoked:
 *  <ul>
 *  <li>InitializablePlugin: If your plugin implements this interface, the initialize()-method is
 *      called once for this class
 *      before any actual execute() methods are called.  You should use the initialize() for e.g.
 *      precalculating things.  But notice that this method is really called only once during the
 *      entire WikiEngine lifetime.  The InitializablePlugin is available from 2.5.30 onwards.</li>
 *  <li>ParserStagePlugin: If you implement this interface, the executeParse() method is called
 *      when JSPWiki is forming the DOM tree.  You will receive an incomplete DOM tree, as well
 *      as the regular parameters.  However, since JSPWiki caches the DOM tree to speed up later
 *      places, which means that whatever this method returns would be irrelevant.  You can do some DOM
 *      tree manipulation, though.  The ParserStagePlugin is available from 2.5.30 onwards.</li>
 *  <li>WikiPlugin: The regular kind of plugin which is executed at every rendering stage.  Each
 *      new page load is guaranteed to invoke the plugin, unlike with the ParserStagePlugins.</li>
 *  </ul>
 *
 *  @since 1.6.1
 */
public class DefaultPluginManager extends ModuleManager implements PluginManager {
	
    private static final String PLUGIN_INSERT_PATTERN = "\\{?(INSERT)?\\s*([\\w\\._]+)[ \\t]*(WHERE)?[ \\t]*";

    private static Logger log = Logger.getLogger( DefaultPluginManager.class );

    private static final String DEFAULT_FORMS_PACKAGE = "org.apache.wiki.forms";

    private ArrayList<String> m_searchPath = new ArrayList<String>();

    private ArrayList<String> m_externalJars = new ArrayList<String>();

    private Pattern m_pluginPattern;

    private boolean m_pluginsEnabled = true;

    /**
     *  Keeps a list of all known plugin classes.
     */
    private Map<String, WikiPluginInfo> m_pluginClassMap = new HashMap<String, WikiPluginInfo>();

    /**
     *  Create a new PluginManager.
     *
     *  @param engine WikiEngine which owns this manager.
     *  @param props Contents of a "jspwiki.properties" file.
     */
    public DefaultPluginManager( WikiEngine engine, Properties props ) {
        super( engine );
        String packageNames = props.getProperty( PROP_SEARCHPATH );

        if ( packageNames != null ) {
            StringTokenizer tok = new StringTokenizer( packageNames, "," );

            while( tok.hasMoreTokens() ) {
                m_searchPath.add( tok.nextToken().trim() );
            }
        }

        String externalJars = props.getProperty( PROP_EXTERNALJARS );

        if( externalJars != null ) {
            StringTokenizer tok = new StringTokenizer( externalJars, "," );

            while( tok.hasMoreTokens() ) {
                m_externalJars.add( tok.nextToken().trim() );
            }
        }

        registerPlugins();

        //
        //  The default packages are always added.
        //
        m_searchPath.add( DEFAULT_PACKAGE );
        m_searchPath.add( DEFAULT_FORMS_PACKAGE );

        PatternCompiler compiler = new Perl5Compiler();

        try {
            m_pluginPattern = compiler.compile( PLUGIN_INSERT_PATTERN );
        } catch( MalformedPatternException e ) {
            log.fatal( "Internal error: someone messed with pluginmanager patterns.", e );
            throw new InternalWikiException( "PluginManager patterns are broken" , e);
        }

    }

    /**
     * {@inheritDoc}
     */
    public void enablePlugins( boolean enabled ) {
        m_pluginsEnabled = enabled;
    }

    /**
     * {@inheritDoc}
     */
    public boolean pluginsEnabled() {
        return m_pluginsEnabled;
    }

    /**
     * {@inheritDoc}
     */
    public Pattern getPluginPattern() {
		return m_pluginPattern;
	}
    
    /**
     * {@inheritDoc}
     */
    public String getPluginSearchPath() {
    	return TextUtil.getStringProperty( m_engine.getWikiProperties(), PROP_SEARCHPATH, null );
    }

	/**
     *  Attempts to locate a plugin class from the class path set in the property file.
     *
     *  @param classname Either a fully fledged class name, or just the name of the file (that is,
     *  "org.apache.wiki.plugin.Counter" or just plain "Counter").
     *
     *  @return A found class.
     *
     *  @throws ClassNotFoundException if no such class exists.
     */
    private Class< ? > findPluginClass( String classname ) throws ClassNotFoundException {
        return ClassUtil.findClass( m_searchPath, m_externalJars, classname );
    }

    /**
     *  Outputs a HTML-formatted version of a stack trace.
     */
    private String stackTrace( Map<String,String> params, Throwable t )
    {
        Element div = XhtmlUtil.element(XHTML.div,"Plugin execution failed, stack trace follows:");
        div.setAttribute(XHTML.ATTR_class,"debug");
        

        StringWriter out = new StringWriter();
        t.printStackTrace(new PrintWriter(out));
        div.addContent(XhtmlUtil.element(XHTML.pre,out.toString()));        
        div.addContent(XhtmlUtil.element(XHTML.b,"Parameters to the plugin"));

        Element list = XhtmlUtil.element(XHTML.ul);
        
        for( Iterator<Map.Entry<String,String>> i = params.entrySet().iterator(); i.hasNext(); ) {
            Map.Entry<String,String> e = i.next();
            String key = e.getKey();
            list.addContent(XhtmlUtil.element(XHTML.li,key + "'='" + e.getValue()));
        }

        div.addContent(list);
        
        return XhtmlUtil.serialize(div);
    }

    /**
     *  Executes a plugin class in the given context.
     *  <P>Used to be private, but is public since 1.9.21.
     *
     *  @param context The current WikiContext.
     *  @param classname The name of the class.  Can also be a
     *  shortened version without the package name, since the class name is searched from the
     *  package search path.
     *
     *  @param params A parsed map of key-value pairs.
     *
     *  @return Whatever the plugin returns.
     *
     *  @throws PluginException If the plugin execution failed for
     *  some reason.
     *
     *  @since 2.0
     */
    public String execute( WikiContext context, String classname, Map< String, String > params ) throws PluginException {
        if( !m_pluginsEnabled ) {
            return "";
        }

        ResourceBundle rb = Preferences.getBundle( context, WikiPlugin.CORE_PLUGINS_RESOURCEBUNDLE );
        boolean debug = TextUtil.isPositive( params.get( PARAM_DEBUG ) );
        try {
            //
            //   Create...
            //
            WikiPlugin plugin = newWikiPlugin( classname, rb );
            if( plugin == null ) {
                return "Plugin '" + classname + "' not compatible with this version of JSPWiki";
            }

            //
            //  ...and launch.
            //
            try {
                return plugin.execute( context, params );
            } catch( PluginException e ) {
                if( debug ) {
                    return stackTrace( params, e );
                }

                // Just pass this exception onward.
                throw ( PluginException )e.fillInStackTrace();
            } catch( Throwable t ) {
                // But all others get captured here.
                log.info( "Plugin failed while executing:", t );
                if( debug ) {
                    return stackTrace( params, t );
                }

                throw new PluginException( rb.getString( "plugin.error.failed" ), t );
            }

        } catch( ClassCastException e ) {
            throw new PluginException( MessageFormat.format( rb.getString( "plugin.error.notawikiplugin" ), classname ), e );
        }
    }

    /**
     *  Parses plugin arguments.  Handles quotes and all other kewl stuff.
     *
     *  <h3>Special parameters</h3>
     *  The plugin body is put into a special parameter defined by {@link #PARAM_BODY};
     *  the plugin's command line into a parameter defined by {@link #PARAM_CMDLINE};
     *  and the bounds of the plugin within the wiki page text by a parameter defined
     *  by {@link #PARAM_BOUNDS}, whose value is stored as a two-element int[] array,
     *  i.e., <tt>[start,end]</tt>.
     *
     * @param argstring The argument string to the plugin.  This is
     *  typically a list of key-value pairs, using "'" to escape
     *  spaces in strings, followed by an empty line and then the
     *  plugin body.  In case the parameter is null, will return an
     *  empty parameter list.
     *
     * @return A parsed list of parameters.
     *
     * @throws IOException If the parsing fails.
     */
    public Map< String, String > parseArgs( String argstring ) throws IOException {
        Map< String, String > arglist = new HashMap< String, String >();

        //
        //  Protection against funny users.
        //
        if( argstring == null ) return arglist;

        arglist.put( PARAM_CMDLINE, argstring );

        StringReader    in      = new StringReader(argstring);
        StreamTokenizer tok     = new StreamTokenizer(in);
        int             type;


        String param = null;
        String value = null;

        tok.eolIsSignificant( true );

        boolean potentialEmptyLine = false;
        boolean quit               = false;

        while( !quit ) {
            String s;
            type = tok.nextToken();

            switch( type ) {
              case StreamTokenizer.TT_EOF:
                quit = true;
                s = null;
                break;

              case StreamTokenizer.TT_WORD:
                s = tok.sval;
                potentialEmptyLine = false;
                break;

              case StreamTokenizer.TT_EOL:
                quit = potentialEmptyLine;
                potentialEmptyLine = true;
                s = null;
                break;

              case StreamTokenizer.TT_NUMBER:
                s = Integer.toString( (int) tok.nval );
                potentialEmptyLine = false;
                break;

              case '\'':
                s = tok.sval;
                break;

              default:
                s = null;
            }

            //
            //  Assume that alternate words on the line are
            //  parameter and value, respectively.
            //
            if( s != null ) {
                if( param == null ) {
                    param = s;
                } else {
                    value = s;

                    arglist.put( param, value );

                    // log.debug("ARG: "+param+"="+value);
                    param = null;
                }
            }
        }

        //
        //  Now, we'll check the body.
        //
        if( potentialEmptyLine ) {
            StringWriter out = new StringWriter();
            FileUtil.copyContents( in, out );

            String bodyContent = out.toString();

            if( bodyContent != null ) {
                arglist.put( PARAM_BODY, bodyContent );
            }
        }

        return arglist;
    }

    /**
     *  Parses a plugin.  Plugin commands are of the form:
     *  [{INSERT myplugin WHERE param1=value1, param2=value2}]
     *  myplugin may either be a class name or a plugin alias.
     *  <P>
     *  This is the main entry point that is used.
     *
     *  @param context The current WikiContext.
     *  @param commandline The full command line, including plugin name, parameters and body.
     *
     *  @return HTML as returned by the plugin, or possibly an error message.
     *  
     *  @throws PluginException From the plugin itself, it propagates, waah!
     */
    public String execute( WikiContext context, String commandline ) throws PluginException {
        if( !m_pluginsEnabled ) {
            return "";
        }

        ResourceBundle rb = Preferences.getBundle( context, WikiPlugin.CORE_PLUGINS_RESOURCEBUNDLE );
        PatternMatcher matcher = new Perl5Matcher();

        try {
            if( matcher.contains( commandline, m_pluginPattern ) ) {
                MatchResult res = matcher.getMatch();

                String plugin   = res.group(2);
                String args     = commandline.substring(res.endOffset(0),
                                                        commandline.length() -
                                                        (commandline.charAt(commandline.length()-1) == '}' ? 1 : 0 ) );
                Map<String, String> arglist  = parseArgs( args );

                return execute( context, plugin, arglist );
            }
        } catch( NoSuchElementException e ) {
            String msg =  "Missing parameter in plugin definition: "+commandline;
            log.warn( msg, e );
            throw new PluginException( MessageFormat.format( rb.getString( "plugin.error.missingparameter" ), commandline ) );
        } catch( IOException e ) {
            String msg = "Zyrf.  Problems with parsing arguments: "+commandline;
            log.warn( msg, e );
            throw new PluginException( MessageFormat.format( rb.getString( "plugin.error.parsingarguments" ), commandline ) );
        }

        // FIXME: We could either return an empty string "", or
        // the original line.  If we want unsuccessful requests
        // to be invisible, then we should return an empty string.
        return commandline;
    }

    /**
     *  Register a plugin.
     */
    private void registerPlugin( WikiPluginInfo pluginClass ) {
        String name;

        // Registrar the plugin with the className without the package-part
        name = pluginClass.getName();
        if( name != null ) {
            log.debug( "Registering plugin [name]: " + name );
            m_pluginClassMap.put( name, pluginClass );
        }

        // Registrar the plugin with a short convenient name.
        name = pluginClass.getAlias();
        if( name != null ) {
            log.debug( "Registering plugin [shortName]: " + name );
            m_pluginClassMap.put( name, pluginClass );
        }

        // Registrar the plugin with the className with the package-part
        name = pluginClass.getClassName();
        if( name != null ) {
            log.debug( "Registering plugin [className]: " + name );
            m_pluginClassMap.put( name, pluginClass );
        }

        pluginClass.initializePlugin( pluginClass, m_engine , m_searchPath, m_externalJars);
    }

    private void registerPlugins() {
        log.info( "Registering plugins" );
        List< Element > plugins = XmlUtil.parse( PLUGIN_RESOURCE_LOCATION, "/modules/plugin" );

        //
        // Register all plugins which have created a resource containing its properties.
        //
        // Get all resources of all plugins.
        //
        for( Element pluginEl : plugins ) {
            String className = pluginEl.getAttributeValue( "class" );
            WikiPluginInfo pluginInfo = WikiPluginInfo.newInstance( className, pluginEl ,m_searchPath, m_externalJars);

            if( pluginInfo != null ) {
                registerPlugin( pluginInfo );
            }
        }
    }

    /**
     *  Contains information about a bunch of plugins.
     *
     *
     */
    // FIXME: This class needs a better interface to return all sorts of possible
    //        information from the plugin XML.  In fact, it probably should have
    //        some sort of a superclass system.
    public static final class WikiPluginInfo extends WikiModuleInfo {
    	
        private String    m_className;
        private String    m_alias;
        private String    m_ajaxAlias;
        private Class<?>  m_clazz;

        private boolean m_initialized = false;

        /**
         *  Creates a new plugin info object which can be used to access a plugin.
         *
         *  @param className Either a fully qualified class name, or a "short" name which is then
         *                   checked against the internal list of plugin packages.
         *  @param el A JDOM Element containing the information about this class.
         *  @param searchPath A List of Strings, containing different package names.
         *  @param externalJars the list of external jars to search
         *  @return A WikiPluginInfo object.
         */
        protected static WikiPluginInfo newInstance( String className, Element el, List<String> searchPath, List<String> externalJars ) {
            if( className == null || className.length() == 0 ) return null;

            WikiPluginInfo info = new WikiPluginInfo( className );
            info.initializeFromXML( el );
            return info;
        }
        
        /**
         *  Initializes a plugin, if it has not yet been initialized.
         *  If the plugin extends {@link HttpServlet} it will automatically 
         *  register it as AJAX using {@link WikiAjaxDispatcherServlet.register}.
         *
         *  @param engine The WikiEngine
         *  @param searchPath A List of Strings, containing different package names.
         *  @param externalJars the list of external jars to search
         */
        protected void initializePlugin( WikiPluginInfo info, WikiEngine engine , List<String> searchPath, List<String> externalJars) {
            if( !m_initialized ) {
                // This makes sure we only try once per class, even if init fails.
                m_initialized = true;

                try {
                    WikiPlugin p = newPluginInstance(searchPath, externalJars);
                    if( p instanceof InitializablePlugin ) {
                        ( ( InitializablePlugin )p ).initialize( engine );
                    }
                    if( p instanceof WikiAjaxServlet ) {
                    	WikiAjaxDispatcherServlet.registerServlet( (WikiAjaxServlet) p );
                    	String ajaxAlias = info.getAjaxAlias();
                    	if (StringUtils.isNotBlank(ajaxAlias)) {
                    		WikiAjaxDispatcherServlet.registerServlet( info.getAjaxAlias(), (WikiAjaxServlet) p );
                    	}
                    }
                } catch( Exception e ) {
                    log.info( "Cannot initialize plugin " + m_className, e );
                }
            }
        }

        /**
         *  {@inheritDoc}
         */
        @Override
        protected void initializeFromXML( Element el ) {
            super.initializeFromXML( el );
            m_alias = el.getChildText( "alias" );
            m_ajaxAlias = el.getChildText( "ajaxAlias" );
        }

        /**
         *  Create a new WikiPluginInfo based on the Class information.
         *  
         *  @param clazz The class to check
         *  @return A WikiPluginInfo instance
         */
        protected static WikiPluginInfo newInstance( Class< ? > clazz ) {
        	return new WikiPluginInfo( clazz.getName() );
        }

        private WikiPluginInfo( String className ) {
            super( className );
            setClassName( className );
        }

        private void setClassName( String fullClassName ) {
            m_name = ClassUtils.getShortClassName( fullClassName );
            m_className = fullClassName;
        }

        /**
         *  Returns the full class name of this object.
         *  @return The full class name of the object.
         */
        public String getClassName() {
            return m_className;
        }

        /**
         *  Returns the alias name for this object.
         *  @return An alias name for the plugin.
         */
        public String getAlias() {
            return m_alias;
        }
        
        /**
         *  Returns the ajax alias name for this object.
         *  @return An ajax alias name for the plugin.
         */
        public String getAjaxAlias() {
            return m_ajaxAlias;
        }

        /**
         *  Creates a new plugin instance.
         *
         *  @param searchPath A List of Strings, containing different package names.
         *  @param externalJars the list of external jars to search

         *  @return A new plugin.
         *  @throws ClassNotFoundException If the class declared was not found.
         *  @throws InstantiationException If the class cannot be instantiated-
         *  @throws IllegalAccessException If the class cannot be accessed.
         */
        
        public WikiPlugin newPluginInstance(List<String> searchPath, List<String> externalJars) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
            if( m_clazz == null ) {
                m_clazz = ClassUtil.findClass(searchPath, externalJars ,m_className);
            }

            return (WikiPlugin) m_clazz.newInstance();
        }

        /**
         *  Returns a text for IncludeResources.
         *
         *  @param type Either "script" or "stylesheet"
         *  @return Text, or an empty string, if there is nothing to be included.
         */
        public String getIncludeText( String type ) {
            try {
                if( "script".equals( type ) ) {
                    return getScriptText();
                } else if( "stylesheet".equals( type ) ) {
                    return getStylesheetText();
                }
            } catch( Exception ex ) {
                // We want to fail gracefully here
                return ex.getMessage();
            }

            return null;
        }

        private String getScriptText() throws IOException {
            if( m_scriptText != null ) {
                return m_scriptText;
            }

            if( m_scriptLocation == null ) {
                return "";
            }

            try {
                m_scriptText = getTextResource(m_scriptLocation);
            } catch( IOException ex ) {
                // Only throw this exception once!
                m_scriptText = "";
                throw ex;
            }

            return m_scriptText;
        }

        private String getStylesheetText() throws IOException {
            if( m_stylesheetText != null ) {
                return m_stylesheetText;
            }

            if( m_stylesheetLocation == null ) {
                return "";
            }

            try {
                m_stylesheetText = getTextResource(m_stylesheetLocation);
            } catch( IOException ex ) {
                // Only throw this exception once!
                m_stylesheetText = "";
                throw ex;
            }

            return m_stylesheetText;
        }

        /**
         *  Returns a string suitable for debugging.  Don't assume that the format would stay the same.
         *  
         *  @return Something human-readable
         */
        public String toString() {
            return "Plugin :[name=" + m_name + "][className=" + m_className + "]";
        }
    } // WikiPluginClass

    /**
     *  {@inheritDoc}
     */
    @Override
    public Collection< WikiModuleInfo > modules() {
        Set< WikiModuleInfo > ls = new TreeSet< WikiModuleInfo >();
        
        for( Iterator< WikiPluginInfo > i = m_pluginClassMap.values().iterator(); i.hasNext(); ) {
            WikiModuleInfo wmi = i.next();
            if( !ls.contains( wmi ) ) ls.add( wmi );
        }
        
        return ls;
    }
    
    /**
     *  {@inheritDoc}
     */
    @Override
    public WikiPluginInfo getModuleInfo(String moduleName) {
        return m_pluginClassMap.get(moduleName);
    }

    /**
     * Creates a {@link WikiPlugin}.
     * 
     * @param pluginName plugin's classname
     * @param rb {@link ResourceBundle} with i18ned text for exceptions.
     * @return a {@link WikiPlugin}.
     * @throws PluginException if there is a problem building the {@link WikiPlugin}.
     */
    public WikiPlugin newWikiPlugin( String pluginName, ResourceBundle rb ) throws PluginException {
        WikiPlugin plugin = null;
        WikiPluginInfo pluginInfo = m_pluginClassMap.get( pluginName );
        try {
            if( pluginInfo == null ) {
                pluginInfo = WikiPluginInfo.newInstance( findPluginClass( pluginName ) );
                registerPlugin( pluginInfo );
            }

            if( !checkCompatibility( pluginInfo ) ) {
                String msg = "Plugin '" + pluginInfo.getName() + "' not compatible with this version of JSPWiki";
                log.info( msg );
            } else {
                plugin = pluginInfo.newPluginInstance(m_searchPath, m_externalJars);
            }
        } catch( ClassNotFoundException e ) {
            throw new PluginException( MessageFormat.format( rb.getString( "plugin.error.couldnotfind" ), pluginName ), e );
        } catch( InstantiationException e ) {
            throw new PluginException( MessageFormat.format( rb.getString( "plugin.error.cannotinstantiate" ), pluginName ), e );
        } catch( IllegalAccessException e ) {
            throw new PluginException( MessageFormat.format( rb.getString( "plugin.error.notallowed" ), pluginName ), e );
        } catch( Exception e ) {
            throw new PluginException( MessageFormat.format( rb.getString( "plugin.error.instantationfailed" ), pluginName ), e );
        }
        return plugin;
    }
    
}
