001/*
002 * Copyright 2002-2014 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.mock.web.portlet;
018
019import java.io.ByteArrayOutputStream;
020import java.io.IOException;
021import java.io.OutputStream;
022import java.io.OutputStreamWriter;
023import java.io.PrintWriter;
024import java.io.UnsupportedEncodingException;
025import java.io.Writer;
026import java.util.Collections;
027import java.util.Enumeration;
028import java.util.Locale;
029import javax.portlet.CacheControl;
030import javax.portlet.MimeResponse;
031import javax.portlet.PortalContext;
032import javax.portlet.PortletRequest;
033import javax.portlet.PortletURL;
034import javax.portlet.ResourceURL;
035
036import org.springframework.util.CollectionUtils;
037import org.springframework.web.util.WebUtils;
038
039/**
040 * Mock implementation of the {@link javax.portlet.MimeResponse} interface.
041 *
042 * @author Juergen Hoeller
043 * @since 3.0
044 */
045public class MockMimeResponse extends MockPortletResponse implements MimeResponse {
046
047        private PortletRequest request;
048
049        private String contentType;
050
051        private String characterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING;
052
053        private PrintWriter writer;
054
055        private Locale locale = Locale.getDefault();
056
057        private int bufferSize = 4096;
058
059        private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
060
061        private final CacheControl cacheControl = new MockCacheControl();
062
063        private boolean committed;
064
065        private String includedUrl;
066
067        private String forwardedUrl;
068
069
070        /**
071         * Create a new MockMimeResponse with a default {@link MockPortalContext}.
072         * @see org.springframework.mock.web.portlet.MockPortalContext
073         */
074        public MockMimeResponse() {
075                super();
076        }
077
078        /**
079         * Create a new MockMimeResponse.
080         * @param portalContext the PortalContext defining the supported
081         * PortletModes and WindowStates
082         */
083        public MockMimeResponse(PortalContext portalContext) {
084                super(portalContext);
085        }
086
087        /**
088         * Create a new MockMimeResponse.
089         * @param portalContext the PortalContext defining the supported
090         * PortletModes and WindowStates
091         * @param request the corresponding render/resource request that this response
092         * is being generated for
093         */
094        public MockMimeResponse(PortalContext portalContext, PortletRequest request) {
095                super(portalContext);
096                this.request = request;
097        }
098
099
100        //---------------------------------------------------------------------
101        // RenderResponse methods
102        //---------------------------------------------------------------------
103
104        @Override
105        public void setContentType(String contentType) {
106                if (this.request != null) {
107                        Enumeration<String> supportedTypes = this.request.getResponseContentTypes();
108                        if (!CollectionUtils.contains(supportedTypes, contentType)) {
109                                throw new IllegalArgumentException("Content type [" + contentType + "] not in supported list: " +
110                                                Collections.list(supportedTypes));
111                        }
112                }
113                this.contentType = contentType;
114        }
115
116        @Override
117        public String getContentType() {
118                return this.contentType;
119        }
120
121        public void setCharacterEncoding(String characterEncoding) {
122                this.characterEncoding = characterEncoding;
123        }
124
125        @Override
126        public String getCharacterEncoding() {
127                return this.characterEncoding;
128        }
129
130        @Override
131        public PrintWriter getWriter() throws UnsupportedEncodingException {
132                if (this.writer == null) {
133                        Writer targetWriter = (this.characterEncoding != null ?
134                                        new OutputStreamWriter(this.outputStream, this.characterEncoding) :
135                                        new OutputStreamWriter(this.outputStream));
136                        this.writer = new PrintWriter(targetWriter);
137                }
138                return this.writer;
139        }
140
141        public byte[] getContentAsByteArray() {
142                flushBuffer();
143                return this.outputStream.toByteArray();
144        }
145
146        public String getContentAsString() throws UnsupportedEncodingException {
147                flushBuffer();
148                return (this.characterEncoding != null ?
149                                this.outputStream.toString(this.characterEncoding) : this.outputStream.toString());
150        }
151
152        public void setLocale(Locale locale) {
153                this.locale = locale;
154        }
155
156        @Override
157        public Locale getLocale() {
158                return this.locale;
159        }
160
161        @Override
162        public void setBufferSize(int bufferSize) {
163                this.bufferSize = bufferSize;
164        }
165
166        @Override
167        public int getBufferSize() {
168                return this.bufferSize;
169        }
170
171        @Override
172        public void flushBuffer() {
173                if (this.writer != null) {
174                        this.writer.flush();
175                }
176                try {
177                        this.outputStream.flush();
178                }
179                catch (IOException ex) {
180                        throw new IllegalStateException("Could not flush OutputStream: " + ex.getMessage());
181                }
182                this.committed = true;
183        }
184
185        @Override
186        public void resetBuffer() {
187                if (this.committed) {
188                        throw new IllegalStateException("Cannot reset buffer - response is already committed");
189                }
190                this.outputStream.reset();
191        }
192
193        public void setCommitted(boolean committed) {
194                this.committed = committed;
195        }
196
197        @Override
198        public boolean isCommitted() {
199                return this.committed;
200        }
201
202        @Override
203        public void reset() {
204                resetBuffer();
205                this.characterEncoding = null;
206                this.contentType = null;
207                this.locale = null;
208        }
209
210        @Override
211        public OutputStream getPortletOutputStream() throws IOException {
212                return this.outputStream;
213        }
214
215        @Override
216        public PortletURL createRenderURL() {
217                return new MockPortletURL(getPortalContext(), MockPortletURL.URL_TYPE_RENDER);
218        }
219
220        @Override
221        public PortletURL createActionURL() {
222                return new MockPortletURL(getPortalContext(), MockPortletURL.URL_TYPE_ACTION);
223        }
224
225        @Override
226        public ResourceURL createResourceURL() {
227                return new MockResourceURL();
228        }
229
230        @Override
231        public CacheControl getCacheControl() {
232                return this.cacheControl;
233        }
234
235
236        //---------------------------------------------------------------------
237        // Methods for MockPortletRequestDispatcher
238        //---------------------------------------------------------------------
239
240        public void setIncludedUrl(String includedUrl) {
241                this.includedUrl = includedUrl;
242        }
243
244        public String getIncludedUrl() {
245                return this.includedUrl;
246        }
247
248        public void setForwardedUrl(String forwardedUrl) {
249                this.forwardedUrl = forwardedUrl;
250        }
251
252        public String getForwardedUrl() {
253                return this.forwardedUrl;
254        }
255
256}