/* * Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com> * Licensed under the Apache License, Version 2.0 (the "License") * $Id: FeedProvider.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.feed.elements; import com.uwyn.rife.config.RifeConfig; import com.uwyn.rife.engine.Element; import com.uwyn.rife.engine.exceptions.EngineException; import com.uwyn.rife.feed.Entry; import com.uwyn.rife.feed.EntryProcessor; import com.uwyn.rife.feed.EntryProvider; import com.uwyn.rife.feed.Feed; import com.uwyn.rife.template.Template; import com.uwyn.rife.template.TemplateFactory; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.text.SimpleDateFormat; import java.util.HashSet; import java.util.Map; /** * An <code>Element</code> that uses an <code>EntryProvider</code> to print * out a feed. * <p>After being passed an IoC property of the <code>EntryProvider</code> and * the feed type one wishes to print out, <code>FeedProvider</code> will do * just that. * <p>The supported properties are: * <table border="1"> * <tr> * <td><code>feedtype</code> * <td><code>rss_2.0</code> or <code>atom_0.3</code> * <tr> * <td><code>provider</code> * <td>an instance of <code>EntryProvider</code> * <tr> * <td><code>classname</code> * <td>the name of an <code>EntryProvider</code> class when the * <code>provider</code> property isn't set * </table> * * @author JR Boyens (jboyens[remove] at uwyn dot com) * @author Geert Bevin (gbevin[remove] at uwyn dot com) * @version $Revision: 3918 $ * @see com.uwyn.rife.engine.Element * @see com.uwyn.rife.feed.EntryProvider * @see com.uwyn.rife.feed.Entry * @see com.uwyn.rife.feed.Feed * @since 1.0 */ public class FeedProvider extends Element implements EntryProcessor { private static final HashSet<String> VALID_FEED_TYPES = new HashSet<String>(); private SimpleDateFormat mIso8601DateFormat = null; private SimpleDateFormat mRfc822DateFormat = null; private Template mFeedTemplate = null; private SimpleDateFormat mDateFormat = null; static { VALID_FEED_TYPES.add("rss_2_0"); VALID_FEED_TYPES.add("atom_0_3"); } public FeedProvider() { mIso8601DateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); mIso8601DateFormat.setTimeZone(RifeConfig.Tools.getDefaultTimeZone()); mRfc822DateFormat = new SimpleDateFormat("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z"); mRfc822DateFormat.setTimeZone(RifeConfig.Tools.getDefaultTimeZone()); } public void processElement() { String feed_type = getPropertyString("feedtype").replace('.', '_'); assert isValidFeedType(feed_type); mFeedTemplate = TemplateFactory.XML.get("feeds."+feed_type); if (feed_type.indexOf("atom") != -1) { mDateFormat = mIso8601DateFormat; } else { mDateFormat = mRfc822DateFormat; } // try and load using IoC first EntryProvider provider = getPropertyTyped("provider", EntryProvider.class); if (provider == null) { // IoC didn't work... try by classname String classname = getPropertyString("classname"); try { provider = loadProvider(classname); } catch (ClassNotFoundException e) { String extendedClassname = "com.uwyn.rife.feed.entryproviders." + classname; try { provider = loadProvider(extendedClassname); } catch (ClassNotFoundException e1) { throw new UnsupportedFeedDataTypeException("Cannot find provider: "+classname+" or "+extendedClassname); } catch (Exception e1) { throw new EngineException(e1); } } catch (Exception e) { throw new EngineException(e); } } if (provider != null) { provider.provideEntries(this, this); Feed feed = provider.getFeedDescriptor(this); mFeedTemplate.setBean(feed, "feed_"); mFeedTemplate.setValue("feed_publishedDate", mDateFormat.format(feed.getPublishedDate())); if (feed.getNamespaces() != null) { for (Map.Entry<String, String> entry : feed.getNamespaces().entrySet()) { mFeedTemplate.setValue("namespace_key", encodeXml(entry.getKey())); mFeedTemplate.setValue("namespace_url", encodeXml(entry.getValue())); mFeedTemplate.appendBlock("namespaces", "namespace"); } } } setContentType("application/xml"); print(mFeedTemplate); } private EntryProvider loadProvider(String classname) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException { if (classname == null) return null; Class<EntryProvider> providerClass = (Class<EntryProvider>)Class.forName(classname); Constructor<EntryProvider> constructor = providerClass.getConstructor(new Class[] {}); return constructor.newInstance(new Object[] {}); } private boolean isValidFeedType(String feedType) { return VALID_FEED_TYPES.contains(feedType); } private class UnsupportedFeedDataTypeException extends RuntimeException { private static final long serialVersionUID = 8910041916874032181L; public UnsupportedFeedDataTypeException() { super(); } public UnsupportedFeedDataTypeException(String message) { super(message); } public UnsupportedFeedDataTypeException(String message, Throwable cause) { super(message, cause); } public UnsupportedFeedDataTypeException(Throwable cause) { super(cause); } } public void setEntry(Entry entry) { mFeedTemplate.setBean(entry, "entry_"); if (entry.isEscaped() && mFeedTemplate.hasValueId("entry_escaped_attribute")) { mFeedTemplate.setBlock("entry_escaped_attribute", "entry_escaped_attribute"); } if (!entry.isEscaped()) { mFeedTemplate.setValue("entry_content", entry.getContent()); } mFeedTemplate.setValue("entry_publishedDate", mDateFormat.format(entry.getPublishedDate())); mFeedTemplate.appendBlock("entries", "entry"); } }