    001/*
    002    Licensed to the Apache Software Foundation (ASF) under one
    003    or more contributor license agreements.  See the NOTICE file
    004    distributed with this work for additional information
    005    regarding copyright ownership.  The ASF licenses this file
    006    to you under the Apache License, Version 2.0 (the
    007    "License"); you may not use this file except in compliance
    008    with the License.  You may obtain a copy of the License at
    009
    010       http://www.apache.org/licenses/LICENSE-2.0
    011
    012    Unless required by applicable law or agreed to in writing,
    013    software distributed under the License is distributed on an
    014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015    KIND, either express or implied.  See the License for the
    016    specific language governing permissions and limitations
    017    under the License.
    018 */
    019package org.apache.wiki.ui;
    020
    021import org.apache.logging.log4j.LogManager;
    022import org.apache.logging.log4j.Logger;
    023import org.apache.wiki.api.core.Context;
    024import org.apache.wiki.api.core.ContextEnum;
    025import org.apache.wiki.api.core.Engine;
    026import org.apache.wiki.api.exceptions.NoSuchVariableException;
    027import org.apache.wiki.modules.BaseModuleManager;
    028import org.apache.wiki.modules.WikiModuleInfo;
    029import org.apache.wiki.preferences.Preferences;
    030import org.apache.wiki.util.XmlUtil;
    031import org.apache.wiki.variables.VariableManager;
    032import org.jdom2.Element;
    033
    034import java.util.Collection;
    035import java.util.HashMap;
    036import java.util.List;
    037import java.util.Map;
    038import java.util.Properties;
    039import java.util.Set;
    040
    041
    042/**
    043 *  Defines an editor manager.  An editor can be added by adding a suitable JSP file under templates/default/editors
    044 *  If you want your editor to include any scripts or something, you can simply request it by adding the following in your
    045 *  {@code ini/jspwiki_module.xml}:
    046 *
    047 *  <pre>
    048 *  &lt;modules>
    049 *   &lt;editor name="myeditor">
    050 *       &lt;author>Janne Jalkanen&lt;/author>
    051 *       &lt;script>foo.js&lt;/script>
    052 *       &lt;stylesheet>foo.css&lt;/stylesheet>
    053 *       &lt;path>editors/myeditor.jsp&lt;/path>
    054 *   &lt;/editor>
    055 *  &lt;/modules>
    056 *  </pre>
    057 *
    058 *  @since 2.4
    059 */
    060public class DefaultEditorManager extends BaseModuleManager implements EditorManager {
    061
    062    private Map< String, WikiEditorInfo > m_editors;
    063
    064    private static final Logger LOG = LogManager.getLogger( DefaultEditorManager.class );
    065
    066    public DefaultEditorManager( final Engine engine ) {
    067        super( engine );
    068    }
    069
    070    /**
    071     * {@inheritDoc}
    072     *
    073     * Initializes the EditorManager.  It also registers any editors it can find.
    074     */
    075    @Override
    076    public void initialize( final Engine engine, final Properties props ) {
    077        registerEditors();
    078    }
    079
    080    /** This method goes through the jspwiki_module.xml files and hunts for editors. Any editors found are put in the registry. */
    081    private void registerEditors() {
    082        LOG.info( "Registering editor modules" );
    083        m_editors = new HashMap<>();
    084
    085        // Register all editors which have created a resource containing its properties. Get all resources of all modules
    086        final List< Element > editors = XmlUtil.parse( PLUGIN_RESOURCE_LOCATION, "/modules/editor" );
    087        for( final Element pluginEl : editors ) {
    088            final String name = pluginEl.getAttributeValue( "name" );
    089            final WikiEditorInfo info = WikiEditorInfo.newInstance( name, pluginEl );
    090
    091            if( checkCompatibility( info ) ) {
    092                m_editors.put( name, info );
    093                LOG.debug( "Registered editor " + name );
    094            } else {
    095                LOG.info( "Editor '" + name + "' not compatible with this version of JSPWiki." );
    096            }
    097        }
    098    }
    099
    100    /** {@inheritDoc} */
    101    @Override
    102    public String getEditorName( final Context context ) {
    103        if( context.getRequestContext().equals( ContextEnum.PAGE_PREVIEW.getRequestContext() ) ) {
    104            return EDITOR_PREVIEW;
    105        }
    106
    107        // User has set an editor in preferences
    108        String editor = Preferences.getPreference( context, PARA_EDITOR );
    109
    110        /* FIXME: actual default 'editor' property is read by the Preferences class */
    111        if( editor == null ) {
    112            // or use the default editor in jspwiki.properties
    113            try {
    114                editor = m_engine.getManager( VariableManager.class ).getValue( context, PROP_EDITORTYPE );
    115            } catch( final NoSuchVariableException e ) {} // This is fine
    116        }
    117
    118        if( editor != null ) {
    119            final String[] editorlist = getEditorList();
    120            editor = editor.trim();
    121            for( final String s : editorlist ) {
    122                if( s.equalsIgnoreCase( editor ) ) {
    123                    return s;
    124                }
    125            }
    126        }
    127
    128        return EDITOR_PLAIN;
    129    }
    130
    131    /** {@inheritDoc} */
    132    @Override
    133    public String[] getEditorList() {
    134        final String[] editors = new String[ m_editors.size() ];
    135        final Set< String > keys = m_editors.keySet();
    136
    137        return keys.toArray( editors );
    138    }
    139
    140    /** {@inheritDoc} */
    141    @Override
    142    public String getEditorPath( final Context context ) {
    143        final String editor = getEditorName( context );
    144        final WikiEditorInfo ed = m_editors.get( editor );
    145        final String path;
    146        if( ed != null ) {
    147            path = ed.getPath();
    148        } else {
    149            path = "editors/"+editor+".jsp";
    150        }
    151
    152        return path;
    153    }
    154
    155    /**  Contains info about an editor. */
    156    private static final class WikiEditorInfo extends WikiModuleInfo {
    157        private String m_path;
    158
    159        static WikiEditorInfo newInstance( final String name, final Element el ) {
    160            if( name == null || name.isEmpty() ) {
    161                return null;
    162            }
    163            final WikiEditorInfo info = new WikiEditorInfo( name );
    164            info.initializeFromXML( el );
    165            return info;
    166        }
    167
    168        /** {@inheritDoc} */
    169        @Override
    170        protected void initializeFromXML( final Element el ) {
    171            super.initializeFromXML( el );
    172            m_path = el.getChildText("path");
    173        }
    174
    175        private WikiEditorInfo( final String name ) {
    176            super( name );
    177        }
    178
    179        public String getPath() {
    180            return m_path;
    181        }
    182    }
    183
    184    /** {@inheritDoc} */
    185    @Override
    186    public Collection< WikiModuleInfo > modules() {
    187        return modules( m_editors.values().iterator() );
    188    }
    189
    190    /** {@inheritDoc} */
    191    @Override
    192    public WikiEditorInfo getModuleInfo( final String moduleName ) {
    193        return m_editors.get( moduleName );
    194    }
    195
    196}