You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by me...@apache.org on 2009/08/30 17:48:07 UTC
svn commit: r809361 - in /incubator/jspwiki/trunk: ./
src/WebContent/WEB-INF/classes/plugin/ src/java/org/apache/wiki/
src/java/org/apache/wiki/content/ src/java/org/apache/wiki/plugin/
tests/java/org/apache/wiki/plugin/
Author: metskem
Date: Sun Aug 30 15:48:06 2009
New Revision: 809361
URL: http://svn.apache.org/viewvc?rev=809361&view=rev
Log:
3.0.0-svn-150
* Introduced the new PageViewPlugin written by Andre van Dalen.
This plugin counts page views and presents the statistics on page views
See http://www.jspwiki.org/wiki/PageViewPlugin for the complete
documentation.
A bit of i18n work for the translators too.....
Added:
incubator/jspwiki/trunk/src/java/org/apache/wiki/plugin/PageViewPlugin.java
incubator/jspwiki/trunk/tests/java/org/apache/wiki/plugin/PageViewPluginTest.java
Modified:
incubator/jspwiki/trunk/ChangeLog
incubator/jspwiki/trunk/README
incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/plugin/PluginResources.properties
incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/plugin/PluginResources_nl.properties
incubator/jspwiki/trunk/src/java/org/apache/wiki/Release.java
incubator/jspwiki/trunk/src/java/org/apache/wiki/content/ReferenceManager.java
incubator/jspwiki/trunk/tests/java/org/apache/wiki/plugin/AllTests.java
Modified: incubator/jspwiki/trunk/ChangeLog
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/ChangeLog?rev=809361&r1=809360&r2=809361&view=diff
==============================================================================
--- incubator/jspwiki/trunk/ChangeLog (original)
+++ incubator/jspwiki/trunk/ChangeLog Sun Aug 30 15:48:06 2009
@@ -1,3 +1,16 @@
+2009-08-30 Harry Metske <me...@apache.org>
+
+ * 3.0.0-svn-150
+
+ * Introduced the new PageViewPlugin written by Andre van Dalen.
+ This plugin counts page views and presents the statistics on page views
+ See http://www.jspwiki.org/wiki/PageViewPlugin for the complete
+ documentation.
+ A bit of i18n work for the translators too.....
+
+ * a bit less verbosity in ReferenceManager.checkValueString(),
+ we now only dump the illegal page name instead of dumping a stacktrace.
+
2009-08-30 Dirk Frederickx <br...@apache.org>
* 3.0.0-svn-149 - align with 2.8.3-svn-16
Modified: incubator/jspwiki/trunk/README
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/README?rev=809361&r1=809360&r2=809361&view=diff
==============================================================================
--- incubator/jspwiki/trunk/README (original)
+++ incubator/jspwiki/trunk/README Sun Aug 30 15:48:06 2009
@@ -182,6 +182,7 @@
The following people (in alphabetical order) have contributed code to JSPWiki:
Andrew R. Jaquith
+Andre van Dalen
Arent-Jan Banck
Christoph Sauer
Chuck Smith
Modified: incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/plugin/PluginResources.properties
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/plugin/PluginResources.properties?rev=809361&r1=809360&r2=809361&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/plugin/PluginResources.properties (original)
+++ incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/plugin/PluginResources.properties Sun Aug 30 15:48:06 2009
@@ -108,4 +108,7 @@
plugin.interwikilinks.noconstruct=Unable to construct InterwikiLinks plugin output (see logs)
# UndefinedPagesPlugin
-plugin.undefined.parm.invalid=parameter is not valid for the UndefinedPagesPlugin
\ No newline at end of file
+plugin.undefined.parm.invalid=parameter is not valid for the UndefinedPagesPlugin
+
+# PageViewPlugin
+plugin.pageview.error=exception while executing PageViewPlugin, stacktrace follows
\ No newline at end of file
Modified: incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/plugin/PluginResources_nl.properties
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/plugin/PluginResources_nl.properties?rev=809361&r1=809360&r2=809361&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/plugin/PluginResources_nl.properties (original)
+++ incubator/jspwiki/trunk/src/WebContent/WEB-INF/classes/plugin/PluginResources_nl.properties Sun Aug 30 15:48:06 2009
@@ -117,4 +117,7 @@
plugin.interwikilinks.noconstruct=Kon InterwikiLinks plugin output niet genereren (kijk in de logs)
# UndefinedPagesPlugin
-plugin.undefined.parm.invalid=parameter is not geldig voor de UndefinedPagesPlugin
\ No newline at end of file
+plugin.undefined.parm.invalid=parameter is not geldig voor de UndefinedPagesPlugin
+
+# PageViewPlugin
+plugin.pageview.error=fout bij het uitvoeren van PageViewPlugin, stacktrace volgt
\ No newline at end of file
Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/Release.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/Release.java?rev=809361&r1=809360&r2=809361&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/Release.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/Release.java Sun Aug 30 15:48:06 2009
@@ -77,7 +77,7 @@
* <p>
* If the build identifier is empty, it is not added.
*/
- public static final String BUILD = "149";
+ public static final String BUILD = "150";
/**
* This is the generic version string you should use
Modified: incubator/jspwiki/trunk/src/java/org/apache/wiki/content/ReferenceManager.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/content/ReferenceManager.java?rev=809361&r1=809360&r2=809361&view=diff
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/content/ReferenceManager.java (original)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/content/ReferenceManager.java Sun Aug 30 15:48:06 2009
@@ -1062,10 +1062,11 @@
*/
private void checkValueString( String v )
{
+ int ch = 0;
boolean highChar = false;
for ( int i = 0; i < v.length(); i++ )
{
- int ch = v.charAt( i );
+ ch = v.charAt( i );
if ( ch < 32 || ch > 127 )
{
highChar = true;
@@ -1075,7 +1076,8 @@
}
if ( highChar )
{
- Thread.dumpStack();
+ System.out.println( "non Roman value detected in String " + v );
+// Thread.dumpStack();
}
}
Added: incubator/jspwiki/trunk/src/java/org/apache/wiki/plugin/PageViewPlugin.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/src/java/org/apache/wiki/plugin/PageViewPlugin.java?rev=809361&view=auto
==============================================================================
--- incubator/jspwiki/trunk/src/java/org/apache/wiki/plugin/PageViewPlugin.java (added)
+++ incubator/jspwiki/trunk/src/java/org/apache/wiki/plugin/PageViewPlugin.java Sun Aug 30 15:48:06 2009
@@ -0,0 +1,809 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ 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.plugin;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.wiki.content.ReferenceManager;
+import org.apache.wiki.util.RegExpUtil;
+import org.apache.wiki.util.TextUtil;
+import org.apache.wiki.WikiContext;
+import org.apache.wiki.WikiEngine;
+import org.apache.wiki.api.PluginException;
+import org.apache.wiki.api.WikiPage;
+import org.apache.wiki.event.WikiEngineEvent;
+import org.apache.wiki.event.WikiEvent;
+import org.apache.wiki.event.WikiEventListener;
+import org.apache.wiki.log.Logger;
+import org.apache.wiki.log.LoggerFactory;
+import org.apache.wiki.plugin.InitializablePlugin;
+import org.apache.wiki.plugin.PluginManager;
+import org.apache.wiki.plugin.WikiPlugin;
+import org.apache.wiki.providers.ProviderException;
+import org.apache.wiki.util.WikiBackgroundThread;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Counts the number of times each page has been viewed. Parameters:
+ * count=yes|no show=none|count|list entries=max number of list entries
+ * min=minimum page count to be listed sort=name|count Default values are
+ * show=none and sort=name.
+ *
+ * @since 2.8
+ */
+public class PageViewPlugin extends AbstractFilteredPlugin implements WikiPlugin, InitializablePlugin
+{
+ private static final Logger log = LoggerFactory.getLogger( PageViewPlugin.class );
+
+ /** The page view manager. */
+ private static PageViewManager c_singleton;
+
+ /** Constant for the 'count' parameter / value. */
+ private static final String PARAM_COUNT = "count";
+
+ /** Name of the 'entries' parameter. */
+ private static final String PARAM_MAX_ENTRIES = "entries";
+
+ /** Name of the 'max' parameter. */
+ private static final String PARAM_MAX_COUNT = "max";
+
+ /** Name of the 'min' parameter. */
+ private static final String PARAM_MIN_COUNT = "min";
+
+ /** Name of the 'refer' parameter. */
+ private static final String PARAM_REFER = "refer";
+
+ /** Name of the 'sort' parameter. */
+ private static final String PARAM_SORT = "sort";
+
+ /** Constant for the 'none' parameter value. */
+ private static final String STR_NONE = "none";
+
+ /** Constant for the 'list' parameter value. */
+ private static final String STR_LIST = "list";
+
+ /** Constant for the 'yes' parameter value. */
+ private static final String STR_YES = "yes";
+
+ /** Constant for empty string. */
+ private static final String STR_EMPTY = "";
+
+ /** Constant for Wiki markup separator. */
+ private static final String STR_SEPARATOR = "----";
+
+ /** Constant for comma-separated list separator. */
+ private static final String STR_COMMA = ",";
+
+ /** Constant for no-op glob exression. */
+ private static final String STR_GLOBSTAR = "*";
+
+ /** Constant for file storage. */
+ private static final String COUNTER_PAGE = "PageCount.txt";
+
+ /** Constant for storage interval in seconds. */
+ private static final int STORAGE_INTERVAL = 60;
+
+ /**
+ * Initialize the PageViewPlugin and its singleton.
+ *
+ * @param engine The wiki engine.
+ */
+ public void initialize( WikiEngine engine )
+ {
+
+ log.info( "initializing PageViewPlugin" );
+
+ synchronized( this )
+ {
+ if( c_singleton == null )
+ {
+
+ c_singleton = new PageViewManager( );
+
+ c_singleton.initialize( engine );
+ }
+ }
+ }
+
+ /**
+ * Cleanup the singleton reference.
+ */
+ private void cleanup()
+ {
+
+ log.info( "cleaning up PageView Manager" );
+
+ c_singleton = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String execute( WikiContext context, Map<String,Object> params ) throws PluginException
+ {
+ ResourceBundle rb = context.getBundle(WikiPlugin.CORE_PLUGINS_RESOURCEBUNDLE);
+ PageViewManager manager = c_singleton;
+ String result = STR_EMPTY;
+
+ if( manager != null )
+ {
+
+ try
+ {
+ result = manager.execute( context, params );
+ }
+ catch( ProviderException e )
+ {
+ log.error("exception while executing PageViewPlugin, stacktrace follows",e);
+ result = rb.getString( "plugin.pageview.error" );
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Page view manager, handling all storage.
+ */
+ public final class PageViewManager implements WikiEventListener
+ {
+ /** Are we initialized? */
+ private boolean m_initialized;
+
+ /** The page counters. */
+ private Map<String, Counter> m_counters;
+
+ /** The page counters in storage format. */
+ private Properties m_storage;
+
+ /** Are all changes stored? */
+ private boolean m_dirty;
+
+ /** The page count storage background thread. */
+ private Thread m_pageCountSaveThread;
+
+ /** The work directory. */
+ private String m_workDir ;
+
+ /** Comparator for descending sort on page count. */
+ private final Comparator<Object> m_compareCountDescending = new Comparator<Object>() {
+ public int compare( Object o1, Object o2 )
+ {
+ final int v1 = getCount( o1 );
+ final int v2 = getCount( o2 );
+ return (v1 == v2) ? ((String) o1).compareTo( (String) o2 ) : (v1 < v2) ? 1 : -1;
+ }
+ };
+
+ /**
+ * Initialize the page view manager.
+ *
+ * @param engine The wiki engine.
+ */
+ public synchronized void initialize( WikiEngine engine )
+ {
+
+ log.info( "initializing PageView Manager" );
+
+ m_workDir = engine.getWorkDir();
+
+ engine.addWikiEventListener( this );
+
+ if( m_counters == null )
+ {
+
+ // Load the counters into a collection
+ m_storage = new Properties();
+ m_counters = new TreeMap<String, Counter>();
+
+ loadCounters();
+ }
+
+ // backup counters every 5 minutes
+ if( m_pageCountSaveThread == null )
+ {
+ m_pageCountSaveThread = new CounterSaveThread( engine, 5 * STORAGE_INTERVAL, this );
+ m_pageCountSaveThread.start();
+ }
+
+ m_initialized = true;
+
+ }
+
+ /**
+ * Handle the shutdown event via the page counter thread.
+ *
+ */
+ private synchronized void handleShutdown()
+ {
+
+ log.info( "handleShutdown: The counter store thread was shut down." );
+
+ cleanup();
+
+ if( m_counters != null )
+ {
+
+ m_dirty = true;
+ storeCounters();
+
+ m_counters.clear();
+ m_counters = null;
+
+ m_storage.clear();
+ m_storage = null;
+ }
+
+ m_initialized = false;
+
+ m_pageCountSaveThread = null;
+ }
+
+ /**
+ * Inspect wiki events for shutdown.
+ *
+ * @param event The wiki event to inspect.
+ */
+ public void actionPerformed( WikiEvent event )
+ {
+
+ if( event instanceof WikiEngineEvent )
+ {
+ if( event.getType() == WikiEngineEvent.SHUTDOWN )
+ {
+
+ log.info( "Detected wiki engine shutdown" );
+ handleShutdown();
+ }
+ }
+ }
+
+ /**
+ * Count a page hit, present a pages' counter or output a list of
+ * pagecounts.
+ *
+ * @param context the wiki context
+ * @param params the plugin parameters
+ * @return String Wiki page snippet
+ * @throws PluginException Malformed pattern parameter.
+ * @throws ProviderException if something goes wrong with finding pages
+ */
+ public String execute( WikiContext context, Map<String,Object> params ) throws PluginException, ProviderException
+ {
+ WikiEngine engine = context.getEngine();
+ WikiPage page = context.getPage();
+ String result = STR_EMPTY;
+
+ if( page != null )
+ {
+ // get parameters
+ String pagename = page.getName();
+ String count = (String) params.get( PARAM_COUNT );
+ String show = (String) params.get( PARAM_SHOW );
+ int entries = TextUtil.parseIntParameter( (String) params.get( PARAM_MAX_ENTRIES ), Integer.MAX_VALUE );
+ final int max = TextUtil.parseIntParameter( (String) params.get( PARAM_MAX_COUNT ), Integer.MAX_VALUE );
+ final int min = TextUtil.parseIntParameter( (String) params.get( PARAM_MIN_COUNT ), Integer.MIN_VALUE );
+ String sort = (String) params.get( PARAM_SORT );
+ String body = (String) params.get( PluginManager.PARAM_BODY );
+ Pattern[] exclude = compileGlobs( PARAM_EXCLUDE, (String) params.get( PARAM_EXCLUDE ) );
+ Pattern[] include = compileGlobs( PARAM_INCLUDE, (String) params.get( PARAM_INCLUDE ) );
+ Pattern[] refer = compileGlobs( PARAM_REFER, (String) params.get( PARAM_REFER ) );
+ boolean increment = false;
+
+ // increment counter?
+ if( STR_YES.equals( count ) )
+ {
+ increment = true;
+ }
+ else
+ {
+ count = null;
+ }
+
+ // default increment counter?
+ if( (show == null || STR_NONE.equals( show )) && count == null )
+ {
+ increment = true;
+ }
+
+ // filter on referring pages?
+ Collection<String> referrers = null;
+
+ if( refer != null )
+ {
+ ReferenceManager refManager = engine.getReferenceManager();
+
+ Iterator iter = refManager.findCreated().iterator();
+
+ while ( iter != null && iter.hasNext() )
+ {
+
+ String name = (String) iter.next();
+ boolean use = false;
+
+ for( int n = 0; !use && n < refer.length; n++ )
+ {
+ Matcher matcher = refer[n].matcher( name );
+ use = matcher.matches( );
+ }
+
+ if( use )
+ {
+ Collection<String> refs = engine.getReferenceManager().findRefersTo( name );
+
+ if( refs != null && !refs.isEmpty() )
+ {
+ if( referrers == null )
+ {
+ referrers = new HashSet<String>();
+ }
+ referrers.addAll( refs );
+ }
+ }
+ }
+ }
+
+ synchronized( this )
+ {
+ Counter counter = m_counters.get( pagename );
+
+ // only count in view mode, keep storage values in sync
+ if( increment && WikiContext.VIEW.equalsIgnoreCase( context.getRequestContext() ) )
+ {
+ if( counter == null )
+ {
+ counter = new Counter();
+ m_counters.put( pagename, counter );
+ }
+ counter.increment();
+ m_storage.setProperty( pagename, counter.toString() );
+ m_dirty = true;
+ }
+
+ if( show == null || STR_NONE.equals( show ) )
+ {
+ // nothing to show
+
+ }
+ else if( PARAM_COUNT.equals( show ) )
+ {
+ // show page count
+ result = counter.toString();
+
+ }
+ else if( body != null && 0 < body.length() && STR_LIST.equals( show ) )
+ {
+ // show list of counts
+ String header = STR_EMPTY;
+ String line = body;
+ String footer = STR_EMPTY;
+ int start = body.indexOf( STR_SEPARATOR );
+
+ // split body into header, line, footer on ----
+ // separator
+ if( 0 < start )
+ {
+ header = body.substring( 0, start );
+
+ start = skipWhitespace( start + STR_SEPARATOR.length(), body );
+
+ int end = body.indexOf( STR_SEPARATOR, start );
+
+ if( start >= end )
+ {
+ line = body.substring( start );
+
+ }
+ else
+ {
+ line = body.substring( start, end );
+
+ end = skipWhitespace( end + STR_SEPARATOR.length(), body );
+
+ footer = body.substring( end );
+ }
+ }
+
+ // sort on name or count?
+ Map<String, Counter> sorted = m_counters;
+
+ if( sort != null && PARAM_COUNT.equals( sort ) )
+ {
+ sorted = new TreeMap<String, Counter>( m_compareCountDescending );
+
+ sorted.putAll( m_counters );
+ }
+
+ // build a messagebuffer with the list in wiki markup
+ StringBuffer buf = new StringBuffer( header );
+ MessageFormat fmt = new MessageFormat( line );
+ Object[] args = new Object[] { pagename, STR_EMPTY, STR_EMPTY };
+ Iterator<Map.Entry<String,Counter>> iter = sorted.entrySet().iterator();
+
+ while ( iter != null && 0 < entries && iter.hasNext() )
+ {
+
+ Entry<String, Counter> entry = iter.next();
+ String name = entry.getKey();
+
+ // check minimum count
+ final int value = entry.getValue().getValue();
+ boolean use = min <= value && value <= max;
+
+ // did we specify a refer-to page?
+ if( use && referrers != null )
+ {
+
+ use = referrers.contains( name );
+ }
+
+ // did we specify what pages to include?
+ if( use && include != null )
+ {
+ use = false;
+
+ for( int n = 0; !use && n < include.length; n++ )
+ {
+ Matcher matcher = include[n].matcher( name );
+ use = matcher.matches( );
+ }
+ }
+
+ // did we specify what pages to exclude?
+ if( use && null != exclude )
+ {
+ for( int n = 0; use && n < exclude.length; n++ )
+ {
+ Matcher matcher = exclude[n].matcher( name );
+ use &= !matcher.matches( );
+ }
+ }
+
+ if( use )
+ {
+ args[1] = engine.beautifyTitle( name );
+ args[2] = entry.getValue();
+
+ fmt.format( args, buf, null );
+
+ entries--;
+ }
+ }
+ buf.append( footer );
+
+ // let the engine render the list
+ result = engine.textToHTML( context, buf.toString() );
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Compile regexp parameter.
+ *
+ * @param name The name of the parameter.
+ * @param value The parameter value.
+ * @return Pattern[] The compiled patterns, or <code>null</code>.
+ * @throws PluginException On malformed patterns.
+ */
+ private Pattern[] compileGlobs( String name, String value ) throws PluginException
+ {
+
+ Pattern[] result = null;
+
+ if( value != null && 0 < value.length() && !STR_GLOBSTAR.equals( value ) )
+ {
+ try
+ {
+ String[] ptrns = StringUtils.split( value, STR_COMMA );
+
+ result = new Pattern[ptrns.length];
+
+ for( int n = 0; n < ptrns.length; n++ )
+ {
+ result[n] = Pattern.compile( RegExpUtil.globToPerl5( ptrns[n].toCharArray() ,RegExpUtil.DEFAULT_MASK ));
+ }
+ }
+ catch( PatternSyntaxException e )
+ {
+ throw new PluginException( "Parameter " + name + " has a pattern syntax error: " + e.getMessage() );
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Adjust ofsset skipping whitespace.
+ *
+ * @param offset The offset in value to adjust.
+ * @param value String in which offset points.
+ * @return int Adjusted offset into value.
+ */
+ private int skipWhitespace( int offset, String value )
+ {
+ while ( Character.isWhitespace( value.charAt( offset ) ) )
+ {
+ offset++;
+ }
+ return offset;
+ }
+
+ /**
+ * Retrieve a page count.
+ *
+ * @return int The page count for the given key.
+ * @param key the key for the Counter
+ */
+ protected int getCount( Object key )
+ {
+ return m_counters.get( key ).getValue();
+ }
+
+ /**
+ * Load the page view counters from file.
+ */
+ private void loadCounters()
+ {
+ if( m_counters != null && m_storage != null )
+ {
+
+ log.info( "loadCounters" );
+ synchronized( this )
+ {
+
+ InputStream fis = null;
+
+ try
+ {
+ fis = new FileInputStream( new File( m_workDir, COUNTER_PAGE ) );
+
+ m_storage.load( fis );
+
+ }
+ catch( IOException ioe )
+ {
+ log.error( "loadCounters: Can't load page counter store: " + ioe.getMessage() + " , will create a new one" );
+
+ }
+ finally
+ {
+ try
+ {
+ if( fis != null )
+ {
+ fis.close();
+ }
+ }
+ catch( Exception ignore )
+ {
+ /** ignore */
+ }
+ }
+
+ // Copy the collection into a sorted map
+ Iterator<Entry<Object,Object>> iter = m_storage.entrySet().iterator();
+
+ while ( iter != null && iter.hasNext() )
+ {
+ Entry<Object,Object> entry = iter.next();
+
+ m_counters.put( (String) entry.getKey(), new Counter( (String) entry.getValue() ) );
+ }
+
+
+ log.info( "loadCounters: counters.size=" + m_counters.size() );
+ }
+ }
+ }
+
+ /**
+ * Save the page view counters to file.
+ *
+ */
+ protected void storeCounters()
+ {
+ if( m_counters != null && m_storage != null && m_dirty )
+ {
+
+
+ log.info( "storeCounters: counters.size=" + m_counters.size() );
+ synchronized( this )
+ {
+
+ OutputStream fos = null;
+
+ // Write out the collection of counters
+ try
+ {
+ fos = new FileOutputStream( new File( m_workDir, COUNTER_PAGE ) );
+
+ m_storage.store( fos, "\n# The number of times each page has been viewed.\n# Do not modify.\n" );
+ fos.flush();
+
+ m_dirty = false;
+
+ }
+ catch( IOException ioe )
+ {
+ log.error( "storeCounters: Can't store counters: " + ioe.getMessage() );
+
+ }
+ finally
+ {
+ try
+ {
+ if( fos != null )
+ {
+ fos.close();
+ }
+ }
+ catch( Exception ignore )
+ {
+ /** ignore */
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Is the given thread still current?
+ *
+ * @return boolean <code>true</code> iff the thread is still the current
+ * background thread.
+ * @param thrd
+ */
+ private synchronized boolean isRunning( Thread thrd )
+ {
+ return m_initialized && thrd == m_pageCountSaveThread;
+ }
+
+ }
+
+ /**
+ * Counter for page hits collection.
+ */
+ private static final class Counter
+ {
+
+ /** The count value. */
+ private int m_count;
+
+ /**
+ * Create a new counter.
+ */
+ public Counter()
+ {
+ }
+
+ /**
+ * Create and initialise a new counter.
+ *
+ * @param value Count value.
+ */
+ public Counter( String value )
+ {
+
+ setValue( value );
+ }
+
+ /**
+ * Increment counter.
+ */
+ public void increment()
+ {
+ m_count++;
+ }
+
+ /**
+ * Get the count value.
+ *
+ * @return int
+ */
+ public int getValue()
+ {
+
+ return m_count;
+ }
+
+ /**
+ * Set the count value.
+ *
+ * @param value String representation of the count.
+ */
+ public void setValue( String value )
+ {
+ try
+ {
+ m_count = Integer.parseInt( value );
+
+ }
+ catch( Exception ignore )
+ {
+ m_count = 0;
+ }
+ }
+
+ /**
+ * @return String String representation of the count.
+ */
+ public String toString()
+ {
+ return String.valueOf( m_count );
+ }
+ }
+
+ /**
+ * Background thread storing the page counters.
+ */
+ static final class CounterSaveThread extends WikiBackgroundThread
+ {
+
+ /** The page view manager. */
+ private final PageViewManager m_manager;
+
+ /**
+ * Create a wiki background thread to store the page counters.
+ *
+ * @param engine The wiki engine.
+ * @param interval Delay in seconds between saves.
+ * @param pageViewManager
+ */
+ public CounterSaveThread( WikiEngine engine, int interval, PageViewManager pageViewManager )
+ {
+
+ super( engine, interval );
+
+ if( pageViewManager == null )
+ {
+ throw new IllegalArgumentException( "Manager cannot be null" );
+ }
+
+ m_manager = pageViewManager;
+ }
+
+ /**
+ * Save the page counters to file.
+ */
+ public void backgroundTask()
+ {
+
+ if( m_manager.isRunning( this ) )
+ {
+ m_manager.storeCounters();
+ }
+ }
+ }
+}
Modified: incubator/jspwiki/trunk/tests/java/org/apache/wiki/plugin/AllTests.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/java/org/apache/wiki/plugin/AllTests.java?rev=809361&r1=809360&r2=809361&view=diff
==============================================================================
--- incubator/jspwiki/trunk/tests/java/org/apache/wiki/plugin/AllTests.java (original)
+++ incubator/jspwiki/trunk/tests/java/org/apache/wiki/plugin/AllTests.java Sun Aug 30 15:48:06 2009
@@ -51,6 +51,7 @@
suite.addTest( RecentChangesPluginTest.suite() );
suite.addTest( IndexPluginTest.suite() );
suite.addTest( InterWikiLinksPluginTest.suite() );
+ suite.addTest( PageViewPluginTest.suite() );
return suite;
}
Added: incubator/jspwiki/trunk/tests/java/org/apache/wiki/plugin/PageViewPluginTest.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/java/org/apache/wiki/plugin/PageViewPluginTest.java?rev=809361&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/java/org/apache/wiki/plugin/PageViewPluginTest.java (added)
+++ incubator/jspwiki/trunk/tests/java/org/apache/wiki/plugin/PageViewPluginTest.java Sun Aug 30 15:48:06 2009
@@ -0,0 +1,204 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ 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.plugin;
+
+import java.util.Properties;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.framework.Test;
+
+import org.apache.wiki.TestEngine;
+import org.apache.wiki.WikiContext;
+import org.apache.wiki.api.WikiPage;
+import org.apache.wiki.providers.ProviderException;
+
+public class PageViewPluginTest extends TestCase
+
+{
+ Properties props = new Properties();
+
+ TestEngine testEngine;
+
+ WikiContext context;
+
+ PluginManager manager;
+
+ public void setUp() throws Exception
+ {
+ props.load( TestEngine.findTestProperties() );
+
+ testEngine = new TestEngine( props );
+
+ // create pages that should be counted
+ testEngine.saveText( "TestPage01", "this is test page 01 [{PageViewPlugin}]" );
+ testEngine.saveText( "TestPage02", "this is test page 02 [{PageViewPlugin}]" );
+
+ manager = new PluginManager( testEngine, props );
+ }
+
+ public void tearDown()
+ {
+ try
+ {
+ testEngine.deletePage( "TestPage01" );
+ testEngine.deletePage( "TestPage02" );
+ testEngine.deletePage( "PageViews" );
+ }
+ catch( ProviderException e )
+ {
+ e.printStackTrace();
+ }
+ TestEngine.emptyWorkDir();
+ }
+
+ public void testShowCountsBasic() throws Exception
+ {
+ WikiPage page1 = testEngine.getPage( "TestPage01" );
+ WikiContext context1 = testEngine.getWikiContextFactory().newViewContext( page1 );
+ WikiPage page2 = testEngine.getPage( "TestPage02" );
+ WikiContext context2 = testEngine.getWikiContextFactory().newViewContext( page2 );
+
+ // generate counts:
+ testEngine.getHTML( context1, page1 );
+ testEngine.getHTML( context2, page2 );
+ testEngine.getHTML( context2, page2 );
+
+ // mind the double \n in the following string:
+ String pageViewPageContent = "[{PageViewPlugin show='list''\n\n* {1} ({2} views)\n}]";
+ testEngine.saveText( "PageViews", pageViewPageContent );
+
+ WikiPage pageviews = testEngine.getPage( "PageViews" );
+ WikiContext contextPV = testEngine.getWikiContextFactory().newViewContext( pageviews );
+
+ String result = testEngine.getHTML( contextPV, pageviews );
+ // System.out.println( result );
+
+ assertTrue( result.contains( "TestPage01</a> (2 views)" ) );
+
+ assertTrue( result.contains( "TestPage02</a> (3 views)" ) );
+ }
+
+ public void testShowCountsExclude() throws Exception
+ {
+ testEngine.saveText( "TestPageExcluded", "this is test page that should be excluded [{PageViewPlugin}]" );
+
+ WikiPage page1 = testEngine.getPage( "TestPage01" );
+ WikiContext context1 = testEngine.getWikiContextFactory().newViewContext( page1 );
+ WikiPage page2 = testEngine.getPage( "TestPage02" );
+ WikiContext context2 = testEngine.getWikiContextFactory().newViewContext( page2 );
+
+ // generate counts:
+ testEngine.getHTML( context1, page1 );
+ testEngine.getHTML( context2, page2 );
+
+ // mind the double \n in the following string:
+ String pageViewPageContent = "[{PageViewPlugin show='list' exclude='TestPageExcl*' '\n\n* {1} ({2} views)\n}]";
+ testEngine.saveText( "PageViews", pageViewPageContent );
+
+ WikiPage pageviews = testEngine.getPage( "PageViews" );
+ WikiContext contextPV = testEngine.getWikiContextFactory().newViewContext( pageviews );
+
+ String result = testEngine.getHTML( contextPV, pageviews );
+ // System.out.println( result );
+
+ assertTrue( result.contains( "TestPage01" ) );
+
+ // this page should not have been shown:
+ assertFalse( result.contains( "TestPageExcluded" ) );
+
+ testEngine.deletePage( "TestPageExcluded" );
+ }
+
+ public void testShowCountsSorted() throws Exception
+ {
+ WikiPage page1 = testEngine.getPage( "TestPage01" );
+ WikiContext context1 = testEngine.getWikiContextFactory().newViewContext( page1 );
+ WikiPage page2 = testEngine.getPage( "TestPage02" );
+ WikiContext context2 = testEngine.getWikiContextFactory().newViewContext( page2 );
+
+ // generate counts:
+ testEngine.getHTML( context1, page1 );
+ testEngine.getHTML( context2, page2 );
+ testEngine.getHTML( context2, page2 );
+
+ // mind the double \n in the following string:
+ String pageViewPageContent = "[{PageViewPlugin show='list' sort=count '\n\n* {1} ({2} views)\n}]";
+ testEngine.saveText( "PageViews", pageViewPageContent );
+
+ WikiPage pageviews = testEngine.getPage( "PageViews" );
+ WikiContext contextPV = testEngine.getWikiContextFactory().newViewContext( pageviews );
+
+ String result = testEngine.getHTML( contextPV, pageviews );
+ // System.out.println( result );
+
+ int start1 = result.indexOf( "TestPage01" );
+ int start2 = result.indexOf( "TestPage02" );
+
+ // page2 should be showed before page1
+ assertTrue( start2 < start1 );
+ }
+
+ public void testShowCountEntries() throws Exception
+ {
+ // create pages that should be counted
+ testEngine.saveText( "TestPage03", "this is test page 03 [{PageViewPlugin}]" );
+ testEngine.saveText( "TestPage04", "this is test page 04 [{PageViewPlugin}]" );
+
+ WikiPage page1 = testEngine.getPage( "TestPage01" );
+ WikiContext context1 = testEngine.getWikiContextFactory().newViewContext( page1 );
+ WikiPage page2 = testEngine.getPage( "TestPage02" );
+ WikiContext context2 = testEngine.getWikiContextFactory().newViewContext( page2 );
+ WikiPage page3 = testEngine.getPage( "TestPage03" );
+ WikiContext context3 = testEngine.getWikiContextFactory().newViewContext( page3 );
+ WikiPage page4 = testEngine.getPage( "TestPage04" );
+ WikiContext context4 = testEngine.getWikiContextFactory().newViewContext( page4 );
+
+ // generate counts:
+ testEngine.getHTML( context1, page1 );
+ testEngine.getHTML( context2, page2 );
+ testEngine.getHTML( context2, page2 );
+ testEngine.getHTML( context3, page3 );
+ testEngine.getHTML( context4, page4 );
+
+ // mind the double \n in the following string:
+ String pageViewPageContent = "[{PageViewPlugin show='list' entries=3'\n\n* {1} ({2} views)\n}]";
+ testEngine.saveText( "PageViews", pageViewPageContent );
+
+ WikiPage pageviews = testEngine.getPage( "PageViews" );
+ WikiContext contextPV = testEngine.getWikiContextFactory().newViewContext( pageviews );
+
+ String result = testEngine.getHTML( contextPV, pageviews );
+ // System.out.println( result );
+
+ assertTrue( result.contains( "TestPage03" ) );
+
+ assertFalse( result.contains( "TestPage04" ) );
+
+ testEngine.deletePage( "TestPage03" );
+ testEngine.deletePage( "TestPage04" );
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite( PageViewPluginTest.class );
+ }
+}