001package org.apache.commons.digester3.rss; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020import java.io.File; 021import java.io.IOException; 022import java.io.InputStream; 023 024import org.apache.commons.digester3.Digester; 025import org.apache.commons.logging.LogFactory; 026import org.xml.sax.InputSource; 027import org.xml.sax.SAXException; 028 029 030/** 031 * <p>Implementation of <strong>org.apache.commons.digester3.Digester</strong> 032 * designed to process input streams that conform to the <em>Rich Site 033 * Summary</em> DTD, version 0.91. For more information about this format, 034 * see the <a href="http://my.netscape.com/publish/">My Netscape</a> site.</p> 035 * 036 * <p>The default implementation object returned by calling 037 * <code>parse()</code> (an instance of 038 * <code>org.apache.commons.digester3.rss.Channel</code>) 039 * knows how to render itself in XML format via the <code>render()</code> 040 * method. See the test <code>main()</code> method below for an 041 * example of using these classes.</p> 042 */ 043 044public class RSSDigester 045 extends Digester 046{ 047 048 // ----------------------------------------------------------- Constructors 049 050 // ----------------------------------------------------- Instance Variables 051 052 /** 053 * Have we been configured yet? 054 */ 055 protected boolean configured = false; 056 057 // ------------------------------------------------------------- Properties 058 059 /** 060 * The fully qualified class name of the <code>Channel</code> 061 * implementation class. 062 */ 063 protected String channelClass = "org.apache.commons.digester3.rss.Channel"; 064 065 public String getChannelClass() 066 { 067 return ( this.channelClass ); 068 } 069 070 public void setChannelClass( String channelClass ) 071 { 072 this.channelClass = channelClass; 073 } 074 075 /** 076 * The fully qualified class name of the <code>Image</code> 077 * implementation class. 078 */ 079 protected String imageClass = "org.apache.commons.digester3.rss.Image"; 080 081 public String getImageClass() 082 { 083 return ( this.imageClass ); 084 } 085 086 public void setImageClass( String imageClass ) 087 { 088 this.imageClass = imageClass; 089 } 090 091 /** 092 * The fully qualified class name of the <code>Item</code> 093 * implementation class. 094 */ 095 protected String itemClass = "org.apache.commons.digester3.rss.Item"; 096 097 public String getItemClass() 098 { 099 return ( this.itemClass ); 100 } 101 102 public void setItemClass( String itemClass ) 103 { 104 this.itemClass = itemClass; 105 } 106 107 /** 108 * The fully qualified class name of the <code>TextInput</code> 109 * implementation class. 110 */ 111 protected String textInputClass = "org.apache.commons.digester3.rss.TextInput"; 112 113 public String getTextInputClass() 114 { 115 return ( this.textInputClass ); 116 } 117 118 public void setTextInputClass( String textInputClass ) 119 { 120 this.textInputClass = textInputClass; 121 } 122 123 // --------------------------------------------------------- Public Methods 124 125 /** 126 * Parse the content of the specified file using this Digester. Returns 127 * the root element from the object stack (which will be the Channel). 128 * 129 * @param file File containing the XML data to be parsed 130 * 131 * @exception IOException if an input/output error occurs 132 * @exception SAXException if a parsing exception occurs 133 */ 134 @Override 135 public <T> T parse( File file ) 136 throws IOException, SAXException 137 { 138 configure(); 139 return ( super.<T>parse( file ) ); 140 } 141 142 /** 143 * Parse the content of the specified input source using this Digester. 144 * Returns the root element from the object stack (which will be the 145 * Channel). 146 * 147 * @param input Input source containing the XML data to be parsed 148 * 149 * @exception IOException if an input/output error occurs 150 * @exception SAXException if a parsing exception occurs 151 */ 152 @Override 153 public <T> T parse( InputSource input ) 154 throws IOException, SAXException 155 { 156 configure(); 157 return ( super.<T>parse( input ) ); 158 } 159 160 161 /** 162 * Parse the content of the specified input stream using this Digester. 163 * Returns the root element from the object stack (which will be 164 * the Channel). 165 * 166 * @param input Input stream containing the XML data to be parsed 167 * 168 * @exception IOException if an input/output error occurs 169 * @exception SAXException if a parsing exception occurs 170 */ 171 @Override 172 public <T> T parse( InputStream input ) 173 throws IOException, SAXException 174 { 175 configure(); 176 return ( super.<T>parse( input ) ); 177 } 178 179 /** 180 * Parse the content of the specified URI using this Digester. 181 * Returns the root element from the object stack (which will be 182 * the Channel). 183 * 184 * @param uri URI containing the XML data to be parsed 185 * 186 * @exception IOException if an input/output error occurs 187 * @exception SAXException if a parsing exception occurs 188 */ 189 @Override 190 public <T> T parse( String uri ) 191 throws IOException, SAXException 192 { 193 configure(); 194 return ( super.<T>parse( uri ) ); 195 } 196 197 // -------------------------------------------------------- Package Methods 198 199 // ------------------------------------------------------ Protected Methods 200 201 /** 202 * Configure the parsing rules that will be used to process RSS input. 203 */ 204 @Override 205 protected void configure() 206 { 207 if ( configured ) 208 { 209 return; 210 } 211 212 // FIXME - validate the "version" attribute of the rss element? 213 214 // Add the rules for the Channel object 215 addObjectCreate( "rss/channel", channelClass ); 216 addCallMethod( "rss/channel/copyright", "setCopyright", 0 ); 217 addCallMethod( "rss/channel/description", "setDescription", 0 ); 218 addCallMethod( "rss/channel/docs", "setDocs", 0 ); 219 addCallMethod( "rss/channel/language", "setLanguage", 0 ); 220 addCallMethod( "rss/channel/lastBuildDate", "setLastBuildDate", 0 ); 221 addCallMethod( "rss/channel/link", "setLink", 0 ); 222 addCallMethod( "rss/channel/managingEditor", "setManagingEditor", 0 ); 223 addCallMethod( "rss/channel/pubDate", "setPubDate", 0 ); 224 addCallMethod( "rss/channel/rating", "setRating", 0 ); 225 addCallMethod( "rss/channel/skipDays/day", "addSkipDay", 0 ); 226 addCallMethod( "rss/channel/skipHours/hour", "addSkipHour", 0 ); 227 addCallMethod( "rss/channel/title", "setTitle", 0 ); 228 addCallMethod( "rss/channel/webMaster", "setWebMaster", 0 ); 229 230 // Add the rules for the Image object 231 addObjectCreate( "rss/channel/image", imageClass ); 232 addSetNext( "rss/channel/image", "setImage", "org.apache.commons.digester3.rss.Image" ); 233 addCallMethod( "rss/channel/image/description", "setDescription", 0 ); 234 addCallMethod( "rss/channel/image/height", "setHeight", 0, new Class[] { Integer.TYPE } ); 235 addCallMethod( "rss/channel/image/link", "setLink", 0 ); 236 addCallMethod( "rss/channel/image/title", "setTitle", 0 ); 237 addCallMethod( "rss/channel/image/url", "setURL", 0 ); 238 addCallMethod( "rss/channel/image/width", "setWidth", 0, new Class[] { Integer.TYPE } ); 239 240 // Add the rules for the Item object 241 addObjectCreate( "rss/channel/item", itemClass ); 242 addSetNext( "rss/channel/item", "addItem", "org.apache.commons.digester3.rss.Item" ); 243 addCallMethod( "rss/channel/item/description", "setDescription", 0 ); 244 addCallMethod( "rss/channel/item/link", "setLink", 0 ); 245 addCallMethod( "rss/channel/item/title", "setTitle", 0 ); 246 247 // Add the rules for the TextInput object 248 addObjectCreate( "rss/channel/textinput", textInputClass ); 249 addSetNext( "rss/channel/textinput", "setTextInput", "org.apache.commons.digester3.rss.TextInput" ); 250 addCallMethod( "rss/channel/textinput/description", "setDescription", 0 ); 251 addCallMethod( "rss/channel/textinput/link", "setLink", 0 ); 252 addCallMethod( "rss/channel/textinput/name", "setName", 0 ); 253 addCallMethod( "rss/channel/textinput/title", "setTitle", 0 ); 254 255 // Mark this digester as having been configured 256 configured = true; 257 } 258 259 // ------------------------------------------------------ Test Main Program 260 261 /** 262 * Test main program that parses the channel description included in this 263 * package as a static resource. 264 * 265 * @param args The command line arguments (ignored) 266 */ 267 public static void main( String args[] ) 268 { 269 try 270 { 271 System.out.println( "RSSDigester Test Program" ); 272 System.out.println( "Opening input stream ..." ); 273 InputStream is = 274 RSSDigester.class.getResourceAsStream( "/org/apache/commons/digester3/rss/rss-example.xml" ); 275 System.out.println( "Creating new digester ..." ); 276 RSSDigester digester = new RSSDigester(); 277 if ( ( args.length > 0 ) && ( args[0].equals( "-debug" ) ) ) 278 { 279 digester.setLogger( LogFactory.getLog( "RSSDigester" ) ); 280 } 281 System.out.println( "Parsing input stream ..." ); 282 Channel channel = (Channel) digester.parse( is ); 283 System.out.println( "Closing input stream ..." ); 284 is.close(); 285 System.out.println( "Dumping channel info ..." ); 286 channel.render( System.out ); 287 } 288 catch ( Exception e ) 289 { 290 System.out.println( "-->Exception" ); 291 e.printStackTrace( System.out ); 292 } 293 } 294 295}