001 /* 002 * Copyright 1999,2004 The Apache Software Foundation. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.apache.commons.feedparser; 018 019 import java.util.Date; 020 021 import org.apache.commons.feedparser.tools.ISO8601DateParser; 022 import org.apache.commons.feedparser.tools.RFC822DateParser; 023 import org.jdom.Element; 024 import org.jdom.Namespace; 025 026 /** 027 * Handles parsing RSS metadata including dates 028 * 029 * @author <a href="mailto:burton@apache.org">Kevin A. Burton (burtonator)</a> 030 * @version $Id: MetaFeedParser.java 373879 2006-01-31 17:23:15Z mvdb $ 031 */ 032 public class MetaFeedParser extends BaseParser { 033 034 /** 035 * 036 */ 037 public static void parse( FeedParserListener listener, 038 FeedParserState state ) throws FeedParserException { 039 040 //FIXME: this should be refactored into a new class called 041 //MetaFeedParser to be used by both Atom and RSS. Also the date 042 //handling below needs to be generic. 043 044 if ( listener instanceof MetaFeedParserListener == false ) 045 return; 046 047 MetaFeedParserListener mfp = (MetaFeedParserListener)listener; 048 049 parseDate( state, mfp ); 050 051 //FIXME: make sure RSS .9 is working and 0.91. I just need to confirm 052 //but I think they are working correctly 053 parseGUID( state, mfp ); 054 055 parseAuthor( state, mfp ); 056 057 parseComments( state, mfp ); 058 059 parseCommentsFeed( state, mfp ); 060 061 } 062 063 private static void parseComments( FeedParserState state, 064 MetaFeedParserListener listener ) 065 throws FeedParserException { 066 067 Element element = state.current.getChild( "comments" ); 068 069 if ( element != null ) { 070 071 String resource = element.getText(); 072 listener.onComments( state, resource ); 073 listener.onCommentsEnd(); 074 075 } 076 077 } 078 079 private static void parseCommentsFeed( FeedParserState state, 080 MetaFeedParserListener listener ) 081 throws FeedParserException { 082 083 Element element = state.current.getChild( "commentRSS", NS.WFW ); 084 085 if ( element != null ) { 086 087 String resource = element.getText(); 088 listener.onCommentsFeed( state, resource ); 089 listener.onCommentsFeedEnd(); 090 091 } 092 093 } 094 095 private static void parseAuthor( FeedParserState state, 096 MetaFeedParserListener listener ) 097 throws FeedParserException { 098 099 Element element = null; 100 101 String name = null; 102 String email = null; 103 String resource = null; 104 105 try { 106 107 //atom:author 108 109 element = state.current.getChild( "author", NS.ATOM ); 110 111 if ( element != null ) { 112 name = selectText( "atom:name", element ); 113 email = selectText( "atom:email", element ); 114 resource = selectText( "atom:uri", element ); 115 } 116 117 //dc:creator (RSS 1.0) 118 element = state.current.getChild( "creator", NS.DC ); 119 120 if ( element != null ) 121 name = element.getText(); 122 123 //author (RSS 2.0) 124 element = state.current.getChild( "author" ); 125 126 if ( element != null ) 127 name = element.getText(); 128 129 if ( name != null && ! "".equals( name ) ) { 130 131 listener.onAuthor( state, 132 name, 133 email, 134 resource ); 135 136 listener.onAuthorEnd(); 137 138 } 139 140 } catch ( Exception e ) { 141 throw new FeedParserException( e ); 142 } 143 144 } 145 146 private static void parseGUID( FeedParserState state, 147 MetaFeedParserListener listener ) 148 throws FeedParserException { 149 150 Element id = null; 151 152 String guid = null; 153 boolean isPermalink = false; 154 155 id = state.current.getChild( "id", NS.ATOM ); 156 157 if ( id != null ) { 158 guid = id.getText(); 159 } 160 161 id = state.current.getChild( "guid" ); 162 163 if ( id != null ) { 164 165 guid = id.getText(); 166 isPermalink = "true".equals( id.getAttributeValue( "isPermalink" ) ); 167 168 } 169 170 if ( guid != null ) { 171 172 listener.onGUID( state, 173 guid, 174 isPermalink ); 175 176 listener.onGUIDEnd(); 177 178 } 179 180 } 181 182 private static void parseDate( FeedParserState state, 183 MetaFeedParserListener listener ) 184 throws FeedParserException { 185 186 if ( parseDate( "date", NS.DC, listener, state ) ) 187 return; 188 189 // http://www.mnot.net/drafts/draft-nottingham-atom-format-02.html#rfc.section.4.13.8 190 // 191 // The "atom:created" element is a Date construct that indicates the 192 // time that the entry was created. atom:entry elements MAY contain 193 // an atom:created element, but MUST NOT contain more than one. 194 195 // The content of an atom:created element MUST have a time zone 196 // whose value SHOULD be "UTC". 197 198 if ( parseDate( "created", NS.ATOM, listener, state ) ) 199 return; 200 201 // http://www.mnot.net/drafts/draft-nottingham-atom-format-02.html#rfc.section.4.13.8 202 // 203 // If atom:created is not present, its content MUST considered to be 204 // the same as that of atom:modified. 205 206 if ( parseDate( "modified", NS.ATOM, listener, state ) ) 207 return; 208 209 //support RSS 2.0 and RSS 0.9x dates. 210 211 if ( parseDate( "pubDate", null, listener, state, false ) ) 212 return; 213 214 } 215 216 private static boolean parseDate( String name, 217 Namespace ns, 218 MetaFeedParserListener listener, 219 FeedParserState state ) { 220 221 return parseDate( name, ns, listener, state, true ); 222 223 } 224 225 private static boolean parseDate( String name, 226 Namespace ns, 227 MetaFeedParserListener listener, 228 FeedParserState state, 229 boolean ISO8601 ) { 230 try { 231 //ok. Support dc:date 232 String v = state.current.getChildText( name, ns ); 233 234 if ( v != null ) { 235 236 Date d = null; 237 if ( ISO8601 ) { 238 d = ISO8601DateParser.parse( v ); 239 } else { 240 d = RFC822DateParser.parse( v ); 241 } 242 243 listener.onCreated( state, d ); 244 listener.onCreatedEnd(); 245 246 return true; 247 } 248 } catch ( Throwable t ) { 249 // ignore the exception, so we can just move on 250 } 251 252 return false; 253 254 } 255 256 }