This is an automated email from the ASF dual-hosted git repository. juanpablo pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/jspwiki.git
commit 5a69bda0b0e04f39293e8070c0c7cc4fe5247083 Author: Juan Pablo Santos RodrÃguez <[email protected]> AuthorDate: Fri Mar 11 14:37:42 2022 +0100 Introduce Engine Lifecycle Extensions - see https://jspwiki-wiki.apache.org/Wiki.jsp?page=HowToWriteAnEngineLifecycleExtension --- .../main/java/org/apache/wiki/api/core/Engine.java | 41 ++++++++++++- .../wiki/api/engine/EngineLifecycleExtension.java | 67 ++++++++++++++++++++++ .../api/engine/EngineLifecycleExtensionTest.java | 56 ++++++++++++++++++ .../engine/EngineLifecycleExtensionTestImpl.java | 42 ++++++++++++++ ...apache.wiki.api.engine.EngineLifecycleExtension | 1 + .../MarkdownSetupEngineLifecycleExtension.java | 52 +++++++++++++++++ ...apache.wiki.api.engine.EngineLifecycleExtension | 1 + .../MarkdownSetupEngineLifecycleExtensionTest.java | 42 ++++++++++++++ 8 files changed, 301 insertions(+), 1 deletion(-) diff --git a/jspwiki-api/src/main/java/org/apache/wiki/api/core/Engine.java b/jspwiki-api/src/main/java/org/apache/wiki/api/core/Engine.java index dab54a5..07e4fb4 100644 --- a/jspwiki-api/src/main/java/org/apache/wiki/api/core/Engine.java +++ b/jspwiki-api/src/main/java/org/apache/wiki/api/core/Engine.java @@ -19,7 +19,9 @@ package org.apache.wiki.api.core; import org.apache.logging.log4j.LogManager; +import org.apache.wiki.api.engine.EngineLifecycleExtension; import org.apache.wiki.api.exceptions.ProviderException; +import org.apache.wiki.api.exceptions.WikiException; import org.apache.wiki.event.WikiEventListener; import org.apache.wiki.util.TextUtil; @@ -37,6 +39,7 @@ import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Properties; +import java.util.ServiceLoader; /** @@ -413,7 +416,43 @@ public interface Engine { < T > T removeAttribute( String key ); /** - * Signals that the Engine will be shut down by the servlet container. + * Initializes the {@code Engine}, notifying all the {@link EngineLifecycleExtension}s. + * + * @param properties Wiki configuration properties. + * @throws WikiException if something happens while setting up the {@code Engine}. + */ + default void start( final Properties properties ) throws WikiException { + final ServiceLoader< EngineLifecycleExtension > loader = ServiceLoader.load( EngineLifecycleExtension.class ); + for( final EngineLifecycleExtension extension : loader ) { + extension.onInit( properties ); + } + initialize( properties ); + for( final EngineLifecycleExtension extension : loader ) { + extension.onStart( this, properties ); + } + } + + /** + * Shuts down the {@code Engine}, notifying all the {@link EngineLifecycleExtension}s. + */ + default void stop() { + final ServiceLoader< EngineLifecycleExtension > loader = ServiceLoader.load( EngineLifecycleExtension.class ); + for( final EngineLifecycleExtension extension : loader ) { + extension.onShutdown( this, getWikiProperties() ); + } + shutdown(); + } + + /** + * Sets up the application's running {@code Engine}. + * + * @param properties Wiki configuration properties. + * @throws WikiException if something happens while setting up the {@code Engine}. + */ + void initialize( Properties properties ) throws WikiException; + + /** + * Signals that the {@code Engine} will be shut down by the servlet container. */ void shutdown(); diff --git a/jspwiki-api/src/main/java/org/apache/wiki/api/engine/EngineLifecycleExtension.java b/jspwiki-api/src/main/java/org/apache/wiki/api/engine/EngineLifecycleExtension.java new file mode 100644 index 0000000..bf03fc3 --- /dev/null +++ b/jspwiki-api/src/main/java/org/apache/wiki/api/engine/EngineLifecycleExtension.java @@ -0,0 +1,67 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.wiki.api.engine; + +import org.apache.wiki.api.core.Engine; + +import java.util.Properties; + +/** + * <p>SPI used to notify JSPWiki extensions about {@link Engine}'s initialization & shutdown, without having to deep + * dive on {@link Engine}'s internals.</p> + * + * <p>Examples of {@code EngineLifecycleExtension}'s use cases: + * <ul> + * <li>Appending a plugin's classpath to {@code jspwiki.plugin.searchPath}, so it can be used as a drop-in, without further configuration.</li> + * <li>Providing default parameters for a custom extension.</li> + * <li>Setting up that expensive singleton, or disposing resources, without having to use or register a {@link org.apache.wiki.event.WikiEventListener WikiEventListener}.</li> + * </ul> + * </p> + * + * <p>As a concrete example, the markdown module uses an {@code EngineLifecycleExtension} to set up all the required properties + * if {@code jspwiki.syntax=markdown} is provided on the {@code jspwiki[-custom].properties file}.</p> + * + * <p>All methods are provided with a {@code default}, do-nothing implementation, so specific EngineLifecycleExtensions only have + * to provide implementations for the methods they're really interested in.</p> + */ +public interface EngineLifecycleExtension { + + /** + * Called before {@link Engine} initialization, after the wiki properties have been sought out. + * + * @param properties wiki configuration properties. + */ + default void onInit( final Properties properties ) {} + + /** + * Called after {@link Engine} initialization. + * + * @param properties wiki configuration properties. + * @param e JSPWiki's ready to be used {@link Engine}. + */ + default void onStart( final Engine e, final Properties properties ) {} + + /** + * Called before {@link Engine} shutdown. + * @param e JSPWiki's running {@link Engine}. + * @param properties wiki configuration properties. + */ + default void onShutdown( final Engine e, final Properties properties ) {} + +} diff --git a/jspwiki-api/src/test/java/org/apache/wiki/api/engine/EngineLifecycleExtensionTest.java b/jspwiki-api/src/test/java/org/apache/wiki/api/engine/EngineLifecycleExtensionTest.java new file mode 100644 index 0000000..e9589f4 --- /dev/null +++ b/jspwiki-api/src/test/java/org/apache/wiki/api/engine/EngineLifecycleExtensionTest.java @@ -0,0 +1,56 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.wiki.api.engine; + +import org.apache.wiki.api.core.Engine; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Properties; + + +@ExtendWith( MockitoExtension.class ) +public class EngineLifecycleExtensionTest { + + @Mock Engine engine; + + @Test + void shouldInvokeEngineLifecycleExtensionTestImpl() throws Exception { + final Properties properties = new Properties(); + Mockito.doAnswer( invocation -> { + final String actual = invocation.getArgument( 0, Properties.class ).getProperty( "test" ); + Assertions.assertEquals( "onInit", actual ); + return null; // void + } ).when( engine ).initialize( Mockito.any( Properties.class ) ); + Mockito.doReturn( properties ).when( engine ).getWikiProperties(); + Mockito.doCallRealMethod().when( engine ).start( Mockito.any( Properties.class ) ); + Mockito.doCallRealMethod().when( engine ).stop(); + + engine.start( properties ); + Assertions.assertEquals( "onStart", properties.getProperty( "test" ) ); + + engine.stop(); + Assertions.assertEquals( "onShutdown", properties.getProperty( "test" ) ); + } + +} diff --git a/jspwiki-api/src/test/java/org/apache/wiki/api/engine/EngineLifecycleExtensionTestImpl.java b/jspwiki-api/src/test/java/org/apache/wiki/api/engine/EngineLifecycleExtensionTestImpl.java new file mode 100644 index 0000000..5dbfddc --- /dev/null +++ b/jspwiki-api/src/test/java/org/apache/wiki/api/engine/EngineLifecycleExtensionTestImpl.java @@ -0,0 +1,42 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.wiki.api.engine; + +import org.apache.wiki.api.core.Engine; + +import java.util.Properties; + +public class EngineLifecycleExtensionTestImpl implements EngineLifecycleExtension { + + /** {@inheritDoc */ + public void onInit( final Properties properties ) { + properties.put( "test", "onInit" ); + } + + /** {@inheritDoc */ + public void onStart( final Engine e, final Properties properties ) { + properties.put( "test", "onStart" ); + } + + /** {@inheritDoc */ + public void onShutdown( final Engine e, final Properties properties ) { + properties.put( "test", "onShutdown" ); + } + +} diff --git a/jspwiki-api/src/test/resources/META-INF/services/org.apache.wiki.api.engine.EngineLifecycleExtension b/jspwiki-api/src/test/resources/META-INF/services/org.apache.wiki.api.engine.EngineLifecycleExtension new file mode 100644 index 0000000..9cfa45f --- /dev/null +++ b/jspwiki-api/src/test/resources/META-INF/services/org.apache.wiki.api.engine.EngineLifecycleExtension @@ -0,0 +1 @@ +org.apache.wiki.api.engine.EngineLifecycleExtensionTestImpl \ No newline at end of file diff --git a/jspwiki-markdown/src/main/java/org/apache/wiki/markdown/MarkdownSetupEngineLifecycleExtension.java b/jspwiki-markdown/src/main/java/org/apache/wiki/markdown/MarkdownSetupEngineLifecycleExtension.java new file mode 100644 index 0000000..76f3b43 --- /dev/null +++ b/jspwiki-markdown/src/main/java/org/apache/wiki/markdown/MarkdownSetupEngineLifecycleExtension.java @@ -0,0 +1,52 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.wiki.markdown; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.wiki.api.engine.EngineLifecycleExtension; + +import java.util.Properties; + + +/** + * {@link EngineLifecycleExtension} that sets up all the relevant properties to enable markdown syntax if the + * {@code jspwiki.syntax} property has been given, with the {@code markdown} value. + */ +public class MarkdownSetupEngineLifecycleExtension implements EngineLifecycleExtension { + + private static final Logger LOG = LogManager.getLogger( MarkdownSetupEngineLifecycleExtension.class ); + + /** {@inheritDoc} */ + @Override + public void onInit( final Properties properties ) { + if( "markdown".equalsIgnoreCase( properties.getProperty( "jspwiki.syntax" ) ) ) { + setWikiProperty( properties, "jspwiki.renderingManager.markupParser", "org.apache.wiki.parser.markdown.MarkdownParser" ); + setWikiProperty( properties, "jspwiki.renderingManager.renderer", "org.apache.wiki.render.markdown.MarkdownRenderer" ); + setWikiProperty( properties, "jspwiki.renderingManager.renderer.wysiwyg", "org.apache.wiki.render.markdown.MarkdownRenderer" ); + setWikiProperty( properties, "jspwiki.syntax.decorator", "org.apache.wiki.htmltowiki.syntax.markdown.MarkdownSyntaxDecorator" ); + } + } + + void setWikiProperty( final Properties properties, final String key, final String value ) { + properties.setProperty( key, value ); + LOG.info( "{} set to {}", key, value ); + } + +} diff --git a/jspwiki-markdown/src/main/resources/META-INF/services/org.apache.wiki.api.engine.EngineLifecycleExtension b/jspwiki-markdown/src/main/resources/META-INF/services/org.apache.wiki.api.engine.EngineLifecycleExtension new file mode 100644 index 0000000..766735d --- /dev/null +++ b/jspwiki-markdown/src/main/resources/META-INF/services/org.apache.wiki.api.engine.EngineLifecycleExtension @@ -0,0 +1 @@ +org.apache.wiki.markdown.MarkdownSetupEngineLifecycleExtension \ No newline at end of file diff --git a/jspwiki-markdown/src/test/java/org/apache/wiki/markdown/MarkdownSetupEngineLifecycleExtensionTest.java b/jspwiki-markdown/src/test/java/org/apache/wiki/markdown/MarkdownSetupEngineLifecycleExtensionTest.java new file mode 100644 index 0000000..6c2aecb --- /dev/null +++ b/jspwiki-markdown/src/test/java/org/apache/wiki/markdown/MarkdownSetupEngineLifecycleExtensionTest.java @@ -0,0 +1,42 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.wiki.markdown; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Properties; + +public class MarkdownSetupEngineLifecycleExtensionTest { + + @Test + void shouldSetUpMarkdownSupportIfJspwikiSyntaxPropertyIsGiven() { + final Properties properties = new Properties(); + properties.put( "jspwiki.syntax", "markdown" ); + final MarkdownSetupEngineLifecycleExtension sut = new MarkdownSetupEngineLifecycleExtension(); + sut.onInit( properties ); + Assertions.assertEquals( 5, properties.size() ); + Assertions.assertEquals( "org.apache.wiki.parser.markdown.MarkdownParser", properties.getProperty( "jspwiki.renderingManager.markupParser" ) ); + + properties.clear(); + sut.onInit( properties ); + Assertions.assertEquals( 0, properties.size() ); + } + +}
