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