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