/*
* OpmlParser.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 logging define
@DLOGDEF@
package com.substanceofcode.rssreader.businesslogic;
import com.substanceofcode.rssreader.businessentities.RssItunesFeed;
import com.substanceofcode.utils.XmlParser;
import javax.microedition.io.*;
import java.util.*;
import java.io.*;
import com.substanceofcode.utils.EncodingUtil;
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.Level;
//#endif
/**
* OpmlParser is an utility class for aquiring and parsing a OPML lists.
* HttpConnection is used to fetch OPML list and kXML is used on xml parsing.
*
* @author Tommi Laukkanen
* @version 1.0
*/
public class OpmlParser extends FeedListParser {
// Future allow reading in OMPL which contain OMPL.
private boolean opmlDirectory = false;
//#ifdef DLOGGING
private Logger m_logger = Logger.getLogger("OpmlParser");
private boolean m_fineLoggable = m_logger.isLoggable(Level.FINE);
private boolean m_finerLoggable = m_logger.isLoggable(Level.FINER);
private boolean m_finestLoggable = m_logger.isLoggable(Level.FINEST);
//#endif
/** Constructor with url, username and password parameters. */
public OpmlParser(String url, String username, String password) {
super(url, username, password);
}
/** Parse OPML list */
public RssItunesFeed[] parseFeeds(InputStream is)
throws IOException, CauseMemoryException, CauseException, Exception {
/** Initialize item collection */
Vector rssFeeds = new Vector();
/** Initialize XML parser and parse OPML XML */
XmlParser parser = new XmlParser(is);
try {
// The first element is the main tag.
int elementType = parser.parse();
// If we found the prologue, get the next entry.
if( elementType == XmlParser.PROLOGUE ) {
elementType = parser.parse();
}
if (elementType == XmlParser.END_DOCUMENT ) {
return null;
}
EncodingUtil encodingUtil = parser.getEncodingUtil();
do {
/** RSS item properties */
String title = "";
String link = "";
String tagName = parser.getName();
System.out.println("tagname: " + tagName);
if (tagName.equals("outline")) {
System.out.println("Parsing <outline> tag");
title = parser.getAttributeValue( "text" );
if (title != null) {
title = EncodingUtil.replaceAlphaEntities(true,
title);
// No need to convert from UTF-8 to Unicode using replace
// umlauts now because it is done with new String...,encoding.
// Replace numeric entities including ’, ‘
// “, and ”
title = EncodingUtil.replaceNumEntity(title);
// Replace special chars like left quote, etc.
// Since we have already converted to unicode, we want
// to replace with uni chars.
title = encodingUtil.replaceSpChars(title);
}
/**
* Create new RSS item and add it do RSS document's item
* collection. Account for wrong OPML which is an
* OPML composed of other OPML. These have url attribute
* instead of link attribute.
*/
if ((link = parser.getAttributeValue( "xmlUrl" )) == null) {
if (opmlDirectory) {
link = parser.getAttributeValue( "url" );
}
}
/** Debugging information */
System.out.println("Title: " + title);
System.out.println("Link: " + link);
if(( link == null ) || ( link.length() == 0 )) {
continue;
}
if (( m_feedNameFilter != null) &&
((title != null) &&
(title.toLowerCase().indexOf(m_feedNameFilter) < 0))) {
continue;
}
if (( m_feedURLFilter != null) &&
( link.toLowerCase().indexOf(m_feedURLFilter) < 0)) {
continue;
}
RssItunesFeed feed = new RssItunesFeed(title, link, "", "");
rssFeeds.addElement( feed );
}
}
while( parser.parse() != XmlParser.END_DOCUMENT );
} catch (CauseMemoryException ex) {
rssFeeds = null;
CauseMemoryException cex = new CauseMemoryException(
"Out of memory error while parsing OPML feed " +
m_url, ex);
throw cex;
} catch (Exception ex) {
System.err.println("OpmlParser.parseFeeds(): Exception " + ex.toString());
ex.printStackTrace();
//#ifdef DLOGGING
m_logger.severe("FeedListParser.run(): Error while parsing " +
"feeds: " + m_url, ex);
//#endif
CauseException cex = new CauseException(
"Error while parsing Opml feed " + m_url, ex);
throw cex;
} catch (OutOfMemoryError ex) {
rssFeeds = null;
CauseMemoryException cex = new CauseMemoryException(
"Out of memory error while parsing OPML feed " +
m_url, ex);
//#ifdef DLOGGING
m_logger.severe("FeedListParser.run(): Error while parsing " +
"feeds: " + m_url, ex);
//#endif
throw cex;
} catch (Throwable t) {
System.err.println("OpmlParser.parseFeeds(): Exception " + t.toString());
t.printStackTrace();
CauseException ex = new CauseException(
"Error while parsing Opml feed " + m_url, t);
//#ifdef DLOGGING
m_logger.severe("FeedListParser.run(): Error while parsing " +
"feeds: " + m_url, ex);
//#endif
throw ex;
}
/** Create array */
RssItunesFeed[] feeds = new RssItunesFeed[ rssFeeds.size() ];
rssFeeds.copyInto(feeds);
return feeds;
}
}