View Javadoc

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 }