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