You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by aj...@apache.org on 2008/02/13 06:54:24 UTC
svn commit: r627255 [32/41] - in
/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src: ./ com/ com/ecyrd/
com/ecyrd/jspwiki/ com/ecyrd/jspwiki/action/ com/ecyrd/jspwiki/attachment/
com/ecyrd/jspwiki/auth/ com/ecyrd/jspwiki/auth/acl/ com/ecyrd/jspwiki...
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/LuceneSearchProvider.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/LuceneSearchProvider.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/LuceneSearchProvider.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/LuceneSearchProvider.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,760 @@
+/*
+JSPWiki - a JSP-based WikiWiki clone.
+
+Copyright (C) 2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+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 com.ecyrd.jspwiki.search;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.MultiFieldQueryParser;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.highlight.Highlighter;
+import org.apache.lucene.search.highlight.QueryScorer;
+import org.apache.lucene.search.highlight.SimpleHTMLEncoder;
+import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+
+import com.ecyrd.jspwiki.*;
+import com.ecyrd.jspwiki.attachment.Attachment;
+import com.ecyrd.jspwiki.attachment.AttachmentManager;
+import com.ecyrd.jspwiki.parser.MarkupParser;
+import com.ecyrd.jspwiki.providers.ProviderException;
+import com.ecyrd.jspwiki.providers.WikiPageProvider;
+import com.ecyrd.jspwiki.util.ClassUtil;
+import com.ecyrd.jspwiki.util.WatchDog;
+import com.ecyrd.jspwiki.util.WikiBackgroundThread;
+
+/**
+ * Interface for the search providers that handle searching the Wiki
+ *
+ * @author Arent-Jan Banck
+ * @since 2.2.21.
+ */
+public class LuceneSearchProvider implements SearchProvider
+{
+ protected static final Logger log = Logger.getLogger(LuceneSearchProvider.class);
+
+ private WikiEngine m_engine;
+
+ // Lucene properties.
+
+ /** Which analyzer to use. Default is StandardAnalyzer. */
+ public static final String PROP_LUCENE_ANALYZER = "jspwiki.lucene.analyzer";
+
+ private static final String PROP_LUCENE_INDEXDELAY = "jspwiki.lucene.indexdelay";
+ private static final String PROP_LUCENE_INITIALDELAY = "jspwiki.lucene.initialdelay";
+
+ private String m_analyzerClass = "org.apache.lucene.analysis.standard.StandardAnalyzer";
+
+ private static final String LUCENE_DIR = "lucene";
+
+ /**
+ * Number of page updates before we optimize the index.
+ */
+ public static final int LUCENE_OPTIMIZE_COUNT = 10;
+ protected static final String LUCENE_ID = "id";
+ protected static final String LUCENE_PAGE_CONTENTS = "contents";
+ protected static final String LUCENE_AUTHOR = "author";
+ protected static final String LUCENE_ATTACHMENTS = "attachment";
+ protected static final String LUCENE_PAGE_NAME = "name";
+
+ private String m_luceneDirectory = null;
+ private int m_updateCount = 0;
+ protected Vector<Object[]> m_updates = new Vector<Object[]>(); // Vector because multi-threaded.
+
+ /** Maximum number of fragments from search matches. */
+ private static final int MAX_FRAGMENTS = 3;
+
+ private static String c_punctuationSpaces = StringUtils.repeat(" ", MarkupParser.PUNCTUATION_CHARS_ALLOWED.length() );
+
+ /**
+ * {@inheritDoc}
+ */
+ public void initialize(WikiEngine engine, Properties props)
+ throws NoRequiredPropertyException, IOException
+ {
+ m_engine = engine;
+
+ m_luceneDirectory = engine.getWorkDir()+File.separator+LUCENE_DIR;
+
+ int initialDelay = TextUtil.getIntegerProperty( props, PROP_LUCENE_INITIALDELAY, LuceneUpdater.INITIAL_DELAY );
+ int indexDelay = TextUtil.getIntegerProperty( props, PROP_LUCENE_INDEXDELAY, LuceneUpdater.INDEX_DELAY );
+
+ m_analyzerClass = TextUtil.getStringProperty( props, PROP_LUCENE_ANALYZER, m_analyzerClass );
+ // FIXME: Just to be simple for now, we will do full reindex
+ // only if no files are in lucene directory.
+
+ File dir = new File(m_luceneDirectory);
+
+ log.info("Lucene enabled, cache will be in: "+dir.getAbsolutePath());
+
+ try
+ {
+ if( !dir.exists() )
+ {
+ dir.mkdirs();
+ }
+
+ if( !dir.exists() || !dir.canWrite() || !dir.canRead() )
+ {
+ log.error("Cannot write to Lucene directory, disabling Lucene: "+dir.getAbsolutePath());
+ throw new IOException( "Invalid Lucene directory." );
+ }
+
+ String[] filelist = dir.list();
+
+ if( filelist == null )
+ {
+ throw new IOException( "Invalid Lucene directory: cannot produce listing: "+dir.getAbsolutePath());
+ }
+ }
+ catch ( IOException e )
+ {
+ log.error("Problem while creating Lucene index - not using Lucene.", e);
+ }
+
+ // Start the Lucene update thread, which waits first
+ // for a little while before starting to go through
+ // the Lucene "pages that need updating".
+ LuceneUpdater updater = new LuceneUpdater( m_engine, this, initialDelay, indexDelay );
+ updater.start();
+ }
+
+ /**
+ * Returns the handling engine.
+ *
+ * @return Current WikiEngine
+ */
+ protected WikiEngine getEngine()
+ {
+ return m_engine;
+ }
+
+ /**
+ * Performs a full Lucene reindex, if necessary.
+ *
+ * @throws IOException If there's a problem during indexing
+ */
+ protected void doFullLuceneReindex()
+ throws IOException
+ {
+ File dir = new File(m_luceneDirectory);
+
+ String[] filelist = dir.list();
+
+ if( filelist == null )
+ {
+ throw new IOException( "Invalid Lucene directory: cannot produce listing: "+dir.getAbsolutePath());
+ }
+
+ try
+ {
+ if( filelist.length == 0 )
+ {
+ //
+ // No files? Reindex!
+ //
+ Date start = new Date();
+ IndexWriter writer = null;
+
+ log.info("Starting Lucene reindexing, this can take a couple minutes...");
+
+ //
+ // Do lock recovery, in case JSPWiki was shut down forcibly
+ //
+ Directory luceneDir = FSDirectory.getDirectory(dir,false);
+
+ if( IndexReader.isLocked(luceneDir) )
+ {
+ log.info("JSPWiki was shut down while Lucene was indexing - unlocking now.");
+ IndexReader.unlock( luceneDir );
+ }
+
+ try
+ {
+ writer = new IndexWriter( m_luceneDirectory,
+ getLuceneAnalyzer(),
+ true );
+ Collection<WikiPage> allPages = m_engine.getPageManager().getAllPages();
+
+ for( WikiPage page : allPages )
+ {
+ String text = m_engine.getPageManager().getPageText( page.getName(),
+ WikiProvider.LATEST_VERSION );
+ luceneIndexPage( page, text, writer );
+ }
+
+ Collection<Attachment> allAttachments = m_engine.getAttachmentManager().getAllAttachments();
+ for( Attachment att : allAttachments )
+ {
+ String text = getAttachmentContent( att.getName(),
+ WikiProvider.LATEST_VERSION );
+ luceneIndexPage( att, text, writer );
+ }
+
+ writer.optimize();
+ }
+ finally
+ {
+ try
+ {
+ if( writer != null ) writer.close();
+ }
+ catch( IOException e ) {}
+ }
+
+ Date end = new Date();
+ log.info("Full Lucene index finished in " +
+ (end.getTime() - start.getTime()) + " milliseconds.");
+ }
+ else
+ {
+ log.info("Files found in Lucene directory, not reindexing.");
+ }
+ }
+ catch( NoClassDefFoundError e )
+ {
+ log.info("Lucene libraries do not exist - not using Lucene.");
+ }
+ catch ( IOException e )
+ {
+ log.error("Problem while creating Lucene index - not using Lucene.", e);
+ }
+ catch ( ProviderException e )
+ {
+ log.error("Problem reading pages while creating Lucene index (JSPWiki won't start.)", e);
+ throw new IllegalArgumentException("unable to create Lucene index");
+ }
+ catch( ClassNotFoundException e )
+ {
+ log.error("Illegal Analyzer specified:",e);
+ }
+ catch( Exception e )
+ {
+ log.error("Unable to start lucene",e);
+ }
+
+ }
+
+ /**
+ * Fetches the attachment content from the repository.
+ * Content is flat text that can be used for indexing/searching or display
+ */
+ protected String getAttachmentContent( String attachmentName, int version )
+ {
+ AttachmentManager mgr = m_engine.getAttachmentManager();
+
+ try
+ {
+ Attachment att = mgr.getAttachmentInfo( attachmentName, version );
+ //FIXME: Find out why sometimes att is null
+ if(att != null)
+ {
+ return getAttachmentContent( att );
+ }
+ }
+ catch (ProviderException e)
+ {
+ log.error("Attachment cannot be loaded", e);
+ }
+ // Something was wrong, no result is returned.
+ return null;
+ }
+
+ /**
+ * @param att Attachment to get content for. Filename extension is used to determine the type of the attachment.
+ * @return String representing the content of the file.
+ * FIXME This is a very simple implementation of some text-based attachment, mainly used for testing.
+ * This should be replaced /moved to Attachment search providers or some other 'plugable' wat to search attachments
+ */
+ protected String getAttachmentContent( Attachment att )
+ {
+ AttachmentManager mgr = m_engine.getAttachmentManager();
+ //FIXME: Add attachment plugin structure
+
+ String filename = att.getFileName();
+
+ if(filename.endsWith(".txt") ||
+ filename.endsWith(".xml") ||
+ filename.endsWith(".ini") ||
+ filename.endsWith(".html"))
+ {
+ InputStream attStream;
+
+ try
+ {
+ attStream = mgr.getAttachmentStream( att );
+
+ StringWriter sout = new StringWriter();
+ FileUtil.copyContents( new InputStreamReader(attStream), sout );
+
+ attStream.close();
+ sout.close();
+
+ return sout.toString();
+ }
+ catch (ProviderException e)
+ {
+ log.error("Attachment cannot be loaded", e);
+ return null;
+ }
+ catch (IOException e)
+ {
+ log.error("Attachment cannot be loaded", e);
+ return null;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Updates the lucene index for a single page.
+ *
+ * @param page The WikiPage to check
+ * @param text The page text to index.
+ */
+ protected synchronized void updateLuceneIndex( WikiPage page, String text )
+ {
+ IndexWriter writer = null;
+
+ log.debug("Updating Lucene index for page '" + page.getName() + "'...");
+
+ try
+ {
+ pageRemoved(page);
+
+ // Now add back the new version.
+ writer = new IndexWriter(m_luceneDirectory, getLuceneAnalyzer(), false);
+ luceneIndexPage(page, text, writer);
+ m_updateCount++;
+ if( m_updateCount >= LUCENE_OPTIMIZE_COUNT )
+ {
+ writer.optimize();
+ m_updateCount = 0;
+ }
+ }
+ catch ( IOException e )
+ {
+ log.error("Unable to update page '" + page.getName() + "' from Lucene index", e);
+ }
+ catch( Exception e )
+ {
+ log.error("Unexpected Lucene exception - please check configuration!",e);
+ }
+ finally
+ {
+ try
+ {
+ if( writer != null ) writer.close();
+ }
+ catch( IOException e ) {}
+ }
+
+ log.debug("Done updating Lucene index for page '" + page.getName() + "'.");
+ }
+
+
+ private Analyzer getLuceneAnalyzer()
+ throws ClassNotFoundException,
+ InstantiationException,
+ IllegalAccessException
+ {
+ Class clazz = ClassUtil.findClass( "", m_analyzerClass );
+ Analyzer analyzer = (Analyzer)clazz.newInstance();
+ return analyzer;
+ }
+
+ /**
+ * Indexes page using the given IndexWriter.
+ *
+ * @param page WikiPage
+ * @param text Page text to index
+ * @param writer The Lucene IndexWriter to use for indexing
+ * @return the created index Document
+ * @throws IOException If there's an indexing problem
+ */
+ protected Document luceneIndexPage( WikiPage page, String text, IndexWriter writer )
+ throws IOException
+ {
+ // make a new, empty document
+ Document doc = new Document();
+
+ if( text == null ) return doc;
+
+ // Raw name is the keyword we'll use to refer to this document for updates.
+ Field field = new Field(LUCENE_ID, page.getName(), Field.Store.YES, Field.Index.UN_TOKENIZED);
+ doc.add( field );
+
+ // Body text. It is stored in the doc for search contexts.
+ field = new Field(LUCENE_PAGE_CONTENTS, text,
+ Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO);
+ doc.add( field );
+
+ // Allow searching by page name. Both beautified and raw
+ String unTokenizedTitle = StringUtils.replaceChars( page.getName(),
+ MarkupParser.PUNCTUATION_CHARS_ALLOWED,
+ c_punctuationSpaces );
+
+ field = new Field(LUCENE_PAGE_NAME,
+ TextUtil.beautifyString( page.getName() ) + " " + unTokenizedTitle,
+ Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO);
+ doc.add( field );
+
+ // Allow searching by authorname
+
+ if( page.getAuthor() != null )
+ {
+ field = new Field(LUCENE_AUTHOR, page.getAuthor(),
+ Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO);
+ doc.add( field );
+ }
+
+ // Now add the names of the attachments of this page
+ try
+ {
+ Collection<Attachment> attachments = m_engine.getAttachmentManager().listAttachments(page);
+ String attachmentNames = "";
+
+ for( Attachment att : attachments )
+ {
+ attachmentNames += att.getName() + ";";
+ }
+ field = new Field(LUCENE_ATTACHMENTS, attachmentNames,
+ Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO);
+ doc.add( field );
+
+ }
+ catch(ProviderException e)
+ {
+ // Unable to read attachments
+ log.error("Failed to get attachments for page", e);
+ }
+ writer.addDocument(doc);
+
+ return doc;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void pageRemoved( WikiPage page )
+ {
+ try
+ {
+ // Must first remove existing version of page.
+ IndexReader reader = IndexReader.open(m_luceneDirectory);
+ reader.deleteDocuments(new Term(LUCENE_ID, page.getName()));
+ reader.close();
+ }
+ catch ( IOException e )
+ {
+ log.error("Unable to update page '" + page.getName() + "' from Lucene index", e);
+ }
+ }
+
+
+ /**
+ * Adds a page-text pair to the lucene update queue. Safe to call always
+ *
+ * @param page WikiPage to add to the update queue.
+ */
+ public void reindexPage( WikiPage page )
+ {
+ if( page != null )
+ {
+ String text;
+
+ // TODO: Think if this was better done in the thread itself?
+
+ if( page instanceof Attachment )
+ {
+ text = getAttachmentContent( (Attachment) page );
+ }
+ else
+ {
+ text = m_engine.getPureText( page );
+ }
+
+ if( text != null )
+ {
+ // Add work item to m_updates queue.
+ Object[] pair = new Object[2];
+ pair[0] = page;
+ pair[1] = text;
+ m_updates.add(pair);
+ log.debug("Scheduling page " + page.getName() + " for index update");
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<SearchResult> findPages( String query )
+ throws ProviderException
+ {
+ return findPages( query, FLAG_CONTEXTS );
+ }
+
+ /**
+ * Create contexts also. Generating contexts can be expensive,
+ * so they're not on by default.
+ */
+ public static final int FLAG_CONTEXTS = 0x01;
+
+ /**
+ * Searches pages using a particular combination of flags.
+ *
+ * @param query The query to perform in Lucene query language
+ * @param flags A set of flags
+ * @return A Collection of SearchResult instances
+ * @throws ProviderException if there is a problem with the backend
+ */
+ public Collection findPages( String query, int flags )
+ throws ProviderException
+ {
+ Searcher searcher = null;
+ ArrayList<SearchResult> list = null;
+ Highlighter highlighter = null;
+
+ try
+ {
+ String[] queryfields = { LUCENE_PAGE_CONTENTS, LUCENE_PAGE_NAME, LUCENE_AUTHOR, LUCENE_ATTACHMENTS };
+ QueryParser qp = new MultiFieldQueryParser( queryfields, getLuceneAnalyzer() );
+
+ //QueryParser qp = new QueryParser( LUCENE_PAGE_CONTENTS, getLuceneAnalyzer() );
+ Query luceneQuery = qp.parse( query );
+
+ if( (flags & FLAG_CONTEXTS) != 0 )
+ {
+ highlighter = new Highlighter(new SimpleHTMLFormatter("<span class=\"searchmatch\">", "</span>"),
+ new SimpleHTMLEncoder(),
+ new QueryScorer(luceneQuery));
+ }
+
+ try
+ {
+ searcher = new IndexSearcher(m_luceneDirectory);
+ }
+ catch( Exception ex )
+ {
+ log.info("Lucene not yet ready; indexing not started",ex);
+ return null;
+ }
+
+ Hits hits = searcher.search(luceneQuery);
+
+ list = new ArrayList<SearchResult>(hits.length());
+ for ( int curr = 0; curr < hits.length(); curr++ )
+ {
+ Document doc = hits.doc(curr);
+ String pageName = doc.get(LUCENE_ID);
+ WikiPage page = m_engine.getPage(pageName, WikiPageProvider.LATEST_VERSION);
+
+ if(page != null)
+ {
+ if(page instanceof Attachment)
+ {
+ // Currently attachments don't look nice on the search-results page
+ // When the search-results are cleaned up this can be enabled again.
+ }
+
+ int score = (int)(hits.score(curr) * 100);
+
+
+ // Get highlighted search contexts
+ String text = doc.get(LUCENE_PAGE_CONTENTS);
+
+ String[] fragments = new String[0];
+ if( text != null && highlighter != null )
+ {
+ TokenStream tokenStream = getLuceneAnalyzer()
+ .tokenStream(LUCENE_PAGE_CONTENTS, new StringReader(text));
+ fragments = highlighter.getBestFragments(tokenStream,
+ text, MAX_FRAGMENTS);
+
+ }
+
+ SearchResult result = new SearchResultImpl( page, score, fragments ); list.add(result);
+ }
+ else
+ {
+ log.error("Lucene found a result page '" + pageName + "' that could not be loaded, removing from Lucene cache");
+ pageRemoved(new WikiPage( m_engine, pageName ));
+ }
+ }
+ }
+ catch( IOException e )
+ {
+ log.error("Failed during lucene search",e);
+ }
+ catch( InstantiationException e )
+ {
+ log.error("Unable to get a Lucene analyzer",e);
+ }
+ catch( IllegalAccessException e )
+ {
+ log.error("Unable to get a Lucene analyzer",e);
+ }
+ catch( ClassNotFoundException e )
+ {
+ log.error("Specified Lucene analyzer does not exist",e);
+ }
+ catch( ParseException e )
+ {
+ log.info("Broken query; cannot parse",e);
+
+ throw new ProviderException("You have entered a query Lucene cannot process: "+e.getMessage());
+ }
+ finally
+ {
+ if( searcher != null )
+ {
+ try
+ {
+ searcher.close();
+ }
+ catch( IOException e )
+ {}
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getProviderInfo()
+ {
+ return "LuceneSearchProvider";
+ }
+
+ /**
+ * Updater thread that updates Lucene indexes.
+ */
+ private static final class LuceneUpdater extends WikiBackgroundThread
+ {
+ protected static final int INDEX_DELAY = 1;
+ protected static final int INITIAL_DELAY = 60;
+ private final LuceneSearchProvider m_provider;
+
+ private int m_initialDelay;
+
+ private WatchDog m_watchdog;
+
+ private LuceneUpdater( WikiEngine engine, LuceneSearchProvider provider,
+ int initialDelay, int indexDelay )
+ {
+ super( engine, indexDelay );
+ m_provider = provider;
+ setName("JSPWiki Lucene Indexer");
+ }
+
+ public void startupTask() throws Exception
+ {
+ m_watchdog = getEngine().getCurrentWatchDog();
+
+ // Sleep initially...
+ try
+ {
+ Thread.sleep( m_initialDelay * 1000L );
+ }
+ catch( InterruptedException e )
+ {
+ throw new InternalWikiException("Interrupted while waiting to start.");
+ }
+
+ m_watchdog.enterState("Full reindex");
+ // Reindex everything
+ m_provider.doFullLuceneReindex();
+ m_watchdog.exitState();
+ }
+
+ public void backgroundTask() throws Exception
+ {
+ m_watchdog.enterState("Emptying index queue", 60);
+
+ synchronized ( m_provider.m_updates )
+ {
+ while( m_provider.m_updates.size() > 0 )
+ {
+ Object[] pair = m_provider.m_updates.remove(0);
+ WikiPage page = ( WikiPage ) pair[0];
+ String text = ( String ) pair[1];
+ m_provider.updateLuceneIndex(page, text);
+ }
+ }
+
+ m_watchdog.exitState();
+ }
+
+ }
+
+ // FIXME: This class is dumb; needs to have a better implementation
+ private static class SearchResultImpl
+ implements SearchResult
+ {
+ private WikiPage m_page;
+ private int m_score;
+ private String[] m_contexts;
+
+ public SearchResultImpl( WikiPage page, int score, String[] contexts )
+ {
+ m_page = page;
+ m_score = score;
+ m_contexts = contexts;
+ }
+
+ public WikiPage getPage()
+ {
+ return m_page;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ecyrd.jspwiki.SearchResult#getScore()
+ */
+ public int getScore()
+ {
+ return m_score;
+ }
+
+
+ public String[] getContexts()
+ {
+ return m_contexts;
+ }
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/SearchManager.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/SearchManager.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/SearchManager.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/SearchManager.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,318 @@
+/*
+JSPWiki - a JSP-based WikiWiki clone.
+
+Copyright (C) 2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+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 com.ecyrd.jspwiki.search;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.apache.commons.lang.time.StopWatch;
+import org.apache.log4j.Logger;
+
+import com.ecyrd.jspwiki.*;
+import com.ecyrd.jspwiki.event.WikiEvent;
+import com.ecyrd.jspwiki.event.WikiEventListener;
+import com.ecyrd.jspwiki.event.WikiEventUtils;
+import com.ecyrd.jspwiki.event.WikiPageEvent;
+import com.ecyrd.jspwiki.filters.BasicPageFilter;
+import com.ecyrd.jspwiki.filters.FilterException;
+import com.ecyrd.jspwiki.modules.InternalModule;
+import com.ecyrd.jspwiki.parser.MarkupParser;
+import com.ecyrd.jspwiki.providers.ProviderException;
+import com.ecyrd.jspwiki.rpc.RPCCallable;
+import com.ecyrd.jspwiki.rpc.json.JSONRPCManager;
+import com.ecyrd.jspwiki.util.ClassUtil;
+
+/**
+ * Manages searching the Wiki.
+ *
+ * @author Arent-Jan Banck
+ * @since 2.2.21.
+ */
+
+public class SearchManager
+ extends BasicPageFilter
+ implements InternalModule, WikiEventListener
+{
+ private static final Logger log = Logger.getLogger(SearchManager.class);
+
+ private static final String DEFAULT_SEARCHPROVIDER = "com.ecyrd.jspwiki.search.LuceneSearchProvider";
+ public static final String PROP_USE_LUCENE = "jspwiki.useLucene";
+ public static final String PROP_SEARCHPROVIDER = "jspwiki.searchProvider";
+
+ private SearchProvider m_searchProvider = null;
+
+ public static final String JSON_SEARCH = "search";
+
+ public SearchManager( WikiEngine engine, Properties properties )
+ throws WikiException
+ {
+ initialize( engine, properties );
+
+ WikiEventUtils.addWikiEventListener(m_engine.getPageManager(),
+ WikiPageEvent.PAGE_DELETE_REQUEST, this);
+
+ JSONRPCManager.registerGlobalObject( JSON_SEARCH, new JSONSearch() );
+ }
+
+ /**
+ * Provides a JSON RPC API to the JSPWiki Search Engine.
+ * @author jalkanen
+ */
+ public class JSONSearch implements RPCCallable
+ {
+ /**
+ * Provides a list of suggestions to use for a page name.
+ * Currently the algorithm just looks into the value parameter,
+ * and returns all page names from that.
+ *
+ * @param wikiName the page name
+ * @param maxLength maximum number of suggestions
+ * @return the suggestions
+ */
+ public List getSuggestions( String wikiName, int maxLength )
+ {
+ StopWatch sw = new StopWatch();
+ sw.start();
+ List<String> list = new ArrayList<String>(maxLength);
+
+ if( wikiName.length() > 0 )
+ {
+ wikiName = MarkupParser.cleanLink(wikiName);
+ wikiName = wikiName.toLowerCase();
+
+ String oldStyleName = MarkupParser.wikifyLink(wikiName).toLowerCase();
+
+ Set<String> allPages = m_engine.getReferenceManager().findCreated();
+
+ int counter = 0;
+ for( Iterator<String> i = allPages.iterator(); i.hasNext() && counter < maxLength; )
+ {
+ String p = i.next();
+ String pp = p.toLowerCase();
+ if( pp.startsWith( wikiName ) || pp.startsWith( oldStyleName ) )
+ {
+ list.add( p );
+ counter++;
+ }
+ }
+ }
+
+ sw.stop();
+ if( log.isDebugEnabled() ) log.debug("Suggestion request for "+wikiName+" done in "+sw);
+ return list;
+ }
+
+ /**
+ * Performs a full search of pages.
+ *
+ * @param searchString The query string
+ * @param maxLength How many hits to return
+ * @return the pages found
+ */
+ public List<HashMap<String,Object>> findPages( String searchString, int maxLength )
+ {
+ StopWatch sw = new StopWatch();
+ sw.start();
+
+ List<HashMap<String,Object>> list = new ArrayList<HashMap<String,Object>>(maxLength);
+
+ if( searchString.length() > 0 )
+ {
+ try
+ {
+ Collection<SearchResult> c;
+
+ if( m_searchProvider instanceof LuceneSearchProvider )
+ c = ((LuceneSearchProvider)m_searchProvider).findPages( searchString, 0 );
+ else
+ c = m_searchProvider.findPages( searchString );
+
+ int count = 0;
+ for( Iterator<SearchResult> i = c.iterator(); i.hasNext() && count < maxLength; count++ )
+ {
+ SearchResult sr = i.next();
+ HashMap<String,Object> hm = new HashMap<String,Object>();
+ hm.put( "page", sr.getPage().getName() );
+ hm.put( "score", new Integer(sr.getScore()) );
+ list.add( hm );
+ }
+ }
+ catch(Exception e)
+ {
+ log.info("AJAX search failed; ",e);
+ }
+ }
+
+ sw.stop();
+ if( log.isDebugEnabled() ) log.debug("AJAX search complete in "+sw);
+ return list;
+ }
+ }
+
+ /**
+ * This particular method starts off indexing and all sorts of various activities,
+ * so you need to run this last, after things are done.
+ *
+ * @param engine the wiki engine
+ * @param properties the properties used to initialize the wiki engine
+ * @throws FilterException if the search provider failed to initialize
+ */
+ public void initialize(WikiEngine engine, Properties properties)
+ throws FilterException
+ {
+ m_engine = engine;
+
+ loadSearchProvider(properties);
+
+ try
+ {
+ m_searchProvider.initialize(engine, properties);
+ }
+ catch (NoRequiredPropertyException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ catch (IOException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void loadSearchProvider(Properties properties)
+ {
+ //
+ // See if we're using Lucene, and if so, ensure that its
+ // index directory is up to date.
+ //
+ String useLucene = properties.getProperty(PROP_USE_LUCENE);
+
+ // FIXME: Obsolete, remove, or change logic to first load searchProvder?
+ // If the old jspwiki.useLucene property is set we use that instead of the searchProvider class.
+ if( useLucene != null )
+ {
+ log.info( PROP_USE_LUCENE+" is deprecated; please use "+PROP_SEARCHPROVIDER+"=<your search provider> instead." );
+ if( TextUtil.isPositive( useLucene ) )
+ {
+ m_searchProvider = new LuceneSearchProvider();
+ }
+ else
+ {
+ m_searchProvider = new BasicSearchProvider();
+ }
+ log.debug("useLucene was set, loading search provider " + m_searchProvider);
+ return;
+ }
+
+ String providerClassName = properties.getProperty( PROP_SEARCHPROVIDER,
+ DEFAULT_SEARCHPROVIDER );
+
+ try
+ {
+ Class providerClass = ClassUtil.findClass( "com.ecyrd.jspwiki.search", providerClassName );
+ m_searchProvider = (SearchProvider)providerClass.newInstance();
+ }
+ catch( ClassNotFoundException e )
+ {
+ log.warn("Failed loading SearchProvider, will use BasicSearchProvider.", e);
+ }
+ catch( InstantiationException e )
+ {
+ log.warn("Failed loading SearchProvider, will use BasicSearchProvider.", e);
+ }
+ catch( IllegalAccessException e )
+ {
+ log.warn("Failed loading SearchProvider, will use BasicSearchProvider.", e);
+ }
+
+ if( null == m_searchProvider )
+ {
+ // FIXME: Make a static with the default search provider
+ m_searchProvider = new BasicSearchProvider();
+ }
+ log.debug("Loaded search provider " + m_searchProvider);
+ }
+
+ public SearchProvider getSearchEngine()
+ {
+ return m_searchProvider;
+ }
+
+ /**
+ * Sends a search to the current search provider. The query is is whatever native format
+ * the query engine wants to use.
+ *
+ * @param query The query. Null is safe, and is interpreted as an empty query.
+ * @return A collection of WikiPages that matched.
+ */
+ public Collection findPages( String query )
+ throws ProviderException, IOException
+ {
+ if( query == null ) query = "";
+ Collection c = m_searchProvider.findPages( query );
+
+ return c;
+ }
+
+ /**
+ * Removes the page from the search cache (if any).
+ * @param page The page to remove
+ */
+ public void pageRemoved(WikiPage page)
+ {
+ m_searchProvider.pageRemoved(page);
+ }
+
+ public void postSave( WikiContext wikiContext, String content )
+ {
+ //
+ // Makes sure that we're indexing the latest version of this
+ // page.
+ //
+ WikiPage p = m_engine.getPage( wikiContext.getPage().getName() );
+ reindexPage( p );
+ }
+
+ /**
+ * Forces the reindex of the given page.
+ *
+ * @param page
+ */
+ public void reindexPage(WikiPage page)
+ {
+ m_searchProvider.reindexPage(page);
+ }
+
+ public void actionPerformed(WikiEvent event)
+ {
+ if( (event instanceof WikiPageEvent) && (event.getType() == WikiPageEvent.PAGE_DELETE_REQUEST) )
+ {
+ String pageName = ((WikiPageEvent) event).getPageName();
+
+ WikiPage p = m_engine.getPage( pageName );
+ if( p != null )
+ {
+ pageRemoved( p );
+ }
+ }
+ }
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/SearchProvider.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/SearchProvider.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/SearchProvider.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/SearchProvider.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,61 @@
+/*
+JSPWiki - a JSP-based WikiWiki clone.
+
+Copyright (C) 2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+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 com.ecyrd.jspwiki.search;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import com.ecyrd.jspwiki.SearchResult;
+import com.ecyrd.jspwiki.WikiPage;
+import com.ecyrd.jspwiki.WikiProvider;
+import com.ecyrd.jspwiki.providers.ProviderException;
+
+/**
+ * Interface for the search providers that handle searching the Wiki
+ *
+ * @author Arent-Jan Banck
+ * @since 2.2.21.
+ */
+public interface SearchProvider extends WikiProvider
+{
+ /**
+ * Delete a page from the search index
+ * @param page Page to remove from search index
+ */
+ public void pageRemoved(WikiPage page);
+
+ /**
+ * Adds a WikiPage for indexing queue. This is called a queue, since
+ * this method is expected to return pretty quickly, and indexing to
+ * be done in a separate thread.
+ *
+ * @param page The WikiPage to be indexed.
+ */
+ public void reindexPage(WikiPage page);
+
+ /**
+ * Search for pages matching a search query
+ * @param query query to search for
+ * @return collection of pages that match query
+ * @throws ProviderException if the search provider failed.
+ * @throws IOException if for some reason the query could not be executed.
+ */
+ public Collection<SearchResult> findPages(String query) throws ProviderException, IOException;
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AdminBeanIteratorInfo.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AdminBeanIteratorInfo.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AdminBeanIteratorInfo.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AdminBeanIteratorInfo.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,46 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2007 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import javax.servlet.jsp.tagext.TagData;
+import javax.servlet.jsp.tagext.TagExtraInfo;
+import javax.servlet.jsp.tagext.VariableInfo;
+
+/**
+ * Just provides iteration support for AdminBeanIteratorTag
+ *
+ * @author jalkanen
+ * @since 2.6.
+ */
+public class AdminBeanIteratorInfo extends TagExtraInfo
+{
+ public VariableInfo[] getVariableInfo(TagData data)
+ {
+ VariableInfo[] var = { new VariableInfo( data.getAttributeString("id"),
+ "com.ecyrd.jspwiki.ui.admin.AdminBean",
+ true,
+ VariableInfo.NESTED )
+ };
+
+ return var;
+
+ }
+}
+
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AdminBeanIteratorTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AdminBeanIteratorTag.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AdminBeanIteratorTag.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AdminBeanIteratorTag.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,60 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2007 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import com.ecyrd.jspwiki.ui.admin.AdminBean;
+import com.ecyrd.jspwiki.ui.admin.AdminBeanManager;
+
+public class AdminBeanIteratorTag extends IteratorTag
+{
+ private static final long serialVersionUID = 1L;
+
+ private int m_type;
+
+ public void setType(String type)
+ {
+ m_type = AdminBeanManager.getTypeFromString( type );
+ }
+
+ public void resetIterator()
+ {
+ AdminBeanManager mgr = m_wikiContext.getEngine().getAdminBeanManager();
+
+ Collection beans = mgr.getAllBeans();
+
+ ArrayList<AdminBean> typedBeans = new ArrayList<AdminBean>();
+
+ for( Iterator i = beans.iterator(); i.hasNext(); )
+ {
+ AdminBean ab = (AdminBean)i.next();
+
+ if( ab.getType() == m_type )
+ {
+ typedBeans.add( ab );
+ }
+ }
+
+ setList( typedBeans );
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AttachmentsIteratorInfo.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AttachmentsIteratorInfo.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AttachmentsIteratorInfo.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AttachmentsIteratorInfo.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,44 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import javax.servlet.jsp.tagext.TagExtraInfo;
+import javax.servlet.jsp.tagext.TagData;
+import javax.servlet.jsp.tagext.VariableInfo;
+
+/**
+ * Just provides the TEI data for AttachmentsIteratorTag.
+ *
+ * @since 2.0
+ */
+public class AttachmentsIteratorInfo extends TagExtraInfo
+{
+ public VariableInfo[] getVariableInfo(TagData data)
+ {
+ VariableInfo[] var = { new VariableInfo( data.getAttributeString("id"),
+ "com.ecyrd.jspwiki.attachment.Attachment",
+ true,
+ VariableInfo.NESTED )
+ };
+
+ return var;
+
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AttachmentsIteratorTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AttachmentsIteratorTag.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AttachmentsIteratorTag.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AttachmentsIteratorTag.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,149 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import java.io.IOException;
+import java.util.Collection;
+import javax.servlet.jsp.JspWriter;
+
+import org.apache.log4j.Logger;
+
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiPage;
+import com.ecyrd.jspwiki.providers.ProviderException;
+import com.ecyrd.jspwiki.action.WikiActionBeanFactory;
+import com.ecyrd.jspwiki.attachment.AttachmentManager;
+import com.ecyrd.jspwiki.attachment.Attachment;
+
+/**
+ * Iterates through the list of attachments one has.
+ *
+ * <P><B>Attributes</B></P>
+ * <UL>
+ * <LI>page - Page name to refer to. Default is the current page.
+ * </UL>
+ *
+ * @author Janne Jalkanen
+ * @since 2.0
+ */
+
+// FIXME: Too much in common with IteratorTag - REFACTOR
+public class AttachmentsIteratorTag
+ extends IteratorTag
+{
+ private static final long serialVersionUID = 0L;
+
+ static Logger log = Logger.getLogger( AttachmentsIteratorTag.class );
+
+ public final int doStartTag()
+ {
+ m_wikiContext = (WikiContext)WikiActionBeanFactory.findActionBean( pageContext );
+
+ WikiEngine engine = m_wikiContext.getEngine();
+ AttachmentManager mgr = engine.getAttachmentManager();
+ WikiPage page;
+
+ page = m_wikiContext.getPage();
+
+ if( !mgr.attachmentsEnabled() )
+ {
+ return SKIP_BODY;
+ }
+
+ try
+ {
+ if( page != null && engine.pageExists(page) )
+ {
+ Collection atts = mgr.listAttachments( page );
+
+ if( atts == null )
+ {
+ log.debug("No attachments to display.");
+ // There are no attachments included
+ return SKIP_BODY;
+ }
+
+ m_iterator = atts.iterator();
+
+ if( m_iterator.hasNext() )
+ {
+ Attachment att = (Attachment) m_iterator.next();
+
+ WikiContext context = (WikiContext)m_wikiContext.clone();
+ context.setPage( att );
+ WikiActionBeanFactory.saveActionBean( pageContext, context );
+
+ pageContext.setAttribute( getId(), att );
+ }
+ else
+ {
+ return SKIP_BODY;
+ }
+ }
+ else
+ {
+ return SKIP_BODY;
+ }
+
+ return EVAL_BODY_BUFFERED;
+ }
+ catch( ProviderException e )
+ {
+ log.fatal("Provider failed while trying to iterator through history",e);
+ // FIXME: THrow something.
+ }
+
+ return SKIP_BODY;
+ }
+
+ public final int doAfterBody()
+ {
+ if( bodyContent != null )
+ {
+ try
+ {
+ JspWriter out = getPreviousOut();
+ out.print(bodyContent.getString());
+ bodyContent.clearBody();
+ }
+ catch( IOException e )
+ {
+ log.error("Unable to get inner tag text", e);
+ // FIXME: throw something?
+ }
+ }
+
+ if( m_iterator != null && m_iterator.hasNext() )
+ {
+ Attachment att = (Attachment) m_iterator.next();
+
+ WikiContext context = (WikiContext)m_wikiContext.clone();
+ context.setPage( att );
+ WikiActionBeanFactory.saveActionBean( pageContext, context );
+
+ pageContext.setAttribute( getId(), att );
+
+ return EVAL_BODY_BUFFERED;
+ }
+
+ return SKIP_BODY;
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AuthorTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AuthorTag.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AuthorTag.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/AuthorTag.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,84 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import java.io.IOException;
+
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiPage;
+import com.ecyrd.jspwiki.TextUtil;
+import com.ecyrd.jspwiki.parser.MarkupParser;
+import com.ecyrd.jspwiki.parser.WikiDocument;
+import com.ecyrd.jspwiki.render.RenderingManager;
+
+/**
+ * Writes the author name of the current page, including a link to that page,
+ * if that page exists.
+ *
+ * @author Janne Jalkanen
+ * @since 2.0
+ */
+public class AuthorTag
+ extends WikiTagBase
+{
+ private static final long serialVersionUID = 0L;
+
+ public final int doWikiStartTag()
+ throws IOException
+ {
+ if ( !( m_actionBean instanceof WikiContext ) )
+ {
+ return SKIP_BODY;
+ }
+
+ WikiContext context = (WikiContext)m_actionBean;
+ WikiEngine engine = context.getEngine();
+ WikiPage page = context.getPage();
+
+ String author = page.getAuthor();
+
+ if( author != null && author.length() > 0 )
+ {
+ author = TextUtil.replaceEntities(author);
+ if( engine.pageExists(author) )
+ {
+ // FIXME: It's very boring to have to do this.
+ // Slow, too.
+
+ RenderingManager mgr = engine.getRenderingManager();
+
+ MarkupParser p = mgr.getParser( context, "["+author+"|"+author+"]" );
+
+ WikiDocument d = p.parse();
+
+ author = mgr.getHTML( context, d );
+ }
+
+ pageContext.getOut().print( author );
+ }
+ else
+ {
+ pageContext.getOut().print( "unknown" );
+ }
+
+ return SKIP_BODY;
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/BaseURLTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/BaseURLTag.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/BaseURLTag.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/BaseURLTag.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,41 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import java.io.IOException;
+
+/**
+ * Writes the jspwiki.baseURL property.
+ *
+ * @author Janne Jalkanen
+ * @since 2.2
+ */
+public class BaseURLTag
+ extends WikiTagBase
+{
+ private static final long serialVersionUID = 0L;
+
+ public final int doWikiStartTag()
+ throws IOException
+ {
+ pageContext.getOut().print( m_actionBean.getEngine().getBaseURL() );
+ return SKIP_BODY;
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/BreadcrumbsTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/BreadcrumbsTag.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/BreadcrumbsTag.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/BreadcrumbsTag.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,182 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2003 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.LinkedList;
+
+import javax.servlet.http.HttpSession;
+import javax.servlet.jsp.JspWriter;
+
+import org.apache.log4j.Logger;
+
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.action.ViewActionBean;
+
+/**
+ * Implement a "breadcrumb" (most recently visited) trail. This tag can be added to any view jsp page.
+ * Separate breadcrumb trails are not tracked across multiple browser windows.<br>
+ * The optional attributes are:
+ * <p>
+ * <b>maxpages</b>, the number of pages to store, 10 by default<br>
+ * <b>separator</b>, the separator string to use between pages, " | " by default<br>
+ * </p>
+ *
+ * <p>
+ * This class is implemented by storing a breadcrumb trail, which is a
+ * fixed size queue, into a session variable "breadCrumbTrail".
+ * This queue is displayed as a series of links separated by a separator
+ * character.
+ * </p>
+ * @author Ken Liu ken@kenliu.net
+ */
+public class BreadcrumbsTag extends WikiTagBase
+{
+ private static final long serialVersionUID = 0L;
+
+ private static final Logger log = Logger.getLogger(BreadcrumbsTag.class);
+ private static final String BREADCRUMBTRAIL_KEY = "breadCrumbTrail";
+ private int m_maxQueueSize = 11;
+ private String m_separator = ", ";
+
+ public void initTag()
+ {
+ super.initTag();
+ m_maxQueueSize = 11;
+ m_separator = ", ";
+ }
+
+ public int getMaxpages()
+ {
+ return m_maxQueueSize;
+ }
+
+ public void setMaxpages(int maxpages)
+ {
+ m_maxQueueSize = maxpages + 1;
+ }
+
+ public String getSeparator()
+ {
+ return m_separator;
+ }
+
+ public void setSeparator(String separator)
+ {
+ m_separator = separator;
+ }
+
+ public int doWikiStartTag() throws IOException
+ {
+ HttpSession session = pageContext.getSession();
+ FixedQueue trail = (FixedQueue) session.getAttribute(BREADCRUMBTRAIL_KEY);
+
+ if( trail == null )
+ {
+ trail = new FixedQueue(m_maxQueueSize);
+ }
+
+ if( m_actionBean instanceof ViewActionBean && m_page != null )
+ {
+ String pageName = m_page.getName();
+ if( trail.isEmpty() )
+ {
+ trail.pushItem( pageName );
+ }
+ else
+ {
+ //
+ // Don't add the page to the queue if the page was just refreshed
+ //
+ if( !((String) trail.getLast()).equals( pageName ) )
+ {
+ trail.pushItem( pageName );
+ log.debug( "added page: " + pageName );
+ }
+ log.debug("didn't add page because of refresh");
+ }
+ }
+
+ session.setAttribute(BREADCRUMBTRAIL_KEY, trail);
+
+ //
+ // Print out the breadcrumb trail
+ //
+
+ // FIXME: this code would be much simpler if we could just output the [pagename] and then use the
+ // wiki engine to output the appropriate wikilink
+
+ JspWriter out = pageContext.getOut();
+ int queueSize = trail.size();
+ String linkclass = "wikipage";
+ String curPage = null;
+
+ for( int i = 0; i < queueSize - 1; i++ )
+ {
+ curPage = (String) trail.get(i);
+
+ //FIXME: I can't figure out how to detect the appropriate jsp page to put here, so I hard coded Wiki.jsp
+ //This breaks when you view an attachment metadata page
+ if ( m_actionBean instanceof WikiContext )
+ {
+ WikiContext context = (WikiContext)m_actionBean;
+ out.print("<a class=\"" + linkclass + "\" href=\"" +
+ context.getViewURL(curPage)+ "\">" + curPage + "</a>");
+ }
+
+ if( i < queueSize - 2 )
+ {
+ out.print(m_separator);
+ }
+ }
+
+ return SKIP_BODY;
+ }
+
+ /**
+ * Extends the LinkedList class to provide a fixed-size queue implementation
+ */
+ public static class FixedQueue
+ extends LinkedList<Object>
+ implements Serializable
+ {
+ private int m_size;
+ private static final long serialVersionUID = 0L;
+
+ FixedQueue(int size)
+ {
+ m_size = size;
+ }
+
+ Object pushItem(Object o)
+ {
+ add(o);
+ if( size() > m_size )
+ {
+ return removeFirst();
+ }
+
+ return null;
+ }
+ }
+
+}
+
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CalendarTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CalendarTag.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CalendarTag.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CalendarTag.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,345 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import java.io.IOException;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.text.SimpleDateFormat;
+import java.text.ParseException;
+
+import javax.servlet.jsp.JspWriter;
+import javax.servlet.http.HttpServletRequest;
+
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.TextUtil;
+import com.ecyrd.jspwiki.action.ViewActionBean;
+import com.ecyrd.jspwiki.providers.ProviderException;
+
+
+/**
+ * Provides a nice calendar. Responds to the following HTTP parameters:
+ * <ul>
+ * <li>calendar.date - If this parameter exists, then the calendar
+ * date is taken from the month and year. The date must be in ddMMyy
+ * format.
+ * <li>weblog.startDate - If calendar.date parameter does not exist,
+ * we then check this date.
+ * </ul>
+ *
+ * If neither calendar.date nor weblog.startDate parameters exist,
+ * then the calendar will default to the current month.
+ *
+ *
+ * @author Janne Jalkanen
+ * @since 2.0
+ */
+
+// FIXME: This class is extraordinarily lacking.
+
+public class CalendarTag
+ extends WikiTagBase
+{
+ private static final long serialVersionUID = 0L;
+
+ private SimpleDateFormat m_pageFormat = null;
+ private SimpleDateFormat m_urlFormat = null;
+ private SimpleDateFormat m_monthUrlFormat = null;
+ private SimpleDateFormat m_dateFormat = new SimpleDateFormat( "ddMMyy" );
+
+ public void initTag()
+ {
+ super.initTag();
+ m_pageFormat = m_urlFormat = m_monthUrlFormat = null;
+ m_dateFormat = new SimpleDateFormat( "ddMMyy" );
+ }
+
+ /*
+ public void setYear( String year )
+ {
+ m_year = year;
+ }
+
+ public void setMonth( String month )
+ {
+ m_month = month;
+ }
+ */
+
+ public void setPageformat( String format )
+ {
+ m_pageFormat = new SimpleDateFormat(format);
+ }
+
+ public void setUrlformat( String format )
+ {
+ m_urlFormat = new SimpleDateFormat(format);
+ }
+
+ public void setMonthurlformat( String format )
+ {
+ m_monthUrlFormat = new SimpleDateFormat( format );
+ }
+
+ private String format( String txt )
+ {
+ if( m_page != null )
+ {
+ return TextUtil.replaceString( txt, "%p", m_page.getName() );
+ }
+
+ return txt;
+ }
+
+ /**
+ * Returns a link to the given day.
+ */
+ private String getDayLink( Calendar day )
+ {
+ WikiEngine engine = m_actionBean.getEngine();
+ String result = "";
+
+ if( m_pageFormat != null )
+ {
+ String pagename = m_pageFormat.format( day.getTime() );
+
+ if( engine.pageExists( pagename ) )
+ {
+ if( m_urlFormat != null )
+ {
+ String url = m_urlFormat.format( day.getTime() );
+
+ result = "<td class=\"link\"><a href=\""+url+"\">"+day.get( Calendar.DATE )+"</a></td>";
+ }
+ else
+ {
+ WikiContext context = (WikiContext)m_actionBean;
+ result = "<td class=\"link\"><a href=\""+context.getViewURL( pagename )+"\">"+
+ day.get( Calendar.DATE )+"</a></td>";
+ }
+ }
+ else
+ {
+ result = "<td class=\"days\">"+day.get(Calendar.DATE)+"</td>";
+ }
+ }
+ else if( m_urlFormat != null )
+ {
+ String url = m_urlFormat.format( day.getTime() );
+
+ result = "<td><a href=\""+url+"\">"+day.get( Calendar.DATE )+"</a></td>";
+ }
+ else
+ {
+ result = "<td class=\"days\">"+day.get(Calendar.DATE)+"</td>";
+ }
+
+ return format(result);
+ }
+
+ private String getMonthLink( Calendar day )
+ {
+ SimpleDateFormat monthfmt = new SimpleDateFormat( "MMMM yyyy" );
+ String result;
+
+ if( m_monthUrlFormat == null )
+ {
+ result = monthfmt.format( day.getTime() );
+ }
+ else
+ {
+ Calendar cal = (Calendar)day.clone();
+ int firstDay = cal.getActualMinimum( Calendar.DATE );
+ int lastDay = cal.getActualMaximum( Calendar.DATE );
+
+ cal.set( Calendar.DATE, lastDay );
+ String url = m_monthUrlFormat.format( cal.getTime() );
+
+ url = TextUtil.replaceString( url, "%d", Integer.toString( lastDay-firstDay+1 ) );
+
+ result = "<a href=\""+url+"\">"+monthfmt.format(cal.getTime())+"</a>";
+ }
+
+ return format(result);
+
+ }
+ private String getMonthNaviLink( Calendar day, String txt, String queryString )
+ {
+ String result = "";
+ queryString = TextUtil.replaceEntities( queryString );
+ Calendar nextMonth = Calendar.getInstance();
+ nextMonth.set( Calendar.DATE, 1 );
+ nextMonth.add( Calendar.DATE, -1);
+ nextMonth.add( Calendar.MONTH, 1 ); // Now move to 1st day of next month
+
+ if ( day.before(nextMonth) && m_page != null )
+ {
+ WikiContext context = (WikiContext)m_actionBean;
+ String pageName = m_page.getName();
+
+ String calendarDate = m_dateFormat.format(day.getTime());
+ Map<String,String> urlParams = new HashMap<String,String>();
+ urlParams.put("calendar.date", calendarDate );
+ String url = context.getContext().getURL( ViewActionBean.class, pageName, urlParams );
+
+ if ( (queryString != null) && (queryString.length() > 0) )
+ {
+ //
+ // Ensure that the 'calendar.date=ddMMyy' has been removed
+ // from the queryString
+ //
+
+ // FIXME: Might be useful to have an entire library of
+ // routines for this. Will fail if it's not calendar.date
+ // but something else.
+
+ int pos1 = queryString.indexOf("calendar.date=");
+ if (pos1 >= 0)
+ {
+ String tmp = queryString.substring(0,pos1);
+ // FIXME: Will this fail when we use & instead of &?
+ // FIXME: should use some parsing routine
+ int pos2 = queryString.indexOf("&",pos1) + 1;
+ if ( (pos2 > 0) && (pos2 < queryString.length()) )
+ {
+ tmp = tmp + queryString.substring(pos2);
+ }
+ queryString = tmp;
+ }
+
+ if( queryString != null && queryString.length() > 0 )
+ {
+ url = url + "&"+queryString;
+ }
+ }
+ result = "<td><a href=\""+url+"\">"+txt+"</a></td>";
+ }
+ else
+ {
+ result="<td> </td>";
+ }
+
+ return format(result);
+ }
+
+ public final int doWikiStartTag()
+ throws IOException,
+ ProviderException
+ {
+ WikiEngine engine = m_actionBean.getEngine();
+ JspWriter out = pageContext.getOut();
+ Calendar cal = Calendar.getInstance();
+ Calendar prevCal = Calendar.getInstance();
+ Calendar nextCal = Calendar.getInstance();
+
+ //
+ // Check if there is a parameter in the request to set the date.
+ //
+ String calendarDate = pageContext.getRequest().getParameter( "calendar.date" );
+ if( calendarDate == null )
+ {
+ calendarDate = pageContext.getRequest().getParameter( "weblog.startDate" );
+ }
+
+ if( calendarDate != null )
+ {
+ try
+ {
+ Date d = m_dateFormat.parse( calendarDate );
+ cal.setTime( d );
+ prevCal.setTime( d );
+ nextCal.setTime( d );
+ }
+ catch( ParseException e )
+ {
+ log.warn( "date format wrong: "+calendarDate );
+ }
+ }
+
+ cal.set( Calendar.DATE, 1 ); // First, set to first day of month
+ prevCal.set( Calendar.DATE, 1 );
+ nextCal.set( Calendar.DATE, 1 );
+
+ prevCal.add(Calendar.MONTH, -1); // Now move to first day of previous month
+ nextCal.add(Calendar.MONTH, 1); // Now move to first day of next month
+
+ out.write( "<table class=\"calendar\">\n" );
+
+ HttpServletRequest httpServletRequest = m_actionBean.getContext().getRequest();
+ String queryString = engine.safeGetQueryString( httpServletRequest );
+ out.write( "<tr>"+
+ getMonthNaviLink(prevCal,"<<", queryString)+
+ "<td colspan=5 class=\"month\">"+
+ getMonthLink( cal )+
+ "</td>"+
+ getMonthNaviLink(nextCal,">>", queryString)+
+ "</tr>\n"
+ );
+
+ int month = cal.get( Calendar.MONTH );
+ cal.set( Calendar.DAY_OF_WEEK, Calendar.MONDAY ); // Then, find the first day of the week.
+
+ out.write( "<tr><td class=\"weekdays\">Mon</td>"+
+ "<td class=\"weekdays\">Tue</td>"+
+ "<td class=\"weekdays\">Wed</td>"+
+ "<td class=\"weekdays\">Thu</td>"+
+ "<td class=\"weekdays\">Fri</td>"+
+ "<td class=\"weekdays\">Sat</td>"+
+ "<td class=\"weekdays\">Sun</td></tr>\n" );
+
+ boolean noMoreDates = false;
+ while( !noMoreDates )
+ {
+ out.write( "<tr>" );
+
+ for( int i = 0; i < 7; i++ )
+ {
+ int mth = cal.get( Calendar.MONTH );
+
+ if( mth != month )
+ {
+ out.write("<td class=\"othermonth\">"+cal.get(Calendar.DATE)+"</td>");
+ }
+ else
+ {
+ out.write( getDayLink(cal) );
+ }
+
+ cal.add( Calendar.DATE, 1 );
+ }
+
+ if( cal.get( Calendar.MONTH ) != month )
+ {
+ noMoreDates = true;
+ }
+
+ out.write( "</tr>\n" );
+ }
+
+ out.write( "</table>\n" );
+
+ return EVAL_BODY_INCLUDE;
+ }
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckLockInfo.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckLockInfo.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckLockInfo.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckLockInfo.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,39 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2007 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import javax.servlet.jsp.tagext.TagExtraInfo;
+import javax.servlet.jsp.tagext.TagData;
+import javax.servlet.jsp.tagext.VariableInfo;
+
+public class CheckLockInfo
+ extends TagExtraInfo
+{
+ public VariableInfo[] getVariableInfo(TagData data)
+ {
+ VariableInfo[] var = { new VariableInfo( data.getAttributeString("id"),
+ "com.ecyrd.jspwiki.PageLock",
+ true,
+ VariableInfo.NESTED )
+ };
+
+ return var;
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckLockTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckLockTag.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckLockTag.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckLockTag.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,103 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpSession;
+
+import com.ecyrd.jspwiki.PageLock;
+import com.ecyrd.jspwiki.PageManager;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.providers.ProviderException;
+
+/**
+ *
+ * @author Janne Jalkanen
+ * @since 2.0
+ */
+public class CheckLockTag
+ extends WikiTagBase
+{
+ private static final long serialVersionUID = 0L;
+
+ public static final int LOCKED = 0;
+ public static final int NOTLOCKED = 1;
+ public static final int OWNED = 2;
+
+ private int m_mode;
+
+ public void initTag()
+ {
+ super.initTag();
+ m_mode = 0;
+ }
+
+ public void setMode( String arg )
+ {
+ if( "locked".equals(arg) )
+ {
+ m_mode = LOCKED;
+ }
+ else if("owned".equals(arg) )
+ {
+ m_mode = OWNED;
+ }
+ else
+ {
+ m_mode = NOTLOCKED;
+ }
+ }
+
+ public final int doWikiStartTag()
+ throws IOException,
+ ProviderException
+ {
+ WikiEngine engine = m_actionBean.getEngine();
+
+ if( m_page != null )
+ {
+ PageManager mgr = engine.getPageManager();
+
+ PageLock lock = mgr.getCurrentLock( m_page );
+
+ HttpSession session = pageContext.getSession();
+
+ PageLock userLock = (PageLock) session.getAttribute("lock-"+m_page.getName());
+
+ if( (lock != null && m_mode == LOCKED && lock != userLock ) ||
+ (lock != null && m_mode == OWNED && lock == userLock ) ||
+ (lock == null && m_mode == NOTLOCKED) )
+ {
+ String tid = getId();
+
+ if( tid != null && lock != null )
+ {
+ pageContext.setAttribute( tid, lock );
+ }
+
+ return EVAL_BODY_INCLUDE;
+ }
+ }
+
+ return SKIP_BODY;
+ }
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckRequestContextTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckRequestContextTag.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckRequestContextTag.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckRequestContextTag.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,90 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import java.io.IOException;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.ecyrd.jspwiki.providers.ProviderException;
+
+/**
+ * Includes body, if the request context matches.
+ *
+ * @author Janne Jalkanen
+ * @since 2.0
+ */
+public class CheckRequestContextTag
+ extends WikiTagBase
+{
+ private static final long serialVersionUID = 0L;
+
+ private String m_context;
+ private String[] m_contextList = {};
+
+
+ public void initTag()
+ {
+ super.initTag();
+ m_context = null;
+ m_contextList = new String[0];
+ }
+
+ public String getContext()
+ {
+ return m_context;
+ }
+
+ public void setContext( String arg )
+ {
+ m_context = arg;
+
+ m_contextList = StringUtils.split(arg,'|');
+ }
+
+ public final int doWikiStartTag()
+ throws IOException,
+ ProviderException
+ {
+ for(int i = 0; i < m_contextList.length; i++ )
+ {
+ String ctx = m_actionBean.getRequestContext();
+
+ String checkedCtx = m_contextList[i];
+
+ if( checkedCtx.length() > 0 )
+ {
+ if( checkedCtx.charAt(0) == '!' )
+ {
+ if( !ctx.equalsIgnoreCase(checkedCtx.substring(1) ) )
+ {
+ return EVAL_BODY_INCLUDE;
+ }
+ }
+ else if( ctx.equalsIgnoreCase(m_contextList[i]) )
+ {
+ return EVAL_BODY_INCLUDE;
+ }
+ }
+ }
+
+ return SKIP_BODY;
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckVersionTag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckVersionTag.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckVersionTag.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/tags/CheckVersionTag.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,121 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
+
+ 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 com.ecyrd.jspwiki.tags;
+
+import java.io.IOException;
+
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiPage;
+import com.ecyrd.jspwiki.providers.ProviderException;
+
+/**
+ * Does a version check on the page. Mode is as follows:
+ * <UL>
+ * <LI>latest = Include page content, if the page is the latest version.
+ * <LI>notlatest = Include page content, if the page is NOT the latest version.
+ * </UL>
+ * If the page does not exist, body content is never included.
+ *
+ * @author Janne Jalkanen
+ * @since 2.0
+ */
+public class CheckVersionTag
+ extends WikiTagBase
+{
+ private static final long serialVersionUID = 0L;
+
+ public static final int LATEST = 0;
+ public static final int NOTLATEST = 1;
+ public static final int FIRST = 2;
+ public static final int NOTFIRST = 3;
+
+ private int m_mode;
+
+ public void initTag()
+ {
+ super.initTag();
+ m_mode = 0;
+ }
+
+ public void setMode( String arg )
+ {
+ if( "latest".equals(arg) )
+ {
+ m_mode = LATEST;
+ }
+ else if( "notfirst".equals(arg) )
+ {
+ m_mode = NOTFIRST;
+ }
+ else if( "first".equals(arg) )
+ {
+ m_mode = FIRST;
+ }
+ else
+ {
+ m_mode = NOTLATEST;
+ }
+ }
+
+ public final int doWikiStartTag()
+ throws IOException,
+ ProviderException
+ {
+ WikiEngine engine = m_actionBean.getEngine();
+
+ if( m_page != null && engine.pageExists(m_page.getName()) )
+ {
+ int version = m_page.getVersion();
+ boolean include = false;
+
+ WikiPage latest = engine.getPage( m_page.getName() );
+
+ //log.debug("Doing version check: this="+page.getVersion()+
+ // ", latest="+latest.getVersion());
+
+ switch( m_mode )
+ {
+ case LATEST:
+ include = (version < 0) || (latest.getVersion() == version);
+ break;
+
+ case NOTLATEST:
+ include = (version > 0) && (latest.getVersion() != version);
+ break;
+
+ case FIRST:
+ include = (version == 1 ) || (version < 0 && latest.getVersion() == 1);
+ break;
+
+ case NOTFIRST:
+ include = version > 1;
+ break;
+ }
+
+ if( include )
+ {
+ // log.debug("INCLD");
+ return EVAL_BODY_INCLUDE;
+ }
+ }
+
+ return SKIP_BODY;
+ }
+}