1 package yarfraw.io;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.net.URI;
7
8 import javax.xml.bind.JAXBContext;
9 import javax.xml.bind.JAXBElement;
10 import javax.xml.bind.JAXBException;
11 import javax.xml.bind.Unmarshaller;
12 import javax.xml.bind.ValidationEvent;
13 import javax.xml.bind.ValidationEventHandler;
14 import javax.xml.bind.helpers.DefaultValidationEventHandler;
15
16 import org.apache.commons.httpclient.HttpException;
17 import org.apache.commons.httpclient.HttpURL;
18 import org.apache.commons.httpclient.methods.GetMethod;
19 import org.apache.commons.httpclient.params.HttpClientParams;
20 import org.apache.commons.io.IOUtils;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24 import yarfraw.core.datamodel.ChannelFeed;
25 import yarfraw.core.datamodel.FeedFormat;
26 import yarfraw.core.datamodel.YarfrawException;
27 import yarfraw.generated.atom10.elements.FeedType;
28 import yarfraw.generated.rss10.elements.RDF;
29 import yarfraw.generated.rss20.elements.TRss;
30 import yarfraw.mapping.backward.impl.ToChannelAtom03Impl;
31 import yarfraw.mapping.backward.impl.ToChannelAtom10Impl;
32 import yarfraw.mapping.backward.impl.ToChannelRss10Impl;
33 import yarfraw.mapping.backward.impl.ToChannelRss20Impl;
34 import yarfraw.utils.JAXBUtils;
35 /***
36 * Provides a set of function to facilitate reading of a RSS feed.
37 *
38 * @author jliang
39 *
40 */
41 public class FeedReader extends AbstractBaseFeedParser{
42 private static final Log LOG = LogFactory.getLog(FeedReader.class);
43 /***
44 * Constructs a {@link FeedReader} to read from a local file.
45 * @param file - the local file to be read from
46 * @param format - the {@link FeedFormat} of the feed.
47 */
48 public FeedReader(File file, FeedFormat format){
49 super(file, format);
50 }
51
52 /***
53 * Constructs a {@link FeedReader} to read from a local file.
54 * @param pathName - full path of the file
55 * @param format - the {@link FeedFormat} of the feed.
56 */
57 public FeedReader(String pathName, FeedFormat format){
58 super(new File(pathName), format);
59 }
60
61 /***
62 * Constructs a {@link FeedReader} to read from a local file.
63 * @param uri - the {@link URI} that points to the file
64 * @param format - the {@link FeedFormat} of the feed.
65 */
66 public FeedReader(URI uri, FeedFormat format){
67 super(new File(uri), format);
68 }
69
70 /***
71 * Constructs a {@link FeedReader} to read from a local file.
72 * <br/>
73 * Note the {@link FeedFormat} will be set to default which is RSS 2.0
74 * @param file - a local file
75 */
76 public FeedReader(File file){
77 super(file);
78 }
79
80 /***
81 * Constructs a {@link FeedReader} to read from a local file.
82 * <br/>
83 * Note the {@link FeedFormat} will be set to default which is RSS 2.0
84 * @param pathName - full path of the file
85 */
86 public FeedReader(String pathName){
87 super(new File(pathName));
88 }
89
90 /***
91 * Constructs a {@link FeedReader} to read from a local file.
92 * <br/>
93 * Note the {@link FeedFormat} will be set to default which is RSS 2.0
94 * @param uri - the uril that points to the file
95 */
96 public FeedReader(URI uri){
97 super(new File(uri));
98 }
99
100 /***
101 * Constructs a {@link FeedReader} to read from a remote source using Http.
102 * <br/>
103 * Format detection will be automatically performed.
104 * @param httpUrl - the {@link HttpURL} of the remote source
105 * @param params - any {@link HttpClientParams}
106 * @throws YarfrawException - if parse failed
107 * @throws IOException - if format detection failed
108 * @Deprecated use {@link CachedFeedReader} for remote feed reading, it offers the same set of
109 * features as this class as well as HTTP conditional get
110 */
111 public FeedReader(HttpURL httpUrl, HttpClientParams params) throws YarfrawException, IOException{
112 super(httpUrl, params);
113 }
114
115 /***
116 * Constructs a {@link FeedReader} to read from a remote source using Http.
117 * <br/>
118 * Format detection will be automatically performed.
119 * @param httpUrl - the {@link HttpURL} of the remote source
120 * @throws YarfrawException - if parse failed
121 * @throws IOException - if format detection failed
122 * @Deprecated use {@link CachedFeedReader} for remote feed reading, it offers the same set of
123 * features as this class as well as HTTP conditional get
124 */
125 public FeedReader(HttpURL httpUrl) throws YarfrawException, IOException{
126 super(httpUrl, null);
127 }
128
129 /***
130 * Constructs a {@link FeedReader} to read from a remote source using Http.
131 * <br/>
132 * Format detection will be automatically performed.
133 * @param getMethod
134 * @throws YarfrawException - if parse failed
135 * @throws IOException - if format detection failed
136 *
137 */
138 public FeedReader(GetMethod getMethod) throws YarfrawException, IOException{
139 super(getMethod);
140 }
141
142 /***
143 * Reads a channel from a local or remote feed with a custom {@link ValidationEventHandler}
144 *
145 * @param format any supported {@link yarfraw.core.datamodel.FeedFormat}
146 * @param inputStream any {@link java.io.InputStream}
147 * @return a {@link ChannelFeed} object
148 * @throws YarfrawException if read operation failed.
149 */
150 public static ChannelFeed readChannel(FeedFormat format, InputStream inputStream) throws YarfrawException{
151 Unmarshaller u;
152 try {
153 u = getUnMarshaller(format);
154 return toChannel(format, u.unmarshal(inputStream));
155 } catch (JAXBException e) {
156 throw new YarfrawException("Unable to unmarshal file", e);
157 }
158 }
159 /***
160 * Reads a channel from a local or remote feed with a custom {@link ValidationEventHandler}
161 *
162 * @param validationEventHandler a custom {@link javax.xml.bind.ValidationEventHandler}
163 * @return a {@link ChannelFeed} object
164 * @throws YarfrawException if read operation failed.
165 */
166 public ChannelFeed readChannel(ValidationEventHandler validationEventHandler) throws YarfrawException{
167 Unmarshaller u;
168 InputStream input = null;
169 try {
170 input = getStream();
171 if(input == null){
172 LOG.warn("Unable to read from null stream, returning null");
173 return null;
174 }
175 u = getUnMarshaller(_format);
176 if(validationEventHandler != null){
177 u.setEventHandler(validationEventHandler);
178 }
179 return toChannel(_format, u.unmarshal(input));
180 } catch (JAXBException e) {
181 throw new YarfrawException("Unable to unmarshal file", e);
182 }
183 catch (HttpException e) {
184 throw new YarfrawException("Unable to read from remote url", e);
185 }
186 catch (IOException e) {
187 throw new YarfrawException("Unable to read", e);
188 }finally{
189 IOUtils.closeQuietly(input);
190 }
191 }
192
193 @SuppressWarnings("unchecked")
194 private static ChannelFeed toChannel(FeedFormat format, Object o) throws YarfrawException{
195 if(format == FeedFormat.RSS20){
196 return ToChannelRss20Impl.getInstance().execute(((JAXBElement<TRss>)o).getValue().getChannel());
197 }else if(format == FeedFormat.RSS10){
198 return ToChannelRss10Impl.getInstance().execute((RDF)o);
199 }else if(format == FeedFormat.ATOM10){
200 return ToChannelAtom10Impl.getInstance().execute(((JAXBElement<FeedType>)o).getValue());
201 }else if(format == FeedFormat.ATOM03){
202 return ToChannelAtom03Impl.getInstance()
203 .execute(((JAXBElement<yarfraw.generated.atom03.elements.FeedType>)o).getValue());
204 }else{
205 throw new UnsupportedOperationException("Unknown Feed Format");
206 }
207 }
208
209 /***
210 * Reads a channel from a local or remote feed.
211 *
212 * @return a {@link ChannelFeed} object
213 * @throws YarfrawException if read operation failed.
214 */
215 public ChannelFeed readChannel() throws YarfrawException{
216 return readChannel(null);
217 }
218
219 private static class WarningHandler implements ValidationEventHandler{
220
221 public boolean handleEvent(ValidationEvent event) {
222 DefaultValidationEventHandler d = new DefaultValidationEventHandler();
223 d.handleEvent(event);
224 return event.getSeverity()== ValidationEvent.FATAL_ERROR;
225 }
226
227 }
228
229 private static Unmarshaller getUnMarshaller(FeedFormat format) throws JAXBException{
230 JAXBContext context = JAXBUtils.getContext(format);
231 Unmarshaller u = context.createUnmarshaller();
232 u.setEventHandler(new WarningHandler());
233 return u;
234 }
235
236
237 }