001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: FeedProvider.java 3714 2007-04-08 02:57:38Z gbevin $
007: */
008: package com.uwyn.rife.feed.elements;
009:
010: import com.uwyn.rife.config.RifeConfig;
011: import com.uwyn.rife.engine.Element;
012: import com.uwyn.rife.engine.exceptions.EngineException;
013: import com.uwyn.rife.feed.Entry;
014: import com.uwyn.rife.feed.EntryProcessor;
015: import com.uwyn.rife.feed.EntryProvider;
016: import com.uwyn.rife.feed.Feed;
017: import com.uwyn.rife.template.Template;
018: import com.uwyn.rife.template.TemplateFactory;
019: import java.lang.reflect.Constructor;
020: import java.lang.reflect.InvocationTargetException;
021: import java.text.SimpleDateFormat;
022: import java.util.HashSet;
023: import java.util.Map;
024:
025: /**
026: * An <code>Element</code> that uses an <code>EntryProvider</code> to print
027: * out a feed.
028: * <p>After being passed an IoC property of the <code>EntryProvider</code> and
029: * the feed type one wishes to print out, <code>FeedProvider</code> will do
030: * just that.
031: * <p>The supported properties are:
032: * <table border="1">
033: * <tr>
034: * <td><code>feedtype</code>
035: * <td><code>rss_2.0</code> or <code>atom_0.3</code>
036: * <tr>
037: * <td><code>provider</code>
038: * <td>an instance of <code>EntryProvider</code>
039: * <tr>
040: * <td><code>classname</code>
041: * <td>the name of an <code>EntryProvider</code> class when the
042: * <code>provider</code> property isn't set
043: * </table>
044: *
045: * @author JR Boyens (jboyens[remove] at uwyn dot com)
046: * @author Geert Bevin (gbevin[remove] at uwyn dot com)
047: * @version $Revision: 3714 $
048: * @see com.uwyn.rife.engine.Element
049: * @see com.uwyn.rife.feed.EntryProvider
050: * @see com.uwyn.rife.feed.Entry
051: * @see com.uwyn.rife.feed.Feed
052: * @since 1.0
053: */
054: public class FeedProvider extends Element implements EntryProcessor {
055: private static final HashSet<String> VALID_FEED_TYPES = new HashSet<String>();
056:
057: private SimpleDateFormat mIso8601DateFormat = null;
058: private SimpleDateFormat mRfc822DateFormat = null;
059:
060: private Template mFeedTemplate = null;
061: private SimpleDateFormat mDateFormat = null;
062:
063: static {
064: VALID_FEED_TYPES.add("rss_2_0");
065: VALID_FEED_TYPES.add("atom_0_3");
066: }
067:
068: public FeedProvider() {
069: mIso8601DateFormat = new SimpleDateFormat(
070: "yyyy-MM-dd'T'HH:mm:ssZ");
071: mIso8601DateFormat.setTimeZone(RifeConfig.Tools
072: .getDefaultTimeZone());
073: mRfc822DateFormat = new SimpleDateFormat(
074: "EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z");
075: mRfc822DateFormat.setTimeZone(RifeConfig.Tools
076: .getDefaultTimeZone());
077: }
078:
079: public void processElement() {
080: String feed_type = getPropertyString("feedtype").replace('.',
081: '_');
082:
083: assert isValidFeedType(feed_type);
084:
085: mFeedTemplate = TemplateFactory.XML.get("feeds." + feed_type);
086: if (feed_type.indexOf("atom") != -1) {
087: mDateFormat = mIso8601DateFormat;
088: } else {
089: mDateFormat = mRfc822DateFormat;
090: }
091:
092: // try and load using IoC first
093: EntryProvider provider = getPropertyTyped("provider",
094: EntryProvider.class);
095: if (provider == null) {
096: // IoC didn't work... try by classname
097: String classname = getPropertyString("classname");
098: try {
099: provider = loadProvider(classname);
100: } catch (ClassNotFoundException e) {
101: String extendedClassname = "com.uwyn.rife.feed.entryproviders."
102: + classname;
103:
104: try {
105: provider = loadProvider(extendedClassname);
106: } catch (ClassNotFoundException e1) {
107: throw new UnsupportedFeedDataTypeException(
108: "Cannot find provider: " + classname
109: + " or " + extendedClassname);
110: } catch (Exception e1) {
111: throw new EngineException(e1);
112: }
113: } catch (Exception e) {
114: throw new EngineException(e);
115: }
116: }
117:
118: if (provider != null) {
119: provider.provideEntries(this , this );
120:
121: Feed feed = provider.getFeedDescriptor(this );
122: mFeedTemplate.setBean(feed, "feed_");
123: mFeedTemplate.setValue("feed_publishedDate", mDateFormat
124: .format(feed.getPublishedDate()));
125: if (feed.getNamespaces() != null) {
126: for (Map.Entry<String, String> entry : feed
127: .getNamespaces().entrySet()) {
128: mFeedTemplate.setValue("namespace_key",
129: encodeXml(entry.getKey()));
130: mFeedTemplate.setValue("namespace_url",
131: encodeXml(entry.getValue()));
132:
133: mFeedTemplate
134: .appendBlock("namespaces", "namespace");
135: }
136: }
137: }
138:
139: setContentType("application/xml");
140:
141: print(mFeedTemplate);
142: }
143:
144: private EntryProvider loadProvider(String classname)
145: throws SecurityException, NoSuchMethodException,
146: IllegalArgumentException, InstantiationException,
147: IllegalAccessException, InvocationTargetException,
148: ClassNotFoundException {
149: if (classname == null)
150: return null;
151:
152: Class<EntryProvider> providerClass = (Class<EntryProvider>) Class
153: .forName(classname);
154: Constructor<EntryProvider> constructor = providerClass
155: .getConstructor(new Class[] {});
156:
157: return constructor.newInstance(new Object[] {});
158: }
159:
160: private boolean isValidFeedType(String feedType) {
161: return VALID_FEED_TYPES.contains(feedType);
162: }
163:
164: private class UnsupportedFeedDataTypeException extends
165: RuntimeException {
166: private static final long serialVersionUID = 8910041916874032181L;
167:
168: public UnsupportedFeedDataTypeException() {
169: super ();
170: }
171:
172: public UnsupportedFeedDataTypeException(String message) {
173: super (message);
174: }
175:
176: public UnsupportedFeedDataTypeException(String message,
177: Throwable cause) {
178: super (message, cause);
179: }
180:
181: public UnsupportedFeedDataTypeException(Throwable cause) {
182: super (cause);
183: }
184: }
185:
186: public void setEntry(Entry entry) {
187: mFeedTemplate.setBean(entry, "entry_");
188: if (entry.isEscaped()
189: && mFeedTemplate.hasValueId("entry_escaped_attribute")) {
190: mFeedTemplate.setBlock("entry_escaped_attribute",
191: "entry_escaped_attribute");
192: }
193: if (!entry.isEscaped()) {
194: mFeedTemplate.setValue("entry_content", entry.getContent());
195: }
196: mFeedTemplate.setValue("entry_publishedDate", mDateFormat
197: .format(entry.getPublishedDate()));
198: mFeedTemplate.appendBlock("entries", "entry");
199: }
200: }
|