    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}