/*
* Created on Apr 4, 2004
*
* This file is part of Thingamablog. ( http://thingamablog.sf.net )
*
* Copyright (c) 2004, Bob Tantlinger All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
package net.sf.thingamablog.feed;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import net.sf.thingamablog.TBGlobals;
import com.sun.syndication.feed.synd.SyndContent;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;
/**
* Class which defines a news feed
*
* @author Bob Tantlinger
*
*/
public class Feed
{
private FeedBackend backend;
private String url = "";
private String link = null;
private Date lastUpdated = null;
private boolean lastUpdateFailed;
private String lastUpdateFailedReason = "";
private boolean isLimitItems = true;
private int itemLimit = 50;
private String title = "";
private String description = "";
private String language = "";
private String imageURL = null;
private String managingEditor = "";
private String copyright = "";
/**
* Constructs a Feed
*
* @param url The url of the Feed
*/
public Feed(String url)
{
this.url = url;
}
/**
* Updates the feed from the file located at the Feed's url
*
* @throws FeedBackendException If an error occurs while updating the feed
*/
public void update() throws FeedBackendException
{
lastUpdateFailed = false;
//SyndFeedI feed = null;
SyndFeed feed = null;
try
{
URL feedUrl = new URL(url);
SyndFeedInput input = new SyndFeedInput();
feed = input.build(new XmlReader(feedUrl));
//feed = input.build(FeedUtils.getFeedReader(feedUrl));
}
catch(MalformedURLException ex)
{
lastUpdateFailedReason = "Invalid URL";
lastUpdateFailed = true;
System.out.println("ERROR: "+ex.getMessage());
}
catch(Exception ex)
{
lastUpdateFailedReason = "Update failed";
lastUpdateFailed = true;
System.out.println("ERROR: "+ex.getMessage());
}
if(lastUpdateFailed)
return;
List fItems = feed.getEntries();
Iterator it = fItems.iterator();
while(it.hasNext())
{
SyndEntry si = (SyndEntry)it.next();
FeedItem fi = new FeedItem();
fi.setChannelLink(url);
fi.setLink(si.getLink());
fi.setAuthor(si.getAuthor());
fi.setTitle(si.getTitle());
fi.setChannelTitle(feed.getTitle());
fi.setRetrieved(new Date());
Date pubDate = si.getPublishedDate();
if(pubDate != null)
fi.setPubDate(pubDate);
else
fi.setPubDate(fi.getRetrieved());
if(feed.getImage() != null)
fi.setChannelImageURL(feed.getImage().getUrl());
String itemDescr = "";
List cont = si.getContents();
Iterator cIt = cont.iterator();
while(cIt.hasNext())
{
SyndContent iContent = (SyndContent)cIt.next();
itemDescr += iContent.getValue();
}
fi.setDescription(itemDescr);
backend.addItem(fi, false);
}
//adjust items for limit
if(isLimitItems)
{
FeedItem items[] = backend.getItems(url, false);
for (int i = 0; i < items.length; i++)
{
if (i >= itemLimit)
removeItem(items[i]);
}
}
setTitle(feed.getTitle());
setDescription(feed.getDescription());
setLanguage(feed.getLanguage());
//setManagingEditor(channel.getManagingEditor());
setLink(feed.getLink());
setCopyright(feed.getCopyright());
setLastUpdated(new Date());
if(feed.getImage() != null)
{
setImageURL(feed.getImage().getUrl());
saveImage(feed.getImage().getUrl());
}
}
private void saveImage(String iUrl)
{
if(iUrl == null)
return;
String imgType = null;
if(iUrl.endsWith(".gif"))
imgType = ".gif";
else if(iUrl.endsWith(".jpg"))
imgType = ".jpg";
else if(iUrl.endsWith(".png"))
imgType = ".png";
else
return;
File dir = new File(TBGlobals.IMG_CACHE_DIR);
if(!dir.exists() || dir.isFile())
dir.mkdir();
String fileName = Math.abs(iUrl.hashCode()) + imgType;
File file = new File(dir, fileName);
if(file.exists())
return; //don't download it if it exists
try
{
URL url = new URL(iUrl);
// Copy resource to local file, use remote file
InputStream is = url.openStream();
FileOutputStream fos = null;
fos = new FileOutputStream(file);
int oneChar, count = 0;
while ((oneChar = is.read()) != -1)
{
fos.write(oneChar);
count++;
}
is.close();
fos.close();
}
catch (MalformedURLException e)
{
System.err.println(e.toString());
}
catch (IOException e)
{
System.err.println(e.toString());
}
}
/**
* Updates a news item that exists in the feed
*
* @param item The Item to update
* @throws FeedBackendException If an error occurs wile updating the item
*/
public void updateItem(FeedItem item) throws FeedBackendException
{
if (item.getChannelLink().equals(url))
backend.updateItem(item);
}
/**
* Finds items in the feed
*
* @param search The search criteria
* @return The items found
* @throws FeedBackendException If an error occurs while finding items
*/
public FeedItem[] findItems(FeedSearch search) throws FeedBackendException
{
return backend.findItems(url, search);
}
/**
* Gets all the items in this feed
*
* @return The items
* @throws FeedBackendException If an error occurs getting the items
*/
public FeedItem[] getItems() throws FeedBackendException
{
return backend.getItems(url, true);
}
/**
* Gets the unread items in the feed
*
* @return unread items
* @throws FeedBackendException If an error occurs getting the items
*/
public FeedItem[] getUnreadItems() throws FeedBackendException
{
return backend.getUnreadItems(url, true);
}
/**
* Marks all the items in the feed as read or unread
*
* @param isRead true if read, false unread
* @throws FeedBackendException If an error occurs marking the items
*/
public void markAllItemsRead(boolean isRead) throws FeedBackendException
{
FeedItem items[] = getItems();
for (int i = 0; i < items.length; i++)
{
items[i].setRead(isRead);
backend.updateItem(items[i]);
}
}
/**
* Removes an item from the feed
*
* @param item The item to remove
* @throws FeedBackendException If an error occurs removing the item
*/
public void removeItem(FeedItem item) throws FeedBackendException
{
if (item.getChannelLink().equals(url))
backend.removeItem(item.getID());
}
/**
* Removes all items from the feed
*
* @throws FeedBackendException If an error occurs removing the items
*/
public void removeAllItems() throws FeedBackendException
{
FeedItem items[] = getItems();
for (int i = 0; i < items.length; i++)
{
backend.removeItem(items[i].getID());
}
}
/**
* Gets the backend for this feed
*
* @return The backend
*/
public FeedBackend getBackend()
{
return backend;
}
/**
* Gets the copyright for this feed
*
* @return The copyright
*/
public String getCopyright()
{
return copyright;
}
/**
* Gets the description for this feed
*
* @return The description
*/
public String getDescription()
{
return description;
}
/**
* Gets the image URL of this feed
*
* @return The image URL
*/
public String getImageURL()
{
return imageURL;
}
/**
* Gets the language of this feed
*
* @return The language
*/
public String getLanguage()
{
return language;
}
/**
* Gets the date the feed was last updated
*
* @return The last updated date
*/
public Date getLastUpdated()
{
return lastUpdated;
}
/**
* Gets the link of this feed
*
* @return The link
*/
public String getLink()
{
return link;
}
/**
* Gets the managing editor of this feed
*
* @return The managing editor
*/
public String getManagingEditor()
{
return managingEditor;
}
/**
* Gets the title of this feed
*
* @return The title
*/
public String getTitle()
{
return title;
}
/**
* Gets the URL of this feed
*
* @return The URL
*/
public String getURL()
{
return url;
}
/**
* Sets the backend for this feed
*
* @param backend The backend
*/
public void setBackend(FeedBackend backend)
{
this.backend = backend;
}
/**
* Sets the copyright for this feed
*
* @param string The copyright
*/
public void setCopyright(String string)
{
copyright = string;
}
/**
* Sets the description for this feed
*
* @param string The description
*/
public void setDescription(String string)
{
description = string;
}
/**
* Sets the image URL for this feed
*
* @param string The image URL
*/
public void setImageURL(String string)
{
imageURL = string;
}
/**
* Sets the language of this feed
*
* @param string The language
*/
public void setLanguage(String string)
{
language = string;
}
/**
* Sets the last updated date of this feed
*
* @param date The date the feed was last updated
*/
public void setLastUpdated(Date date)
{
lastUpdated = date;
}
/**
* Sets the link of the feed
*
* @param string The link
*/
public void setLink(String string)
{
link = string;
}
/**
* Sets the managing editor of the feed
*
* @param string The managing editor
*/
public void setManagingEditor(String string)
{
managingEditor = string;
}
/**
* Sets the title of the feed
*
* @param string The title
*/
public void setTitle(String string)
{
title = string;
}
/**
* Sets the URL of the feed
*
* @param string The URL
*/
public void setURL(String string)
{
url = string;
}
/**
* Overriden to return the feed title
*/
public String toString()
{
return getTitle();
}
/**
* Indicates if the last update failed
*
* @return true if it failed, false otherwise
*/
public boolean isLastUpdateFailed()
{
return lastUpdateFailed;
}
/**
* Gets the reason the last update failed
*
* @return The failue reason
*/
public String getLastUpdateFailedReason()
{
if (isLastUpdateFailed())
return lastUpdateFailedReason;
return "";
}
/**
* Indicate that the last update failed
*
* @param b true if failed, false otherwise
*/
public void setLastUpdateFailed(boolean b)
{
lastUpdateFailed = b;
}
/**
* Sets the reason for the update failure
*
* @param string The reason
*/
public void setLastUpdateFailedReason(String string)
{
lastUpdateFailedReason = string;
}
/**
* Indicates whether or not this feed limits the number of items
*
* @return true if it limits, false otherwise
*/
public boolean isLimitItems()
{
return isLimitItems;
}
/**
* Gets the maximum number of items this feed can contain
*
* @return The item limit
*/
public int getItemLimit()
{
return itemLimit;
}
/**
* Sets whether or not to limit items
*
* @param b true to limit, false otherwise
*/
public void setLimitItems(boolean b)
{
isLimitItems = b;
}
/**
* Sets the number of items this feed can contain
*
* @param i The item limit
*/
public void setItemLimit(int i)
{
itemLimit = i;
}
}