/* * ImportFeedsForm.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 MIDP define //#define DMIDP20 // Expand to define DJSR75 define //#define DNOJSR75 // Expand to define itunes define //#define DNOITUNES // Expand to define logging define //#define DNOLOGGING // Expand to define test ui define //#define DNOTESTUI package com.substanceofcode.rssreader.presentation; import java.lang.IllegalArgumentException; import java.io.IOException; import java.util.Hashtable; import com.substanceofcode.rssreader.businessentities.RssReaderSettings; import javax.microedition.lcdui.Alert; import javax.microedition.lcdui.AlertType; import javax.microedition.lcdui.Choice; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; //#ifndef DTESTUI //@import javax.microedition.lcdui.ChoiceGroup; //@import javax.microedition.lcdui.Form; //@import javax.microedition.lcdui.TextField; //@import javax.microedition.lcdui.StringItem; //#else // If using the test UI define the Test UI's import com.substanceofcode.testlcdui.ChoiceGroup; import com.substanceofcode.testlcdui.Form; import com.substanceofcode.testlcdui.List; import com.substanceofcode.testlcdui.TextBox; import com.substanceofcode.testlcdui.TextField; import com.substanceofcode.testlcdui.StringItem; //#endif import javax.microedition.lcdui.Item; //#ifndef DSMALLMEM import com.substanceofcode.rssreader.presentation.HelpForm; //#endif import com.substanceofcode.utils.CauseException; import com.substanceofcode.utils.CauseMemoryException; import com.substanceofcode.rssreader.businessentities.RssItunesFeed; import com.substanceofcode.rssreader.businessentities.RssFeedStore; import com.substanceofcode.rssreader.businesslogic.FeedListParser; import com.substanceofcode.rssreader.businesslogic.LineByLineParser; import com.substanceofcode.rssreader.businesslogic.OpmlParser; import com.substanceofcode.rssreader.businesslogic.RssFeedParser; //#ifndef DSMALLMEM import com.substanceofcode.rssreader.businesslogic.HTMLAutoLinkParser; import com.substanceofcode.rssreader.businesslogic.HTMLLinkParser; //#endif //#ifdef DJSR75 import org.kablog.kgui.KFileSelectorMgr; //#endif import cz.cacek.ebook.util.ResourceProviderME; //#ifdef DLOGGING import net.sf.jlogmicro.util.logging.Logger; import net.sf.jlogmicro.util.logging.LogManager; import net.sf.jlogmicro.util.logging.Level; //#endif /** * * @author Tommi Laukkanen */ /* Form to import feeds. */ final public class ImportFeedsForm extends Form implements CommandListener, Runnable { static private byte[] m_importSave = null; // Import form save private boolean m_debugOutput = false; // Flag to write to output for test private boolean m_getFeedList = false; // The noticy flag for list parsing private boolean m_getFeedTitleList = false; // The noticy flag for title/list parsing // The noticy flag for override existing feeds private boolean m_override = false; // The noticy flag for override private boolean m_needWakeup = false; // Flag to show need to wakeup //#ifndef DSMALLMEM private boolean m_getHelp = false; // The help form flag //#endif private boolean m_process = true; // Flag to continue looping private int m_addBkmrk; // Place to add (insert) imported bookmarks private FeedListParser m_listParser; // The feed list parser private TextField m_feedListURL; // The feed list URL field private TextField m_feedNameFilter; // The feed name filter string private TextField m_feedURLFilter; // The feed URL filter string private TextField m_feedListUsername; // The feed list username private TextField m_feedListPassword; // The feed list password private ChoiceGroup m_importFormatGroup;// The import type choice group private ChoiceGroup m_importTitleGroup; // The import title choice group private ChoiceGroup m_importHTMLGroup; // The import HTML redirect choice group private ChoiceGroup m_importOvrGroup; // The import override choice group private Command m_importInsCmd; // The import before the current point? private Command m_importAddCmd; // The import after the current point? private Command m_importAppndCmd; // The import append private Command m_importCancelCmd; // The Cancel command for importing private Command m_importFileCmd; // The find files command for importing //#ifndef DSMALLMEM private Command m_pasteImportURLCmd;// The paste command //#endif //#ifndef DSMALLMEM private Command m_helpCmd; // The help command //#endif //#ifdef DTESTUI private Command m_testImportCmd; // Test UI rss opml command //#endif private RssReaderMIDlet m_midlet; // The application midlet private RssFeedStore m_rssFeeds; // The bookmark URLs private RssReaderSettings m_appSettings;// The application settings private PromptList m_bookmarkList; // The bookmark list private RssReaderMIDlet.LoadingForm m_loadForm; // The application settings //#ifdef DLOGGING private Logger m_logger = Logger.getLogger("ImportFeedsForm"); 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 /** Initialize import form */ public ImportFeedsForm(RssReaderMIDlet midlet, PromptList bookmarkList, RssFeedStore rssFeeds, RssReaderSettings appSettings, RssReaderMIDlet.LoadingForm loadForm, String url) { super("Import feeds"); m_midlet = midlet; m_bookmarkList = bookmarkList; m_rssFeeds = rssFeeds; m_appSettings = appSettings; m_loadForm = loadForm; m_getFeedList = false; m_getFeedTitleList = false; m_listParser = null; if(url.length()==0) { url = "http://"; } m_feedListURL = new TextField("URL", url, 256, TextField.URL); super.append(m_feedListURL); m_importFormatGroup = new ChoiceGroup("Format", ChoiceGroup.EXCLUSIVE, new String[] {"OPML", "line by line" //#ifndef DSMALLMEM , "HTML OPML Auto link", "HTML RSS Auto links" , "HTML Links" //#endif }, null); super.append(m_importFormatGroup); m_feedNameFilter = new TextField("Name filter string (optional)", "", 256, TextField.ANY); super.append(m_feedNameFilter); m_feedURLFilter = new TextField("URL filter string (optional)", "", 256, TextField.ANY); super.append(m_feedURLFilter); final String username = m_appSettings.getImportUrlUsername(); m_feedListUsername = new TextField("Username (optional)", username, 64, TextField.ANY); super.append(m_feedListUsername); final String password = m_appSettings.getImportUrlPassword(); m_feedListPassword = new TextField("Password (optional)", password, 64, TextField.PASSWORD); super.append(m_feedListPassword); m_importTitleGroup = new ChoiceGroup("Missing title (optionl)", ChoiceGroup.EXCLUSIVE, new String[] {"Skip feed with missing title", "Get missing titles from feed"}, null); super.append(m_importTitleGroup); m_importHTMLGroup = new ChoiceGroup("Treat HTML mime type as valid import (optional)", ChoiceGroup.EXCLUSIVE, new String[] {"Redirect if HTML (ignored for HTML link import)", "Treat HTML as import"}, null); m_importOvrGroup = new ChoiceGroup( "Override existing feeds in place (optionl)", ChoiceGroup.EXCLUSIVE, new String[] {"Don't override existing feeds.", "Override (replace) existing feeds."}, null); super.append(m_importOvrGroup); if (m_importSave != null) { Item[] items = {m_importFormatGroup, m_feedNameFilter, m_feedURLFilter, m_feedListUsername, m_feedListPassword, m_importFormatGroup, m_importTitleGroup, m_importHTMLGroup }; UiUtil.restorePrevValues(items, m_importSave); } super.append(m_importHTMLGroup); /* Insert import */ /* Insert current import */ m_importInsCmd = UiUtil.getCmdRsc("cmd.i.imp", "cmd.li.imp", Command.SCREEN, 1); /* Add import */ /* Add current import */ m_importAddCmd = UiUtil.getCmdRsc("cmd.a.imp", "cmd.la.imp", Command.SCREEN, 2); /* Append import */ /* Append end import */ m_importAppndCmd = UiUtil.getCmdRsc("cmd.ap.imp", "cmd.lap.imp", Command.SCREEN, 3); /* Cancel */ m_importCancelCmd = UiUtil.getCmdRsc("cmd.cancel", Command.CANCEL, 4); /* Find files */ m_importFileCmd = UiUtil.getCmdRsc("cmd.f.fl", Command.SCREEN, 5); //#ifndef DSMALLMEM /* Allow paste */ m_pasteImportURLCmd = UiUtil.getCmdRsc("cmd.a.pst", Command.SCREEN, 6); //#endif //#ifndef DSMALLMEM m_helpCmd = UiUtil.getCmdRsc("cmd.help", Command.HELP, 6); //#endif super.addCommand( m_importInsCmd ); super.addCommand( m_importAddCmd ); super.addCommand( m_importAppndCmd ); super.addCommand( m_importCancelCmd ); //#ifdef DJSR75 super.addCommand( m_importFileCmd ); //#endif //#ifndef DSMALLMEM if (m_appSettings.getUseTextBox()) { super.addCommand(m_pasteImportURLCmd); } //#endif //#ifndef DSMALLMEM super.addCommand(m_helpCmd); //#endif //#ifdef DTESTUI /* Test bookmarks imported */ m_testImportCmd = UiUtil.getCmdRsc("cmd.t.imp", Command.SCREEN, 9); super.addCommand( m_testImportCmd ); //#endif super.setCommandListener(this); m_process = true; //#ifdef DCLDCV11 new Thread(this, "ImportFeedsForm").start(); //#else new Thread(this).start(); //#endif } /** Add from feed list (from import). */ final private void addFeedLists() throws CauseException, Exception { // Feed list parsing is ready System.out.println("Feed list parsing is ready"); if(!m_listParser.isSuccessfull()) { throw m_listParser.getEx(); } RssItunesFeed[] feeds = m_listParser.getFeeds(); boolean notesShown = false; for(int feedIndex=0; feedIndex<feeds.length; feedIndex++) { String name = feeds[feedIndex].getName(); //#ifdef DTEST System.out.println("Adding: " + name); //#endif // If no title (name) and we are getting the title from the // feed being imported, parse the name(title) only. if (((name == null) || (name.length() == 0)) && m_getFeedTitleList) { RssItunesFeed feed = feeds[feedIndex]; RssFeedParser fparser = new RssFeedParser( feed ); /* Loading title for */ m_loadForm.appendMsg(ResourceProviderME.get("text.ld.t", feed.getUrl())); //#ifdef DLOGGING if (m_finestLoggable) {m_logger.finest("Getting title for url=" + feed.getUrl());} //#endif fparser.setGetTitleOnly(true); /** Get RSS feed */ int maxItemCount = m_appSettings.getMaximumItemCountInFeed(); try { fparser.parseRssFeed( false, true, maxItemCount ); name = feed.getName(); m_loadForm.appendMsg("ok\n"); } catch(Exception ex) { m_midlet.recordExcForm("Error loading title for feed " + feed.getUrl(), ex); notesShown = true; } } if((name != null) && (name.length()>0)) { final boolean pres = m_rssFeeds.containsKey( name ); if(m_override || !pres) { if(pres) { m_loadForm.appendMsg( ResourceProviderME.get("text.wr.dup", name)); } m_rssFeeds.put( name, feeds[feedIndex] ); if(!pres) { m_bookmarkList.insert(m_addBkmrk++, name, null); } } else { /* Error: Feed already exists with name (name) */ /*. Existing feed not updated. */ CauseException ce = new CauseException( ResourceProviderME.get("exc.fd.ex", name)); m_loadForm.appendMsg(ce.getMessage()); m_loadForm.addExc(ce); notesShown = true; } } } if (notesShown) { m_midlet.recordFin(); m_midlet.setCurrent( m_loadForm ); } else { m_process = false; m_loadForm.removeRef(this); Item[] items = {m_importFormatGroup, m_feedNameFilter, m_feedURLFilter, m_feedListUsername, m_feedListPassword, m_importFormatGroup, m_importTitleGroup, m_importHTMLGroup }; m_importSave = UiUtil.storeValues(items); m_midlet.showBookmarkList(); } m_getFeedTitleList = false; } /** Run method is used to get RSS feed with HttpConnection */ public void run(){ /* Use networking if necessary */ long lngStart; long lngTimeTaken; while(m_process) { try { // Add feeds from import. if( m_getFeedList ) { m_getFeedList = false; m_midlet.initializeLoadingFormRsc("text.l.imp.f", this); m_midlet.setCurrent( m_loadForm ); final String url = m_feedListURL.getString().trim(); try { // 2. Import feeds int selectedImportType = m_importFormatGroup.getSelectedIndex(); RssItunesFeed[] feeds = null; String feedNameFilter = m_feedNameFilter.getString(); String feedURLFilter = m_feedURLFilter.getString(); String username = m_feedListUsername.getString(); String password = m_feedListPassword.getString(); m_getFeedTitleList = m_importTitleGroup.isSelected(1); m_override = m_importOvrGroup.isSelected(1); //#ifdef DLOGGING if (m_finestLoggable) {m_logger.finest("m_getFeedTitleList=" + m_getFeedTitleList);} if (m_finestLoggable) {m_logger.finest("selectedImportType=" + selectedImportType);} //#endif // Save settings m_appSettings.setImportUrl(url); m_appSettings.setImportUrlUsername(username); m_appSettings.setImportUrlPassword(password); switch (selectedImportType) { case 0: // Use OPML parser m_listParser = new OpmlParser(url, username, password); break; case 1: // Use line by line parser m_listParser = new LineByLineParser(url, username, password); break; //#ifndef DSMALLMEM case 2: // Use line by HMTL OPML auto link parser m_listParser = new HTMLAutoLinkParser(url, username, password); ((HTMLAutoLinkParser)m_listParser).setNeedRss(false); break; case 3: // Use line by HMTL RSS auto link parser m_listParser = new HTMLAutoLinkParser(url, username, password); ((HTMLAutoLinkParser)m_listParser).setNeedRss(true); break; case 4: // Use line by HMTL link parser m_listParser = new HTMLLinkParser(url, username, password); break; //#endif } m_listParser.setFeedNameFilter(feedNameFilter); m_listParser.setFeedURLFilter(feedURLFilter); //#ifndef DSMALLMEM m_listParser.setRedirectHtml(m_importHTMLGroup.isSelected(0) && !(m_listParser instanceof HTMLAutoLinkParser) && !(m_listParser instanceof HTMLLinkParser)); //#endif //#ifdef DLOGGING if (m_fineLoggable) {m_logger.fine("redirect html=" + m_listParser.isRedirectHtml());} //#endif // Start parsing m_listParser.startParsing(); // 3. Show result screen // 4. Show list of feeds } catch(Exception ex) { m_listParser = null; m_midlet.recordExcFormFin("Error importing feeds from " + url, ex); } catch(OutOfMemoryError ex) { m_listParser = null; /* Out Of Memory Error importing feeds from */ m_midlet.recordExcFormFinRsc("exc.om.imp", url, ex); } catch(Throwable t) { m_listParser = null; /* Internal error importing feeds from */ m_midlet.recordExcFormFinRsc("exc.int.imp", url, t); } } if(m_listParser != null) { try { try { if(m_listParser.isReady()) { addFeedLists(); m_listParser = null; } else { //#ifndef DTESTUI if (m_debugOutput) System.out.println("Feed list parsing isn't ready"); //#endif } } catch(OutOfMemoryError e) { throw new CauseMemoryException( "Error importing feeds from " + m_listParser.getUrl() + " " + e.getMessage(), e); } } catch(CauseMemoryException ex) { m_midlet.recordExcFormFin( "Out of memory error importing feeds " + "from " + m_listParser.getUrl() + " " + ex.getMessage(), ex); m_getFeedTitleList = false; m_listParser = null; // TODO empty list parser m_listParser = null; } catch(Exception ex) { m_midlet.recordExcFormFin( "Error importing feeds from " + m_listParser.getUrl(), ex); m_getFeedTitleList = false; m_listParser = null; } catch(Throwable t) { m_midlet.recordExcFormFin( "Internal error importing feeds from " + m_listParser.getUrl(), t); m_getFeedTitleList = false; m_listParser = null; } } //#ifndef DSMALLMEM else if (m_getHelp) { m_getHelp = false; m_midlet.initializeLoadingFormRsc("text.l.h", this); m_midlet.setCurrent( m_loadForm ); final HelpForm helpForm = new HelpForm(m_midlet, this); helpForm.appendRsc("text.abmc.help"); helpForm.appendItemHelpRsc(m_importOvrGroup, "text.oimp.help"); helpForm.appendItemHelpRsc(m_importFormatGroup, "text.fimp.help"); helpForm.appendCmdHelpRsc(m_importAddCmd, "text.aimp.help"); helpForm.appendCmdHelpRsc(m_importAppndCmd, "text.pimp.help"); m_midlet.setCurrent( helpForm ); } //#endif lngStart = System.currentTimeMillis(); lngTimeTaken = System.currentTimeMillis()-lngStart; if(lngTimeTaken<100L) { synchronized(this) { if (!m_needWakeup) { super.wait(75L-lngTimeTaken); } m_needWakeup = false; } } } catch (InterruptedException e) { break; } } } /** Respond to commands */ public void commandAction(final Command c, final Displayable s) { //#ifdef DTESTUI super.outputCmdAct(c, s); //#endif /** Import list of feeds */ m_addBkmrk = UiUtil.getPlaceIndex(c, m_addBkmrk, m_importInsCmd, m_importAddCmd, m_importAppndCmd, m_bookmarkList); if( m_addBkmrk >= 0 ) { m_getFeedList = true; } //#ifdef DJSR75 /** Find import file in file system */ if( c == m_importFileCmd ) { if (!m_midlet.JSR75_ENABLED) { Alert invalidAlert = new Alert( "JSR-75 not enabled", "Find files (JSR-75) not enabled on the phone.", null, AlertType.WARNING); invalidAlert.setTimeout(Alert.FOREVER); m_midlet.setCurrent( invalidAlert, this ); return; } try { m_midlet.reqFindFiles( this, m_feedListURL ); m_midlet.wakeUp(); }catch(Throwable t) { //#ifdef DLOGGING m_logger.severe("RssReaderMIDlet find files ", t); //#endif /** Error while executing find files */ System.out.println("RssReaderMIDlet find files " + t.getMessage()); t.printStackTrace(); } } //#endif /** Cancel importing -> Show list of feeds */ if( c == m_importCancelCmd ) { m_loadForm.removeRef(this); m_process = false; m_midlet.setCurrent( m_bookmarkList ); m_midlet.wakeUp(); } //#ifndef DSMALLMEM if( c == m_helpCmd ) { m_getHelp = true; } //#endif //#ifndef DSMALLMEM /** Put current import URL into URL box. */ if( c == m_pasteImportURLCmd ) { new UiUtil().initializeURLBox(m_midlet, m_feedListURL.getString(), this, m_feedListURL); } //#endif //#ifdef DTESTUI /** Import list of feeds and auto edit bookmarks/feeds */ if( c == m_testImportCmd ) { m_midlet.setBookmarkIndex(m_bookmarkList.size()); System.out.println("Test UI Test Rss feeds m_bookmarkIndex=" + m_midlet.getBookmarkIndex()); commandAction(m_importAppndCmd, this); } //#endif importWakeUp(); } /* Notify us that we are finished. */ final public void importWakeUp() { synchronized(this) { m_needWakeup = true; super.notify(); } } }