001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019package org.apache.wiki.rss; 020 021import java.io.IOException; 022import java.io.StringWriter; 023import java.util.ArrayList; 024import java.util.Collection; 025import java.util.Date; 026import java.util.Iterator; 027import java.util.List; 028 029import javax.servlet.ServletContext; 030 031import org.apache.commons.lang.time.DateFormatUtils; 032import org.apache.wiki.Release; 033import org.apache.wiki.WikiContext; 034import org.apache.wiki.WikiEngine; 035import org.apache.wiki.WikiPage; 036import org.apache.wiki.api.exceptions.ProviderException; 037import org.apache.wiki.attachment.Attachment; 038import org.jdom2.Element; 039import org.jdom2.Namespace; 040import org.jdom2.output.Format; 041import org.jdom2.output.XMLOutputter; 042 043/** 044 * Provides an Atom 1.0 standard feed, with enclosures. 045 * 046 */ 047public class AtomFeed extends Feed 048{ 049 private Namespace m_atomNameSpace = Namespace.getNamespace("http://www.w3.org/2005/Atom"); 050 051 /** 052 * Defines a SimpleDateFormat string for RFC3339-formatted dates. 053 */ 054 public static final String RFC3339FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZ"; 055 056 /** 057 * Create a new AtomFeed for a given WikiContext. 058 * 059 * @param c A WikiContext. 060 */ 061 public AtomFeed( WikiContext c ) 062 { 063 super(c); 064 } 065 066 /** 067 * This is a bit complicated right now, as there is no proper metadata 068 * store in JSPWiki. 069 * 070 * @return An unique feed ID. 071 */ 072 private String getFeedID() 073 { 074 return m_wikiContext.getEngine().getBaseURL(); // FIXME: This is not a feed id 075 } 076 077 private String getEntryID( Entry e ) 078 { 079 return e.getURL(); // FIXME: Not really a feed id! 080 } 081 082 private Collection<Element> getItems() 083 { 084 ArrayList<Element> list = new ArrayList<Element>(); 085 086 WikiEngine engine = m_wikiContext.getEngine(); 087 ServletContext servletContext = null; 088 089 if( m_wikiContext.getHttpRequest() != null ) 090 servletContext = m_wikiContext.getHttpRequest().getSession().getServletContext(); 091 092 for( Iterator< Entry > i = m_entries.iterator(); i.hasNext(); ) 093 { 094 Entry e = i.next(); 095 096 WikiPage p = e.getPage(); 097 098 Element entryEl = getElement("entry"); 099 100 // 101 // Mandatory elements 102 // 103 104 entryEl.addContent( getElement("id").setText( getEntryID(e)) ); 105 entryEl.addContent( getElement("title").setAttribute("type","html").setText( e.getTitle() )); 106 entryEl.addContent( getElement("updated").setText( DateFormatUtils.formatUTC(p.getLastModified(), 107 RFC3339FORMAT ))); 108 // 109 // Optional elements 110 // 111 112 entryEl.addContent( getElement("author").addContent( getElement("name").setText( e.getAuthor() ))); 113 entryEl.addContent( getElement("link").setAttribute("rel","alternate").setAttribute("href",e.getURL())); 114 entryEl.addContent( getElement("content").setAttribute("type","html").setText( e.getContent() )); 115 116 // 117 // Check for enclosures 118 // 119 120 if( engine.getAttachmentManager().hasAttachments(p) && servletContext != null ) 121 { 122 try 123 { 124 List< Attachment > c = engine.getAttachmentManager().listAttachments(p); 125 126 for( Iterator< Attachment > a = c.iterator(); a.hasNext(); ) 127 { 128 Attachment att = a.next(); 129 130 Element attEl = getElement("link"); 131 attEl.setAttribute( "rel","enclosure" ); 132 attEl.setAttribute( "href", engine.getURL(WikiContext.ATTACH, att.getName(), null, true ) ); 133 attEl.setAttribute( "length", Long.toString(att.getSize()) ); 134 attEl.setAttribute( "type", getMimeType( servletContext, att.getFileName() ) ); 135 136 entryEl.addContent( attEl ); 137 } 138 } 139 catch( ProviderException ex ) 140 { 141 // FIXME: log.info("Can't get attachment data",ex); 142 } 143 } 144 145 146 list.add( entryEl ); 147 } 148 149 return list; 150 } 151 152 /** 153 * {@inheritDoc} 154 */ 155 @Override 156 public String getString() 157 { 158 Element root = getElement("feed"); 159 WikiEngine engine = m_wikiContext.getEngine(); 160 161 Date lastModified = new Date(0L); 162 163 for( Iterator< Entry > i = m_entries.iterator(); i.hasNext(); ) 164 { 165 Entry e = i.next(); 166 167 if( e.getPage().getLastModified().after(lastModified) ) 168 lastModified = e.getPage().getLastModified(); 169 } 170 171 // 172 // Mandatory parts 173 // 174 root.addContent( getElement("title").setText( getChannelTitle() ) ); 175 root.addContent( getElement("id").setText(getFeedID()) ); 176 root.addContent( getElement("updated").setText(DateFormatUtils.formatUTC( lastModified, 177 RFC3339FORMAT ) )); 178 179 // 180 // Optional 181 // 182 // root.addContent( getElement("author").addContent(getElement("name").setText(format()))) 183 root.addContent( getElement("link").setAttribute("href",engine.getBaseURL())); 184 root.addContent( getElement("generator").setText("JSPWiki "+Release.VERSTR)); 185 186 String rssFeedURL = engine.getURL(WikiContext.NONE, "rss.jsp", 187 "page="+engine.encodeName(m_wikiContext.getPage().getName())+ 188 "&mode="+m_mode+ 189 "&type=atom", 190 true ); 191 Element self = getElement("link").setAttribute("rel","self"); 192 self.setAttribute("href",rssFeedURL); 193 root.addContent(self); 194 195 // 196 // Items 197 // 198 199 root.addContent( getItems() ); 200 201 // 202 // aaand output 203 // 204 XMLOutputter output = new XMLOutputter(); 205 206 output.setFormat( Format.getPrettyFormat() ); 207 208 try 209 { 210 StringWriter res = new StringWriter(); 211 output.output( root, res ); 212 213 return res.toString(); 214 } 215 catch( IOException e ) 216 { 217 return null; 218 } 219 } 220 221 private Element getElement( String name ) 222 { 223 return new Element( name, m_atomNameSpace ); 224 } 225}