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