package railo.runtime.text.feed; import java.io.IOException; import java.io.InputStream; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.ext.Locator2; import org.xml.sax.helpers.DefaultHandler; import railo.commons.io.IOUtil; import railo.commons.io.SystemUtil; import railo.commons.io.res.Resource; import railo.commons.lang.StringUtil; import railo.runtime.exp.DatabaseException; import railo.runtime.exp.PageException; import railo.runtime.text.xml.XMLUtil; import railo.runtime.type.Collection; import railo.runtime.type.Collection.Key; import railo.runtime.type.KeyImpl; import railo.runtime.type.Query; import railo.runtime.type.QueryImpl; import railo.runtime.type.Struct; import railo.runtime.type.StructImpl; public final class RSSHandler extends DefaultHandler { public final static String DEFAULT_SAX_PARSER="org.apache.xerces.parsers.SAXParser"; private static final Key RSSLINK = KeyImpl.intern("RSSLINK"); private static final Key CONTENT = KeyImpl.intern("CONTENT"); private static final Key LINK = KeyImpl.intern("LINK"); private static final Key DESCRIPTION = KeyImpl.intern("DESCRIPTION"); private static Collection.Key[] COLUMNS=new Collection.Key[]{ KeyImpl.intern("AUTHOREMAIL"), KeyImpl.intern("AUTHORNAME"), KeyImpl.intern("AUTHORURI"), KeyImpl.intern("CATEGORYLABEL"), KeyImpl.intern("CATEGORYSCHEME"), KeyImpl.intern("CATEGORYTERM"), KeyImpl.intern("COMMENTS"), CONTENT, KeyImpl.intern("CONTENTMODE"), KeyImpl.intern("CONTENTSRC"), KeyImpl.intern("CONTENTTYPE"), KeyImpl.intern("CONTRIBUTOREMAIL"), KeyImpl.intern("CONTRIBUTORNAME"), KeyImpl.intern("CONTRIBUTORURI"), KeyImpl.intern("CREATEDDATE"), KeyImpl.intern("EXPIRATIONDATE"), KeyImpl.intern("ID"), KeyImpl.intern("IDPERMALINK"), KeyImpl.intern("LINKHREF"), KeyImpl.intern("LINKHREFLANG"), KeyImpl.intern("LINKLENGTH"), KeyImpl.intern("LINKREL"), KeyImpl.intern("LINKTITLE"), KeyImpl.intern("LINKTYPE"), KeyImpl.intern("PUBLISHEDDATE"), KeyImpl.intern("RIGHTS"), RSSLINK, KeyImpl.intern("SOURCE"), KeyImpl.intern("SOURCEURL"), KeyImpl.intern("SUMMARY"), KeyImpl.intern("SUMMARYMODE"), KeyImpl.intern("SUMMARYSRC"), KeyImpl.intern("SUMMARYTYPE"), KeyImpl.intern("TITLE"), KeyImpl.intern("TITLETYPE"), KeyImpl.intern("UPDATEDDATE"), KeyImpl.intern("URI"), KeyImpl.intern("XMLBASE") }; private XMLReader xmlReader; private String lcInside; private StringBuffer content=new StringBuffer(); private boolean insideImage; private boolean insideItem; private Struct image; private Struct properties; private Query items; private Collection.Key inside; /** * Constructor of the class * @param res * @throws IOException * @throws SAXException * @throws DatabaseException */ public RSSHandler(Resource res) throws IOException, SAXException, DatabaseException { InputStream is=null; try { InputSource source=new InputSource(is=res.getInputStream()); source.setSystemId(res.getPath()); init(DEFAULT_SAX_PARSER,source); } finally { IOUtil.closeEL(is); } } /** * Constructor of the class * @param stream * @throws IOException * @throws SAXException * @throws DatabaseException */ public RSSHandler(InputStream stream) throws IOException, SAXException, DatabaseException { InputSource is=new InputSource(IOUtil.getReader(stream, SystemUtil.getCharset())); init(DEFAULT_SAX_PARSER,is); } private void init(String saxParser,InputSource is) throws SAXException, IOException, DatabaseException { properties=new StructImpl(); items=new QueryImpl(COLUMNS,0,"query"); xmlReader=XMLUtil.createXMLReader(saxParser); xmlReader.setContentHandler(this); xmlReader.setErrorHandler(this); //xmlReader.setEntityResolver(new TagLibEntityResolver()); xmlReader.parse(is); //properties.setEL("encoding",is.getEncoding()); } public void setDocumentLocator(Locator locator) { if (locator instanceof Locator2) { Locator2 locator2 = (Locator2) locator; properties.setEL("encoding", locator2.getEncoding()); } } @Override public void startElement(String uri, String name, String qName, Attributes atts) { inside = KeyImpl.getInstance(qName); lcInside=qName.toLowerCase(); if(lcInside.equals("image")) insideImage=true; else if(qName.equals("item")) { items.addRow(); insideItem=true; } else if(lcInside.equals("rss")) { String version = atts.getValue("version"); if(!StringUtil.isEmpty(version)) properties.setEL("version", "rss_"+version); } /* / cloud else if(!insideItem && lcInside.equals("cloud")) { String url = atts.getValue("url"); if(!StringUtil.isEmpty(url))items.setAtEL("LINKHREF", items.getRowCount(), url); String length = atts.getValue("length"); if(!StringUtil.isEmpty(length))items.setAtEL("LINKLENGTH", items.getRowCount(), length); String type = atts.getValue("type"); if(!StringUtil.isEmpty(type))items.setAtEL("LINKTYPE", items.getRowCount(), type); }*/ // enclosure else if(insideItem && lcInside.equals("enclosure")) { String url = atts.getValue("url"); if(!StringUtil.isEmpty(url))items.setAtEL("LINKHREF", items.getRowCount(), url); String length = atts.getValue("length"); if(!StringUtil.isEmpty(length))items.setAtEL("LINKLENGTH", items.getRowCount(), length); String type = atts.getValue("type"); if(!StringUtil.isEmpty(type))items.setAtEL("LINKTYPE", items.getRowCount(), type); } else if(atts.getLength()>0) { int len=atts.getLength(); Struct sct=new StructImpl(); for(int i=0;i<len;i++) { sct.setEL(atts.getQName(i), atts.getValue(i)); } properties.setEL(inside, sct); } //<enclosure url="http://www.scripting.com/mp3s/weatherReportDicksPicsVol7.mp3" length="6182912" type="audio/mpeg"/> } @Override public void endElement(String uri, String name, String qName) { setContent(content.toString().trim()); content=new StringBuffer(); inside=null; lcInside=""; if(qName.equals("image")) insideImage=false; if(qName.equals("item")) insideItem=false; } @Override public void characters (char ch[], int start, int length) { content.append(new String(ch,start,length)); } private void setContent(String value) { if(StringUtil.isEmpty(lcInside)) return; if(insideImage) { if(image==null){ image=new StructImpl(); properties.setEL("image",image); } image.setEL(inside,value); } else if(insideItem) { try { items.setAt(toItemColumn(inside), items.getRowCount(), value); } catch (PageException e) { //print.err(inside); } } else { if(!(StringUtil.isEmpty(value,true) && properties.containsKey(inside))) properties.setEL(inside,value); } } private Collection.Key toItemColumn(Collection.Key key) { if(key.equalsIgnoreCase(LINK)) return RSSLINK; else if(key.equalsIgnoreCase(DESCRIPTION))return CONTENT; return key; } /** * @return the properties */ public Struct getProperties() { return properties; } /** * @return the items */ public Query getItems() { return items; } /*public static void main(String[] args) throws IOException, SAXException { ResourceProvider frp = ResourcesImpl.getFileResourceProvider(); Resource res = frp.getResource("/Users/mic/Projects/Railo/webroot/jm/feed/092.xml"); RSSHandler rss=new RSSHandler(res); print.out(rss.getProperties()); print.out(rss.getItems()); }*/ }