/* <> ReferredPagesPlugin Dirk Frederickx Aug 2004, Jan 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package brushed.jspwiki.plugin; import org.apache.log4j.Logger; import com.ecyrd.jspwiki.*; import com.ecyrd.jspwiki.plugin.*; import org.apache.oro.text.*; import org.apache.oro.text.regex.*; import java.util.*; /** * Displays the pages referring to the current page. * *

Parameters

* * * @author Dirk Frederickx */ public class ReferredPagesPlugin implements WikiPlugin { private static Logger log = Logger.getLogger( ReferredPagesPlugin.class ); private WikiEngine m_engine; private int m_depth; private HashSet m_exists = new HashSet(); private StringBuffer m_result = new StringBuffer(); private PatternMatcher m_matcher = new Perl5Matcher(); private Pattern m_wikiPluginPattern; private Pattern m_includePattern; private Pattern m_excludePattern; private boolean m_localLink = false; private boolean m_externalLink = false; private boolean m_attachmentLink = false; private boolean m_formatCompact = true; private boolean m_formatSort = false; private String m_outlinkImage = ""; /** If true, all outward links (external links) have a small link image appended. */ public static final String PROP_USEOUTLINKIMAGE = "jspwiki.translatorReader.useOutlinkImage"; public static final String PARAM_ROOT = "page"; public static final String PARAM_DEPTH = "depth"; public static final String PARAM_TYPE = "type"; public static final String PARAM_INCLUDE = "include"; public static final String PARAM_EXCLUDE = "exclude"; public static final String PARAM_FORMAT = "format"; public static final int MIN_DEPTH = 1; public static final int MAX_DEPTH = 8; public String execute( WikiContext context, Map params ) throws PluginException { m_engine = context.getEngine(); WikiPage page = context.getPage(); if( page == null ) return ""; // parse parameters String rootname = (String)params.get( PARAM_ROOT ); if( rootname == null ) rootname = page.getName() ; String linkType = (String)params.get( PARAM_TYPE ); if( linkType == null ) linkType = "local" ; if( linkType.indexOf( "local" ) >= 0 ) m_localLink = true; if( linkType.indexOf( "external" ) >= 0 ) m_externalLink = true; if( linkType.indexOf( "attachment" ) >= 0 ) m_attachmentLink = true; if( TextUtil.getBooleanProperty(m_engine.getWikiProperties(), PROP_USEOUTLINKIMAGE, true) ) { m_outlinkImage = "\"\""; } String format = (String)params.get( PARAM_FORMAT ); if( format == null) format = ""; if( format.indexOf( "full" ) >=0 ) m_formatCompact = false ; if( format.indexOf( "sort" ) >=0 ) m_formatSort = true ; m_depth = TextUtil.parseIntParameter( (String)params.get( PARAM_DEPTH ), MIN_DEPTH ); if( m_depth > MAX_DEPTH ) m_depth = MAX_DEPTH; String includePattern = (String) params.get(PARAM_INCLUDE); if( includePattern == null ) includePattern = ".*"; String excludePattern = (String) params.get(PARAM_EXCLUDE); if( excludePattern == null ) excludePattern = "^$"; log.debug( "Fetching referred pages for "+ rootname + " with a depth of "+ m_depth + " with include pattern of "+ includePattern + " with exclude pattern of "+ excludePattern ); // // do the actual work // String href = m_engine.getViewURL(rootname); String title = "ReferredPagesPlugin: type["+linkType+"] depth["+m_depth+ "] include["+includePattern+"] exclude["+excludePattern+ "] format["+(m_formatCompact ? "compact" : "full") + (m_formatSort ? " sort" : "") + "]"; m_result.append("
\n"); m_result.append("" + rootname + "\n"); m_exists.add(rootname); // pre compile all needed patterns // glob compiler : * is 0..n instance of any char -- more convenient as input // perl5 compiler : .* is 0..n instances of any char -- more powerful //PatternCompiler g_compiler = new GlobCompiler(); PatternCompiler compiler = new Perl5Compiler(); try { m_includePattern = compiler.compile(includePattern); m_excludePattern = compiler.compile(excludePattern); m_wikiPluginPattern = compiler.compile( "\\[{(INSERT\\s+)?(((brushed.)?(jspwiki.))?(plugin.))?ReferredPagesPlugin([^}])*}\\]" ); } catch( MalformedPatternException e ) { if (m_includePattern == null ) { throw new PluginException("Illegal include pattern detected."); } else if (m_excludePattern == null ) { throw new PluginException("Illegal exclude pattern detected."); } else { throw new PluginException("Illegal internal pattern detected."); } } // go get all referred links getReferredPages(rootname, 0); // close and finish m_result.append ("
\n" ) ; return m_result.toString() ; } /** * Retrieves a list of all referred pages. * Is called recursively depending on the depth parameter */ protected void getReferredPages(String pagename, int depth ) { if( depth >= m_depth ) return; //end of recursion if( pagename == null ) return; if( !m_engine.pageExists(pagename) ) return; // Retrieve the page as pure text // and remove all references to this plugin to avoid endless looping WikiPage page = m_engine.getPage( pagename ); if (page == null) return; String pagedata = Util.substitute( m_matcher, m_wikiPluginPattern, new Perl5Substitution(""), m_engine.getPureText( page ), Util.SUBSTITUTE_ALL ); // Retrieve all local, external and attachment links // code borrowed from the RPCHandler LinkCollector localCollector = new LinkCollector(); LinkCollector extCollector = new LinkCollector(); LinkCollector attCollector = new LinkCollector(); m_engine.textToHTML( new WikiContext(m_engine, page), pagedata, localCollector, extCollector, attCollector ); if( m_localLink ) handleLocalLink(localCollector, depth+1, pagename); if( depth != 0 ) return ; //only show external links for the first iteration if( m_externalLink ) handleOtherLink(extCollector,false); if( m_attachmentLink ) handleOtherLink(attCollector, true); } protected void handleLocalLink(LinkCollector localCollector, int depth, String pagename) { boolean UL = false; HashSet localLinkSet = new HashSet(); //needed to skip multiple links to the same page localLinkSet.add(pagename); ArrayList allLinks = new ArrayList(localCollector.getLinks()); if( m_formatSort ) Collections.sort(allLinks); for( Iterator i = allLinks.iterator(); i.hasNext(); ) { String link = (String) i.next() ; if( localLinkSet.contains( link ) ) continue; //skip multiple links to the same page localLinkSet.add( link ); if( !m_engine.pageExists( link ) ) continue; //hide links to non existing pages if( m_matcher.matches( link , m_excludePattern ) ) continue; if( !m_matcher.matches( link , m_includePattern ) ) continue; if( m_exists.contains( link ) ) { if( !m_formatCompact ) { if( !UL ) { UL = true; m_result.append("