001: //
002: // Informa -- RSS Library for Java
003: // Copyright (c) 2002 by Niko Schmuck
004: //
005: // Niko Schmuck
006: // http://sourceforge.net/projects/informa
007: // mailto:niko_schmuck@users.sourceforge.net
008: //
009: // This library is free software.
010: //
011: // You may redistribute it and/or modify it under the terms of the GNU
012: // Lesser General Public License as published by the Free Software Foundation.
013: //
014: // Version 2.1 of the license should be included with this distribution in
015: // the file LICENSE. If the license is not included with this distribution,
016: // you may find a copy at the FSF web site at 'www.gnu.org' or 'www.fsf.org',
017: // or you may write to the Free Software Foundation, 675 Mass Ave, Cambridge,
018: // MA 02139 USA.
019: //
020: // This library is distributed in the hope that it will be useful,
021: // but WITHOUT ANY WARRANTY; without even the implied waranty of
022: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
023: // Lesser General Public License for more details.
024: //
025:
026: // $Id: UpdateChannelTask.java,v 1.33 2004/05/13 22:55:17 niko_schmuck Exp $
027:
028: package de.nava.informa.utils;
029:
030: import java.io.IOException;
031: import java.util.Date;
032: import java.util.Iterator;
033: import java.util.TimerTask;
034:
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037:
038: import de.nava.informa.core.*;
039: import de.nava.informa.core.ChannelBuilderIF;
040: import de.nava.informa.impl.basic.ChannelBuilder;
041: import de.nava.informa.core.ChannelFormat;
042: import de.nava.informa.core.ChannelIF;
043: import de.nava.informa.core.ItemIF;
044: import de.nava.informa.core.ParseException;
045: import de.nava.informa.core.UnsupportedFormatException;
046: import de.nava.informa.parsers.FeedParser;
047:
048: /**
049: * Class for performing a channel retrieval in periodic intervals as a
050: * TimerTask. The existing items of a channel are compared to the
051: * items contained in the newly gotten channel, and if there are any
052: * new items they are appended.
053: *
054: * @author Niko Schmuck (niko@nava.de)
055: */
056: public class UpdateChannelTask extends TimerTask {
057:
058: private static Log logger = LogFactory
059: .getLog(UpdateChannelTask.class);
060:
061: private ChannelRegistry registry;
062: private ChannelIF channel;
063: private ChannelBuilderIF builder;
064: private UpdateChannelInfo info;
065: private ChannelBuilderIF tempBuilder;
066:
067: public UpdateChannelTask(ChannelRegistry registry,
068: ChannelBuilderIF builder, ChannelIF channel,
069: UpdateChannelInfo info) {
070: this .registry = registry;
071: this .channel = channel;
072: this .builder = builder;
073: this .info = info;
074:
075: // builder that is passed in on construction *may* be for persistent Channels.
076: // tempBuilder is forced to be memory only so it will not be persisted.
077: tempBuilder = new ChannelBuilder();
078: }
079:
080: public void run() {
081: logger.info("Task Run()");
082: Thread.currentThread().setName("Informa Update Channel Task");
083: /**
084: * ChannelBuilder is not re-entrant and it is shared by all the
085: * UpdateChannelTasks which are created by single ChannelRegistry.
086: * Note that all the beginTransaction() must have a corresponding endTransaction()
087: */
088: synchronized (builder) {
089: if (!info.getFormatDetected())
090: /**
091: * If this is the first time we see this Channel, then we will now attempt
092: * to parse it and if this works we remember the format and proceed.
093: * Otherwise we trigger error case handling and eventually deactivate it.
094: */
095: {
096: try {
097: builder.beginTransaction();
098: ChannelFormat format = FormatDetector
099: .getFormat(channel.getLocation());
100: channel.setFormat(format);
101: info.setFormatDetected(true);
102: channel.setLastUpdated(new Date());
103: builder.endTransaction();
104: } catch (UnsupportedFormatException ex) {
105: logger.info("Unsupported format for Channel");
106: incrementProblems(ex);
107: return;
108: } catch (IOException ioe) {
109: logger.info("Cannot retrieve Channel");
110: incrementProblems(ioe);
111: return;
112: } catch (ChannelBuilderException e) {
113: e.printStackTrace();
114: }
115: }
116: try {
117: synchronized (channel) {
118: builder.beginTransaction();
119: ChannelIF tempChannel = FeedParser.parse(
120: tempBuilder, channel.getLocation());
121: logger.info("Updating channel from "
122: + channel.getLocation() + ": "
123: + tempChannel + "(new) " + channel
124: + "(old)");
125: InformaUtils.copyChannelProperties(tempChannel,
126: channel);
127: builder.update(channel);
128: channel.setLastUpdated(new Date());
129: // compare with existing items, only add new ones
130: if (tempChannel.getItems().isEmpty()) {
131: logger.warn("No items found in channel "
132: + channel);
133: } else {
134: Iterator it = tempChannel.getItems().iterator();
135: while (it.hasNext()) {
136: ItemIF item = (ItemIF) it.next();
137: if (!channel.getItems().contains(item)) {
138: logger.debug("Found new item: " + item);
139: channel.addItem(builder.createItem(
140: null, item));
141: // }
142: }
143: } // while more items
144: }
145: builder.endTransaction();
146: }
147: } catch (ParseException pe) {
148: incrementProblems(pe);
149: } catch (IOException ioe) {
150: incrementProblems(ioe);
151: } catch (ChannelBuilderException e) {
152: e.printStackTrace();
153: }
154: }
155: }
156:
157: /**
158: * Increases the count of problems occurred so far and put out an error
159: * message based on the given exception.
160: */
161: private void incrementProblems(Exception e) {
162: info.increaseProblemsOccurred(e);
163: if (info.shouldDeactivate()) {
164: logger.warn("Deactivating channel after "
165: + info.getNrProblemsOccurred()
166: + " problems occurred.");
167: registry.deactivateChannel(channel);
168: }
169: logger.warn(e);
170: }
171:
172: }
|