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 }