* anti-abuse upgrade: filters now stored in the database (experimental)
[mir.git] / source / mir / rss / RSS091Reader.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30 package mir.rss;
31
32 import mir.util.HTTPClientHelper;
33 import mir.util.xml.XMLParserEngine;
34 import mir.util.xml.XMLParserExc;
35 import mir.util.xml.XMLParserFailure;
36
37 import java.io.InputStream;
38 import java.util.*;
39
40 /**
41  *
42  * <p>Title: </p>
43  * <p>Description: </p>
44  * <p>Copyright: Copyright (c) 2003</p>
45  * <p>Company: </p>
46  * @author not attributable
47  * @version 1.0
48  */
49
50 public class RSS091Reader {
51   private final static String MAPPED_CHANNEL_PROPERTIES[][]  =
52      {
53        {"link",        "rss:link"        },
54        {"title",       "rss:title"       },
55        {"description", "rss:description" },
56        {"item",        "rss:item" },
57        {"language",    "dc:language" }
58      };
59
60   private final static String MAPPED_ITEM_PROPERTIES[][]  =
61     {
62       {"link",        "rss:link"        },
63       {"title",       "rss:title"       },
64       {"description", "rss:description" },
65       {"author",      "dc:creator" },
66     };
67
68   private Map mappedChannelProperties = new HashMap();
69   private Map mappedItemProperties = new HashMap();
70
71   public RSS091Reader() {
72     int i;
73
74     for (i=0; i<MAPPED_CHANNEL_PROPERTIES.length; i++) {
75       mappedChannelProperties.put(MAPPED_CHANNEL_PROPERTIES[i][0], MAPPED_CHANNEL_PROPERTIES[i][1]);
76     }
77
78     for (i=0; i<MAPPED_ITEM_PROPERTIES.length; i++) {
79       mappedItemProperties.put(MAPPED_ITEM_PROPERTIES[i][0], MAPPED_ITEM_PROPERTIES[i][1]);
80     }
81   }
82
83   public RSSData parseInputStream(InputStream aStream) throws RSSExc, RSSFailure {
84     try {
85       RSSData result = new RSSData();
86       XMLParserEngine.getInstance().parse("html", aStream, new RootSectionHandler(result));
87
88       return result;
89     }
90     catch (Throwable t) {
91       throw new RSSFailure(t);
92     }
93   }
94
95   public RSSData parseInputStream(InputStream aStream, String anEncoding) throws RSSExc, RSSFailure {
96     try {
97       RSSData result = new RSSData();
98       XMLParserEngine.getInstance().parse("html", aStream, anEncoding, new RootSectionHandler(result));
99
100       return result;
101     }
102     catch (Throwable t) {
103       throw new RSSFailure(t);
104     }
105   }
106
107   public RSSData parseUrl(String anUrl) throws RSSExc, RSSFailure {
108     try {
109       HTTPClientHelper httpClientHelper = new HTTPClientHelper();       
110       InputStream inputStream = httpClientHelper.getUrl(anUrl);
111  
112       if (inputStream==null)
113         throw new RSSExc("RSSChannel.parseUrl: Can't get url content");
114
115       RSSData theRSSData =  parseInputStream(inputStream);
116       httpClientHelper.releaseHTTPConnection();
117       return theRSSData;
118
119     }
120     catch (Throwable t) {
121       throw new RSSFailure(t);
122     }
123   }
124
125   public RSSData parseUrl(String anUrl, String anEncoding) throws RSSExc, RSSFailure {
126     try {
127       HTTPClientHelper httpClientHelper = new HTTPClientHelper();       
128       InputStream inputStream = httpClientHelper.getUrl(anUrl);
129
130       if (inputStream==null)
131         throw new RSSExc("RSSChannel.parseUrl: Can't get url content");
132       
133       RSSData theRSSData = parseInputStream(inputStream, anEncoding);
134       httpClientHelper.releaseHTTPConnection();
135       return theRSSData;
136     }
137
138     catch (Throwable t) {
139       throw new RSSFailure(t);
140     }
141   }
142
143   private class RootSectionHandler extends mir.util.xml.AbstractSectionHandler {
144     private RSSData data;
145
146     public RootSectionHandler(RSSData aData) {
147       data = aData;
148     }
149
150     public mir.util.xml.SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc {
151       if (aTag.getLocalName().equals("rss")) {
152         return new RSS091SectionHandler(data);
153       }
154       else
155         throw new XMLParserFailure(new RSSExc("'rss' tag expected"));
156     };
157
158     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
159     };
160
161     public void characters(String aCharacters) throws XMLParserExc {
162       if (aCharacters.trim().length()>0)
163         throw new XMLParserExc("No character data allowed here");
164     };
165
166     public void finishSection() throws XMLParserExc {
167     };
168   }
169
170   private class RSS091SectionHandler extends mir.util.xml.AbstractSectionHandler {
171     private RSSData data;
172
173
174     public RSS091SectionHandler(RSSData aData) {
175       data = aData;
176     }
177
178     public mir.util.xml.SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc {
179       if (aTag.getLocalName().equals("channel"))
180         return new RSS091ChannelSectionHandler(data);
181       else
182         throw new XMLParserExc("channel tag expected, " + aTag.getLocalName() + " found");
183     };
184
185     public void characters(String aCharacters) throws XMLParserExc {
186       if (aCharacters.trim().length()>0)
187         throw new XMLParserExc("No character data allowed here");
188     };
189
190     public void finishSection() throws XMLParserExc {
191     };
192   }
193
194   private class RSS091ChannelSectionHandler extends mir.util.xml.AbstractSectionHandler {
195     private String currentTag;
196
197     private RSSData data;
198     private List items;
199     private RDFResource channel;
200     private Map attributes;
201
202     public RSS091ChannelSectionHandler(RSSData aData) {
203       data = aData;
204       items = new ArrayList();
205       channel = new RDFResource("rss:channel");
206       attributes = new HashMap();
207     }
208
209     public mir.util.xml.SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc {
210       String tag = aTag.getLocalName();
211
212       if (tag.equals("item"))
213         return new RSS091ItemSectionHandler();
214       else if (mappedChannelProperties.containsKey(tag)) {
215         currentTag=(String) mappedChannelProperties.get(tag);
216         return new PCDATASectionHandler();
217       }
218       else
219         return new DiscardingSectionHandler();
220     };
221
222     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
223       if (aHandler instanceof PCDATASectionHandler) {
224         attributes.put(currentTag, (((PCDATASectionHandler) aHandler).getData()));
225       }
226       else if (aHandler instanceof RSS091ItemSectionHandler) {
227         items.add((((RSS091ItemSectionHandler) aHandler).getItem()));
228       }
229     };
230
231     public void characters(String aCharacters) throws XMLParserExc {
232       if (aCharacters.trim().length()>0)
233         throw new XMLParserExc("No character data allowed here");
234     };
235
236     public void finishSection() throws XMLParserExc {
237       Iterator i = items.iterator();
238
239       while (i.hasNext()) {
240         data.addResource((RDFResource) i.next());
241       }
242     };
243   }
244
245   private class RSS091ItemSectionHandler extends mir.util.xml.AbstractSectionHandler {
246     private String currentTag;
247
248     private RDFResource item;
249     private Map attributes;
250
251     public RSS091ItemSectionHandler() {
252       attributes = new HashMap();
253     }
254
255     public mir.util.xml.SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc {
256       String tag = aTag.getLocalName();
257
258       if (mappedItemProperties.containsKey(tag)) {
259         currentTag=(String) mappedItemProperties.get(tag);
260         return new PCDATASectionHandler();
261       }
262       else
263         return new DiscardingSectionHandler();
264     };
265
266     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
267       if (aHandler instanceof PCDATASectionHandler) {
268         attributes.put(currentTag, (((PCDATASectionHandler) aHandler).getData()));
269       }
270     };
271
272     public void characters(String aCharacters) throws XMLParserExc {
273       if (aCharacters.trim().length()>0)
274         throw new XMLParserExc("No character data allowed here");
275     };
276
277     public void finishSection() throws XMLParserExc {
278       item = new RDFResource("rss:item", (String) attributes.get("rss:link"));
279
280       Iterator i = attributes.entrySet().iterator();
281       while (i.hasNext()) {
282         Map.Entry entry = (Map.Entry) i.next();
283
284         item.set((String) entry.getKey(), entry.getValue());
285       }
286     };
287
288     public RDFResource getItem() {
289       return item;
290     }
291   }
292
293
294   private class PCDATASectionHandler extends mir.util.xml.AbstractSectionHandler {
295     private StringBuffer data;
296
297     public PCDATASectionHandler() {
298       data = new StringBuffer();
299     }
300
301     public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
302       throw new XMLParserFailure(new RSSExc("No subtags allowed here"));
303     };
304
305     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
306     };
307
308     public void characters(String aCharacters) throws XMLParserExc {
309       data.append(aCharacters);
310     };
311
312     public void finishSection() throws XMLParserExc {
313     };
314
315     public String getData() {
316       return data.toString();
317     }
318   }
319
320
321   private class RDFSequenceSectionHandler extends mir.util.xml.AbstractSectionHandler {
322     private List items;
323
324     public RDFSequenceSectionHandler() {
325       items = new ArrayList();
326     }
327
328     public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
329       if (aTag.equals("rdf:li")) {
330         String item = (String) anAttributes.get("rdf:resource");
331
332         if (item!=null)
333           items.add(item);
334       }
335
336       return new DiscardingSectionHandler();
337     };
338
339     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
340     };
341
342     public void characters(String aCharacters) throws XMLParserExc {
343     };
344
345     public void finishSection() throws XMLParserExc {
346     };
347
348     public List getItems() {
349       return items;
350     }
351   }
352
353   private class DiscardingSectionHandler extends mir.util.xml.AbstractSectionHandler {
354     public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
355       return this;
356     };
357
358     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
359     };
360
361     public void characters(String aCharacters) throws XMLParserExc {
362     };
363
364     public void finishSection() throws XMLParserExc {
365     };
366   }
367 }