JSPWIKI-806: add the possibility of loading custom managers on WikiEngine (was: EntityManager Proposal)
* WikiEngine will look on classpath for a ini/classmappings-extra.xml file, with the same structure as ini/classmappings.xml
* if found, will register each requestedClass with its correspondent mappedClass
* these custom manager must have a no-arg constructor
* if there's a need to perform some initialization tasks querying the Engine, the custom manager should implement o.a.w.api.engine.Initializable and perform those tasks there
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/WikiEngine.java b/jspwiki-main/src/main/java/org/apache/wiki/WikiEngine.java
index 22ca833..7664c19 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/WikiEngine.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/WikiEngine.java
@@ -328,22 +328,22 @@
final Class< ? > urlclass = ClassUtil.findClass( "org.apache.wiki.url", urlConstructorClassName );
initComponent( CommandResolver.class, this, props );
- initComponent( urlclass.getName(), URLConstructor.class, ( Object )null );
+ initComponent( urlclass.getName(), URLConstructor.class );
initComponent( PageManager.class, this, props );
initComponent( PluginManager.class, this, props );
initComponent( DifferenceManager.class, this, props );
initComponent( AttachmentManager.class, this, props );
initComponent( VariableManager.class, props );
initComponent( SearchManager.class, this, props );
- initComponent( AuthenticationManager.class, ( Object )null );
- initComponent( AuthorizationManager.class, ( Object )null );
- initComponent( UserManager.class, ( Object )null );
- initComponent( GroupManager.class, ( Object )null );
+ initComponent( AuthenticationManager.class );
+ initComponent( AuthorizationManager.class );
+ initComponent( UserManager.class );
+ initComponent( GroupManager.class );
initComponent( EditorManager.class, this );
initComponent( ProgressManager.class, this );
- initComponent( aclClassName, AclManager.class, ( Object )null );
- initComponent( WorkflowManager.class, ( Object )null );
- initComponent( TasksManager.class, ( Object )null );
+ initComponent( aclClassName, AclManager.class );
+ initComponent( WorkflowManager.class );
+ initComponent( TasksManager.class );
initComponent( InternationalizationManager.class, this );
initComponent( TemplateManager.class, this, props );
initComponent( FilterManager.class, this, props );
@@ -388,12 +388,26 @@
log.error( "Unable to start RSS generator - JSPWiki will still work, but there will be no RSS feed.", e );
}
+ final Map< String, String > extraComponents = ClassUtil.getExtraClassMappings();
+ initExtraComponents( extraComponents );
+
fireEvent( WikiEngineEvent.INITIALIZED ); // initialization complete
log.info( "WikiEngine configured." );
m_isConfigured = true;
}
+ void initExtraComponents( final Map< String, String > extraComponents ) {
+ for( final Map.Entry< String, String > extraComponent : extraComponents.entrySet() ) {
+ try {
+ log.info( "Registering on WikiEngine " + extraComponent.getKey() + " as " + extraComponent.getValue() );
+ initComponent( extraComponent.getKey(), Class.forName( extraComponent.getValue() ) );
+ } catch( final Exception e ) {
+ log.error( "Unable to start " + extraComponent.getKey(), e );
+ }
+ }
+ }
+
< T > void initComponent( final Class< T > componentClass, final Object... initArgs ) throws Exception {
initComponent( componentClass.getName(), componentClass, initArgs );
}
@@ -405,10 +419,10 @@
} else {
component = ClassUtil.getMappedObject( componentInitClass, initArgs );
}
+ managers.put( componentClass, component );
if( Initializable.class.isAssignableFrom( componentClass ) ) {
( ( Initializable )component ).initialize( this, m_properties );
}
- managers.put( componentClass, component );
}
/** {@inheritDoc} */
diff --git a/jspwiki-util/src/main/java/org/apache/wiki/util/ClassUtil.java b/jspwiki-util/src/main/java/org/apache/wiki/util/ClassUtil.java
index bf51959..8fe90e2 100644
--- a/jspwiki-util/src/main/java/org/apache/wiki/util/ClassUtil.java
+++ b/jspwiki-util/src/main/java/org/apache/wiki/util/ClassUtil.java
@@ -52,29 +52,34 @@
/** The location of the classmappings.xml document. It will be searched for in the classpath. It's value is "{@value}". */
public static final String MAPPINGS = "ini/classmappings.xml";
- private static Map< String, String > c_classMappings = new ConcurrentHashMap<>();
+ /** The location of the classmappings-extra.xml document. It will be searched for in the classpath. It's value is "{@value}". */
+ public static final String MAPPINGS_EXTRA = "ini/classmappings-extra.xml";
+
+ /** Initialize the class mappings document. */
+ private static Map< String, String > c_classMappings = populateClassMappingsFrom( MAPPINGS );
+
+ /** Initialize the class mappings extra document. */
+ private static Map< String, String > c_classMappingsExtra = populateClassMappingsFrom( MAPPINGS_EXTRA ) ;
private static boolean classLoaderSetup = false;
private static ClassLoader loader = null;
-
- /*
- * Initialize the class mappings document.
- */
- static {
- final List< Element > nodes = XmlUtil.parse( MAPPINGS, "/classmappings/mapping" );
+ private static Map< String, String > populateClassMappingsFrom( final String fileLoc ) {
+ final Map< String, String > map = new ConcurrentHashMap<>();
+ final List< Element > nodes = XmlUtil.parse( fileLoc, "/classmappings/mapping" );
if( nodes.size() > 0 ) {
for( final Element f : nodes ) {
final String key = f.getChildText( "requestedClass" );
final String className = f.getChildText( "mappedClass" );
- c_classMappings.put( key, className );
+ map.put( key, className );
log.debug( "Mapped class '" + key + "' to class '" + className + "'" );
}
} else {
log.info( "Didn't find class mapping document in " + MAPPINGS );
}
+ return map;
}
/**
@@ -343,5 +348,9 @@
}
return false;
}
+
+ public static Map< String, String > getExtraClassMappings() {
+ return c_classMappingsExtra;
+ }
}