| /* |
| JSPWiki - a JSP-based WikiWiki clone. |
| |
| 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.ui; |
| |
| import java.net.URL; |
| import java.util.*; |
| |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.jsp.PageContext; |
| |
| import org.apache.wiki.NoSuchVariableException; |
| import org.apache.wiki.WikiContext; |
| import org.apache.wiki.WikiEngine; |
| import org.apache.wiki.log.Logger; |
| import org.apache.wiki.log.LoggerFactory; |
| import org.apache.wiki.modules.ModuleManager; |
| import org.apache.wiki.modules.WikiModuleInfo; |
| import org.apache.wiki.preferences.Preferences; |
| import org.jdom.Document; |
| import org.jdom.Element; |
| import org.jdom.JDOMException; |
| import org.jdom.input.SAXBuilder; |
| import org.jdom.xpath.XPath; |
| |
| |
| /** |
| * Defines an editor manager. An editor can be added by adding a |
| * suitable JSP file under templates/default/editors |
| * If you want your editor to include any scripts or something, you |
| * can simply request it by adding the following in your |
| * ini/jspwiki_module.xml: |
| * |
| * <pre> |
| * <modules> |
| * <editor name="myeditor"> |
| * <author>Janne Jalkanen</author> |
| * <script>foo.js</script> |
| * <stylesheet>foo.css</stylesheet> |
| * <path>editors/myeditor.jsp</path> |
| * </editor> |
| * </modules> |
| * </pre> |
| * |
| * @since 2.4 |
| */ |
| public class EditorManager extends ModuleManager |
| { |
| /** The property name for setting the editor. Current value is "jspwiki.editor" */ |
| /* not used anymore -- replaced by defaultpref.template.editor */ |
| public static final String PROP_EDITORTYPE = "jspwiki.editor"; |
| |
| /** Parameter for changing editors at run-time */ |
| public static final String PARA_EDITOR = "editor"; |
| |
| /** Known name for the plain wikimarkup editor. */ |
| public static final String EDITOR_PLAIN = "plain"; |
| |
| /** Known attribute name for storing the user edited text inside a HTTP parameter. */ |
| public static final String REQ_EDITEDTEXT = "_editedtext"; |
| |
| /** Known attribute name for storing the user edited text inside a session or a page context */ |
| public static final String ATTR_EDITEDTEXT = REQ_EDITEDTEXT; |
| |
| private Map<String, WikiEditorInfo> m_editors; |
| |
| private static Logger log = LoggerFactory.getLogger( EditorManager.class ); |
| |
| public EditorManager( WikiEngine engine ) |
| { |
| super(engine); |
| } |
| |
| /** |
| * Initializes the EditorManager. It also registers any editors it can find. |
| * |
| * @param props Properties for setup. |
| */ |
| public void initialize( Properties props ) |
| { |
| registerEditors(); |
| } |
| |
| /** |
| * This method goes through the jspwiki_module.xml files and hunts for editors. |
| * Any editors found are put in the registry. |
| * |
| */ |
| private void registerEditors() |
| { |
| log.info( "Registering editor modules" ); |
| |
| m_editors = new HashMap<String, WikiEditorInfo>(); |
| SAXBuilder builder = new SAXBuilder(); |
| |
| try |
| { |
| // |
| // Register all editors which have created a resource containing its properties. |
| // |
| // Get all resources of all modules |
| // |
| |
| Enumeration<URL> resources = getClass().getClassLoader().getResources( MODULE_RESOURCE_LOCATION ); |
| |
| while( resources.hasMoreElements() ) |
| { |
| URL resource = resources.nextElement(); |
| |
| try |
| { |
| log.debug( "Processing XML: " + resource ); |
| |
| Document doc = builder.build( resource ); |
| |
| List<?> plugins = XPath.selectNodes( doc, "/modules/editor"); |
| |
| for( Iterator<?> i = plugins.iterator(); i.hasNext(); ) |
| { |
| Element pluginEl = (Element) i.next(); |
| |
| String name = pluginEl.getAttributeValue("name"); |
| |
| WikiEditorInfo info = WikiEditorInfo.newInstance(name, pluginEl); |
| |
| if( checkCompatibility(info) ) |
| { |
| m_editors.put( name, info ); |
| |
| log.debug("Registered editor "+name); |
| } |
| else |
| { |
| log.info("Editor '"+name+"' not compatible with this version of JSPWiki."); |
| } |
| } |
| } |
| catch( java.io.IOException e ) |
| { |
| log.error( "Couldn't load " + ModuleManager.MODULE_RESOURCE_LOCATION + " resources: " + resource, e ); |
| } |
| catch( JDOMException e ) |
| { |
| log.error( "Error parsing XML for plugin: "+ModuleManager.MODULE_RESOURCE_LOCATION ); |
| } |
| } |
| } |
| catch( java.io.IOException e ) |
| { |
| log.error( "Couldn't load all " + MODULE_RESOURCE_LOCATION + " resources", e ); |
| } |
| } |
| |
| /** |
| * Returns an editor for the current context. The editor names are matched in |
| * a case insensitive manner. At the moment, the only place that this method |
| * looks in is the property file, but in the future this will also look at |
| * user preferences. |
| * <p> |
| * Determines the editor to use by the following order of conditions: |
| * 1. Editor set in User Preferences |
| * 2. Default Editor set in jspwiki.properties |
| * <p> |
| * For the PREVIEW context, this method returns the "preview" editor. |
| * |
| * @param context The context that is chosen. |
| * @return The name of the chosen editor. If no match could be found, will |
| * revert to the default "plain" editor. |
| */ |
| public String getEditorName( WikiContext context ) |
| { |
| String editor = null; |
| |
| // User has set an editor in preferences |
| Preferences prefs = Preferences.getPreferences( context.getHttpRequest() ); |
| editor = (String)prefs.get( Preferences.PREFS_EDITOR ); |
| |
| /* FIXME: actual default 'editor' property is read by the Preferences class */ |
| if (editor == null) |
| { |
| // or use the default editor in jspwiki.properties |
| try |
| { |
| editor = m_engine.getVariableManager().getValue( context, PROP_EDITORTYPE ); |
| } |
| catch( NoSuchVariableException e ) {} // This is fine |
| } |
| |
| if (editor != null) |
| { |
| String[] editorlist = getEditorList(); |
| |
| editor = editor.trim(); |
| |
| for( int i = 0; i < editorlist.length; i++ ) |
| { |
| if( editorlist[i].equalsIgnoreCase(editor)) |
| { |
| return editorlist[i]; |
| } |
| } |
| } |
| |
| return EDITOR_PLAIN; |
| } |
| |
| /** |
| * Returns a list of editors as Strings of editor names. |
| * |
| * @return the list of available editors |
| */ |
| public String[] getEditorList() |
| { |
| String[] editors = new String[m_editors.size()]; |
| |
| Set<String> keys = m_editors.keySet(); |
| |
| return keys.toArray( editors ); |
| } |
| |
| /** |
| * Convenience method for getting the path to the editor JSP file. |
| * |
| * @param context |
| * @return e.g. "editors/plain.jsp" |
| */ |
| public String getEditorPath( WikiContext context ) |
| { |
| String path = null; |
| |
| String editor = getEditorName( context ); |
| |
| WikiEditorInfo ed = m_editors.get( editor ); |
| |
| if( ed != null ) |
| { |
| path = ed.getPath(); |
| } |
| else |
| { |
| path = "editors/"+editor+".jsp"; |
| } |
| |
| return path; |
| } |
| |
| /** |
| * Convenience function which examines the current context and attempts to figure |
| * out whether the edited text is in the HTTP request parameters or somewhere in |
| * the session. |
| * |
| * @param ctx the JSP page context |
| * @return the edited text, if present in the session page context or as a parameter |
| */ |
| public static String getEditedText( PageContext ctx ) |
| { |
| String usertext = ctx.getRequest().getParameter( REQ_EDITEDTEXT ); |
| |
| if( usertext == null ) |
| { |
| usertext = (String)ctx.findAttribute( ATTR_EDITEDTEXT ); |
| } |
| |
| return usertext; |
| } |
| |
| /** |
| * Convenience method that examines the current context and attempts to |
| * figure out whether the edited text is in the HTTP request parameters or |
| * somewhere in the session. The request parameter |
| * {@link EditorManager#REQ_EDITEDTEXT} is checked first; then, the session |
| * attribute {@link EditorManager#ATTR_EDITEDTEXT}. This method is similar |
| * in most respects to {@link #getEditedText(PageContext)} |
| * except that this method does not consult the PageContext (because it has |
| * no access to it). |
| * |
| * @return the edited text, if present in the session page context or as a |
| * parameter |
| */ |
| public static String getEditedText( HttpServletRequest request ) |
| { |
| String usertext = request.getParameter( EditorManager.REQ_EDITEDTEXT ); |
| |
| if( usertext == null ) |
| { |
| usertext = request.getSession().getAttribute( EditorManager.ATTR_EDITEDTEXT ).toString(); |
| } |
| |
| return usertext; |
| } |
| |
| /** |
| * Contains info about an editor. |
| * |
| */ |
| private static final class WikiEditorInfo |
| extends WikiModuleInfo |
| { |
| private String m_path; |
| |
| protected static WikiEditorInfo newInstance( String name, Element el ) |
| { |
| if( name == null || name.length() == 0 ) return null; |
| WikiEditorInfo info = new WikiEditorInfo( name ); |
| |
| info.initializeFromXML( el ); |
| return info; |
| } |
| |
| protected void initializeFromXML( Element el ) |
| { |
| super.initializeFromXML( el ); |
| m_path = el.getChildText("path"); |
| } |
| |
| private WikiEditorInfo( String name ) |
| { |
| super(name); |
| } |
| |
| public String getPath() |
| { |
| return m_path; |
| } |
| } |
| |
| public Collection<WikiModuleInfo> modules() |
| { |
| ArrayList<WikiModuleInfo> ls = new ArrayList<WikiModuleInfo>(); |
| |
| ls.addAll( m_editors.values() ); |
| |
| return ls; |
| } |
| |
| } |