View Javadoc

1   /*
2   Wotonomy: OpenStep design patterns for pure Java applications.
3   Copyright (C) 2000 Blacksmith, Inc.
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Lesser General Public License for more details.
14  
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, see http://www.gnu.org
17  */
18  package net.wotonomy.web;
19  
20  import net.wotonomy.foundation.NSArray;
21  import net.wotonomy.foundation.NSData;
22  import net.wotonomy.foundation.NSDictionary;
23  import net.wotonomy.foundation.NSMutableData;
24  import net.wotonomy.foundation.NSMutableDictionary;
25  
26  /***
27  * A pure java implementation of WOResponse.
28  *
29  * @author ezamudio@nasoft.com
30  * @author $Author: cgruber $
31  * @version $Revision: 905 $
32  */
33  public class WOMessage {
34  
35  	protected String _contentEncoding = "ISO8859_1";
36  	protected NSMutableDictionary _headers = new NSMutableDictionary();
37  	protected NSMutableDictionary _cookies = new NSMutableDictionary();
38  	private NSMutableDictionary _userInfo = new NSMutableDictionary();
39  	protected NSMutableData _contentData = new NSMutableData();
40  
41  	public WOMessage() {
42  		super();
43  	}
44  
45  	/***
46  	* Sets the content encoding for the response.
47  	*/
48  	public void setContentEncoding (String encoding)
49  	{
50  		_contentEncoding = encoding;
51  	}
52  
53  	/***
54  	* Gets the current content encoding for the response.
55  	*/
56  	public String contentEncoding () {
57  		return _contentEncoding;
58  	}	
59  
60  	/***
61  	* Sets the specified array of values as headers under
62  	* the specified key.
63  	*/
64  	public void setHeaders (NSArray headerArray, String aKey) {
65  		_headers.setObjectForKey( headerArray, aKey );
66  	}
67  
68  	/***
69  	* Sets the specified header value for the specified key.
70  	*/
71  	public void setHeader (String aValue, String aKey) {
72  		_headers.setObjectForKey( new NSArray( aValue ), aKey );
73  	}
74  
75  	/***
76  	* Returns an array of all the header keys that have been
77  	* set in the response.
78  	*/
79  	public NSArray headerKeys () {
80  		return _headers.allKeys();
81  	}
82  
83  	/***
84  	* Returns an array of all the header values for the specified key,
85  	* or null if the key does not exist.
86  	*/
87  	public NSArray headersForKey (String aKey) {
88  		return (NSArray)_headers.objectForKey( aKey );
89  	}
90  
91  	/***
92  	* Returns one header value for the specified key.
93  	* Provided as a convenience, since most header keys
94  	* will have a single value.
95  	*/
96  	public String headerForKey (String aKey) {
97  		NSArray values = (NSArray)_headers.objectForKey( aKey );
98  		if ( values != null && values.count() > 0 ) {
99  			return values.objectAtIndex( 0 ).toString();
100 		}
101 		return null;
102 	}
103 
104 	/***
105 	* Sets the content of the response to the bytes represented
106 	* by the specified data object.
107 	*/
108 	public void setContent(NSData aData) {
109 		_contentData.setData( aData );
110 		setHeader(Integer.toString(aData.length()), "content-length");
111 	}
112 
113 	/***
114 	* Retrieves the current content of the response.
115 	*/
116 	public NSData content() {
117 		return _contentData;
118 	}
119 
120 	/***
121 	* Sets the current user info dictionary.  These values
122 	* are for application-specific uses and are available to
123 	* other actions and components in the request-response cycle.
124 	*/
125 	public void setUserInfo (NSDictionary aDict) {
126 		_userInfo = new NSMutableDictionary( aDict );
127 	}
128 
129 	/***
130 	* Gets the current user info dictionary.  These values
131 	* are for application-specific uses are are available to
132 	* other actions and components in the request-response cycle.
133 	*/
134 	public NSDictionary userInfo () {
135 		return new NSDictionary(_userInfo);
136 	}
137 
138 	/***
139 	* Appends the bytes in the specified data object to the response.
140 	*/
141 	public void appendContentData (NSData aData)
142 	{
143 		_contentData.appendData( aData );
144 		setHeader(Integer.toString(_contentData.length()), "content-length");
145 	}
146 
147 	/***
148 	* Appends the specified byte to the response.
149 	*/
150 	public void appendContentCharacter (char character) {
151 		_contentData.appendByte((byte)character);
152 		setHeader(Integer.toString(_contentData.length()), "content-length");
153 	}
154 
155 	/***
156 	* Appends the specified string to the response.
157 	* Any special characters will not be escaped.
158 	* The string will be encoded in the current content encoding.
159 	*/
160 	public void appendContentString (String aString)
161 	{
162 		_contentData.appendData( new NSData( aString.getBytes() ) );
163 		setHeader(Integer.toString(_contentData.length()), "content-length");
164 	}
165 
166 	/***
167 	* Appends the specified string containing HTML to the response.
168 	* Any special characters will be escaped appropriately.
169 	* The string will be encoded in the current content encoding.
170 	*/
171 	public void appendContentHTMLString (String aString)
172 	{
173 		_contentData.appendData( 
174 			new NSData( stringByEscapingHTMLString( 
175 				aString ).getBytes() ) );
176 		setHeader(Integer.toString(_contentData.length()), "content-length");
177 	}
178 
179 	/***
180 	* Appends the specified string containing HTML to the response.
181 	* Any special characters will be escaped appropriately.
182 	* This method escapes tabs and new-line characters as well.
183 	* The string will be encoded in the current content encoding.
184 	*/
185 	public void appendContentHTMLAttributeValue (String aString)
186 	{
187 		_contentData.appendData ( 
188 			new NSData( stringByEscapingHTMLAttributeValue( 
189 				aString ).getBytes() ) );
190 		setHeader(Integer.toString(_contentData.length()), "content-length");
191 	}
192 
193 	/***
194 	* Adds the specified cookie to the response.
195 	*/
196 	public void addCookie (WOCookie aCookie)
197 	{
198 		_cookies.setObjectForKey( aCookie, aCookie.name() );
199 	}
200 
201 	/***
202 	* Removes the specified cookie from the response.
203 	*/
204 	public void removeCookie (WOCookie aCookie)
205 	{
206 		_cookies.removeObjectForKey( aCookie.name() ); 
207 	}
208 
209 	/***
210 	* Returns an array of cookies currently being sent with the response.
211 	* Contains whatever cookies have previously been set in this response.
212 	*/
213 	public NSArray cookies ()
214 	{
215 		return _cookies.allValues();	
216 	}
217 
218 	/***
219 	* Sets the HTTP version header in the response.
220 	*/
221 	public void setHTTPVersion (String aString)
222 	{
223 		setHeader( aString, "Protocol");
224 	}
225 
226 	/***
227 	* Gets the current HTTP version header for the response.
228 	* Because servlet responses do not allow read access 
229 	* to headers, this method returns null if setHTTPVersion
230 	* has not been called.
231 	*/
232 	public String httpVersion ()
233 	{
234 		return headerForKey( "Protocol" );
235 	}
236 
237 	/***
238 	* Returns a sting containing the contents of the specified
239 	* string after escaping all special HTML characters.
240 	*/
241 	public static String stringByEscapingHTMLString 
242 		(String aString)
243 	{
244 		int len = aString.length();
245 		StringBuffer result = new StringBuffer();
246 		char[] buf = new char[ len ];
247 		aString.getChars( 0, len, buf, 0 );
248 		for ( int i = 0; i < len; i++ )
249 		{
250 			if ( buf[i] == '&' ) 
251 			{
252 				result.append( "&amp;" );		    
253 			}
254 			else
255 			if ( buf[i] == '//' ) 
256 			{
257 				result.append( "&quot;" );		    
258 			}
259 			else
260 			if ( buf[i] == '<' ) 
261 			{
262 				result.append( "&lt;" );		    
263 			}
264 			else
265 			if ( buf[i] == '>' ) 
266 			{
267 				result.append( "&gt;" );		    
268 			}
269 			else
270 			{
271 				result.append( buf[i] );
272 			}
273 		} 	 
274 		return result.toString();   
275 	}
276 	
277 	/***
278 	* Returns a sting containing the contents of the specified
279 	* string after escaping all special HTML characters.
280 	* This method escapes tabs and new-line characters as well.
281 	*/
282 	public static String stringByEscapingHTMLAttributeValue 
283 		(String aString)
284 	{
285 		int len = aString.length();
286 		StringBuffer result = new StringBuffer();
287 		char[] buf = new char[ len ];
288 		aString.getChars( 0, len, buf, 0 );
289 		for ( int i = 0; i < len; i++ )
290 		{
291 			if ( buf[i] == '&' ) 
292 			{
293 				result.append( "&amp;" );		    
294 			}
295 			else
296 			if ( buf[i] == '//' ) 
297 			{
298 				result.append( "&quot;" );		    
299 			}
300 			else
301 			if ( buf[i] == '<' ) 
302 			{
303 				result.append( "&lt;" );		    
304 			}
305 			else
306 			if ( buf[i] == '>' ) 
307 			{
308 				result.append( "&gt;" );		    
309 			}
310 			else
311 			if ( buf[i] == '\t' ) 
312 			{
313 				result.append( "&#9;" );		    
314 			}
315 			else
316 			if ( buf[i] == '\n' ) 
317 			{
318 				result.append( "&#10;" );		    
319 			}
320 			else
321 			if ( buf[i] == '\r' ) 
322 			{
323 				result.append( "&#13;" );		    
324 			}
325 			else
326 			{
327 				result.append( buf[i] );
328 			}
329 		} 	 
330 		return result.toString();   
331 	}
332 
333 }