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 [31/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/rpc/atom/AtomAPIServlet.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/atom/AtomAPIServlet.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/atom/AtomAPIServlet.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/atom/AtomAPIServlet.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,332 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2001-2004 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.rpc.atom;
+
+import java.io.*;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import java.util.Date;
+import java.util.Collection;
+import java.util.Iterator;
+import org.apache.log4j.Logger;
+import org.intabulas.sandler.*;
+import org.intabulas.sandler.exceptions.*;
+import org.intabulas.sandler.elements.*;
+
+import com.ecyrd.jspwiki.*;
+import com.ecyrd.jspwiki.util.*;
+
+import com.ecyrd.jspwiki.plugin.WeblogEntryPlugin;
+import com.ecyrd.jspwiki.plugin.WeblogPlugin;
+import com.ecyrd.jspwiki.providers.ProviderException;
+
+/**
+ * Handles incoming requests for the Atom API. This class uses the
+ * "sandler" Atom API implementation.
+ *
+ * @author Janne Jalkanen
+ * @since 2.1.97
+ */
+public class AtomAPIServlet extends HttpServlet
+{
+ static final Logger log = Logger.getLogger( AtomAPIServlet.class );
+
+ private static final long serialVersionUID = 0L;
+
+ private WikiEngine m_engine;
+
+ /**
+ * Initializes the servlet.
+ */
+ public void init( ServletConfig config )
+ throws ServletException
+ {
+ m_engine = WikiEngine.getInstance( config );
+ }
+
+ /**
+ * Takes the name of the page from the request URI.
+ * The initial slash is also removed. If there is no page,
+ * returns null.
+ */
+ private String getPageName( HttpServletRequest request )
+ {
+ String name = request.getPathInfo();
+
+ if( name == null || name.length() <= 1 )
+ {
+ return null;
+ }
+ else if( name.charAt(0) == '/' )
+ {
+ name = name.substring(1);
+ }
+
+ name = TextUtil.urlDecodeUTF8( name );
+
+ return name;
+ }
+
+ /**
+ * Implements the PostURI of the Atom spec.
+ * <p>
+ * Implementation notes:
+ * <ul>
+ * <li>Only fetches the first content. All other contents are ignored.
+ * <li>Assumes that incoming code is plain text or WikiMarkup, not html.
+ * </ul>
+ */
+ public void doPost( HttpServletRequest request, HttpServletResponse response )
+ throws ServletException
+ {
+ log.debug("Received POST to AtomAPIServlet");
+
+ try
+ {
+ String blogid = getPageName( request );
+
+ WikiPage page = m_engine.getPage( blogid );
+
+ if( page == null )
+ {
+ throw new ServletException("Page "+blogid+" does not exist, cannot add blog post.");
+ }
+
+ //FIXME: Do authentication here
+ Entry entry = Sandler.unmarshallEntry( request.getInputStream() );
+
+ //
+ // Fetch the obligatory parts of the content.
+ //
+ Content title = entry.getTitle();
+ Content content = entry.getContent(0);
+
+ Person author = entry.getAuthor();
+
+ //FIXME: Sandler 0.5 does not support generator
+
+ //
+ // Generate new blog entry.
+ //
+ WeblogEntryPlugin plugin = new WeblogEntryPlugin();
+
+ String pageName = plugin.getNewEntryPage( m_engine, blogid );
+ String username = author.getName();
+
+ WikiPage entryPage = new WikiPage( m_engine, pageName );
+ entryPage.setAuthor( username );
+
+ WikiContext context = m_engine.getWikiActionBeanFactory().newViewActionBean( request, response, entryPage );
+
+ StringBuffer text = new StringBuffer();
+ text.append( "!"+title.getBody() );
+ text.append( "\n\n" );
+ text.append( content.getBody() );
+
+ log.debug("Writing entry: "+text);
+
+ m_engine.saveText( context, text.toString() );
+
+ }
+ catch( FeedMarshallException e )
+ {
+ log.error("Received faulty Atom entry",e);
+ throw new ServletException("Faulty Atom entry",e);
+ }
+ catch( IOException e )
+ {
+ log.error("I/O exception",e);
+ throw new ServletException("Could not get body of request",e);
+ }
+ catch( WikiException e )
+ {
+ log.error("Provider exception while posting",e);
+ throw new ServletException("JSPWiki cannot save the entry",e);
+ }
+ }
+
+ /**
+ * Handles HTTP GET. However, we do not respond to GET requests,
+ * other than to show an explanatory text.
+ */
+ public void doGet( HttpServletRequest request, HttpServletResponse response )
+ throws ServletException
+ {
+ log.debug("Received HTTP GET to AtomAPIServlet");
+
+ String blogid = getPageName( request );
+
+ log.debug("Requested page "+blogid);
+
+ try
+ {
+ if( blogid == null )
+ {
+ Feed feed = listBlogs();
+
+ response.setContentType("application/x.atom+xml; charset=UTF-8");
+ response.getWriter().println( Sandler.marshallFeed(feed) );
+
+ response.getWriter().flush();
+ }
+ else
+ {
+ Entry entry = getBlogEntry( blogid );
+
+ response.setContentType("application/x.atom+xml; charset=UTF-8");
+ response.getWriter().println( Sandler.marshallEntry(entry) );
+
+ response.getWriter().flush();
+ }
+ }
+ catch( Exception e )
+ {
+ log.error("Unable to generate response",e);
+ throw new ServletException("Internal problem - whack Janne on the head to get a better error report",e);
+ }
+
+ }
+
+ private Entry getBlogEntry( String entryid )
+ throws ProviderException
+ {
+ WikiPage page = m_engine.getPage( entryid );
+ WikiPage firstVersion = m_engine.getPage( entryid, 1 );
+
+ Entry entry = SyndicationFactory.newSyndicationEntry();
+
+ String pageText = m_engine.getText(page.getName());
+ String title = "";
+ int firstLine = pageText.indexOf('\n');
+
+ if( firstLine > 0 )
+ {
+ title = pageText.substring( 0, firstLine );
+ }
+
+ if( title.trim().length() == 0 ) title = page.getName();
+
+ // Remove wiki formatting
+ while( title.startsWith("!") ) title = title.substring(1);
+
+ entry.setTitle( title );
+ entry.setCreated( firstVersion.getLastModified() );
+ entry.setModified( page.getLastModified() );
+ entry.setAuthor( SyndicationFactory.createPerson( page.getAuthor(),
+ null,
+ null ) );
+
+ entry.addContent( SyndicationFactory.createEscapedContent(pageText) );
+
+ return entry;
+ }
+
+ /**
+ * Creates and outputs a full list of all available blogs
+ */
+ private Feed listBlogs()
+ throws ProviderException,
+ IOException
+ {
+ Collection pages = m_engine.getPageManager().getAllPages();
+
+ Feed feed = SyndicationFactory.newSyndicationFeed();
+ feed.setTitle("List of blogs at this site");
+ feed.setModified( new Date() );
+
+ for( Iterator i = pages.iterator(); i.hasNext(); )
+ {
+ WikiPage p = (WikiPage) i.next();
+
+ //
+ // List only weblogs
+ // FIXME: Unfortunately, a weblog is not known until it has
+ // been executed once, because plugins are off during
+ // the initial startup phase.
+ //
+
+ log.debug( p.getName()+" = "+p.getAttribute(WeblogPlugin.ATTR_ISWEBLOG)) ;
+
+ if( !("true".equals(p.getAttribute(WeblogPlugin.ATTR_ISWEBLOG)) ) )
+ continue;
+
+ String encodedName = TextUtil.urlEncodeUTF8( p.getName() );
+
+ WikiContext context = m_engine.getWikiActionBeanFactory().newViewActionBean( p );
+
+ String title = TextUtil.replaceEntities(BlogUtil.getSiteName(context));
+
+ Link postlink = createLink( "service.post",
+ m_engine.getBaseURL()+"atom/"+encodedName,
+ title );
+
+ Link editlink = createLink( "service.edit",
+ m_engine.getBaseURL()+"atom/"+encodedName,
+ title );
+
+ Link feedlink = createLink( "service.feed",
+ m_engine.getBaseURL()+"atom.jsp?page="+encodedName,
+ title );
+
+
+ feed.addLink( postlink );
+ feed.addLink( feedlink );
+ feed.addLink( editlink );
+ }
+
+ return feed;
+ }
+
+ private Link createLink( String rel,
+ String href,
+ String title )
+ {
+ org.intabulas.sandler.elements.impl.LinkImpl link = new org.intabulas.sandler.elements.impl.LinkImpl();
+
+ link.setRelationship( rel );
+ link.setTitle( title );
+ link.setType( "application/x.atom+xml" );
+ link.setHref( href );
+
+ return link;
+ }
+
+ /**
+ *
+ */
+ public void doDelete( HttpServletRequest request, HttpServletResponse response )
+ throws ServletException
+ {
+ log.debug("Received HTTP DELETE");
+ }
+
+ /**
+ *
+ */
+ public void doPut( HttpServletRequest request, HttpServletResponse response )
+ throws ServletException
+ {
+ log.debug("Received HTTP PUT");
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/json/JSONRPCManager.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/json/JSONRPCManager.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/json/JSONRPCManager.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/json/JSONRPCManager.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,309 @@
+/*
+ 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.rpc.json;
+
+import java.lang.reflect.Method;
+import java.security.Permission;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.log4j.Logger;
+
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiSession;
+import com.ecyrd.jspwiki.action.NoneActionBean;
+import com.ecyrd.jspwiki.auth.WikiSecurityException;
+import com.ecyrd.jspwiki.auth.permissions.PagePermission;
+import com.ecyrd.jspwiki.rpc.RPCCallable;
+import com.ecyrd.jspwiki.rpc.RPCManager;
+import com.ecyrd.jspwiki.ui.TemplateManager;
+import com.metaparadigm.jsonrpc.InvocationCallback;
+import com.metaparadigm.jsonrpc.JSONRPCBridge;
+
+/**
+ * Provides an easy-to-use interface for different modules to AJAX-enable
+ * themselves. This class is a static class, so it cannot be instantiated,
+ * but it easily available from anywhere (including JSP pages).
+ * <p>
+ * Any object which wants to expose its methods through JSON calls, needs
+ * to implement the RPCCallable interface. JSONRPCManager will expose
+ * <i>all</i> methods, so be careful which you want to expose.
+ * <p>
+ * Due to some limitations of the JSON-RPC library, we do not use the
+ * Global bridge object.
+ * @see com.ecyrd.jspwiki.rpc.RPCCallable
+ * @author Janne Jalkanen
+ * @since 2.5.4
+ */
+// FIXME: Must be mootool-ified.
+public final class JSONRPCManager extends RPCManager
+{
+ private static final String JSONRPCBRIDGE = "JSONRPCBridge";
+ private static HashMap c_globalObjects = new HashMap();
+
+ /** Prevent instantiation */
+ private JSONRPCManager()
+ {
+ super();
+ }
+
+ /**
+ * Emits JavaScript to do a JSON RPC Call. You would use this method e.g.
+ * in your plugin generation code to embed an AJAX call to your object.
+ *
+ * @param context The Wiki Context
+ * @param c An RPCCallable object
+ * @param function Name of the method to call
+ * @param params Parameters to pass to the method
+ * @return generated JavasSript code snippet that calls the method
+ */
+ public static String emitJSONCall( WikiContext context, RPCCallable c, String function, String params )
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("<script>");
+ sb.append("var result = jsonrpc."+getId(c)+"."+function+"("+params+");\r\n");
+ sb.append("document.write(result);\r\n");
+ sb.append("</script>");
+
+ return sb.toString();
+ }
+
+ /**
+ * Finds this user's personal RPC Bridge. If it does not exist, will
+ * create one and put it in the context. If there is no HTTP Request included,
+ * returns the global bridge.
+ *
+ * @param context WikiContext to find the bridge in
+ * @return A JSON RPC Bridge
+ */
+ // FIXME: Is returning the global bridge a potential security threat?
+ private static JSONRPCBridge getBridge( WikiContext context )
+ {
+ JSONRPCBridge bridge = null;
+ HttpServletRequest req = context.getHttpRequest();
+
+ if( req != null )
+ {
+ HttpSession hs = req.getSession();
+
+ if( hs != null )
+ {
+ bridge = (JSONRPCBridge)hs.getAttribute(JSONRPCBRIDGE);
+
+ if( bridge == null )
+ {
+ bridge = new JSONRPCBridge();
+
+ hs.setAttribute(JSONRPCBRIDGE, bridge);
+ }
+ }
+ }
+
+ if( bridge == null) bridge = JSONRPCBridge.getGlobalBridge();
+ bridge.setDebug(false);
+
+ return bridge;
+ }
+
+ /**
+ * Registers a callable to JSON global bridge and requests JSON libraries to be added
+ * to the page.
+ *
+ * @param context The WikiContext.
+ * @param c The RPCCallable to register
+ * @return the ID of the registered callable object
+ */
+ public static String registerJSONObject( WikiContext context, RPCCallable c )
+ {
+ String id = getId(c);
+ getBridge(context).registerObject( id, c );
+
+ requestJSON( context );
+ return id;
+ }
+
+ /**
+ * Requests the JSON Javascript and object to be generated in the HTML.
+ * @param context The WikiContext.
+ */
+ public static void requestJSON( WikiContext context )
+ {
+ TemplateManager.addResourceRequest(context,
+ TemplateManager.RESOURCE_SCRIPT,
+ context.getContext().getURL(NoneActionBean.class,"scripts/json-rpc/jsonrpc.js"));
+
+ String jsonurl = context.getContext().getURL( NoneActionBean.class, "JSON-RPC" );
+ TemplateManager.addResourceRequest(context,
+ TemplateManager.RESOURCE_JSFUNCTION,
+ "jsonrpc = new JSONRpcClient(\""+jsonurl+"\");");
+
+ getBridge(context).registerCallback(new WikiJSONAccessor(), HttpServletRequest.class);
+ }
+
+ /**
+ * Provides access control to the JSON calls. Rather private.
+ * Unfortunately we have to check the permission every single time, because
+ * the user can log in and we would need to reset the permissions at that time.
+ * Note that this is an obvious optimization piece if this becomes
+ * a bottleneck.
+ *
+ * @author Janne Jalkanen
+ */
+ static class WikiJSONAccessor implements InvocationCallback
+ {
+ private static final long serialVersionUID = 1L;
+ private static final Logger log = Logger.getLogger( WikiJSONAccessor.class );
+
+ /**
+ * Create an accessor.
+ */
+ public WikiJSONAccessor()
+ {}
+
+ /**
+ * Does not do anything.
+ *
+ * {@inheritDoc}
+ */
+ public void postInvoke(Object context, Object instance, Method method, Object result) throws Exception
+ {
+ }
+
+ /**
+ * Checks access against the permission given.
+ *
+ * {@inheritDoc}
+ */
+ public void preInvoke(Object context, Object instance, Method method, Object[] arguments) throws Exception
+ {
+ if( context instanceof HttpServletRequest )
+ {
+ boolean canDo = false;
+ HttpServletRequest req = (HttpServletRequest) context;
+
+ WikiEngine e = WikiEngine.getInstance( req.getSession().getServletContext(), null );
+
+ for( Iterator i = c_globalObjects.values().iterator(); i.hasNext(); )
+ {
+ CallbackContainer cc = (CallbackContainer) i.next();
+
+ if( cc.m_object == instance )
+ {
+ canDo = e.getAuthorizationManager().checkPermission( WikiSession.getWikiSession(e, req),
+ cc.m_permission );
+
+ break;
+ }
+ }
+
+ if( canDo )
+ {
+ return;
+ }
+ }
+
+ log.debug("Failed JSON permission check: "+instance);
+ throw new WikiSecurityException("No permission to access this AJAX method!");
+ }
+
+ }
+
+ /**
+ * Registers a global object (i.e. something which can be called by any
+ * JSP page). Typical examples is e.g. "search". By default, the RPCCallable
+ * shall need a "view" permission to access.
+ *
+ * @param id The name under which this shall be registered (e.g. "search")
+ * @param object The RPCCallable which shall be associated to this id.
+ */
+ public static void registerGlobalObject(String id, RPCCallable object)
+ {
+ registerGlobalObject(id, object, PagePermission.VIEW);
+ }
+
+ /**
+ * Registers a global object (i.e. something which can be called by any
+ * JSP page) with a specific permission.
+ *
+ * @param id The name under which this shall be registered (e.g. "search")
+ * @param object The RPCCallable which shall be associated to this id.
+ * @param perm The permission which is required to access this object.
+ */
+ public static void registerGlobalObject(String id, RPCCallable object, Permission perm )
+ {
+ CallbackContainer cc = new CallbackContainer();
+ cc.m_permission = perm;
+ cc.m_id = id;
+ cc.m_object = object;
+
+ c_globalObjects.put( id, cc );
+ }
+
+ /**
+ * Is called whenever a session is created. This method creates a new JSONRPCBridge
+ * and adds it to the user session. This is done because the global JSONRPCBridge
+ * InvocationCallbacks are not called; only session locals. This may be a bug
+ * in JSON-RPC, or it may be a design feature...
+ * <p>
+ * The JSONRPCBridge object will go away once the session expires.
+ *
+ * @param session The HttpSession which was created.
+ */
+ public static void sessionCreated( HttpSession session )
+ {
+ JSONRPCBridge bridge = (JSONRPCBridge)session.getAttribute(JSONRPCBRIDGE);
+
+ if( bridge == null )
+ {
+ bridge = new JSONRPCBridge();
+
+ session.setAttribute( JSONRPCBRIDGE, bridge );
+ }
+
+ WikiJSONAccessor acc = new WikiJSONAccessor();
+
+ bridge.registerCallback( acc, HttpServletRequest.class );
+
+ for( Iterator i = c_globalObjects.values().iterator(); i.hasNext(); )
+ {
+ CallbackContainer cc = (CallbackContainer) i.next();
+
+ bridge.registerObject( cc.m_id, cc.m_object );
+ }
+
+ }
+
+ /**
+ * Just stores the registered global method.
+ *
+ * @author Janne Jalkanen
+ *
+ */
+ private static class CallbackContainer
+ {
+ String m_id;
+ RPCCallable m_object;
+ Permission m_permission;
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/json/package.html
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/json/package.html?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/json/package.html (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rpc/json/package.html Tue Feb 12 21:53:55 2008
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Insert title here</title>
+</head>
+<body>
+Provides utility classes for using the JSON-RPC AJAX library.
+<h3>Package Specification</h3>
+
+<p>This package contains utility classes for using the JSON-RPC AJAX library.
+The JSON-RPC library is available from
+<a href="http://oss.metaparadigm.com/jsonrpc/">http://oss.metaparadigm.com/jsonrpc/</a>.
+
+<h3>Related Documentation</h3>
+
+<a href="http://oss.metaparadigm.com/jsonrpc/">JSON-RPC</a>.
+
+</body>
+</html>
\ No newline at end of file
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/AtomFeed.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/AtomFeed.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/AtomFeed.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/AtomFeed.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,217 @@
+/*
+ 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.rss;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.*;
+
+import javax.servlet.ServletContext;
+
+import org.apache.commons.lang.time.DateFormatUtils;
+import org.jdom.Element;
+import org.jdom.Namespace;
+import org.jdom.output.Format;
+import org.jdom.output.XMLOutputter;
+
+import com.ecyrd.jspwiki.Release;
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiPage;
+import com.ecyrd.jspwiki.action.AttachActionBean;
+import com.ecyrd.jspwiki.action.RSSActionBean;
+import com.ecyrd.jspwiki.attachment.Attachment;
+import com.ecyrd.jspwiki.providers.ProviderException;
+
+/**
+ * Provides an Atom 1.0 standard feed, with enclosures.
+ *
+ * @author jalkanen
+ *
+ */
+public class AtomFeed extends Feed
+{
+ private Namespace m_atomNameSpace = Namespace.getNamespace("http://www.w3.org/2005/Atom");
+
+ public static final String RFC3339FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZ";
+
+ public AtomFeed( WikiContext c )
+ {
+ super(c);
+ }
+
+ /**
+ * This is a bit complicated right now, as there is no proper metadata
+ * store in JSPWiki.
+ *
+ * @return
+ */
+ private String getFeedID()
+ {
+ return m_wikiContext.getEngine().getBaseURL(); // FIXME: This is not a feed id
+ }
+
+ private String getEntryID( Entry e )
+ {
+ return e.getURL(); // FIXME: Not really a feed id!
+ }
+
+ private Collection getItems()
+ {
+ ArrayList list = new ArrayList();
+
+ WikiEngine engine = m_wikiContext.getEngine();
+ ServletContext servletContext = null;
+
+ if( m_wikiContext.getHttpRequest() != null )
+ servletContext = m_wikiContext.getHttpRequest().getSession().getServletContext();
+
+ for( Iterator i = m_entries.iterator(); i.hasNext(); )
+ {
+ Entry e = (Entry)i.next();
+
+ WikiPage p = e.getPage();
+
+ Element entryEl = getElement("entry");
+
+ //
+ // Mandatory elements
+ //
+
+ entryEl.addContent( getElement("id").setText( getEntryID(e)) );
+ entryEl.addContent( getElement("title").setAttribute("type","html").setText( e.getTitle() ));
+ entryEl.addContent( getElement("updated").setText( DateFormatUtils.formatUTC(p.getLastModified(),
+ RFC3339FORMAT )));
+ //
+ // Optional elements
+ //
+
+ entryEl.addContent( getElement("author").addContent( getElement("name").setText( e.getAuthor() )));
+ entryEl.addContent( getElement("link").setAttribute("rel","alternate").setAttribute("href",e.getURL()));
+ entryEl.addContent( getElement("content").setAttribute("type","html").setText( e.getContent() ));
+
+ //
+ // Check for enclosures
+ //
+
+ if( engine.getAttachmentManager().hasAttachments(p) && servletContext != null )
+ {
+ try
+ {
+ Collection c = engine.getAttachmentManager().listAttachments(p);
+
+ for( Iterator a = c.iterator(); a.hasNext(); )
+ {
+ Attachment att = (Attachment) a.next();
+
+ Element attEl = getElement("link");
+ attEl.setAttribute( "rel","enclosure" );
+ attEl.setAttribute( "href", m_wikiContext.getContext().getURL(AttachActionBean.class, att.getName(), null, true ) );
+ attEl.setAttribute( "length", Long.toString(att.getSize()) );
+ attEl.setAttribute( "type", getMimeType( servletContext, att.getFileName() ) );
+
+ entryEl.addContent( attEl );
+ }
+ }
+ catch( ProviderException ex )
+ {
+ // FIXME: log.info("Can't get attachment data",ex);
+ }
+ }
+
+
+ list.add( entryEl );
+ }
+
+ return list;
+ }
+
+ public String getString()
+ {
+ Element root = getElement("feed");
+ WikiEngine engine = m_wikiContext.getEngine();
+
+ Date lastModified = new Date(0L);
+
+ for( Iterator i = m_entries.iterator(); i.hasNext(); )
+ {
+ Entry e = (Entry)i.next();
+
+ if( e.getPage().getLastModified().after(lastModified) )
+ lastModified = e.getPage().getLastModified();
+ }
+
+ //
+ // Mandatory parts
+ //
+ root.addContent( getElement("title").setText( getChannelTitle() ) );
+ root.addContent( getElement("id").setText(getFeedID()) );
+ root.addContent( getElement("updated").setText(DateFormatUtils.formatUTC( lastModified,
+ RFC3339FORMAT ) ));
+
+ //
+ // Optional
+ //
+ // root.addContent( getElement("author").addContent(getElement("name").setText(format())))
+ root.addContent( getElement("link").setAttribute("href",engine.getBaseURL()));
+ root.addContent( getElement("generator").setText("JSPWiki "+Release.VERSTR));
+
+ Map<String,String> rssParams = new HashMap<String,String>();
+ rssParams.put("mode", m_mode);
+ rssParams.put("type", "atom");
+ String rssFeedURL = m_wikiContext.getContext().getURL(RSSActionBean.class,
+ "page="+engine.encodeName(m_wikiContext.getPage().getName()),
+ rssParams,
+ true );
+ Element self = getElement("link").setAttribute("rel","self");
+ self.setAttribute("href",rssFeedURL);
+ root.addContent(self);
+
+ //
+ // Items
+ //
+
+ root.addContent( getItems() );
+
+ //
+ // aaand output
+ //
+ XMLOutputter output = new XMLOutputter();
+
+ output.setFormat( Format.getPrettyFormat() );
+
+ try
+ {
+ StringWriter res = new StringWriter();
+ output.output( root, res );
+
+ return res.toString();
+ }
+ catch( IOException e )
+ {
+ return null;
+ }
+ }
+
+ private final Element getElement( String name )
+ {
+ return new Element( name, m_atomNameSpace );
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/Entry.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/Entry.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/Entry.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/Entry.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,86 @@
+/*
+ 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.rss;
+
+import com.ecyrd.jspwiki.WikiPage;
+
+/**
+ * @author jalkanen
+ *
+ * @since
+ */
+public class Entry
+{
+ private String m_content;
+ private String m_URL;
+ private String m_title;
+ private WikiPage m_page;
+ private String m_author;
+
+ public void setAuthor( String author )
+ {
+ m_author = author;
+ }
+
+ public String getAuthor()
+ {
+ return m_author;
+ }
+
+ public WikiPage getPage()
+ {
+ return m_page;
+ }
+
+ public void setPage( WikiPage p )
+ {
+ m_page = p;
+ }
+
+ public void setTitle( String title )
+ {
+ m_title = title;
+ }
+
+ public String getTitle()
+ {
+ return m_title;
+ }
+
+ public void setURL( String url )
+ {
+ m_URL = url;
+ }
+
+ public String getURL()
+ {
+ return m_URL;
+ }
+
+ public void setContent( String content )
+ {
+ m_content = content;
+ }
+
+ public String getContent()
+ {
+ return m_content;
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/Feed.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/Feed.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/Feed.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/Feed.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,145 @@
+/*
+ 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.rss;
+
+import java.util.*;
+
+import javax.servlet.ServletContext;
+
+import com.ecyrd.jspwiki.TextUtil;
+import com.ecyrd.jspwiki.WikiContext;
+
+/**
+ * @author jalkanen
+ *
+ * @since
+ */
+public abstract class Feed
+{
+ protected List m_entries = new ArrayList();
+
+ protected String m_feedURL;
+ protected String m_channelTitle;
+ protected String m_channelDescription;
+ protected String m_channelLanguage;
+
+ protected WikiContext m_wikiContext;
+
+ protected String m_mode = RSSGenerator.MODE_WIKI;
+
+ public Feed( WikiContext context )
+ {
+ m_wikiContext = context;
+ }
+
+ public void setMode( String mode )
+ {
+ m_mode = mode;
+ }
+
+ public void addEntry( Entry e )
+ {
+ m_entries.add( e );
+ }
+
+ public abstract String getString();
+ /**
+ * @return Returns the m_channelDescription.
+ */
+ public String getChannelDescription()
+ {
+ return m_channelDescription;
+ }
+ /**
+ * @param description The m_channelDescription to set.
+ */
+ public void setChannelDescription( String description )
+ {
+ m_channelDescription = description;
+ }
+ /**
+ * @return Returns the m_channelLanguage.
+ */
+ public String getChannelLanguage()
+ {
+ return m_channelLanguage;
+ }
+ /**
+ * @param language The m_channelLanguage to set.
+ */
+ public void setChannelLanguage( String language )
+ {
+ m_channelLanguage = language;
+ }
+ /**
+ * @return Returns the m_channelTitle.
+ */
+ public String getChannelTitle()
+ {
+ return m_channelTitle;
+ }
+ /**
+ * @param title The m_channelTitle to set.
+ */
+ public void setChannelTitle( String title )
+ {
+ m_channelTitle = title;
+ }
+
+ /**
+ * @return Returns the m_feedURL.
+ */
+ public String getFeedURL()
+ {
+ return m_feedURL;
+ }
+ /**
+ * @param feedurl The m_feedURL to set.
+ */
+ public void setFeedURL( String feedurl )
+ {
+ m_feedURL = feedurl;
+ }
+
+ protected String getMimeType(ServletContext c, String name)
+ {
+ String type = c.getMimeType(name);
+
+ if( type == null ) type = "application/octet-stream";
+
+ return type;
+ }
+
+ /**
+ * Does the required formatting and entity replacement for XML.
+ */
+ public static String format( String s )
+ {
+ if( s != null )
+ {
+ s = TextUtil.replaceString( s, "&", "&" );
+ s = TextUtil.replaceString( s, "<", "<" );
+ s = TextUtil.replaceString( s, ">", ">" );
+
+ return s.trim();
+ }
+ return null;
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSS10Feed.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSS10Feed.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSS10Feed.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSS10Feed.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,211 @@
+/*
+ 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.rss;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.ecs.xml.XML;
+
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiPage;
+import com.ecyrd.jspwiki.action.DiffActionBean;
+import com.ecyrd.jspwiki.action.PageInfoActionBean;
+
+/**
+ * @author jalkanen
+ *
+ * @since
+ */
+public class RSS10Feed extends Feed
+{
+ public RSS10Feed( WikiContext context )
+ {
+ super(context);
+ }
+
+ private XML getRDFItems()
+ {
+ XML items = new XML( "items" );
+
+ XML rdfseq = new XML( "rdf:Seq" );
+
+ for( Iterator i = m_entries.iterator(); i.hasNext(); )
+ {
+ Entry e = (Entry)i.next();
+
+ String url = e.getURL();
+
+ rdfseq.addElement( new XML("rdf:li").addAttribute( "rdf:resource", url ) );
+ }
+
+ items.addElement( rdfseq );
+
+ return items;
+ }
+
+ private void addItemList( XML root )
+ {
+ SimpleDateFormat iso8601fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+
+ WikiEngine engine = m_wikiContext.getEngine();
+
+ for( Iterator i = m_entries.iterator(); i.hasNext(); )
+ {
+ Entry e = (Entry)i.next();
+
+ String url = e.getURL();
+
+ XML item = new XML( "item" );
+ item.addAttribute( "rdf:about", url );
+
+ item.addElement( new XML("title").addElement( format(e.getTitle()) ) );
+
+ item.addElement( new XML("link").addElement( url ) );
+
+ XML content = new XML("description");
+
+ // TODO: Add a size limiter here
+ content.addElement( format(e.getContent()) );
+
+ item.addElement( content );
+
+ WikiPage p = e.getPage();
+
+ if( p.getVersion() != -1 )
+ {
+ item.addElement( new XML("wiki:version").addElement( Integer.toString(p.getVersion()) ) );
+ }
+
+ if( p.getVersion() > 1 )
+ {
+ Map<String,String> rssParams = new HashMap<String,String>();
+ rssParams.put("r1", "-1");
+ item.addElement( new XML("wiki:diff").addElement( m_wikiContext.getContext().getURL( DiffActionBean.class,
+ p.getName(),
+ rssParams,
+ true) ) );
+ }
+
+
+ //
+ // Modification date.
+ //
+ Calendar cal = Calendar.getInstance();
+ cal.setTime( p.getLastModified() );
+ cal.add( Calendar.MILLISECOND,
+ - (cal.get( Calendar.ZONE_OFFSET ) +
+ (cal.getTimeZone().inDaylightTime( p.getLastModified() ) ? cal.get( Calendar.DST_OFFSET ) : 0 )) );
+
+ item.addElement( new XML("dc:date").addElement( iso8601fmt.format( cal.getTime() )));
+
+ //
+ // Author
+ String author = e.getAuthor();
+ if( author == null ) author = "unknown";
+
+ XML contributor = new XML("dc:creator");
+
+ item.addElement( contributor );
+
+ /*
+ XML description = new XML("rdf:Description");
+ if( m_wikiContext.getEngine().pageExists(author) )
+ {
+ description.addAttribute( "link", engine.getURL( WikiContext.VIEW,
+ author,
+ null,
+ true ) );
+ }
+
+ description.addElement( new XML("value").addElement( format(author) ) );
+ contributor.addElement( description );
+ */
+
+ // Not too many aggregators seem to like this. Therefore we're
+ // just adding the name here.
+
+ contributor.addElement( format(author) );
+
+ // PageHistory
+
+ item.addElement( new XML("wiki:history").addElement( m_wikiContext.getContext().getURL( PageInfoActionBean.class,
+ p.getName(),
+ null,
+ true ) ) );
+
+ //
+ // Add to root
+ //
+
+ root.addElement( item );
+ }
+ }
+
+ private XML getChannelElement()
+ {
+ XML channel = new XML( "channel" );
+
+ channel.addAttribute("rdf:about", m_feedURL );
+
+ channel.addElement( new XML("link").addElement( m_feedURL ) );
+
+ if( m_channelTitle != null )
+ channel.addElement( new XML("title").addElement( format(m_channelTitle)) );
+
+ if( m_channelDescription != null )
+ channel.addElement( new XML("description").addElement( format(m_channelDescription)) );
+
+ if( m_channelLanguage != null )
+ channel.addElement( new XML("dc:language").addElement(m_channelLanguage) );
+
+ channel.setPrettyPrint( true );
+
+ channel.addElement( getRDFItems() );
+
+ return channel;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ecyrd.jspwiki.rss.Feed#getString()
+ */
+ public String getString()
+ {
+ XML root = new XML("rdf:RDF");
+
+ root.addAttribute( "xmlns:rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" );
+ root.addAttribute( "xmlns", "http://purl.org/rss/1.0/" );
+ root.addAttribute( "xmlns:dc", "http://purl.org/dc/elements/1.1/" );
+ root.addAttribute( "xmlns:wiki", "http://purl.org/rss/1.0/modules/wiki/" );
+
+ root.addElement( getChannelElement() );
+
+ addItemList( root );
+
+ root.setPrettyPrint( true );
+
+ return root.toString();
+ }
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSS20Feed.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSS20Feed.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSS20Feed.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSS20Feed.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,186 @@
+/*
+ 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.rss;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import javax.servlet.ServletContext;
+
+import org.jdom.Element;
+import org.jdom.output.Format;
+import org.jdom.output.XMLOutputter;
+
+import com.ecyrd.jspwiki.Release;
+import com.ecyrd.jspwiki.WikiContext;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiPage;
+import com.ecyrd.jspwiki.action.AttachActionBean;
+import com.ecyrd.jspwiki.attachment.Attachment;
+import com.ecyrd.jspwiki.providers.ProviderException;
+
+/**
+ * Represents an RSS 2.0 feed (with enclosures).
+ *
+ * @author jalkanen
+ *
+ * @since 2.2.27
+ */
+public class RSS20Feed extends Feed
+{
+
+ public RSS20Feed( WikiContext context )
+ {
+ super( context );
+ }
+
+ private List getItems()
+ {
+ ArrayList list = new ArrayList();
+ SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'");
+
+ WikiEngine engine = m_wikiContext.getEngine();
+ ServletContext servletContext = null;
+
+ if( m_wikiContext.getHttpRequest() != null )
+ servletContext = m_wikiContext.getHttpRequest().getSession().getServletContext();
+
+ for( Iterator i = m_entries.iterator(); i.hasNext(); )
+ {
+ Entry e = (Entry)i.next();
+ WikiPage p = e.getPage();
+
+ String url = e.getURL();
+
+ Element item = new Element("item");
+
+ item.addContent( new Element("link").setText(url) );
+
+ item.addContent( new Element("title").setText( e.getTitle()) );
+
+ item.addContent( new Element("description").setText( e.getContent()) );
+
+ //
+ // Attachments for enclosures
+ //
+
+ if( engine.getAttachmentManager().hasAttachments(p) && servletContext != null )
+ {
+ try
+ {
+ Collection c = engine.getAttachmentManager().listAttachments(p);
+
+ for( Iterator a = c.iterator(); a.hasNext(); )
+ {
+ Attachment att = (Attachment) a.next();
+
+ Element attEl = new Element("enclosure");
+ attEl.setAttribute( "url", m_wikiContext.getContext().getURL(AttachActionBean.class, att.getName(), null, true ) );
+ attEl.setAttribute( "length", Long.toString(att.getSize()) );
+ attEl.setAttribute( "type", getMimeType( servletContext, att.getFileName() ) );
+
+ item.addContent( attEl );
+ }
+ }
+ catch( ProviderException ex )
+ {
+ // FIXME: log.info("Can't get attachment data",ex);
+ }
+ }
+
+ //
+ // Modification date.
+ //
+ Calendar cal = Calendar.getInstance();
+ cal.setTime( p.getLastModified() );
+ cal.add( Calendar.MILLISECOND,
+ - (cal.get( Calendar.ZONE_OFFSET ) +
+ (cal.getTimeZone().inDaylightTime( p.getLastModified() ) ? cal.get( Calendar.DST_OFFSET ) : 0 )) );
+
+ item.addContent( new Element("pubDate").setText(fmt.format(cal.getTime())) );
+
+ list.add( item );
+ }
+
+ return list;
+ }
+
+ public String getString()
+ {
+ WikiEngine engine = m_wikiContext.getEngine();
+ Element root = new Element("rss");
+ root.setAttribute("version","2.0");
+
+ Element channel = new Element("channel");
+ root.addContent( channel );
+
+ //
+ // Mandatory parts
+ //
+ channel.addContent( new Element("title").setText( getChannelTitle() ) );
+ channel.addContent( new Element("link").setText(engine.getBaseURL()));
+ channel.addContent( new Element("description").setText( getChannelDescription() ));
+
+ //
+ // Optional
+ //
+ channel.addContent( new Element("language").setText(getChannelLanguage()));
+ channel.addContent( new Element("generator").setText("JSPWiki "+Release.VERSTR));
+
+ String mail = engine.getVariable(m_wikiContext,RSSGenerator.PROP_RSS_AUTHOREMAIL);
+ if( mail != null )
+ {
+ String editor = engine.getVariable( m_wikiContext,RSSGenerator.PROP_RSS_AUTHOR );
+
+ if( editor != null )
+ mail = mail + " ("+editor+")";
+
+ channel.addContent( new Element("managingEditor").setText(mail) );
+ }
+
+ //
+ // Items
+ //
+
+ channel.addContent( getItems() );
+
+ //
+ // aaand output
+ //
+ XMLOutputter output = new XMLOutputter();
+
+ output.setFormat( Format.getPrettyFormat() );
+
+ try
+ {
+ StringWriter res = new StringWriter();
+ output.output( root, res );
+
+ return res.toString();
+ }
+ catch( IOException e )
+ {
+ return null;
+ }
+ }
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSSGenerator.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSSGenerator.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSSGenerator.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSSGenerator.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,590 @@
+/*
+ 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.rss;
+
+import java.util.*;
+
+import org.apache.log4j.Logger;
+
+import com.ecyrd.jspwiki.*;
+import com.ecyrd.jspwiki.action.AttachActionBean;
+import com.ecyrd.jspwiki.action.PageInfoActionBean;
+import com.ecyrd.jspwiki.action.RSSActionBean;
+import com.ecyrd.jspwiki.action.ViewActionBean;
+import com.ecyrd.jspwiki.attachment.Attachment;
+import com.ecyrd.jspwiki.auth.permissions.PagePermission;
+import com.ecyrd.jspwiki.providers.ProviderException;
+
+/**
+ * Generates an RSS feed from the recent changes.
+ * <P>
+ * We use the 1.0 spec, including the wiki-specific extensions. Wiki extensions
+ * have been defined in <A HREF="http://usemod.com/cgi-bin/mb.pl?ModWiki">UseMod:ModWiki</A>.
+ *
+ * @author Janne Jalkanen
+ * @since 1.7.5.
+ */
+// FIXME: Limit diff and page content size.
+public class RSSGenerator
+{
+ static Logger log = Logger.getLogger( RSSGenerator.class );
+ private WikiEngine m_engine;
+
+ private String m_channelDescription = "";
+ private String m_channelLanguage = "en-us";
+ private boolean m_enabled = true;
+
+ public static final String RSS10 = "rss10";
+ public static final String RSS20 = "rss20";
+ public static final String ATOM = "atom";
+
+ public static final String MODE_BLOG = "blog";
+ public static final String MODE_WIKI = "wiki";
+ public static final String MODE_FULL = "full";
+
+ /**
+ * Defines the property name for the RSS channel description. Default value for the
+ * channel description is an empty string.
+ * @since 1.7.6.
+ */
+ public static final String PROP_CHANNEL_DESCRIPTION = "jspwiki.rss.channelDescription";
+
+ /**
+ * Defines the property name for the RSS channel language. Default value for the
+ * language is "en-us".
+ * @since 1.7.6.
+ */
+ public static final String PROP_CHANNEL_LANGUAGE = "jspwiki.rss.channelLanguage";
+
+ public static final String PROP_CHANNEL_TITLE = "jspwiki.rss.channelTitle";
+
+ /**
+ * Defines the property name for the RSS generator main switch.
+ * @since 1.7.6.
+ */
+ public static final String PROP_GENERATE_RSS = "jspwiki.rss.generate";
+
+ /**
+ * Defines the property name for the RSS file that the wiki should generate.
+ * @since 1.7.6.
+ */
+ public static final String PROP_RSSFILE = "jspwiki.rss.fileName";
+
+ public static final String PROP_RSSAUTHOR = "jspwiki.rss.author";
+ public static final String PROP_RSSAUTHOREMAIL = "jspwiki.rss.author.email";
+
+ /**
+ * Defines the property name for the RSS generation interval in seconds.
+ * @since 1.7.6.
+ */
+ public static final String PROP_INTERVAL = "jspwiki.rss.interval";
+
+ public static final String PROP_RSS_AUTHOR = "jspwiki.rss.author";
+ public static final String PROP_RSS_AUTHOREMAIL = "jspwiki.rss.author.email";
+ public static final String PROP_RSS_COPYRIGHT = "jspwiki.rss.copyright";
+
+ private static final int MAX_CHARACTERS = Integer.MAX_VALUE-1;
+
+ /**
+ * Initialize the RSS generator.
+ */
+ public RSSGenerator( WikiEngine engine, Properties properties )
+ throws NoRequiredPropertyException
+ {
+ m_engine = engine;
+
+ // FIXME: This assumes a bit too much.
+ if( engine.getBaseURL() == null || engine.getBaseURL().length() == 0 )
+ {
+ throw new NoRequiredPropertyException( "RSS requires jspwiki.baseURL to be set!",
+ WikiEngine.PROP_BASEURL );
+ }
+
+ m_channelDescription = properties.getProperty( PROP_CHANNEL_DESCRIPTION,
+ m_channelDescription );
+ m_channelLanguage = properties.getProperty( PROP_CHANNEL_LANGUAGE,
+ m_channelLanguage );
+ }
+
+ /**
+ * Does the required formatting and entity replacement for XML.
+ */
+ public static String format( String s )
+ {
+ s = TextUtil.replaceString( s, "&", "&" );
+ s = TextUtil.replaceString( s, "<", "<" );
+ s = TextUtil.replaceString( s, "]]>", "]]>" );
+
+ return s.trim();
+ }
+
+ private String getAuthor( WikiPage page )
+ {
+ String author = page.getAuthor();
+
+ if( author == null ) author = "An unknown author";
+
+ return author;
+ }
+
+ private String getAttachmentDescription( WikiContext wikiContext, Attachment att )
+ {
+ String author = getAuthor(att);
+ StringBuffer sb = new StringBuffer();
+
+ if( att.getVersion() != 1 )
+ {
+ sb.append(author+" uploaded a new version of this attachment on "+att.getLastModified() );
+ }
+ else
+ {
+ sb.append(author+" created this attachment on "+att.getLastModified() );
+ }
+
+ sb.append("<br /><hr /><br />");
+ sb.append( "Parent page: <a href=\""+
+ wikiContext.getContext().getURL( ViewActionBean.class, att.getParentName(), null, true ) +
+ "\">"+att.getParentName()+"</a><br />" );
+ sb.append( "Info page: <a href=\""+
+ wikiContext.getContext().getURL( PageInfoActionBean.class, att.getName(), null, true ) +
+ "\">"+att.getName()+"</a>" );
+
+ return sb.toString();
+ }
+
+ private String getPageDescription( WikiPage page )
+ {
+ StringBuffer buf = new StringBuffer();
+ String author = getAuthor(page);
+
+ WikiContext ctx = m_engine.getWikiActionBeanFactory().newViewActionBean( page );
+ if( page.getVersion() > 1 )
+ {
+ String diff = m_engine.getDiff( ctx,
+ page.getVersion()-1, // FIXME: Will fail when non-contiguous versions
+ page.getVersion() );
+
+ buf.append(author+" changed this page on "+page.getLastModified()+":<br /><hr /><br />" );
+ buf.append(diff);
+ }
+ else
+ {
+ buf.append(author+" created this page on "+page.getLastModified()+":<br /><hr /><br />" );
+ buf.append(m_engine.getHTML( page.getName() ));
+ }
+
+ return buf.toString();
+ }
+
+ private String getEntryDescription( WikiContext context, WikiPage page )
+ {
+ String res;
+
+ if( page instanceof Attachment )
+ {
+ res = getAttachmentDescription( context, (Attachment)page );
+ }
+ else
+ {
+ res = getPageDescription( page );
+ }
+
+ return res;
+ }
+
+ // FIXME: This should probably return something more intelligent
+ private String getEntryTitle( WikiPage page )
+ {
+ return page.getName()+", version "+page.getVersion();
+ }
+
+ /**
+ * Generates the RSS resource. You probably want to output this
+ * result into a file or something, or serve as output from a servlet.
+ */
+ public String generate() throws WikiException
+ {
+ // FIXME: This will absolutely, positively not work. We need to do something else
+ WikiContext context = (WikiContext)m_engine.getWikiActionBeanFactory().newActionBean(null,null,RSSActionBean.class);
+ context.setPage( new WikiPage( m_engine, "__DUMMY" ) );
+ Feed feed = new RSS10Feed( context );
+
+ String result = generateFullWikiRSS( context, feed );
+
+ result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + result;
+
+ return result;
+ }
+
+ /**
+ * Returns the content type of this RSS feed.
+ * @since 2.3.15
+ * @param mode the RSS mode: {@link #RSS10}, {@link #RSS20} or {@link #ATOM}.
+ * @return the content type
+ */
+ public static String getContentType( String mode )
+ {
+ if( mode.equals( RSS10 )||mode.equals(RSS20) )
+ {
+ return "application/rss+xml";
+ }
+ else if( mode.equals(ATOM) )
+ {
+ return "application/atom+xml";
+ }
+
+ return "application/octet-stream"; // Unknown type
+ }
+
+ /**
+ * Generates a feed based on a context and list of changes.
+ * @param wikiContext The WikiContext
+ * @param changed A list of Entry objects
+ * @param mode The mode (wiki/blog)
+ * @param type The type (RSS10, RSS20, ATOM). Default is RSS 1.0
+ * @return Fully formed XML.
+ *
+ * @throws ProviderException If the underlying provider failed.
+ * @throws IllegalArgumentException If an illegal mode is given.
+ */
+ public String generateFeed( WikiContext wikiContext, List changed, String mode, String type )
+ throws ProviderException
+ {
+ Feed feed = null;
+ String res = null;
+
+ if( ATOM.equals(type) )
+ {
+ feed = new AtomFeed( wikiContext );
+ }
+ else if( RSS20.equals( type ) )
+ {
+ feed = new RSS20Feed( wikiContext );
+ }
+ else
+ {
+ feed = new RSS10Feed( wikiContext );
+ }
+
+ feed.setMode( mode );
+
+ if( MODE_BLOG.equals( mode ) )
+ {
+ res = generateBlogRSS( wikiContext, changed, feed );
+ }
+ else if( MODE_FULL.equals(mode) )
+ {
+ res = generateFullWikiRSS( wikiContext, feed );
+ }
+ else if( MODE_WIKI.equals(mode) )
+ {
+ res = generateWikiPageRSS( wikiContext, changed, feed );
+ }
+ else
+ {
+ throw new IllegalArgumentException( "Invalid value for feed mode: "+mode );
+ }
+
+ return res;
+ }
+
+ /**
+ * Returns <code>true</code> if RSS generation is enabled.
+ * @return whether RSS generation is currently enabled
+ */
+ public boolean isEnabled()
+ {
+ return m_enabled;
+ }
+
+ /**
+ * Turns RSS generation on or off. This setting is used to set
+ * the "enabled" flag only for use by callers, and does not
+ * actually affect whether the {@link #generate()} or
+ * {@link #generateFeed(WikiContext, List, String, String)}
+ * methods output anything.
+ * @param enabled whether RSS generation is considered enabled.
+ */
+ public synchronized void setEnabled( boolean enabled )
+ {
+ m_enabled = enabled;
+ }
+
+ /**
+ * Generates an RSS feed for the entire wiki. Each item should be an instance of the RSSItem class.
+ */
+ protected String generateFullWikiRSS( WikiContext wikiContext, Feed feed )
+ {
+ feed.setChannelTitle( m_engine.getApplicationName() );
+ feed.setFeedURL( m_engine.getBaseURL() );
+ feed.setChannelLanguage( m_channelLanguage );
+ feed.setChannelDescription( m_channelDescription );
+
+ Collection changed = m_engine.getRecentChanges();
+
+ WikiSession session = WikiSession.guestSession( m_engine );
+ int items = 0;
+ for( Iterator i = changed.iterator(); i.hasNext() && items < 15; items++ )
+ {
+ WikiPage page = (WikiPage) i.next();
+
+ //
+ // Check if the anonymous user has view access to this page.
+ //
+
+ if( !m_engine.getAuthorizationManager().checkPermission(session,
+ new PagePermission(page,PagePermission.VIEW_ACTION) ) )
+ {
+ // No permission, skip to the next one.
+ continue;
+ }
+
+ Entry e = new Entry();
+
+ e.setPage( page );
+
+ String url;
+
+ if( page instanceof Attachment )
+ {
+ url = wikiContext.getContext().getURL( AttachActionBean.class,
+ page.getName(),
+ null,
+ true );
+ }
+ else
+ {
+ url = wikiContext.getContext().getURL( ViewActionBean.class,
+ page.getName(),
+ null,
+ true );
+ }
+
+ e.setURL( url );
+ e.setTitle( page.getName() );
+ e.setContent( getEntryDescription(wikiContext, page) );
+ e.setAuthor( getAuthor(page) );
+
+ feed.addEntry( e );
+ }
+
+ return feed.getString();
+ }
+
+ /**
+ * Create RSS/Atom as if this page was a wikipage (in contrast to Blog mode).
+ *
+ * @param wikiContext
+ * @param changed
+ * @param feed
+ * @return
+ */
+ protected String generateWikiPageRSS( WikiContext wikiContext, List changed, Feed feed )
+ {
+ feed.setChannelTitle( m_engine.getApplicationName()+": "+wikiContext.getPage().getName() );
+ feed.setFeedURL( wikiContext.getViewURL( wikiContext.getPage().getName() ) );
+ String language = m_engine.getVariable( wikiContext, PROP_CHANNEL_LANGUAGE );
+
+ if( language != null )
+ feed.setChannelLanguage( language );
+ else
+ feed.setChannelLanguage( m_channelLanguage );
+
+ String channelDescription = m_engine.getVariable( wikiContext, PROP_CHANNEL_DESCRIPTION );
+
+ if( channelDescription != null )
+ {
+ feed.setChannelDescription( channelDescription );
+ }
+
+ Collections.sort( changed, new PageTimeComparator() );
+
+ int items = 0;
+ for( Iterator i = changed.iterator(); i.hasNext() && items < 15; items++ )
+ {
+ WikiPage page = (WikiPage) i.next();
+
+ Entry e = new Entry();
+
+ e.setPage( page );
+
+ String url;
+
+ Map<String,String> rssParams = new HashMap<String,String>();
+ rssParams.put("version", String.valueOf(page.getVersion()));
+ if( page instanceof Attachment )
+ {
+ url = wikiContext.getContext().getURL( AttachActionBean.class,
+ page.getName(),
+ rssParams,
+ true );
+ }
+ else
+ {
+ url = wikiContext.getContext().getURL( ViewActionBean.class,
+ page.getName(),
+ rssParams,
+ true );
+ }
+
+ // Unfortunately, this is needed because the code will again go through
+ // replacement conversion
+
+ url = TextUtil.replaceString( url, "&", "&" );
+
+ e.setURL( url );
+ e.setTitle( getEntryTitle(page) );
+ e.setContent( getEntryDescription(wikiContext, page) );
+ e.setAuthor( getAuthor(page) );
+
+ feed.addEntry( e );
+ }
+
+ return feed.getString();
+ }
+
+
+ /**
+ * Creates RSS from modifications as if this page was a blog (using the WeblogPlugin).
+ *
+ * @param wikiContext The WikiContext, as usual.
+ * @param changed A list of the changed pages.
+ * @param feed A valid Feed object. The feed will be used to create the RSS/Atom, depending
+ * on which kind of an object you want to put in it.
+ * @return A String of valid RSS or Atom.
+ * @throws ProviderException If reading of pages was not possible.
+ */
+ protected String generateBlogRSS( WikiContext wikiContext, List changed, Feed feed )
+ throws ProviderException
+ {
+ if( log.isDebugEnabled() ) log.debug("Generating RSS for blog, size="+changed.size());
+
+ String ctitle = m_engine.getVariable( wikiContext, PROP_CHANNEL_TITLE );
+
+ if( ctitle != null )
+ feed.setChannelTitle( ctitle );
+ else
+ feed.setChannelTitle( m_engine.getApplicationName()+":"+wikiContext.getPage().getName() );
+
+ feed.setFeedURL( wikiContext.getViewURL( wikiContext.getPage().getName() ) );
+
+ String language = m_engine.getVariable( wikiContext, PROP_CHANNEL_LANGUAGE );
+
+ if( language != null )
+ feed.setChannelLanguage( language );
+ else
+ feed.setChannelLanguage( m_channelLanguage );
+
+ String channelDescription = m_engine.getVariable( wikiContext, PROP_CHANNEL_DESCRIPTION );
+
+ if( channelDescription != null )
+ {
+ feed.setChannelDescription( channelDescription );
+ }
+
+ Collections.sort( changed, new PageTimeComparator() );
+
+ int items = 0;
+ for( Iterator i = changed.iterator(); i.hasNext() && items < 15; items++ )
+ {
+ WikiPage page = (WikiPage) i.next();
+
+ Entry e = new Entry();
+
+ e.setPage( page );
+
+ String url;
+
+ if( page instanceof Attachment )
+ {
+ url = wikiContext.getContext().getURL( AttachActionBean.class,
+ page.getName(),
+ null,
+ true );
+ }
+ else
+ {
+ url = wikiContext.getContext().getURL( ViewActionBean.class,
+ page.getName(),
+ null,
+ true );
+ }
+
+ e.setURL( url );
+
+ //
+ // Title
+ //
+
+ String pageText = m_engine.getPureText(page.getName(), WikiProvider.LATEST_VERSION );
+
+ String title = "";
+ int firstLine = pageText.indexOf('\n');
+
+ if( firstLine > 0 )
+ {
+ title = pageText.substring( 0, firstLine ).trim();
+ }
+
+ if( title.length() == 0 ) title = page.getName();
+
+ // Remove wiki formatting
+ while( title.startsWith("!") ) title = title.substring(1);
+
+ e.setTitle( title );
+
+ //
+ // Description
+ //
+
+ if( firstLine > 0 )
+ {
+ int maxlen = pageText.length();
+ if( maxlen > MAX_CHARACTERS ) maxlen = MAX_CHARACTERS;
+
+ if( maxlen > 0 )
+ {
+ pageText = m_engine.textToHTML( wikiContext,
+ pageText.substring( firstLine+1,
+ maxlen ).trim() );
+
+ if( maxlen == MAX_CHARACTERS ) pageText += "...";
+
+ e.setContent( pageText );
+ }
+ else
+ {
+ e.setContent( title );
+ }
+ }
+ else
+ {
+ e.setContent( title );
+ }
+
+ e.setAuthor( getAuthor(page) );
+
+ feed.addEntry( e );
+ }
+
+ return feed.getString();
+ }
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSSThread.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSSThread.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSSThread.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/rss/RSSThread.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,125 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Copyright (C) 2005-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.rss;
+
+
+import java.io.BufferedWriter;
+import java.io.File;
+
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+
+import org.apache.log4j.Logger;
+
+import com.ecyrd.jspwiki.FileUtil;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.util.WatchDog;
+import com.ecyrd.jspwiki.util.WikiBackgroundThread;
+
+/**
+ * Runs the RSS generation thread.
+ * FIXME: MUST be somewhere else, this is not a good place.
+ */
+public class RSSThread extends WikiBackgroundThread
+{
+ static Logger log = Logger.getLogger( RSSThread.class );
+
+ private final File m_rssFile;
+ private final int m_rssInterval;
+ private final RSSGenerator m_generator;
+
+ private WatchDog m_watchdog;
+
+ public RSSThread( WikiEngine engine, File rssFile, int rssInterval )
+ {
+ super( engine, rssInterval );
+ m_generator = engine.getRSSGenerator();
+ m_rssFile = rssFile;
+ m_rssInterval = rssInterval;
+ setName("JSPWiki RSS Generator");
+ log.debug( "RSS file will be at "+m_rssFile.getAbsolutePath() );
+ log.debug( "RSS refresh interval (seconds): "+m_rssInterval );
+ }
+
+ public void startupTask() throws Exception
+ {
+ m_watchdog = getEngine().getCurrentWatchDog();
+ }
+
+ /**
+ * Runs the RSS generator thread.
+ * If a previous RSS generation operation encountered a
+ * file I/O or other error, this method will turn off generation.
+ * <code>false</code>.
+ * @see java.lang.Thread#run()
+ */
+ public void backgroundTask() throws Exception
+ {
+ if ( m_generator.isEnabled() )
+ {
+ Writer out = null;
+ Reader in = null;
+
+ m_watchdog.enterState( "Generating RSS feed", 60 );
+
+ try
+ {
+ //
+ // Generate RSS file, output it to
+ // default "rss.rdf".
+ //
+ log.debug("Regenerating RSS feed to "+m_rssFile);
+
+ String feed = m_generator.generate();
+
+ in = new StringReader(feed);
+ out = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( m_rssFile ), "UTF-8") );
+
+ FileUtil.copyContents( in, out );
+ }
+ catch( IOException e )
+ {
+ log.error("Cannot generate RSS feed to "+m_rssFile.getAbsolutePath(), e );
+ m_generator.setEnabled( false );
+ }
+ finally
+ {
+ try
+ {
+ if( in != null ) in.close();
+ if( out != null ) out.close();
+ }
+ catch( IOException e )
+ {
+ log.fatal("Could not close I/O for RSS", e );
+ m_generator.setEnabled( false );
+ }
+ m_watchdog.exitState();
+ }
+
+ }
+ }
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/BasicSearchProvider.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/BasicSearchProvider.java?rev=627255&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/BasicSearchProvider.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_STRIPES_BRANCH/src/com/ecyrd/jspwiki/search/BasicSearchProvider.java Tue Feb 12 21:53:55 2008
@@ -0,0 +1,200 @@
+/*
+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 java.util.Iterator;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+
+import org.apache.log4j.Logger;
+
+import com.ecyrd.jspwiki.NoRequiredPropertyException;
+import com.ecyrd.jspwiki.QueryItem;
+import com.ecyrd.jspwiki.SearchMatcher;
+import com.ecyrd.jspwiki.SearchResult;
+import com.ecyrd.jspwiki.SearchResultComparator;
+import com.ecyrd.jspwiki.WikiEngine;
+import com.ecyrd.jspwiki.WikiPage;
+import com.ecyrd.jspwiki.attachment.Attachment;
+import com.ecyrd.jspwiki.providers.ProviderException;
+import com.ecyrd.jspwiki.providers.WikiPageProvider;
+
+/**
+ * Interface for the search providers that handle searching the Wiki
+ *
+ * @author Arent-Jan Banck
+ * @since 2.2.21.
+ */
+public class BasicSearchProvider implements SearchProvider
+{
+ private static final Logger log = Logger.getLogger(BasicSearchProvider.class);
+
+ private WikiEngine m_engine;
+
+ public void initialize(WikiEngine engine, Properties props)
+ throws NoRequiredPropertyException, IOException
+ {
+ m_engine = engine;
+ }
+
+ public void pageRemoved(WikiPage page) {}
+
+ public void reindexPage(WikiPage page) {}
+
+ public QueryItem[] parseQuery(String query)
+ {
+ StringTokenizer st = new StringTokenizer( query, " \t," );
+
+ QueryItem[] items = new QueryItem[st.countTokens()];
+ int word = 0;
+
+ log.debug("Expecting "+items.length+" items");
+
+ //
+ // Parse incoming search string
+ //
+
+ while( st.hasMoreTokens() )
+ {
+ log.debug("Item "+word);
+ String token = st.nextToken().toLowerCase();
+
+ items[word] = new QueryItem();
+
+ switch( token.charAt(0) )
+ {
+ case '+':
+ items[word].type = QueryItem.REQUIRED;
+ token = token.substring(1);
+ log.debug("Required word: "+token);
+ break;
+
+ case '-':
+ items[word].type = QueryItem.FORBIDDEN;
+ token = token.substring(1);
+ log.debug("Forbidden word: "+token);
+ break;
+
+ default:
+ items[word].type = QueryItem.REQUESTED;
+ log.debug("Requested word: "+token);
+ break;
+ }
+
+ items[word++].word = token;
+ }
+
+ return items;
+ }
+
+ private String attachmentNames(WikiPage page, String separator)
+ {
+ if(m_engine.getAttachmentManager().hasAttachments(page))
+ {
+ Collection<Attachment> attachments;
+ try
+ {
+ attachments = m_engine.getAttachmentManager().listAttachments(page);
+ }
+ catch (ProviderException e)
+ {
+ log.error("Unable to get attachments for page", e);
+ return "";
+ }
+
+ StringBuffer attachmentNames = new StringBuffer();
+ for( Iterator<Attachment> it = attachments.iterator(); it.hasNext(); )
+ {
+ Attachment att = it.next();
+ attachmentNames.append(att.getName());
+ if(it.hasNext())
+ attachmentNames.append(separator);
+ }
+ return attachmentNames.toString();
+ }
+
+ return "";
+ }
+
+ private Collection<SearchResult> findPages( QueryItem[] query )
+ {
+ TreeSet<SearchResult> res = new TreeSet<SearchResult>( new SearchResultComparator() );
+ SearchMatcher matcher = new SearchMatcher( m_engine, query );
+
+ Collection<WikiPage> allPages = null;
+ try
+ {
+ allPages = m_engine.getPageManager().getAllPages();
+ }
+ catch( ProviderException pe )
+ {
+ log.error( "Unable to retrieve page list", pe );
+ return null;
+ }
+
+ Iterator<WikiPage> it = allPages.iterator();
+ while( it.hasNext() )
+ {
+ try
+ {
+ WikiPage page = it.next();
+ if (page != null)
+ {
+ String pageName = page.getName();
+ String pageContent = m_engine.getPageManager().getPageText(pageName, WikiPageProvider.LATEST_VERSION) +
+ attachmentNames(page, " ");
+ SearchResult comparison = matcher.matchPageContent( pageName, pageContent );
+
+ if( comparison != null )
+ {
+ res.add( comparison );
+ }
+ }
+ }
+ catch( ProviderException pe )
+ {
+ log.error( "Unable to retrieve page from cache", pe );
+ }
+ catch( IOException ioe )
+ {
+ log.error( "Failed to search page", ioe );
+ }
+ }
+
+ return res;
+ }
+
+ public Collection<SearchResult> findPages(String query)
+ {
+ return findPages(parseQuery(query));
+ }
+
+ /**
+ * @see com.ecyrd.jspwiki.WikiProvider#getProviderInfo()
+ */
+ public String getProviderInfo()
+ {
+ return "BasicSearchProvider";
+ }
+
+}