KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > nava > informa > utils > poller > PollerWorkerThread


1 //
2
// Informa -- RSS Library for Java
3
// Copyright (c) 2002 by Niko Schmuck
4
//
5
// Niko Schmuck
6
// http://sourceforge.net/projects/informa
7
// mailto:niko_schmuck@users.sourceforge.net
8
//
9
// This library is free software.
10
//
11
// You may redistribute it and/or modify it under the terms of the GNU
12
// Lesser General Public License as published by the Free Software Foundation.
13
//
14
// Version 2.1 of the license should be included with this distribution in
15
// the file LICENSE. If the license is not included with this distribution,
16
// you may find a copy at the FSF web site at 'www.gnu.org' or 'www.fsf.org',
17
// or you may write to the Free Software Foundation, 675 Mass Ave, Cambridge,
18
// MA 02139 USA.
19
//
20
// This library is distributed in the hope that it will be useful,
21
// but WITHOUT ANY WARRANTY; without even the implied waranty of
22
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23
// Lesser General Public License for more details.
24
//
25
// $Id: PollerWorkerThread.java,v 1.3 2004/09/02 09:14:55 spyromus Exp $
26
//
27

28 package de.nava.informa.utils.poller;
29
30 import de.nava.informa.impl.basic.ChannelBuilder;
31 import de.nava.informa.parsers.FeedParser;
32 import de.nava.informa.utils.FormatDetector;
33 import de.nava.informa.utils.InformaUtils;
34 import de.nava.informa.utils.toolkit.ChannelRecord;
35 import de.nava.informa.utils.toolkit.WorkerThread;
36 import de.nava.informa.core.ParseException;
37 import de.nava.informa.core.ChannelBuilderIF;
38 import de.nava.informa.core.ChannelIF;
39 import de.nava.informa.core.UnsupportedFormatException;
40 import de.nava.informa.core.ChannelFormat;
41 import de.nava.informa.core.ItemIF;
42
43 import java.io.IOException JavaDoc;
44 import java.util.Collection JavaDoc;
45 import java.net.URL JavaDoc;
46
47 /**
48  * Worker thread is the main processing unit. Worker thread is not dedicated to single channel,
49  * group or whatever else. It represents a single thread, which is capable of doing well-defined
50  * and unified job. <code>WorkersManager</code> submits jobs for free <code>WorkerThread</code>'s.
51  * Workers simply do their jobs. This architecture allows to scale to as much threads as necessary.
52  *
53  * @author Aleksey Gureev (spyromus@noizeramp.com)
54  */

55 public class PollerWorkerThread extends WorkerThread {
56   private static final ChannelBuilderIF BUILDER = new ChannelBuilder();
57
58   private PollerObserverIF observer;
59   private PollerApproverIF approver;
60
61   /**
62    * Creates worker thread for poller with given observer and approver.
63    *
64    * @param observer observer object.
65    * @param approver approver object.
66    */

67   public PollerWorkerThread(PollerObserverIF observer, PollerApproverIF approver) {
68     super("Poller - Worker thread");
69
70     this.observer = observer;
71     this.approver = approver;
72   }
73
74   /**
75    * Processes record.
76    *
77    * @param record record to process.
78    */

79   protected final void processRecord(ChannelRecord record) {
80     final ChannelIF channel = record.getChannel();
81
82     // Notify observer
83
observer.pollStarted(channel);
84
85     try {
86       // Resolve format of channel it it isn't resolved yet.
87
if (!record.isFormatResolved()) {
88         resolveFormat(record);
89       }
90
91       // Read the contents and check for possible new items.
92
checkContents(record);
93
94       // Notify observer
95
observer.pollFinished(channel);
96
97     } catch (Exception JavaDoc e) {
98       observer.channelErrored(channel, e);
99     }
100   }
101
102   /**
103    * Resolve channel format.
104    *
105    * @param record channel record to process.
106    * @throws IOException
107    * @throws UnsupportedFormatException
108    */

109   private void resolveFormat(ChannelRecord record)
110     throws IOException JavaDoc, UnsupportedFormatException {
111     // Resolve channel format.
112
final ChannelIF channel = record.getChannel();
113     final ChannelFormat format = FormatDetector.getFormat(channel.getLocation());
114
115     channel.setFormat(format);
116     record.setFormatResolved(true);
117   }
118
119   /**
120    * Check for item updates.
121    *
122    * @param record channel record to process.
123    * @throws IOException
124    * @throws ParseException
125    */

126   private void checkContents(ChannelRecord record)
127     throws IOException JavaDoc, ParseException {
128     // Read channel from URL.
129
final ChannelIF channel = record.getChannel();
130     final ChannelIF tempChannel = FeedParser.parse(BUILDER, channel.getLocation());
131
132     // Copy channel information from newly retreived instance.
133
if (channelHasChanged(channel, tempChannel)) {
134       InformaUtils.copyChannelProperties(tempChannel, channel);
135       observer.channelChanged(channel);
136     }
137
138     // Walk through the items list and check if we have newcomers.
139
checkItems(tempChannel, channel);
140   }
141
142   /**
143    * Walks through the items and checks if new items present.
144    *
145    * @param newChannel new channel taken from web.
146    * @param existingChannel currently existing channel to match against.
147    */

148   final void checkItems(ChannelIF newChannel, ChannelIF existingChannel) {
149     final ItemIF[] newItems = (ItemIF[]) newChannel.getItems().toArray(new ItemIF[0]);
150     final Collection JavaDoc currentItems = existingChannel.getItems();
151
152     for (int i = 0; i < newItems.length; i++) {
153       final ItemIF newItem = newItems[i];
154
155       // If current list of item has no this item and approver allows to add item then proceed.
156
if (!currentItems.contains(newItem) && approver.canAddItem(newItem, existingChannel)) {
157         // Notify observer
158
try {
159           observer.itemFound(newItem, existingChannel);
160         } catch (RuntimeException JavaDoc e) {
161           // For the case when observer fails.
162
}
163       }
164     }
165   }
166
167   /**
168    * Checks if channel has changed.
169    *
170    * @param o old channel.
171    * @param n new channel.
172    * @return result of the check.
173    */

174   static boolean channelHasChanged(ChannelIF o, ChannelIF n) {
175     // Note that this list has no LastUpdated and LastBuildDate. We don't need to compare them.
176
// LastUpdated changes each time we create new channel.
177
// LastBuildDate is generated by the server-side software during build operation
178
// each time we ask for a channel.
179

180     return o == null
181       || differ(o.getTitle(), n.getTitle())
182       || differ(o.getDescription(), n.getDescription())
183       || differ(o.getSite(), n.getSite())
184       || differ(o.getCreator(), n.getCreator())
185       || differ(o.getCopyright(), n.getCopyright())
186       || differ(o.getPublisher(), n.getPublisher())
187       || differ(o.getLanguage(), n.getLanguage())
188       || differ(o.getRating(), n.getRating())
189       || differ(o.getGenerator(), n.getGenerator())
190       || differ(o.getDocs(), n.getDocs())
191       || o.getTtl() != n.getTtl()
192       || differ(o.getUpdateBase(), n.getUpdateBase())
193       || o.getUpdateFrequency() != n.getUpdateFrequency()
194       || differ(o.getUpdatePeriod(), n.getUpdatePeriod())
195       || differ(o.getPubDate(), n.getPubDate());
196   }
197
198   /**
199    * Checks if two objects differ. NULL isn't different from other NULL.
200    *
201    * @param a object.
202    * @param b object.
203    * @return result of the check.
204    */

205   static boolean differ(Object JavaDoc a, Object JavaDoc b) {
206     return !((a == null && b == null)
207       || (a instanceof URL JavaDoc && b instanceof URL JavaDoc && (a.toString().equals(b.toString())))
208       || (a != null && a.equals(b)));
209   }
210 }
211
Popular Tags