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.wiki.api.Release; 022import org.apache.wiki.api.core.Attachment; 023import org.apache.wiki.api.core.Context; 024import org.apache.wiki.api.core.ContextEnum; 025import org.apache.wiki.api.core.Engine; 026import org.apache.wiki.api.core.Page; 027import org.apache.wiki.api.exceptions.ProviderException; 028import org.apache.wiki.attachment.AttachmentManager; 029import org.apache.wiki.variables.VariableManager; 030import org.jdom2.Element; 031import org.jdom2.output.Format; 032import org.jdom2.output.XMLOutputter; 033 034import jakarta.servlet.ServletContext; 035import java.io.IOException; 036import java.io.StringWriter; 037import java.text.SimpleDateFormat; 038import java.util.ArrayList; 039import java.util.Calendar; 040import java.util.List; 041import org.apache.logging.log4j.LogManager; 042import org.apache.logging.log4j.Logger; 043import org.apache.wiki.util.HttpUtil; 044 045/** 046 * Represents an RSS 2.0 feed (with enclosures). This feed provides no 047 * fizz-bang features. 048 * 049 * @since 2.2.27 050 */ 051public class RSS20Feed extends Feed 052{ 053 private static final Logger LOG = LogManager.getLogger( RSS20Feed.class ); 054 055 /** 056 * Creates an RSS 2.0 feed for the specified Context. 057 * 058 * @param context The WikiContext. 059 */ 060 public RSS20Feed( final Context context ) 061 { 062 super( context ); 063 } 064 065 private List<Element> getItems() 066 { 067 final ArrayList<Element> list = new ArrayList<>(); 068 final SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'"); 069 070 final Engine engine = m_wikiContext.getEngine(); 071 ServletContext servletContext = null; 072 073 if( m_wikiContext.getHttpRequest() != null ) 074 servletContext = m_wikiContext.getHttpRequest().getSession().getServletContext(); 075 076 for( final Entry e : m_entries ) { 077 final Page p = e.getPage(); 078 final String url = e.getURL(); 079 final Element item = new Element( "item" ); 080 //FIXME this needs to be an absolute url, not a relative one 081 item.addContent( new Element( "link" ).setText( url ) ); 082 item.addContent( new Element( "title" ).setText( e.getTitle() ) ); 083 item.addContent( new Element( "description" ).setText( e.getContent() ) ); 084 085 // 086 // Attachments for enclosures 087 // 088 if( engine.getManager( AttachmentManager.class ).hasAttachments( p ) && servletContext != null ) { 089 try { 090 final List< Attachment > c = engine.getManager( AttachmentManager.class ).listAttachments( p ); 091 for( final Attachment att : c ) { 092 final Element attEl = new Element( "enclosure" ); 093 attEl.setAttribute( "url", engine.getURL( ContextEnum.PAGE_ATTACH.getRequestContext(), att.getName(), null ) ); 094 attEl.setAttribute( "length", Long.toString( att.getSize() ) ); 095 attEl.setAttribute( "type", getMimeType( servletContext, att.getFileName() ) ); 096 097 item.addContent( attEl ); 098 } 099 } catch( final ProviderException ex ) { 100 LOG.info("Can't get attachment data",ex); 101 } 102 } 103 104 // 105 // Modification date. 106 // 107 final Calendar cal = Calendar.getInstance(); 108 cal.setTime( p.getLastModified() ); 109 cal.add( Calendar.MILLISECOND, -( cal.get( Calendar.ZONE_OFFSET ) + ( cal.getTimeZone().inDaylightTime( p.getLastModified() ) ? 110 cal.get( Calendar.DST_OFFSET ) : 111 0 ) ) ); 112 113 item.addContent( new Element( "pubDate" ).setText( fmt.format( cal.getTime() ) ) ); 114 115 list.add( item ); 116 } 117 118 return list; 119 } 120 121 /** 122 * {@inheritDoc} 123 */ 124 @Override 125 public String getString() 126 { 127 final Engine engine = m_wikiContext.getEngine(); 128 final Element root = new Element("rss"); 129 root.setAttribute("version","2.0"); 130 131 final Element channel = new Element("channel"); 132 root.addContent( channel ); 133 134 // 135 // Mandatory parts 136 // 137 channel.addContent( new Element("title").setText( getChannelTitle() ) ); 138 channel.addContent( new Element("link").setText(HttpUtil.getAbsoluteUrl(m_wikiContext.getHttpRequest(), engine.getBaseURL()))); 139 channel.addContent( new Element("description").setText( getChannelDescription() )); 140 141 // 142 // Optional 143 // 144 channel.addContent( new Element("language").setText(getChannelLanguage())); 145 channel.addContent( new Element("generator").setText("JSPWiki "+Release.VERSTR)); 146 147 String mail = engine.getManager( VariableManager.class ).getVariable(m_wikiContext,RSSGenerator.PROP_RSS_AUTHOREMAIL); 148 if( mail != null ) 149 { 150 final String editor = engine.getManager( VariableManager.class ).getVariable( m_wikiContext,RSSGenerator.PROP_RSS_AUTHOR ); 151 152 if( editor != null ) 153 mail = mail + " ("+editor+")"; 154 155 channel.addContent( new Element("managingEditor").setText(mail) ); 156 } 157 158 // 159 // Items 160 // 161 162 channel.addContent( getItems() ); 163 164 // 165 // aaand output 166 // 167 final XMLOutputter output = new XMLOutputter(); 168 169 output.setFormat( Format.getPrettyFormat() ); 170 171 try { 172 final StringWriter res = new StringWriter(); 173 output.output( root, res ); 174 175 return res.toString(); 176 } catch( final IOException e ) { 177 LOG.debug(e.getMessage(), e); 178 return null; 179 } 180 } 181 182}