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}