001/* 002 * Copyright 2002-2017 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.http.converter.feed; 018 019import java.io.IOException; 020import java.io.InputStreamReader; 021import java.io.OutputStreamWriter; 022import java.io.Reader; 023import java.io.Writer; 024import java.nio.charset.Charset; 025 026import com.rometools.rome.feed.WireFeed; 027import com.rometools.rome.io.FeedException; 028import com.rometools.rome.io.WireFeedInput; 029import com.rometools.rome.io.WireFeedOutput; 030 031import org.springframework.http.HttpInputMessage; 032import org.springframework.http.HttpOutputMessage; 033import org.springframework.http.MediaType; 034import org.springframework.http.converter.AbstractHttpMessageConverter; 035import org.springframework.http.converter.HttpMessageNotReadableException; 036import org.springframework.http.converter.HttpMessageNotWritableException; 037import org.springframework.util.StringUtils; 038 039/** 040 * Abstract base class for Atom and RSS Feed message converters, using the 041 * <a href="https://github.com/rometools/rome">ROME tools</a> project. 042 * 043 * <p>><b>NOTE: As of Spring 4.1, this is based on the {@code com.rometools} 044 * variant of ROME, version 1.5. Please upgrade your build dependency.</b> 045 * 046 * @author Arjen Poutsma 047 * @since 3.0.2 048 * @see AtomFeedHttpMessageConverter 049 * @see RssChannelHttpMessageConverter 050 */ 051public abstract class AbstractWireFeedHttpMessageConverter<T extends WireFeed> extends AbstractHttpMessageConverter<T> { 052 053 public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 054 055 056 protected AbstractWireFeedHttpMessageConverter(MediaType supportedMediaType) { 057 super(supportedMediaType); 058 } 059 060 061 @Override 062 @SuppressWarnings("unchecked") 063 protected T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage) 064 throws IOException, HttpMessageNotReadableException { 065 066 WireFeedInput feedInput = new WireFeedInput(); 067 MediaType contentType = inputMessage.getHeaders().getContentType(); 068 Charset charset = (contentType != null && contentType.getCharset() != null ? 069 contentType.getCharset() : DEFAULT_CHARSET); 070 try { 071 Reader reader = new InputStreamReader(inputMessage.getBody(), charset); 072 return (T) feedInput.build(reader); 073 } 074 catch (FeedException ex) { 075 throw new HttpMessageNotReadableException("Could not read WireFeed: " + ex.getMessage(), ex); 076 } 077 } 078 079 @Override 080 protected void writeInternal(T wireFeed, HttpOutputMessage outputMessage) 081 throws IOException, HttpMessageNotWritableException { 082 083 Charset charset = (StringUtils.hasLength(wireFeed.getEncoding()) ? 084 Charset.forName(wireFeed.getEncoding()) : DEFAULT_CHARSET); 085 MediaType contentType = outputMessage.getHeaders().getContentType(); 086 if (contentType != null) { 087 contentType = new MediaType(contentType.getType(), contentType.getSubtype(), charset); 088 outputMessage.getHeaders().setContentType(contentType); 089 } 090 091 WireFeedOutput feedOutput = new WireFeedOutput(); 092 try { 093 Writer writer = new OutputStreamWriter(outputMessage.getBody(), charset); 094 feedOutput.output(wireFeed, writer); 095 } 096 catch (FeedException ex) { 097 throw new HttpMessageNotWritableException("Could not write WireFeed: " + ex.getMessage(), ex); 098 } 099 } 100 101}