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 */
019 package org.apache.wiki.rss;
020
021 import java.io.IOException;
022 import java.io.StringWriter;
023 import java.util.ArrayList;
024 import java.util.Collection;
025 import java.util.Date;
026 import java.util.Iterator;
027
028 import javax.servlet.ServletContext;
029
030 import org.apache.commons.lang.time.DateFormatUtils;
031 import org.jdom2.Element;
032 import org.jdom2.Namespace;
033 import org.jdom2.output.Format;
034 import org.jdom2.output.XMLOutputter;
035 import org.apache.wiki.Release;
036 import org.apache.wiki.WikiContext;
037 import org.apache.wiki.WikiEngine;
038 import org.apache.wiki.WikiPage;
039 import org.apache.wiki.api.exceptions.ProviderException;
040 import org.apache.wiki.attachment.Attachment;
041
042 /**
043 * Provides an Atom 1.0 standard feed, with enclosures.
044 *
045 */
046 public 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 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 i = m_entries.iterator(); i.hasNext(); )
092 {
093 Entry e = (Entry)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 Collection c = engine.getAttachmentManager().listAttachments(p);
124
125 for( Iterator a = c.iterator(); a.hasNext(); )
126 {
127 Attachment att = (Attachment) 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 i = m_entries.iterator(); i.hasNext(); )
163 {
164 Entry e = (Entry)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 }