001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. The ASF licenses this file to You
004: * under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License. For additional information regarding
015: * copyright in this work, please see the NOTICE file in the top level
016: * directory of this distribution.
017: */
018:
019: package org.apache.roller.ui.rendering.velocity.deprecated;
020:
021: import com.sun.syndication.feed.synd.SyndFeed;
022: import com.sun.syndication.io.SyndFeedInput;
023: import java.io.InputStreamReader;
024: import java.io.UnsupportedEncodingException;
025: import java.net.URL;
026: import java.net.URLConnection;
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.apache.roller.config.RollerConfig;
030: import org.apache.roller.util.LRUCache2;
031:
032: /**
033: * Returns parsed RSS feed by pulling one from a cache or by retrieving and
034: * parging the specified feed using the Flock RSS parser.
035: *
036: * TODO: use PlanetRoller to implement NewsfeedCache instead.
037: */
038: public class NewsfeedCache {
039:
040: private static Log mLogger = LogFactory.getLog(NewsfeedCache.class);
041:
042: /** Static singleton * */
043: private static NewsfeedCache mInstance = null;
044:
045: /** Instance vars * */
046: private boolean aggregator_enabled = true;
047: private boolean aggregator_cache_enabled = true;
048: private int aggregator_cache_timeout = 14400;
049:
050: /** LRU cache */
051: LRUCache2 mCache = null;
052:
053: /** Constructor */
054: private NewsfeedCache() {
055: // lookup the props we need
056: String enabled = RollerConfig.getProperty("aggregator.enabled");
057: String usecache = RollerConfig
058: .getProperty("aggregator.cache.enabled");
059: String cachetime = RollerConfig
060: .getProperty("aggregator.cache.timeout");
061:
062: if ("true".equalsIgnoreCase(enabled))
063: this .aggregator_enabled = true;
064:
065: if ("true".equalsIgnoreCase(usecache))
066: this .aggregator_cache_enabled = true;
067:
068: try {
069: this .aggregator_cache_timeout = Integer.parseInt(cachetime);
070: } catch (Exception e) {
071: mLogger.warn(e);
072: }
073:
074: // finally ... create the cache
075: this .mCache = new LRUCache2(100,
076: 1000 * this .aggregator_cache_timeout);
077: }
078:
079: /** static singleton retriever */
080: public static NewsfeedCache getInstance() {
081: synchronized (NewsfeedCache.class) {
082: if (mInstance == null) {
083: if (mLogger.isDebugEnabled()) {
084: mLogger.debug("Instantiating new NewsfeedCache");
085: }
086: mInstance = new NewsfeedCache();
087: }
088: }
089: return mInstance;
090: }
091:
092: /**
093: * Returns a Channel object for the supplied RSS newsfeed URL.
094: *
095: * @param feedUrl RSS newsfeed URL.
096: * @return FlockFeedI for specified RSS newsfeed URL.
097: */
098: public SyndFeed getChannel(String feedUrl) {
099:
100: SyndFeed feed = null;
101: try {
102: // If aggregator has been disable return null
103: if (!aggregator_enabled) {
104: return null;
105: }
106:
107: if (aggregator_cache_enabled) {
108: if (mLogger.isDebugEnabled()) {
109: mLogger.debug("Newsfeed: use Cache for " + feedUrl);
110: }
111:
112: // Get pre-parsed feed from the cache
113: feed = (SyndFeed) mCache.get(feedUrl);
114: if (mLogger.isDebugEnabled()) {
115: mLogger.debug("Newsfeed: got from Cache");
116: }
117:
118: if (feed == null) {
119: try {
120: // Parse the feed
121: SyndFeedInput feedInput = new SyndFeedInput();
122: feed = feedInput.build(new InputStreamReader(
123: new URL(feedUrl).openStream()));
124: } catch (Exception e1) {
125: mLogger.info("Error parsing RSS: " + feedUrl);
126: }
127: }
128: // Store parsed feed in the cache
129: mCache.put(feedUrl, feed);
130: mLogger.debug("Newsfeed: not in Cache");
131:
132: } else {
133: if (mLogger.isDebugEnabled()) {
134: mLogger.debug("Newsfeed: not using Cache for "
135: + feedUrl);
136: }
137: try {
138: // charset fix from Jason Rumney (see ROL-766)
139: URLConnection connection = new URL(feedUrl)
140: .openConnection();
141: connection.connect();
142: String contentType = connection.getContentType();
143: // Default charset to UTF-8, since we are expecting XML
144: String charset = "UTF-8";
145: if (contentType != null) {
146: int charsetStart = contentType
147: .indexOf("charset=");
148: if (charsetStart >= 0) {
149: int charsetEnd = contentType.indexOf(";",
150: charsetStart);
151: if (charsetEnd == -1)
152: charsetEnd = contentType.length();
153: charsetStart += "charset=".length();
154: charset = contentType.substring(
155: charsetStart, charsetEnd);
156: // Check that charset is recognized by Java
157: try {
158: byte[] test = "test".getBytes(charset);
159: } catch (UnsupportedEncodingException codingEx) {
160: // default to UTF-8
161: charset = "UTF-8";
162: }
163: }
164: }
165: // Parse the feed
166: SyndFeedInput feedInput = new SyndFeedInput();
167: feed = feedInput.build(new InputStreamReader(
168: connection.getInputStream(), charset));
169: } catch (Exception e1) {
170: mLogger.info("Error parsing RSS: " + feedUrl);
171: }
172: }
173:
174: } catch (Exception ioe) {
175: if (mLogger.isDebugEnabled()) {
176: mLogger.debug("Newsfeed: Unexpected exception", ioe);
177: }
178: }
179:
180: return feed;
181: }
182:
183: }
|