001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.request;
018
019import java.io.IOException;
020import java.io.OutputStream;
021
022import org.apache.wicket.util.lang.Args;
023
024/**
025 * Abstract base class for different implementations of response writing.
026 * <p>
027 * The implementation may not support calling both {@link #write(byte[])} and
028 * {@link #write(CharSequence)} on the same {@link Response} instance.
029 * 
030 * @author Matej Knopp
031 * @author igor.vaynberg
032 */
033public abstract class Response
034{
035        /**
036         * Writes the {@link CharSequence} to output.
037         * 
038         * @param sequence
039         * @throws IllegalStateException
040         *             if {@link #write(byte[])} has already been called on this instance
041         */
042        public abstract void write(CharSequence sequence);
043
044        /**
045         * Writes the buffer to output.
046         * 
047         * @param array
048         *            the data.
049         * @throws IllegalStateException
050         *             if {@link #write(CharSequence)} has already been called on this instance
051         */
052        public abstract void write(byte[] array);
053
054        /**
055         * Writes the buffer to output.
056         * 
057         * @param array
058         *            the data.
059         * @param offset
060         *            the start offset in the data.
061         * @param length
062         *            the number of bytes to write.
063         * 
064         * @throws IllegalStateException
065         *             if {@link #write(CharSequence)} has already been called on this instance
066         * @since 1.5.1
067         */
068        public abstract void write(byte[] array, int offset, int length);
069
070        /**
071         * Closes the response
072         */
073        public void close()
074        {
075        }
076
077
078        /**
079         * Encodes the specified URL by including the session ID in it, or, if encoding is not needed,
080         * returns the URL unchanged.
081         * 
082         * @param url
083         * @return encoded URL
084         */
085        public abstract String encodeURL(CharSequence url);
086
087        /**
088         * Called when the Response needs to reset itself. Subclasses can empty there buffer or build up
089         * state.
090         */
091        public void reset()
092        {
093        }
094
095        /**
096         * Provides access to the low-level container response object that implementaion of this
097         * {@link Response} delegate to. This allows users to access features provided by the container
098         * response but not by generalized Wicket {@link Response} objects.
099         * 
100         * @return low-level container response object, or {@code null} if none
101         */
102        public abstract Object getContainerResponse();
103
104        /**
105         * Returns an {@link OutputStream} suitable for writing binary data in the response. The servlet
106         * container does not encode the binary data.
107         * 
108         * <p>
109         * Calling flush() on the OutputStream commits the response.
110         * </p>
111         * <p>
112         * This method returns an output stream that delegates to {@link #write(byte[])},
113         * {@link #write(byte[], int, int)}, and {@link #close()} methods of this response instance
114         * </p>
115         * 
116         * @return output stream
117         */
118        public OutputStream getOutputStream()
119        {
120                return new StreamAdapter(this);
121        }
122
123        private static class StreamAdapter extends OutputStream
124        {
125                private final Response response;
126
127                public StreamAdapter(Response response)
128                {
129                        Args.notNull(response, "response");
130                        this.response = response;
131                }
132
133                @Override
134                public void write(int b) throws IOException
135                {
136                        response.write(new byte[] { (byte)b });
137                }
138
139                @Override
140                public void write(byte[] b) throws IOException
141                {
142                        response.write(b);
143                }
144
145                @Override
146                public void write(byte[] b, int off, int len) throws IOException
147                {
148                        response.write(b, off, len);
149                }
150
151                @Override
152                public void close() throws IOException
153                {
154                        super.close();
155                        response.close();
156                }
157        }
158
159}