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; 020 021import org.apache.commons.lang3.StringUtils; 022import org.apache.logging.log4j.LogManager; 023import org.apache.logging.log4j.Logger; 024import org.apache.wiki.api.Release; 025import org.apache.wiki.api.core.Engine; 026import org.apache.wiki.api.core.Page; 027import org.apache.wiki.api.engine.Initializable; 028import org.apache.wiki.api.exceptions.ProviderException; 029import org.apache.wiki.api.exceptions.WikiException; 030import org.apache.wiki.attachment.AttachmentManager; 031import org.apache.wiki.auth.AuthenticationManager; 032import org.apache.wiki.auth.AuthorizationManager; 033import org.apache.wiki.auth.UserManager; 034import org.apache.wiki.auth.acl.AclManager; 035import org.apache.wiki.auth.authorize.GroupManager; 036import org.apache.wiki.cache.CachingManager; 037import org.apache.wiki.content.PageRenamer; 038import org.apache.wiki.diff.DifferenceManager; 039import org.apache.wiki.event.WikiEngineEvent; 040import org.apache.wiki.event.WikiEventListener; 041import org.apache.wiki.event.WikiEventManager; 042import org.apache.wiki.event.WikiPageEvent; 043import org.apache.wiki.filters.FilterManager; 044import org.apache.wiki.i18n.InternationalizationManager; 045import org.apache.wiki.pages.PageManager; 046import org.apache.wiki.plugin.PluginManager; 047import org.apache.wiki.references.ReferenceManager; 048import org.apache.wiki.render.RenderingManager; 049import org.apache.wiki.rss.RSSGenerator; 050import org.apache.wiki.search.SearchManager; 051import org.apache.wiki.tasks.TasksManager; 052import org.apache.wiki.ui.CommandResolver; 053import org.apache.wiki.ui.EditorManager; 054import org.apache.wiki.ui.TemplateManager; 055import org.apache.wiki.ui.admin.AdminBeanManager; 056import org.apache.wiki.ui.progress.ProgressManager; 057import org.apache.wiki.url.URLConstructor; 058import org.apache.wiki.util.ClassUtil; 059import org.apache.wiki.util.PropertyReader; 060import org.apache.wiki.util.TextUtil; 061import org.apache.wiki.variables.VariableManager; 062import org.apache.wiki.workflow.WorkflowManager; 063 064import javax.servlet.ServletConfig; 065import javax.servlet.ServletContext; 066import java.io.File; 067import java.io.UnsupportedEncodingException; 068import java.net.MalformedURLException; 069import java.net.URL; 070import java.net.URLDecoder; 071import java.net.URLEncoder; 072import java.nio.charset.Charset; 073import java.nio.charset.StandardCharsets; 074import java.util.ArrayList; 075import java.util.Collection; 076import java.util.Date; 077import java.util.Enumeration; 078import java.util.List; 079import java.util.Locale; 080import java.util.Map; 081import java.util.Properties; 082import java.util.TimeZone; 083import java.util.concurrent.ConcurrentHashMap; 084import java.util.stream.Collectors; 085 086 087/** 088 * Main implementation for {@link Engine}. 089 * 090 * <P> 091 * Using this class: Always get yourself an instance from JSP page by using the {@code WikiEngine.getInstance(..)} method. Never create 092 * a new WikiEngine() from scratch, unless you're writing tests. 093 * 094 * <p> 095 * {@inheritDoc} 096 */ 097public class WikiEngine implements Engine { 098 099 private static final String ATTR_WIKIENGINE = "org.apache.wiki.WikiEngine"; 100 private static final Logger LOG = LogManager.getLogger( WikiEngine.class ); 101 102 /** Stores properties. */ 103 private Properties m_properties; 104 105 /** Should the user info be saved with the page data as well? */ 106 private boolean m_saveUserInfo = true; 107 108 /** If true, uses UTF8 encoding for all data */ 109 private boolean m_useUTF8 = true; 110 111 /** Store the file path to the basic URL. When we're not running as a servlet, it defaults to the user's current directory. */ 112 private String m_rootPath = System.getProperty( "user.dir" ); 113 114 /** Store the ServletContext that we're in. This may be null if WikiEngine is not running inside a servlet container (i.e. when testing). */ 115 private ServletContext m_servletContext; 116 117 /** Stores the template path. This is relative to "templates". */ 118 private String m_templateDir; 119 120 /** The default front page name. Defaults to "Main". */ 121 private String m_frontPage; 122 123 /** The time when this engine was started. */ 124 private Date m_startTime; 125 126 /** The location where the work directory is. */ 127 private String m_workDir; 128 129 /** Each engine has their own application id. */ 130 private String m_appid = ""; 131 132 /** engine is up and running or not */ 133 private boolean m_isConfigured; 134 135 /** Stores wikiengine attributes. */ 136 private final Map< String, Object > m_attributes = new ConcurrentHashMap<>(); 137 138 /** Stores WikiEngine's associated managers. */ 139 protected final Map< Class< ? >, Object > managers = new ConcurrentHashMap<>(); 140 141 /** 142 * Gets a WikiEngine related to this servlet. Since this method is only called from JSP pages (and JspInit()) to be specific, 143 * we throw a RuntimeException if things don't work. 144 * 145 * @param config The ServletConfig object for this servlet. 146 * @return A WikiEngine instance. 147 * @throws InternalWikiException in case something fails. This is a RuntimeException, so be prepared for it. 148 */ 149 public static synchronized WikiEngine getInstance( final ServletConfig config ) throws InternalWikiException { 150 return getInstance( config.getServletContext(), null ); 151 } 152 153 /** 154 * Gets a WikiEngine related to the servlet. Works like getInstance(ServletConfig), but does not force the Properties object. 155 * This method is just an optional way of initializing a WikiEngine for embedded JSPWiki applications; normally, you 156 * should use getInstance(ServletConfig). 157 * 158 * @param config The ServletConfig of the webapp servlet/JSP calling this method. 159 * @param props A set of properties, or null, if we are to load JSPWiki's default jspwiki.properties (this is the usual case). 160 * 161 * @return One well-behaving WikiEngine instance. 162 */ 163 public static synchronized WikiEngine getInstance( final ServletConfig config, final Properties props ) { 164 return getInstance( config.getServletContext(), props ); 165 } 166 167 /** 168 * Gets a WikiEngine related to the servlet. Works just like getInstance( ServletConfig ) 169 * 170 * @param context The ServletContext of the webapp servlet/JSP calling this method. 171 * @param props A set of properties, or null, if we are to load JSPWiki's default jspwiki.properties (this is the usual case). 172 * @return One fully functional, properly behaving WikiEngine. 173 * @throws InternalWikiException If the WikiEngine instantiation fails. 174 */ 175 public static synchronized WikiEngine getInstance( final ServletContext context, Properties props ) throws InternalWikiException { 176 WikiEngine engine = ( WikiEngine )context.getAttribute( ATTR_WIKIENGINE ); 177 if( engine == null ) { 178 final String appid = Integer.toString( context.hashCode() ); 179 context.log(" Assigning new engine to "+appid); 180 try { 181 if( props == null ) { 182 props = PropertyReader.loadWebAppProps( context ); 183 } 184 185 engine = new WikiEngine( context, appid, props ); 186 context.setAttribute( ATTR_WIKIENGINE, engine ); 187 } catch( final Exception e ) { 188 context.log( "ERROR: Failed to create a Wiki engine: " + e.getMessage() ); 189 LOG.error( "ERROR: Failed to create a Wiki engine, stacktrace follows ", e ); 190 throw new InternalWikiException( "No wiki engine, check logs.", e ); 191 } 192 } 193 return engine; 194 } 195 196 /** 197 * Instantiate the WikiEngine using a given set of properties. Use this constructor for testing purposes only. 198 * 199 * @param properties A set of properties to use to initialize this WikiEngine. 200 * @throws WikiException If the initialization fails. 201 */ 202 public WikiEngine( final Properties properties ) throws WikiException { 203 initialize( properties ); 204 } 205 206 /** 207 * Instantiate using this method when you're running as a servlet and WikiEngine will figure out where to look for the property file. 208 * Do not use this method - use WikiEngine.getInstance() instead. 209 * 210 * @param context A ServletContext. 211 * @param appid An Application ID. This application is a unique random string which is used to recognize this WikiEngine. 212 * @param props The WikiEngine configuration. 213 * @throws WikiException If the WikiEngine construction fails. 214 */ 215 protected WikiEngine( final ServletContext context, final String appid, final Properties props ) throws WikiException { 216 m_servletContext = context; 217 m_appid = appid; 218 219 // Stash the WikiEngine in the servlet context 220 if ( context != null ) { 221 context.setAttribute( ATTR_WIKIENGINE, this ); 222 m_rootPath = context.getRealPath("/"); 223 } 224 225 try { 226 // Note: May be null, if JSPWiki has been deployed in a WAR file. 227 initialize( props ); 228 LOG.info( "Root path for this Wiki is: '{}'", m_rootPath ); 229 } catch( final Exception e ) { 230 final String msg = Release.APPNAME+": Unable to load and setup properties from jspwiki.properties. "+e.getMessage(); 231 if ( context != null ) { 232 context.log( msg ); 233 } 234 throw new WikiException( msg, e ); 235 } 236 } 237 238 /** 239 * Does all the real initialization. 240 */ 241 private void initialize( final Properties props ) throws WikiException { 242 m_startTime = new Date(); 243 m_properties = props; 244 245 LOG.info( "*******************************************" ); 246 LOG.info( "{} {} starting. Whee!", Release.APPNAME, Release.getVersionString() ); 247 248 fireEvent( WikiEngineEvent.INITIALIZING ); // begin initialization 249 250 LOG.debug( "Java version: {}", System.getProperty( "java.runtime.version" ) ); 251 LOG.debug( "Java vendor: {}", System.getProperty( "java.vm.vendor" ) ); 252 LOG.debug( "OS: {} {} {}", System.getProperty( "os.name" ), System.getProperty( "os.version" ), System.getProperty( "os.arch" ) ); 253 LOG.debug( "Default server locale: {}", Locale.getDefault() ); 254 LOG.debug( "Default server timezone: {}", TimeZone.getDefault().getDisplayName( true, TimeZone.LONG ) ); 255 256 if( m_servletContext != null ) { 257 LOG.info( "Servlet container: {}", m_servletContext.getServerInfo() ); 258 if( m_servletContext.getMajorVersion() < 3 || ( m_servletContext.getMajorVersion() == 3 && m_servletContext.getMinorVersion() < 1 ) ) { 259 throw new InternalWikiException( "JSPWiki requires a container which supports at least version 3.1 of Servlet specification" ); 260 } 261 } 262 263 LOG.debug( "Configuring WikiEngine..." ); 264 265 // Create and find the default working directory. 266 m_workDir = TextUtil.getStringProperty( props, PROP_WORKDIR, null ); 267 268 if( m_workDir == null ) { 269 m_workDir = System.getProperty( "java.io.tmpdir", "." ); 270 m_workDir += File.separator + Release.APPNAME + "-" + m_appid; 271 } 272 273 try { 274 final File f = new File( m_workDir ); 275 f.mkdirs(); 276 277 // 278 // A bunch of sanity checks 279 // 280 if( !f.exists() ) { 281 throw new WikiException( "Work directory does not exist: " + m_workDir ); 282 } 283 if( !f.canRead() ) { 284 throw new WikiException( "No permission to read work directory: " + m_workDir ); 285 } 286 if( !f.canWrite() ) { 287 throw new WikiException( "No permission to write to work directory: " + m_workDir ); 288 } 289 if( !f.isDirectory() ) { 290 throw new WikiException( "jspwiki.workDir does not point to a directory: " + m_workDir ); 291 } 292 } catch( final SecurityException e ) { 293 LOG.fatal( "Unable to find or create the working directory: {}", m_workDir, e ); 294 throw new IllegalArgumentException( "Unable to find or create the working dir: " + m_workDir, e ); 295 } 296 297 LOG.info( "JSPWiki working directory is '{}'", m_workDir ); 298 299 m_saveUserInfo = TextUtil.getBooleanProperty( props, PROP_STOREUSERNAME, m_saveUserInfo ); 300 m_useUTF8 = StandardCharsets.UTF_8.name().equals( TextUtil.getStringProperty( props, PROP_ENCODING, StandardCharsets.ISO_8859_1.name() ) ); 301 m_templateDir = TextUtil.getStringProperty( props, PROP_TEMPLATEDIR, "default" ); 302 enforceValidTemplateDirectory(); 303 m_frontPage = TextUtil.getStringProperty( props, PROP_FRONTPAGE, "Main" ); 304 305 // 306 // Initialize the important modules. Any exception thrown by the managers means that we will not start up. 307 // 308 try { 309 final String aclClassName = m_properties.getProperty( PROP_ACL_MANAGER_IMPL, ClassUtil.getMappedClass( AclManager.class.getName() ).getName() ); 310 final String urlConstructorClassName = TextUtil.getStringProperty( props, PROP_URLCONSTRUCTOR, "DefaultURLConstructor" ); 311 final Class< URLConstructor > urlclass = ClassUtil.findClass( "org.apache.wiki.url", urlConstructorClassName ); 312 313 initComponent( CommandResolver.class, this, props ); 314 initComponent( urlclass.getName(), URLConstructor.class ); 315 initComponent( CachingManager.class, this, props ); 316 initComponent( PageManager.class, this, props ); 317 initComponent( PluginManager.class, this, props ); 318 initComponent( DifferenceManager.class, this, props ); 319 initComponent( AttachmentManager.class, this, props ); 320 initComponent( VariableManager.class, props ); 321 initComponent( SearchManager.class, this, props ); 322 initComponent( AuthenticationManager.class ); 323 initComponent( AuthorizationManager.class ); 324 initComponent( UserManager.class ); 325 initComponent( GroupManager.class ); 326 initComponent( EditorManager.class, this ); 327 initComponent( ProgressManager.class, this ); 328 initComponent( aclClassName, AclManager.class ); 329 initComponent( WorkflowManager.class ); 330 initComponent( TasksManager.class ); 331 initComponent( InternationalizationManager.class, this ); 332 initComponent( TemplateManager.class, this, props ); 333 initComponent( FilterManager.class, this, props ); 334 initComponent( AdminBeanManager.class, this ); 335 initComponent( PageRenamer.class, this, props ); 336 337 // RenderingManager depends on FilterManager events. 338 initComponent( RenderingManager.class ); 339 340 // ReferenceManager has the side effect of loading all pages. Therefore, after this point, all page attributes are available. 341 // initReferenceManager is indirectly using m_filterManager, so it has to be called after it was initialized. 342 initReferenceManager(); 343 344 // Hook the different manager routines into the system. 345 getManager( FilterManager.class ).addPageFilter( getManager( ReferenceManager.class ), -1001 ); 346 getManager( FilterManager.class ).addPageFilter( getManager( SearchManager.class ), -1002 ); 347 } catch( final RuntimeException e ) { 348 // RuntimeExceptions may occur here, even if they shouldn't. 349 LOG.fatal( "Failed to start managers.", e ); 350 throw new WikiException( "Failed to start managers: " + e.getMessage(), e ); 351 } catch( final ClassNotFoundException e ) { 352 LOG.fatal( "JSPWiki could not start, URLConstructor was not found: {}", e.getMessage(), e ); 353 throw new WikiException( e.getMessage(), e ); 354 } catch( final InstantiationException e ) { 355 LOG.fatal( "JSPWiki could not start, URLConstructor could not be instantiated: {}", e.getMessage(), e ); 356 throw new WikiException( e.getMessage(), e ); 357 } catch( final IllegalAccessException e ) { 358 LOG.fatal( "JSPWiki could not start, URLConstructor cannot be accessed: {}", e.getMessage(), e ); 359 throw new WikiException( e.getMessage(), e ); 360 } catch( final Exception e ) { 361 // Final catch-all for everything 362 LOG.fatal( "JSPWiki could not start, due to an unknown exception when starting.", e ); 363 throw new WikiException( "Failed to start. Caused by: " + e.getMessage() + "; please check log files for better information.", e ); 364 } 365 366 // Initialize the good-to-have-but-not-fatal modules. 367 try { 368 if( TextUtil.getBooleanProperty( props, RSSGenerator.PROP_GENERATE_RSS,false ) ) { 369 initComponent( RSSGenerator.class, this, props ); 370 } 371 } catch( final Exception e ) { 372 LOG.error( "Unable to start RSS generator - JSPWiki will still work, but there will be no RSS feed.", e ); 373 } 374 375 final Map< String, String > extraComponents = ClassUtil.getExtraClassMappings(); 376 initExtraComponents( extraComponents ); 377 378 fireEvent( WikiEngineEvent.INITIALIZED ); // initialization complete 379 380 LOG.info( "WikiEngine configured." ); 381 m_isConfigured = true; 382 } 383 384 void initExtraComponents( final Map< String, String > extraComponents ) { 385 for( final Map.Entry< String, String > extraComponent : extraComponents.entrySet() ) { 386 try { 387 LOG.info( "Registering on WikiEngine {} as {}", extraComponent.getKey(), extraComponent.getValue() ); 388 initComponent( extraComponent.getKey(), Class.forName( extraComponent.getValue() ) ); 389 } catch( final Exception e ) { 390 LOG.error( "Unable to start {}", extraComponent.getKey(), e ); 391 } 392 } 393 } 394 395 < T > void initComponent( final Class< T > componentClass, final Object... initArgs ) throws Exception { 396 initComponent( componentClass.getName(), componentClass, initArgs ); 397 } 398 399 < T > void initComponent( final String componentInitClass, final Class< T > componentClass, final Object... initArgs ) throws Exception { 400 final T component; 401 if( initArgs == null || initArgs.length == 0 ) { 402 component = ClassUtil.getMappedObject( componentInitClass ); 403 } else { 404 component = ClassUtil.getMappedObject( componentInitClass, initArgs ); 405 } 406 managers.put( componentClass, component ); 407 if( Initializable.class.isAssignableFrom( component.getClass() ) ) { 408 ( ( Initializable )component ).initialize( this, m_properties ); 409 } 410 } 411 412 /** {@inheritDoc} */ 413 @Override 414 @SuppressWarnings( "unchecked" ) 415 public < T > T getManager( final Class< T > manager ) { 416 return ( T )managers.entrySet().stream() 417 .filter( e -> manager.isAssignableFrom( e.getKey() ) ) 418 .map( Map.Entry::getValue ) 419 .findFirst().orElse( null ); 420 } 421 422 /** {@inheritDoc} */ 423 @Override 424 @SuppressWarnings( "unchecked" ) 425 public < T > List< T > getManagers( final Class< T > manager ) { 426 return ( List< T > )managers.entrySet().stream() 427 .filter( e -> manager.isAssignableFrom( e.getKey() ) ) 428 .map( Map.Entry::getValue ) 429 .collect( Collectors.toList() ); 430 } 431 432 /** {@inheritDoc} */ 433 @Override 434 public boolean isConfigured() { 435 return m_isConfigured; 436 } 437 438 /** 439 * Checks if the template directory specified in the wiki's properties actually exists. If it doesn't, then {@code m_templateDir} is 440 * set to {@link #DEFAULT_TEMPLATE_NAME}. 441 * <p> 442 * This checks the existence of the <tt>ViewTemplate.jsp</tt> file, which exists in every template using {@code m_servletContext.getRealPath("/")}. 443 * <p> 444 * {@code m_servletContext.getRealPath("/")} can return {@code null} on certain servers/conditions (f.ex, packed wars), an extra check 445 * against {@code m_servletContext.getResource} is made. 446 */ 447 void enforceValidTemplateDirectory() { 448 if( m_servletContext != null ) { 449 final String viewTemplate = "templates" + File.separator + getTemplateDir() + File.separator + "ViewTemplate.jsp"; 450 boolean exists = new File( m_servletContext.getRealPath("/") + viewTemplate ).exists(); 451 if( !exists ) { 452 try { 453 final URL url = m_servletContext.getResource( viewTemplate ); 454 exists = url != null && StringUtils.isNotEmpty( url.getFile() ); 455 } catch( final MalformedURLException e ) { 456 LOG.warn( "template not found with viewTemplate {}", viewTemplate ); 457 } 458 } 459 if( !exists ) { 460 LOG.warn( "{} template not found, updating WikiEngine's default template to {}", getTemplateDir(), DEFAULT_TEMPLATE_NAME ); 461 m_templateDir = DEFAULT_TEMPLATE_NAME; 462 } 463 } 464 } 465 466 /** 467 * Initializes the reference manager. Scans all existing WikiPages for 468 * internal links and adds them to the ReferenceManager object. 469 * 470 * @throws WikiException If the reference manager initialization fails. 471 */ 472 public void initReferenceManager() throws WikiException { 473 try { 474 // Build a new manager with default key lists. 475 if( getManager( ReferenceManager.class ) == null ) { 476 final ArrayList< Page > pages = new ArrayList<>(); 477 pages.addAll( getManager( PageManager.class ).getAllPages() ); 478 pages.addAll( getManager( AttachmentManager.class ).getAllAttachments() ); 479 initComponent( ReferenceManager.class, this ); 480 481 getManager( ReferenceManager.class ).initialize( pages ); 482 } 483 484 } catch( final ProviderException e ) { 485 LOG.fatal( "PageProvider is unable to list pages: ", e ); 486 } catch( final Exception e ) { 487 throw new WikiException( "Could not instantiate ReferenceManager: " + e.getMessage(), e ); 488 } 489 } 490 491 /** {@inheritDoc} */ 492 @Override 493 public Properties getWikiProperties() { 494 return m_properties; 495 } 496 497 /** {@inheritDoc} */ 498 @Override 499 public String getWorkDir() { 500 return m_workDir; 501 } 502 503 /** {@inheritDoc} */ 504 @Override 505 public String getTemplateDir() { 506 return m_templateDir; 507 } 508 509 /** {@inheritDoc} */ 510 @Override 511 public Date getStartTime() { 512 return ( Date )m_startTime.clone(); 513 } 514 515 /** {@inheritDoc} */ 516 @Override 517 public String getBaseURL() { 518 return m_servletContext.getContextPath(); 519 } 520 521 /** {@inheritDoc} */ 522 @Override 523 public String getGlobalRSSURL() { 524 final RSSGenerator rssGenerator = getManager( RSSGenerator.class ); 525 if( rssGenerator != null && rssGenerator.isEnabled() ) { 526 return getBaseURL() + "/" + rssGenerator.getRssFile(); 527 } 528 529 return null; 530 } 531 532 /** {@inheritDoc} */ 533 @Override 534 public String getInterWikiURL( final String wikiName ) { 535 return TextUtil.getStringProperty( m_properties,PROP_INTERWIKIREF + wikiName,null ); 536 } 537 538 /** {@inheritDoc} */ 539 @Override 540 public String getURL( final String context, String pageName, final String params ) { 541 if( pageName == null ) { 542 pageName = getFrontPage(); 543 } 544 final URLConstructor urlConstructor = getManager( URLConstructor.class ); 545 return urlConstructor.makeURL( context, pageName, params ); 546 } 547 548 /** {@inheritDoc} */ 549 @Override 550 public String getFrontPage() { 551 return m_frontPage; 552 } 553 554 /** {@inheritDoc} */ 555 @Override 556 public ServletContext getServletContext() { 557 return m_servletContext; 558 } 559 560 /** {@inheritDoc} */ 561 @Override 562 public Collection< String > getAllInterWikiLinks() { 563 final ArrayList< String > list = new ArrayList<>(); 564 for( final Enumeration< ? > i = m_properties.propertyNames(); i.hasMoreElements(); ) { 565 final String prop = ( String )i.nextElement(); 566 if( prop.startsWith( PROP_INTERWIKIREF ) ) { 567 list.add( prop.substring( prop.lastIndexOf( "." ) + 1 ) ); 568 } 569 } 570 571 return list; 572 } 573 574 /** {@inheritDoc} */ 575 @Override 576 public Collection< String > getAllInlinedImagePatterns() { 577 final ArrayList< String > ptrnlist = new ArrayList<>(); 578 for( final Enumeration< ? > e = m_properties.propertyNames(); e.hasMoreElements(); ) { 579 final String name = ( String )e.nextElement(); 580 if( name.startsWith( PROP_INLINEIMAGEPTRN ) ) { 581 ptrnlist.add( TextUtil.getStringProperty( m_properties, name, null ) ); 582 } 583 } 584 585 if( ptrnlist.isEmpty() ) { 586 ptrnlist.add( DEFAULT_INLINEPATTERN ); 587 } 588 589 return ptrnlist; 590 } 591 592 /** {@inheritDoc} */ 593 @Override 594 public String getSpecialPageReference( final String original ) { 595 return getManager( CommandResolver.class ).getSpecialPageReference( original ); 596 } 597 598 /** {@inheritDoc} */ 599 @Override 600 public String getApplicationName() { 601 final String appName = TextUtil.getStringProperty( m_properties, PROP_APPNAME, Release.APPNAME ); 602 return TextUtil.cleanString( appName, TextUtil.PUNCTUATION_CHARS_ALLOWED ); 603 } 604 605 /** {@inheritDoc} */ 606 @Override 607 public String getFinalPageName( final String page ) throws ProviderException { 608 return getManager( CommandResolver.class ).getFinalPageName( page ); 609 } 610 611 /** {@inheritDoc} */ 612 @Override 613 public String encodeName( final String pagename ) { 614 try { 615 return URLEncoder.encode( pagename, m_useUTF8 ? StandardCharsets.UTF_8.name() : StandardCharsets.ISO_8859_1.name() ); 616 } catch( final UnsupportedEncodingException e ) { 617 throw new InternalWikiException( "ISO-8859-1 not a supported encoding!?! Your platform is borked." , e); 618 } 619 } 620 621 /** {@inheritDoc} */ 622 @Override 623 public String decodeName( final String pagerequest ) { 624 try { 625 return URLDecoder.decode( pagerequest, m_useUTF8 ? StandardCharsets.UTF_8.name() : StandardCharsets.ISO_8859_1.name() ); 626 } catch( final UnsupportedEncodingException e ) { 627 throw new InternalWikiException("ISO-8859-1 not a supported encoding!?! Your platform is borked.", e); 628 } 629 } 630 631 /** {@inheritDoc} */ 632 @Override 633 public Charset getContentEncoding() { 634 if( m_useUTF8 ) { 635 return StandardCharsets.UTF_8; 636 } 637 return StandardCharsets.ISO_8859_1; 638 } 639 640 /** 641 * {@inheritDoc} 642 * <p>It is called by {@link WikiServlet#destroy()}. When this method is called, it fires a "shutdown" WikiEngineEvent to 643 * all registered listeners. 644 */ 645 @Override 646 public void shutdown() { 647 getManager( CachingManager.class ).shutdown(); 648 fireEvent( WikiEngineEvent.SHUTDOWN ); 649 getManager( FilterManager.class ).destroy(); 650 WikiEventManager.shutdown(); 651 } 652 653 /** 654 * Returns the current TemplateManager. 655 * 656 * @return A TemplateManager instance. 657 * @deprecated use {@code getManager( TemplateManager.class )} instead. 658 */ 659 @Deprecated 660 public TemplateManager getTemplateManager() { 661 return getManager( TemplateManager.class ); 662 } 663 664 /** 665 * Returns the {@link org.apache.wiki.workflow.WorkflowManager} associated with this WikiEngine. If the WikiEngine has not been 666 * initialized, this method will return <code>null</code>. 667 * 668 * @return the task queue 669 * @deprecated use {@code getManager( WorkflowManager.class )} instead. 670 */ 671 @Deprecated 672 public WorkflowManager getWorkflowManager() { 673 return getManager( WorkflowManager.class ); 674 } 675 676 /** 677 * Returns this object's ReferenceManager. 678 * 679 * @return The current ReferenceManager instance. 680 * @since 1.6.1 681 * @deprecated use {@code getManager( ReferenceManager.class )} instead. 682 */ 683 @Deprecated 684 public ReferenceManager getReferenceManager() { 685 return getManager( ReferenceManager.class ); 686 } 687 688 /** 689 * Returns the current rendering manager for this wiki application. 690 * 691 * @since 2.3.27 692 * @return A RenderingManager object. 693 * @deprecated use {@code getManager( RenderingManager.class )} instead. 694 */ 695 @Deprecated 696 public RenderingManager getRenderingManager() { 697 return getManager( RenderingManager.class ); 698 } 699 700 /** 701 * Returns the current plugin manager. 702 * 703 * @since 1.6.1 704 * @return The current PluginManager instance 705 * @deprecated use {@code getManager( PluginManager.class )} instead. 706 */ 707 @Deprecated 708 public PluginManager getPluginManager() { 709 return getManager( PluginManager.class ); 710 } 711 712 /** 713 * Returns the current variable manager. 714 * 715 * @return The current VariableManager. 716 * @deprecated use {@code getManager( VariableManager.class )} instead. 717 */ 718 @Deprecated 719 public VariableManager getVariableManager() { 720 return getManager( VariableManager.class ); 721 } 722 723 /** 724 * Returns the current PageManager which is responsible for storing and managing WikiPages. 725 * 726 * @return The current PageManager instance. 727 * @deprecated use {@code getManager( PageManager.class )} instead. 728 */ 729 @Deprecated 730 public PageManager getPageManager() { 731 return getManager( PageManager.class ); 732 } 733 734 /** 735 * Returns the CommandResolver for this wiki engine. 736 * 737 * @return the resolver 738 * @deprecated use {@code getManager( CommandResolver.class )} instead. 739 */ 740 @Deprecated 741 public CommandResolver getCommandResolver() { 742 return getManager( CommandResolver.class ); 743 } 744 745 /** 746 * Returns the current AttachmentManager, which is responsible for storing and managing attachments. 747 * 748 * @since 1.9.31. 749 * @return The current AttachmentManager instance 750 * @deprecated use {@code getManager( AttachmentManager.class )} instead. 751 */ 752 @Deprecated 753 public AttachmentManager getAttachmentManager() { 754 return getManager( AttachmentManager.class ); 755 } 756 757 /** 758 * Returns the currently used authorization manager. 759 * 760 * @return The current AuthorizationManager instance. 761 * @deprecated use {@code getManager( AuthorizationManager.class )} instead. 762 */ 763 @Deprecated 764 public AuthorizationManager getAuthorizationManager() { 765 return getManager( AuthorizationManager.class ); 766 } 767 768 /** 769 * Returns the currently used authentication manager. 770 * 771 * @return The current AuthenticationManager instance. 772 * @deprecated use {@code getManager( AuthenticationManager.class )} instead. 773 */ 774 @Deprecated 775 public AuthenticationManager getAuthenticationManager() { 776 return getManager( AuthenticationManager.class ); 777 } 778 779 /** 780 * Returns the manager responsible for the filters. 781 * 782 * @since 2.1.88 783 * @return The current FilterManager instance. 784 * @deprecated use {@code getManager( FilterManager.class )} instead. 785 */ 786 @Deprecated 787 public FilterManager getFilterManager() { 788 return getManager( FilterManager.class ); 789 } 790 791 /** 792 * Returns the manager responsible for searching the Wiki. 793 * 794 * @since 2.2.21 795 * @return The current SearchManager instance. 796 * @deprecated use {@code getManager( SearchManager.class )} instead. 797 */ 798 @Deprecated 799 public SearchManager getSearchManager() { 800 return getManager( SearchManager.class ); 801 } 802 803 /** 804 * Returns the progress manager we're using 805 * 806 * @return A ProgressManager. 807 * @since 2.6 808 * @deprecated use {@code getManager( ProgressManager.class )} instead. 809 */ 810 @Deprecated 811 public ProgressManager getProgressManager() { 812 return getManager( ProgressManager.class ); 813 } 814 815 /** {@inheritDoc} */ 816 @Override 817 public String getRootPath() { 818 return m_rootPath; 819 } 820 821 /** 822 * @since 2.2.6 823 * @return the URL constructor. 824 * @deprecated use {@code getManager( URLConstructor.class )} instead. 825 */ 826 @Deprecated 827 public URLConstructor getURLConstructor() { 828 return getManager( URLConstructor.class ); 829 } 830 831 /** 832 * Returns the RSSGenerator. If the property <code>jspwiki.rss.generate</code> has not been set to <code>true</code>, this method 833 * will return <code>null</code>, <em>and callers should check for this value.</em> 834 * 835 * @since 2.1.165 836 * @return the RSS generator 837 * @deprecated use {@code getManager( RSSGenerator.class )} instead. 838 */ 839 @Deprecated 840 public RSSGenerator getRSSGenerator() { 841 return getManager( RSSGenerator.class ); 842 } 843 844 /** 845 * Returns the PageRenamer employed by this WikiEngine. 846 * 847 * @since 2.5.141 848 * @return The current PageRenamer instance. 849 * @deprecated use {@code getManager( PageRenamer.class )} instead. 850 */ 851 @Deprecated 852 public PageRenamer getPageRenamer() { 853 return getManager( PageRenamer.class ); 854 } 855 856 /** 857 * Returns the UserManager employed by this WikiEngine. 858 * 859 * @since 2.3 860 * @return The current UserManager instance. 861 * @deprecated use {@code getManager( UserManager.class )} instead. 862 */ 863 @Deprecated 864 public UserManager getUserManager() { 865 return getManager( UserManager.class ); 866 } 867 868 /** 869 * Returns the TasksManager employed by this WikiEngine. 870 * 871 * @return The current TasksManager instance. 872 * @deprecated use {@code getManager( TaskManager.class )} instead. 873 */ 874 @Deprecated 875 public TasksManager getTasksManager() { 876 return getManager( TasksManager.class ); 877 } 878 879 /** 880 * Returns the GroupManager employed by this WikiEngine. 881 * 882 * @since 2.3 883 * @return The current GroupManager instance. 884 * @deprecated use {@code getManager( GroupManager.class )} instead. 885 */ 886 @Deprecated 887 public GroupManager getGroupManager() { 888 return getManager( GroupManager.class ); 889 } 890 891 /** 892 * Returns the current {@link AdminBeanManager}. 893 * 894 * @return The current {@link AdminBeanManager}. 895 * @since 2.6 896 * @deprecated use {@code getManager( AdminBeanManager.class )} instead. 897 */ 898 @Deprecated 899 public AdminBeanManager getAdminBeanManager() { 900 return getManager( AdminBeanManager.class ); 901 } 902 903 /** 904 * Returns the AclManager employed by this WikiEngine. The AclManager is lazily initialized. 905 * <p> 906 * The AclManager implementing class may be set by the System property {@link #PROP_ACL_MANAGER_IMPL}. 907 * </p> 908 * 909 * @since 2.3 910 * @return The current AclManager. 911 * @deprecated use {@code getManager( AclManager.class )} instead. 912 */ 913 @Deprecated 914 public AclManager getAclManager() { 915 return getManager( AclManager.class ); 916 } 917 918 /** 919 * Returns the DifferenceManager so that texts can be compared. 920 * 921 * @return the difference manager. 922 * @deprecated use {@code getManager( DifferenceManager.class )} instead. 923 */ 924 @Deprecated 925 public DifferenceManager getDifferenceManager() { 926 return getManager( DifferenceManager.class ); 927 } 928 929 /** 930 * Returns the current EditorManager instance. 931 * 932 * @return The current EditorManager. 933 * @deprecated use {@code getManager( EditorManager.class )} instead. 934 */ 935 @Deprecated 936 public EditorManager getEditorManager() { 937 return getManager( EditorManager.class ); 938 } 939 940 /** 941 * Returns the current i18n manager. 942 * 943 * @return The current Intertan... Interante... Internatatializ... Whatever. 944 * @deprecated use {@code getManager( InternationalizationManager.class )} instead. 945 */ 946 @Deprecated 947 public InternationalizationManager getInternationalizationManager() { 948 return getManager( InternationalizationManager.class ); 949 } 950 951 /** {@inheritDoc} */ 952 @Override 953 public final synchronized void addWikiEventListener( final WikiEventListener listener ) { 954 WikiEventManager.addWikiEventListener( this, listener ); 955 } 956 957 /** {@inheritDoc} */ 958 @Override 959 public final synchronized void removeWikiEventListener( final WikiEventListener listener ) { 960 WikiEventManager.removeWikiEventListener( this, listener ); 961 } 962 963 /** 964 * Fires a WikiEngineEvent to all registered listeners. 965 * 966 * @param type the event type 967 */ 968 protected final void fireEvent( final int type ) { 969 if( WikiEventManager.isListening(this ) ) { 970 WikiEventManager.fireEvent( this, new WikiEngineEvent(this, type ) ); 971 } 972 } 973 974 /** 975 * Fires a WikiPageEvent to all registered listeners. 976 * 977 * @param type the event type 978 */ 979 protected final void firePageEvent( final int type, final String pageName ) { 980 if( WikiEventManager.isListening(this ) ) { 981 WikiEventManager.fireEvent(this,new WikiPageEvent(this, type, pageName ) ); 982 } 983 } 984 985 /** {@inheritDoc} */ 986 @Override 987 public void setAttribute( final String key, final Object value ) { 988 m_attributes.put( key, value ); 989 } 990 991 /** {@inheritDoc} */ 992 @Override 993 @SuppressWarnings( "unchecked" ) 994 public < T > T getAttribute( final String key ) { 995 return ( T )m_attributes.get( key ); 996 } 997 998 /** {@inheritDoc} */ 999 @Override 1000 @SuppressWarnings( "unchecked" ) 1001 public < T > T removeAttribute( final String key ) { 1002 return ( T )m_attributes.remove( key ); 1003 } 1004 1005}