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 ccb852bbefe68a9619b0c49daed8a2871ec2f493 Author: juanpablo <[email protected]> AuthorDate: Thu Dec 19 23:09:42 2019 +0100 JSPWIKI-120: PageRenamer renamed as WikiPageRenamer, with new PageRenamer extracted as interface of WikiPageRenamer --- .../src/main/java/org/apache/wiki/WikiEngine.java | 4 +- .../java/org/apache/wiki/content/PageRenamer.java | 302 +-------------------- .../src/main/resources/ini/classmappings.xml | 4 + .../test/java/org/apache/wiki/WikiEngineTest.java | 14 +- 4 files changed, 15 insertions(+), 309 deletions(-) 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 a37e3da..3258915 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/WikiEngine.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/WikiEngine.java @@ -635,10 +635,10 @@ public class WikiEngine { // try { if( TextUtil.getBooleanProperty( props, RSSGenerator.PROP_GENERATE_RSS,false ) ) { - m_rssGenerator = (RSSGenerator)ClassUtil.getMappedObject(RSSGenerator.class.getName(), this, props ); + m_rssGenerator = ClassUtil.getMappedObject( RSSGenerator.class.getName(), this, props ); } - m_pageRenamer = (PageRenamer)ClassUtil.getMappedObject(PageRenamer.class.getName(), this, props ); + m_pageRenamer = ClassUtil.getMappedObject( PageRenamer.class.getName(), this, props ); } catch( final Exception e ) { log.error( "Unable to start RSS generator - JSPWiki will still work, but there will be no RSS feed.", e ); } diff --git a/jspwiki-main/src/main/java/org/apache/wiki/content/PageRenamer.java b/jspwiki-main/src/main/java/org/apache/wiki/content/PageRenamer.java index 0bf86c9..c62b478 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/content/PageRenamer.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/content/PageRenamer.java @@ -18,26 +18,8 @@ */ package org.apache.wiki.content; -import org.apache.log4j.Logger; -import org.apache.wiki.InternalWikiException; import org.apache.wiki.WikiContext; -import org.apache.wiki.WikiEngine; -import org.apache.wiki.WikiPage; -import org.apache.wiki.api.exceptions.ProviderException; import org.apache.wiki.api.exceptions.WikiException; -import org.apache.wiki.attachment.Attachment; -import org.apache.wiki.event.WikiEventManager; -import org.apache.wiki.event.WikiPageRenameEvent; -import org.apache.wiki.parser.JSPWikiMarkupParser; -import org.apache.wiki.parser.MarkupParser; -import org.apache.wiki.util.TextUtil; - -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Provides page renaming functionality. Note that there used to be a similarly named class in 2.6, but due to unclear copyright, the @@ -45,12 +27,8 @@ import java.util.regex.Pattern; * * @since 2.8 */ -public class PageRenamer { +public interface PageRenamer { - private static final Logger log = Logger.getLogger( PageRenamer.class ); - - private boolean m_camelCase = false; - /** * Renames a page. * @@ -61,81 +39,7 @@ public class PageRenamer { * @return The final new name (in case it had to be modified) * @throws WikiException If the page cannot be renamed. */ - public String renamePage( final WikiContext context, final String renameFrom, final String renameTo, final boolean changeReferrers ) throws WikiException { - // Sanity checks first - if( renameFrom == null || renameFrom.length() == 0 ) { - throw new WikiException( "From name may not be null or empty" ); - } - if( renameTo == null || renameTo.length() == 0 ) { - throw new WikiException( "To name may not be null or empty" ); - } - - // Clean up the "to" -name so that it does not contain anything illegal - final String renameToClean = MarkupParser.cleanLink( renameTo.trim() ); - if( renameToClean.equals( renameFrom ) ) { - throw new WikiException( "You cannot rename the page to itself" ); - } - - // Preconditions: "from" page must exist, and "to" page must not yet exist. - final WikiEngine engine = context.getEngine(); - final WikiPage fromPage = engine.getPage( renameFrom ); - if( fromPage == null ) { - throw new WikiException("No such page "+renameFrom); - } - WikiPage toPage = engine.getPage( renameToClean ); - if( toPage != null ) { - throw new WikiException( "Page already exists " + renameToClean ); - } - - final Set< String > referrers = getReferencesToChange( fromPage, engine ); - - // Do the actual rename by changing from the frompage to the topage, including all of the attachments - // Remove references to attachments under old name - final List< Attachment > attachmentsOldName = engine.getAttachmentManager().listAttachments( fromPage ); - for( final Attachment att: attachmentsOldName ) { - final WikiPage fromAttPage = engine.getPage( att.getName() ); - engine.getReferenceManager().pageRemoved( fromAttPage ); - } - - engine.getPageManager().getProvider().movePage( renameFrom, renameToClean ); - if( engine.getAttachmentManager().attachmentsEnabled() ) { - engine.getAttachmentManager().getCurrentProvider().moveAttachmentsForPage( renameFrom, renameToClean ); - } - - // Add a comment to the page notifying what changed. This adds a new revision to the repo with no actual change. - toPage = engine.getPage( renameToClean ); - if( toPage == null ) { - throw new InternalWikiException( "Rename seems to have failed for some strange reason - please check logs!" ); - } - toPage.setAttribute( WikiPage.CHANGENOTE, fromPage.getName() + " ==> " + toPage.getName() ); - toPage.setAuthor( context.getCurrentUser().getName() ); - engine.getPageManager().putPageText( toPage, engine.getPureText( toPage ) ); - - // Update the references - engine.getReferenceManager().pageRemoved( fromPage ); - engine.updateReferences( toPage ); - - // Update referrers - if( changeReferrers ) { - updateReferrers( context, fromPage, toPage, referrers ); - } - - // re-index the page including its attachments - engine.getSearchManager().reindexPage( toPage ); - - final Collection< Attachment > attachmentsNewName = engine.getAttachmentManager().listAttachments( toPage ); - for( final Attachment att:attachmentsNewName ) { - final WikiPage toAttPage = engine.getPage( att.getName() ); - // add reference to attachment under new page name - engine.updateReferences( toAttPage ); - engine.getSearchManager().reindexPage( att ); - } - - firePageRenameEvent( renameFrom, renameToClean ); - - // Done, return the new name. - return renameToClean; - } + String renamePage( WikiContext context, String renameFrom, String renameTo, boolean changeReferrers ) throws WikiException; /** * Fires a WikiPageRenameEvent to all registered listeners. Currently not used internally by JSPWiki itself, but you can use it for @@ -144,206 +48,6 @@ public class PageRenamer { * @param oldName the former page name * @param newName the new page name */ - public void firePageRenameEvent( final String oldName, final String newName ) { - if( WikiEventManager.isListening(this) ) { - WikiEventManager.fireEvent(this, new WikiPageRenameEvent(this, oldName, newName ) ); - } - } - - /** - * This method finds all the pages which have anything to do with the fromPage and - * change any referrers it can figure out in that page. - * - * @param context WikiContext in which we operate - * @param fromPage The old page - * @param toPage The new page - */ - private void updateReferrers( final WikiContext context, final WikiPage fromPage, final WikiPage toPage, final Set< String > referrers ) { - if( referrers.isEmpty() ) { // No referrers - return; - } - - final WikiEngine engine = context.getEngine(); - for( String pageName : referrers ) { - // In case the page was just changed from under us, let's do this small kludge. - if( pageName.equals( fromPage.getName() ) ) { - pageName = toPage.getName(); - } - - final WikiPage p = engine.getPage( pageName ); - - final String sourceText = engine.getPureText( p ); - String newText = replaceReferrerString( context, sourceText, fromPage.getName(), toPage.getName() ); - - m_camelCase = TextUtil.getBooleanProperty( engine.getWikiProperties(), JSPWikiMarkupParser.PROP_CAMELCASELINKS, m_camelCase ); - if( m_camelCase ) { - newText = replaceCCReferrerString( context, newText, fromPage.getName(), toPage.getName() ); - } - - if( !sourceText.equals( newText ) ) { - p.setAttribute( WikiPage.CHANGENOTE, fromPage.getName()+" ==> "+toPage.getName() ); - p.setAuthor( context.getCurrentUser().getName() ); - - try { - engine.getPageManager().putPageText( p, newText ); - engine.updateReferences( p ); - } catch( final ProviderException e ) { - // We fail with an error, but we will try to continue to rename other referrers as well. - log.error("Unable to perform rename.",e); - } - } - } - } - - private Set<String> getReferencesToChange( final WikiPage fromPage, final WikiEngine engine ) { - final Set< String > referrers = new TreeSet<>(); - final Collection< String > r = engine.getReferenceManager().findReferrers( fromPage.getName() ); - if( r != null ) { - referrers.addAll( r ); - } - - try { - final List< Attachment > attachments = engine.getAttachmentManager().listAttachments( fromPage ); - for( final Attachment att : attachments ) { - final Collection< String > c = engine.getReferenceManager().findReferrers( att.getName() ); - if( c != null ) { - referrers.addAll( c ); - } - } - } catch( final ProviderException e ) { - // We will continue despite this error - log.error( "Provider error while fetching attachments for rename", e ); - } - return referrers; - } - - /** - * Replaces camelcase links. - */ - private String replaceCCReferrerString( final WikiContext context, final String sourceText, final String from, final String to ) { - final StringBuilder sb = new StringBuilder( sourceText.length()+32 ); - final Pattern linkPattern = Pattern.compile( "\\p{Lu}+\\p{Ll}+\\p{Lu}+[\\p{L}\\p{Digit}]*" ); - final Matcher matcher = linkPattern.matcher( sourceText ); - int start = 0; - - while( matcher.find( start ) ) { - final String match = matcher.group(); - sb.append( sourceText.substring( start, matcher.start() ) ); - final int lastOpenBrace = sourceText.lastIndexOf( '[', matcher.start() ); - final int lastCloseBrace = sourceText.lastIndexOf( ']', matcher.start() ); - - if( match.equals( from ) && lastCloseBrace >= lastOpenBrace ) { - sb.append( to ); - } else { - sb.append( match ); - } - - start = matcher.end(); - } - - sb.append( sourceText.substring( start ) ); - - return sb.toString(); - } - - private String replaceReferrerString( final WikiContext context, final String sourceText, final String from, final String to ) { - final StringBuilder sb = new StringBuilder( sourceText.length()+32 ); - - // This monstrosity just looks for a JSPWiki link pattern. But it is pretty cool for a regexp, isn't it? If you can - // understand this in a single reading, you have way too much time in your hands. - final Pattern linkPattern = Pattern.compile( "([\\[\\~]?)\\[([^\\|\\]]*)(\\|)?([^\\|\\]]*)(\\|)?([^\\|\\]]*)\\]" ); - final Matcher matcher = linkPattern.matcher( sourceText ); - int start = 0; - - while( matcher.find( start ) ) { - char charBefore = (char)-1; - - if( matcher.start() > 0 ) { - charBefore = sourceText.charAt( matcher.start() - 1 ); - } - - if( matcher.group(1).length() > 0 || charBefore == '~' || charBefore == '[' ) { - // Found an escape character, so I am escaping. - sb.append( sourceText.substring( start, matcher.end() ) ); - start = matcher.end(); - continue; - } - - String text = matcher.group(2); - String link = matcher.group(4); - final String attr = matcher.group(6); - - if( link.length() == 0 ) { - text = replaceSingleLink( context, text, from, to ); - } else { - link = replaceSingleLink( context, link, from, to ); - - // A very simple substitution, but should work for quite a few cases. - text = TextUtil.replaceString( text, from, to ); - } - - // - // Construct the new string - // - sb.append( sourceText.substring( start, matcher.start() ) ); - sb.append( "[" ).append( text ); - if( link.length() > 0 ) { - sb.append( "|" ).append( link ); - } - if( attr.length() > 0 ) { - sb.append( "|" ).append( attr ); - } - sb.append( "]" ); - - start = matcher.end(); - } - - sb.append( sourceText.substring( start ) ); - - return sb.toString(); - } - - /** - * This method does a correct replacement of a single link, taking into account anchors and attachments. - */ - private String replaceSingleLink( final WikiContext context, final String original, final String from, final String newlink ) { - final int hash = original.indexOf( '#' ); - final int slash = original.indexOf( '/' ); - String realLink = original; - - if( hash != -1 ) { - realLink = original.substring( 0, hash ); - } - if( slash != -1 ) { - realLink = original.substring( 0,slash ); - } + void firePageRenameEvent( String oldName, String newName ); - realLink = MarkupParser.cleanLink( realLink ); - final String oldStyleRealLink = MarkupParser.wikifyLink( realLink ); - - //WikiPage realPage = context.getEngine().getPage( reallink ); - // WikiPage p2 = context.getEngine().getPage( from ); - - // System.out.println(" "+reallink+" :: "+ from); - // System.out.println(" "+p+" :: "+p2); - - // - // Yes, these point to the same page. - // - if( realLink.equals( from ) || original.equals( from ) || oldStyleRealLink.equals( from ) ) { - // - // if the original contains blanks, then we should introduce a link, for example: [My Page] => [My Page|My Renamed Page] - final int blank = realLink.indexOf( " "); - - if( blank != -1 ) { - return original + "|" + newlink; - } - - return newlink + - ( ( hash > 0 ) ? original.substring( hash ) : "" ) + - ( ( slash > 0 ) ? original.substring( slash ) : "" ) ; - } - - return original; - } } diff --git a/jspwiki-main/src/main/resources/ini/classmappings.xml b/jspwiki-main/src/main/resources/ini/classmappings.xml index a0f1cc9..649f034 100644 --- a/jspwiki-main/src/main/resources/ini/classmappings.xml +++ b/jspwiki-main/src/main/resources/ini/classmappings.xml @@ -96,6 +96,10 @@ <mappedClass>org.apache.wiki.auth.authorize.GroupManager</mappedClass> </mapping> <mapping> + <requestedClass>org.apache.wiki.content.PageRenamer</requestedClass> + <mappedClass>org.apache.wiki.content.WikiPageRenamer</mappedClass> + </mapping> + <mapping> <requestedClass>org.apache.wiki.diff.DifferenceManager</requestedClass> <mappedClass>org.apache.wiki.diff.DifferenceManager</mappedClass> </mapping> diff --git a/jspwiki-main/src/test/java/org/apache/wiki/WikiEngineTest.java b/jspwiki-main/src/test/java/org/apache/wiki/WikiEngineTest.java index 6faa84f..aa6ab6b 100644 --- a/jspwiki-main/src/test/java/org/apache/wiki/WikiEngineTest.java +++ b/jspwiki-main/src/test/java/org/apache/wiki/WikiEngineTest.java @@ -19,12 +19,7 @@ package org.apache.wiki; -import java.io.File; -import java.util.Collection; -import java.util.Iterator; -import java.util.Properties; - -import org.apache.wiki.api.exceptions.NoRequiredPropertyException; +import net.sf.ehcache.CacheManager; import org.apache.wiki.attachment.Attachment; import org.apache.wiki.attachment.AttachmentManager; import org.apache.wiki.pages.PageManager; @@ -38,7 +33,10 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import net.sf.ehcache.CacheManager; +import java.io.File; +import java.util.Collection; +import java.util.Iterator; +import java.util.Properties; public class WikiEngineTest { @@ -766,7 +764,7 @@ public class WikiEngineTest WikiContext ctx = new WikiContext( m_engine, m_engine.getPage("OldNameTestPage") ); - m_engine.renamePage( ctx, "OldNameTestPage", "NewNameTestPage", true ); + m_engine.getPageRenamer().renamePage( ctx, "OldNameTestPage", "NewNameTestPage", true ); Assertions.assertFalse( m_engine.pageExists( "OldNameTestPage"), "did not vanish" ); Assertions.assertTrue( m_engine.pageExists( "NewNameTestPage"), "did not appear" );
