/* Wotonomy: OpenStep design patterns for pure Java applications. Copyright (C) 2000 Blacksmith, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see http://www.gnu.org */ package net.wotonomy.web; import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSData; import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSMutableData; import net.wotonomy.foundation.NSMutableDictionary; /** * A pure java implementation of WOResponse. * * @author ezamudio@nasoft.com * @author $Author: cgruber $ * @version $Revision: 905 $ */ public class WOMessage { protected String _contentEncoding = "ISO8859_1"; protected NSMutableDictionary> _headers = new NSMutableDictionary<>(); protected NSMutableDictionary _cookies = new NSMutableDictionary<>(); private NSMutableDictionary _userInfo = new NSMutableDictionary<>(); protected NSMutableData _contentData = new NSMutableData(); public WOMessage() { super(); } /** * Sets the content encoding for the response. */ public void setContentEncoding(String encoding) { _contentEncoding = encoding; } /** * Gets the current content encoding for the response. */ public String contentEncoding() { return _contentEncoding; } /** * Sets the specified array of values as headers under the specified key. */ public void setHeaders(NSArray headerArray, String aKey) { _headers.setObjectForKey(headerArray, aKey); } /** * Sets the specified header value for the specified key. */ public void setHeader(String aValue, String aKey) { _headers.setObjectForKey(new NSArray<>(aValue), aKey); } /** * Returns an array of all the header keys that have been set in the response. */ public NSArray headerKeys() { return _headers.allKeys(); } /** * Returns an array of all the header values for the specified key, or null if * the key does not exist. */ public NSArray headersForKey(String aKey) { return _headers.objectForKey(aKey); } /** * Returns one header value for the specified key. Provided as a convenience, * since most header keys will have a single value. */ public String headerForKey(String aKey) { NSArray values = _headers.objectForKey(aKey); if (values != null && values.count() > 0) { return values.objectAtIndex(0).toString(); } return null; } /** * Sets the content of the response to the bytes represented by the specified * data object. */ public void setContent(NSData aData) { _contentData.setData(aData); setHeader(Integer.toString(aData.length()), "content-length"); } /** * Retrieves the current content of the response. */ public NSData content() { return _contentData; } /** * Sets the current user info dictionary. These values are for * application-specific uses and are available to other actions and components * in the request-response cycle. */ public void setUserInfo(NSDictionary aDict) { _userInfo = new NSMutableDictionary<>(aDict); } /** * Gets the current user info dictionary. These values are for * application-specific uses are are available to other actions and components * in the request-response cycle. */ public NSDictionary userInfo() { return new NSDictionary<>(_userInfo); } /** * Appends the bytes in the specified data object to the response. */ public void appendContentData(NSData aData) { _contentData.appendData(aData); setHeader(Integer.toString(_contentData.length()), "content-length"); } /** * Appends the specified byte to the response. */ public void appendContentCharacter(char character) { _contentData.appendByte((byte) character); setHeader(Integer.toString(_contentData.length()), "content-length"); } /** * Appends the specified string to the response. Any special characters will not * be escaped. The string will be encoded in the current content encoding. */ public void appendContentString(String aString) { _contentData.appendData(new NSData(aString.getBytes())); setHeader(Integer.toString(_contentData.length()), "content-length"); } /** * Appends the specified string containing HTML to the response. Any special * characters will be escaped appropriately. The string will be encoded in the * current content encoding. */ public void appendContentHTMLString(String aString) { _contentData.appendData(new NSData(stringByEscapingHTMLString(aString).getBytes())); setHeader(Integer.toString(_contentData.length()), "content-length"); } /** * Appends the specified string containing HTML to the response. Any special * characters will be escaped appropriately. This method escapes tabs and * new-line characters as well. The string will be encoded in the current * content encoding. */ public void appendContentHTMLAttributeValue(String aString) { _contentData.appendData(new NSData(stringByEscapingHTMLAttributeValue(aString).getBytes())); setHeader(Integer.toString(_contentData.length()), "content-length"); } /** * Adds the specified cookie to the response. */ public void addCookie(WOCookie aCookie) { _cookies.setObjectForKey(aCookie, aCookie.name()); } /** * Removes the specified cookie from the response. */ public void removeCookie(WOCookie aCookie) { _cookies.removeObjectForKey(aCookie.name()); } /** * Returns an array of cookies currently being sent with the response. Contains * whatever cookies have previously been set in this response. */ public NSArray cookies() { return _cookies.allValues(); } /** * Sets the HTTP version header in the response. */ public void setHTTPVersion(String aString) { setHeader(aString, "Protocol"); } /** * Gets the current HTTP version header for the response. Because servlet * responses do not allow read access to headers, this method returns null if * setHTTPVersion has not been called. */ public String httpVersion() { return headerForKey("Protocol"); } /** * Returns a sting containing the contents of the specified string after * escaping all special HTML characters. */ public static String stringByEscapingHTMLString(String aString) { int len = aString.length(); StringBuffer result = new StringBuffer(); char[] buf = new char[len]; aString.getChars(0, len, buf, 0); for (int i = 0; i < len; i++) { if (buf[i] == '&') { result.append("&"); } else if (buf[i] == '\\') { result.append("""); } else if (buf[i] == '<') { result.append("<"); } else if (buf[i] == '>') { result.append(">"); } else { result.append(buf[i]); } } return result.toString(); } /** * Returns a sting containing the contents of the specified string after * escaping all special HTML characters. This method escapes tabs and new-line * characters as well. */ public static String stringByEscapingHTMLAttributeValue(String aString) { int len = aString.length(); StringBuffer result = new StringBuffer(); char[] buf = new char[len]; aString.getChars(0, len, buf, 0); for (int i = 0; i < len; i++) { if (buf[i] == '&') { result.append("&"); } else if (buf[i] == '\\') { result.append("""); } else if (buf[i] == '<') { result.append("<"); } else if (buf[i] == '>') { result.append(">"); } else if (buf[i] == '\t') { result.append(" "); } else if (buf[i] == '\n') { result.append(" "); } else if (buf[i] == '\r') { result.append(" "); } else { result.append(buf[i]); } } return result.toString(); } }