/*
* FeedListParser.java
*
* Copyright (C) 2005-2006 Tommi Laukkanen
* http://www.substanceofcode.com
*
* 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
*
*/
// Expand to define test define
@DTESTDEF@
// Expand to define logging define
@DLOGDEF@
package com.substanceofcode.rssreader.businesslogic;
import com.substanceofcode.rssreader.businessentities.RssItunesFeed;
import java.io.IOException;
import java.io.InputStream;
import cz.cacek.ebook.util.ResourceProviderME;
import com.substanceofcode.utils.CauseException;
import com.substanceofcode.utils.CauseMemoryException;
//#ifdef DLOGGING
import net.sf.jlogmicro.util.logging.Logger;
import net.sf.jlogmicro.util.logging.LogManager;
import net.sf.jlogmicro.util.logging.Level;
//#endif
/**
* Base class for feed list parsers.
*
* @author Tommi Laukkanen
*/
public abstract class FeedListParser extends URLHandler implements Runnable{
private Thread m_parsingThread;
protected String m_url;
protected String m_username;
protected String m_password;
protected String m_feedNameFilter;
protected String m_feedURLFilter;
protected boolean m_redirectHtml = false;
protected RssItunesFeed[] m_feeds;
private boolean m_ready;
private boolean m_successfull = false;
private CauseException m_ex = null;
private boolean m_redirect = false; // The RSS feed is redirected
//#ifdef DLOGGING
private Logger logger = Logger.getLogger("FeedListParser");
private boolean fineLoggable = logger.isLoggable(Level.FINE);
private boolean finerLoggable = logger.isLoggable(Level.FINER);
private boolean finestLoggable = logger.isLoggable(Level.FINEST);
//#endif
/** Creates a new instance of FeedListParser */
public FeedListParser(String url, String username, String password) {
super();
m_parsingThread = new Thread(this);
m_url = url;
m_username = username;
m_password = m_password;
}
/** Start parsing the feed list */
public void startParsing() {
m_ready = false;
m_parsingThread.start();
//#ifdef DLOGGING
if (fineLoggable) {logger.fine("Thread started=" + m_parsingThread);}
//#endif
}
/** Check whatever parsing is ready or not */
public boolean isReady() {
return m_ready;
}
/** Get feed list */
public RssItunesFeed[] getFeeds() {
return m_feeds;
}
/** Parsing thread */
public void run() {
try {
//#ifdef DLOGGING
if (fineLoggable) {logger.fine("Thread running=" + this);}
//#endif
m_feeds = parseFeeds();
m_successfull = true;
} catch( IOException ex ) {
//#ifdef DLOGGING
logger.severe("FeedListParser.run(): Error while parsing " +
"feeds: " + m_url, ex);
//#endif
System.err.println("FeedListParser.run(): Error while parsing feeds: " + ex.toString());
m_ex = new CauseException("Error while parsing feed " + m_url, ex);
} catch( CauseMemoryException ex ) {
m_feeds = null;
System.gc();
m_ex = new CauseMemoryException("Out of memory error while " +
"parsing feed " + m_url, ex);
//#ifdef DLOGGING
logger.severe(m_ex.getMessage(), ex);
//#endif
} catch( Exception ex ) {
//#ifdef DLOGGING
logger.severe("FeedListParser.run(): Error while parsing " +
"feeds: " + m_url, ex);
//#endif
System.err.println("FeedListParser.run(): Error while parsing feeds: " + ex.toString());
m_ex = new CauseException("Error while parsing feed " + m_url, ex);
} catch( OutOfMemoryError t ) {
m_feeds = null;
System.gc();
//#ifdef DLOGGING
logger.severe("FeedListParser.run(): Out Of Memory Error while " +
"parsing feeds: " + m_url, t);
//#endif
System.err.println("FeedListParser.run(): " +
"Out Of Memory Error while parsing feeds: " + t.toString());
m_ex = new CauseMemoryException("Out Of Memory Error while " +
"parsing feed " + m_url, t);
} catch( Throwable t ) {
//#ifdef DLOGGING
logger.severe("FeedListParser.run(): Error while parsing " +
"feeds: " + m_url, t);
//#endif
System.err.println("FeedListParser.run(): Error while parsing feeds: " + t.toString());
m_ex = new CauseException("Internal error while parsing feed " +
m_url, t);
} finally {
m_ready = true;
}
}
/** Get feeds from selected url */
public RssItunesFeed[] parseFeeds()
throws IOException, CauseMemoryException, CauseException, Exception {
try {
super.handleOpen(m_url, m_username, m_password);
if (m_needRedirect) {
m_needRedirect = false;
m_feeds = parseHeaderRedirect(m_location);
return m_feeds;
}
//#ifdef DLOGGING
if (fineLoggable) {logger.fine("m_redirectHtml=" + m_redirectHtml);}
//#endif
// If we find HTML, usually it is redirection
if (m_redirectHtml && (m_contentType != null) &&
(m_contentType.indexOf("html") >= 0)) {
return parseHTMLRedirect();
} else {
return parseFeeds(m_inputStream);
}
} catch(CauseMemoryException e) {
throw e;
} catch(Exception e) {
/* Error while parsing import data: */
CauseException ce = new CauseException(ResourceProviderME.get(
"exc.err.imp", m_url), e);
//#ifdef DLOGGING
logger.severe(ce.getMessage(), e);
//#endif
if ((m_url != null) && m_url.startsWith("file://")) {
System.err.println("Cannot process file.");
}
throw ce;
} catch(OutOfMemoryError t) {
m_feeds = null;
System.gc();
//#ifdef DLOGGING
logger.severe("Out Of Memory Error with " + m_url, t);
//#endif
if ((m_url != null) && m_url.startsWith("file://")) {
System.err.println("Cannot process file.");
}
/* Out Of Memory Error while parsing RSS data */
throw new CauseMemoryException(ResourceProviderME.get(
"exc.om.rsd", m_url), t);
} catch(Throwable t) {
//#ifdef DLOGGING
logger.severe("parseFeeds error with " + m_url, t);
//#endif
if ((m_url != null) && m_url.startsWith("file://")) {
System.err.println("Cannot process file.");
}
throw new CauseException(
"Internal error while parsing RSS data " + m_url, t);
} finally {
super.handleClose();
}
}
/** If header shows redirect, handle it here. */
private RssItunesFeed[] parseHeaderRedirect(String newUrl)
throws IOException, CauseMemoryException, CauseException, Exception {
if (m_redirect) {
//#ifdef DLOGGING
logger.severe("Error 2nd header redirect url: " + newUrl);
//#endif
System.out.println("Error 2nd header redirect url " +
m_redirectUrl + " to 2nd redirect " + newUrl);
throw new IOException("Error 2nd header redirect url " +
m_redirectUrl + " to 2nd redirect " + newUrl);
}
m_redirect = true;
m_redirectUrl = m_url;
String svUrl = m_url;
m_url = newUrl;
try {
return parseFeeds();
} finally {
m_url = newUrl;
}
}
/** Read HTML and if it has links, redirect and parse the XML. */
private RssItunesFeed[] parseHTMLRedirect()
throws IOException, CauseMemoryException, CauseException, Exception {
String svUrl = m_url;
m_url = super.parseHTMLRedirect(m_url, m_inputStream);
try {
return parseFeeds();
} finally {
m_url = svUrl;
}
}
abstract RssItunesFeed[] parseFeeds(InputStream is)
throws IOException, CauseMemoryException, CauseException, Exception;
public void setFeedNameFilter(String m_feedNameFilter) {
if (m_feedNameFilter == null) {
this.m_feedNameFilter = null;
} else if (m_feedNameFilter.length() == 0) {
this.m_feedNameFilter = null;
} else {
this.m_feedNameFilter = m_feedNameFilter.toLowerCase();
}
}
public String getFeedNameFilter() {
return (m_feedNameFilter);
}
public void setFeedURLFilter(String m_feedURLFilter) {
if (m_feedURLFilter == null) {
this.m_feedURLFilter = null;
} else if (m_feedURLFilter.length() == 0) {
this.m_feedURLFilter = null;
} else {
this.m_feedURLFilter = m_feedURLFilter.toLowerCase();
}
}
public String getFeedURLFilter() {
return (m_feedURLFilter);
}
public boolean isSuccessfull() {
return (m_successfull);
}
public void setRedirectHtml(boolean m_redirectHtml) {
this.m_redirectHtml = m_redirectHtml;
}
public boolean isRedirectHtml() {
return (m_redirectHtml);
}
public CauseException getEx() {
return (m_ex);
}
public String getUrl() {
return (m_url);
}
}