001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.servlet.view.feed; 018 019import java.io.OutputStreamWriter; 020import java.util.Map; 021 022import javax.servlet.ServletOutputStream; 023import javax.servlet.http.HttpServletRequest; 024import javax.servlet.http.HttpServletResponse; 025 026import com.rometools.rome.feed.WireFeed; 027import com.rometools.rome.io.WireFeedOutput; 028 029import org.springframework.util.StringUtils; 030import org.springframework.web.servlet.view.AbstractView; 031 032/** 033 * Abstract base class for Atom and RSS Feed views, using the 034 * <a href="https://github.com/rometools/rome">ROME</a> package. 035 * 036 * <p>><b>NOTE: As of Spring 4.1, this is based on the {@code com.rometools} 037 * variant of ROME, version 1.5. Please upgrade your build dependency.</b> 038 * 039 * <p>Application-specific view classes will typically extend from either 040 * {@link AbstractRssFeedView} or {@link AbstractAtomFeedView} instead of from this class. 041 * 042 * <p>Thanks to Jettro Coenradie and Sergio Bossa for the original feed view prototype! 043 * 044 * @author Arjen Poutsma 045 * @author Juergen Hoeller 046 * @since 3.0 047 * @param <T> the {@link WireFeed} type 048 * @see AbstractRssFeedView 049 * @see AbstractAtomFeedView 050 */ 051public abstract class AbstractFeedView<T extends WireFeed> extends AbstractView { 052 053 @Override 054 protected final void renderMergedOutputModel( 055 Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) 056 throws Exception { 057 058 T wireFeed = newFeed(); 059 buildFeedMetadata(model, wireFeed, request); 060 buildFeedEntries(model, wireFeed, request, response); 061 062 setResponseContentType(request, response); 063 if (!StringUtils.hasText(wireFeed.getEncoding())) { 064 wireFeed.setEncoding("UTF-8"); 065 } 066 067 WireFeedOutput feedOutput = new WireFeedOutput(); 068 ServletOutputStream out = response.getOutputStream(); 069 feedOutput.output(wireFeed, new OutputStreamWriter(out, wireFeed.getEncoding())); 070 out.flush(); 071 } 072 073 /** 074 * Create a new feed to hold the entries. 075 * @return the newly created Feed instance 076 */ 077 protected abstract T newFeed(); 078 079 /** 080 * Populate the feed metadata (title, link, description, etc.). 081 * <p>Default is an empty implementation. Subclasses can override this method 082 * to add meta fields such as title, link description, etc. 083 * @param model the model, in case meta information must be populated from it 084 * @param feed the feed being populated 085 * @param request in case we need locale etc. Shouldn't look at attributes. 086 */ 087 protected void buildFeedMetadata(Map<String, Object> model, T feed, HttpServletRequest request) { 088 } 089 090 /** 091 * Subclasses must implement this method to build feed entries, given the model. 092 * <p>Note that the passed-in HTTP response is just supposed to be used for 093 * setting cookies or other HTTP headers. The built feed itself will automatically 094 * get written to the response after this method returns. 095 * @param model the model Map 096 * @param feed the feed to add entries to 097 * @param request in case we need locale etc. Shouldn't look at attributes. 098 * @param response in case we need to set cookies. Shouldn't write to it. 099 * @throws Exception any exception that occurred during building 100 */ 101 protected abstract void buildFeedEntries(Map<String, Object> model, T feed, 102 HttpServletRequest request, HttpServletResponse response) throws Exception; 103 104}