0001: /*******************************************************************************
0002: * Licensed to the Apache Software Foundation (ASF) under one
0003: * or more contributor license agreements. See the NOTICE file
0004: * distributed with this work for additional information
0005: * regarding copyright ownership. The ASF licenses this file
0006: * to you under the Apache License, Version 2.0 (the
0007: * "License"); you may not use this file except in compliance
0008: * with the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing,
0013: * software distributed under the License is distributed on an
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015: * KIND, either express or implied. See the License for the
0016: * specific language governing permissions and limitations
0017: * under the License.
0018: *******************************************************************************/package org.ofbiz.base.util;
0019:
0020: import java.io.BufferedInputStream;
0021: import java.io.BufferedOutputStream;
0022: import java.io.ByteArrayInputStream;
0023: import java.io.IOException;
0024: import java.io.InputStream;
0025: import java.io.OutputStream;
0026: import java.io.UnsupportedEncodingException;
0027: import java.net.FileNameMap;
0028: import java.net.URLConnection;
0029: import java.net.URLEncoder;
0030: import java.sql.Timestamp;
0031: import java.util.ArrayList;
0032: import java.util.Arrays;
0033: import java.util.Calendar;
0034: import java.util.Collection;
0035: import java.util.Currency;
0036: import java.util.Enumeration;
0037: import java.util.HashMap;
0038: import java.util.HashSet;
0039: import java.util.Iterator;
0040: import java.util.List;
0041: import java.util.Locale;
0042: import java.util.Map;
0043: import java.util.Set;
0044: import java.util.StringTokenizer;
0045:
0046: import javax.servlet.http.HttpServletRequest;
0047: import javax.servlet.http.HttpServletResponse;
0048: import javax.servlet.http.HttpSession;
0049:
0050: import javolution.util.FastList;
0051: import javolution.util.FastMap;
0052:
0053: /**
0054: * HttpUtil - Misc TTP Utility Functions
0055: */
0056: public class UtilHttp {
0057:
0058: public static final String module = UtilHttp.class.getName();
0059:
0060: public static final String MULTI_ROW_DELIMITER = "_o_";
0061: public static final String ROW_SUBMIT_PREFIX = "_rowSubmit_o_";
0062: public static final String COMPOSITE_DELIMITER = "_c_";
0063: public static final int MULTI_ROW_DELIMITER_LENGTH = MULTI_ROW_DELIMITER
0064: .length();
0065: public static final int ROW_SUBMIT_PREFIX_LENGTH = ROW_SUBMIT_PREFIX
0066: .length();
0067: public static final int COMPOSITE_DELIMITER_LENGTH = COMPOSITE_DELIMITER
0068: .length();
0069:
0070: /**
0071: * Create a map from an HttpServletRequest object
0072: * @return The resulting Map
0073: */
0074: public static Map getParameterMap(HttpServletRequest request) {
0075: Map paramMap = FastMap.newInstance();
0076:
0077: // add all the actual HTTP request parameters
0078: Enumeration e = request.getParameterNames();
0079: while (e.hasMoreElements()) {
0080: String name = (String) e.nextElement();
0081: Object value = null;
0082: String[] paramArr = request.getParameterValues(name);
0083: if (paramArr != null) {
0084: if (paramArr.length > 1) {
0085: value = Arrays.asList(paramArr);
0086: } else {
0087: value = paramArr[0];
0088: // does the same thing basically, nothing better about it as far as I can see: value = request.getParameter(name);
0089: }
0090: }
0091: paramMap.put(name, value);
0092: }
0093:
0094: // now add in all path info parameters /~name1=value1/~name2=value2/
0095: // note that if a parameter with a given name already exists it will be put into a list with all values
0096: String pathInfoStr = request.getPathInfo();
0097:
0098: if (pathInfoStr != null && pathInfoStr.length() > 0) {
0099: // make sure string ends with a trailing '/' so we get all values
0100: if (!pathInfoStr.endsWith("/"))
0101: pathInfoStr += "/";
0102:
0103: int current = pathInfoStr.indexOf('/');
0104: int last = current;
0105: while ((current = pathInfoStr.indexOf('/', last + 1)) != -1) {
0106: String element = pathInfoStr.substring(last + 1,
0107: current);
0108: last = current;
0109: if (element.charAt(0) == '~'
0110: && element.indexOf('=') > -1) {
0111: String name = element.substring(1, element
0112: .indexOf('='));
0113: String value = element.substring(element
0114: .indexOf('=') + 1);
0115: Object curValue = paramMap.get(name);
0116: if (curValue != null) {
0117: List paramList = null;
0118: if (curValue instanceof List) {
0119: paramList = (List) curValue;
0120: paramList.add(value);
0121: } else {
0122: String paramString = (String) curValue;
0123: paramList = FastList.newInstance();
0124: paramList.add(paramString);
0125: paramList.add(value);
0126: }
0127: paramMap.put(name, paramList);
0128: } else {
0129: paramMap.put(name, value);
0130: }
0131: }
0132: }
0133: }
0134:
0135: if (paramMap.size() == 0) {
0136: // nothing found in the parameters; maybe we read the stream instead
0137: Map multiPartMap = (Map) request
0138: .getAttribute("multiPartMap");
0139: if (multiPartMap != null && multiPartMap.size() > 0) {
0140: paramMap.putAll(multiPartMap);
0141: }
0142: }
0143:
0144: //Debug.logInfo("Made parameterMap: \n" + UtilMisc.printMap(paramMap), module);
0145: if (Debug.verboseOn()) {
0146: Debug.logVerbose("Made Request Parameter Map with ["
0147: + paramMap.size() + "] Entries", module);
0148: Iterator entryIter = paramMap.entrySet().iterator();
0149: while (entryIter.hasNext()) {
0150: Map.Entry entry = (Map.Entry) entryIter.next();
0151: Debug.logVerbose("Request Parameter Map Entry: ["
0152: + entry.getKey() + "] --> " + entry.getValue(),
0153: module);
0154: }
0155: }
0156:
0157: return paramMap;
0158: }
0159:
0160: public static Map makeParamMapWithPrefix(
0161: HttpServletRequest request, String prefix, String suffix) {
0162: return makeParamMapWithPrefix(request, null, prefix, suffix);
0163: }
0164:
0165: public static Map makeParamMapWithPrefix(
0166: HttpServletRequest request, Map additionalFields,
0167: String prefix, String suffix) {
0168: Map paramMap = new HashMap();
0169: Enumeration parameterNames = request.getParameterNames();
0170: while (parameterNames.hasMoreElements()) {
0171: String parameterName = (String) parameterNames
0172: .nextElement();
0173: if (parameterName.startsWith(prefix)) {
0174: if (suffix != null && suffix.length() > 0) {
0175: if (parameterName.endsWith(suffix)) {
0176: String key = parameterName.substring(prefix
0177: .length(), parameterName.length()
0178: - (suffix.length()));
0179: String value = request
0180: .getParameter(parameterName);
0181: paramMap.put(key, value);
0182: }
0183: } else {
0184: String key = parameterName.substring(prefix
0185: .length());
0186: String value = request.getParameter(parameterName);
0187: paramMap.put(key, value);
0188: }
0189: }
0190: }
0191: if (additionalFields != null) {
0192: Iterator i = additionalFields.keySet().iterator();
0193: while (i.hasNext()) {
0194: String fieldName = (String) i.next();
0195: if (fieldName.startsWith(prefix)) {
0196: if (suffix != null && suffix.length() > 0) {
0197: if (fieldName.endsWith(suffix)) {
0198: String key = fieldName.substring(prefix
0199: .length(), fieldName.length()
0200: - (suffix.length() - 1));
0201: Object value = additionalFields
0202: .get(fieldName);
0203: paramMap.put(key, value);
0204:
0205: // check for image upload data
0206: if (!(value instanceof String)) {
0207: String nameKey = "_" + key
0208: + "_fileName";
0209: Object nameVal = additionalFields
0210: .get("_" + fieldName
0211: + "_fileName");
0212: if (nameVal != null) {
0213: paramMap.put(nameKey, nameVal);
0214: }
0215:
0216: String typeKey = "_" + key
0217: + "_contentType";
0218: Object typeVal = additionalFields
0219: .get("_" + fieldName
0220: + "_contentType");
0221: if (typeVal != null) {
0222: paramMap.put(typeKey, typeVal);
0223: }
0224:
0225: String sizeKey = "_" + key + "_size";
0226: Object sizeVal = additionalFields
0227: .get("_" + fieldName + "_size");
0228: if (sizeVal != null) {
0229: paramMap.put(sizeKey, sizeVal);
0230: }
0231: }
0232: }
0233: } else {
0234: String key = fieldName.substring(prefix
0235: .length());
0236: Object value = additionalFields.get(fieldName);
0237: paramMap.put(key, value);
0238:
0239: // check for image upload data
0240: if (!(value instanceof String)) {
0241: String nameKey = "_" + key + "_fileName";
0242: Object nameVal = additionalFields.get("_"
0243: + fieldName + "_fileName");
0244: if (nameVal != null) {
0245: paramMap.put(nameKey, nameVal);
0246: }
0247:
0248: String typeKey = "_" + key + "_contentType";
0249: Object typeVal = additionalFields.get("_"
0250: + fieldName + "_contentType");
0251: if (typeVal != null) {
0252: paramMap.put(typeKey, typeVal);
0253: }
0254:
0255: String sizeKey = "_" + key + "_size";
0256: Object sizeVal = additionalFields.get("_"
0257: + fieldName + "_size");
0258: if (sizeVal != null) {
0259: paramMap.put(sizeKey, sizeVal);
0260: }
0261: }
0262: }
0263: }
0264: }
0265: }
0266: return paramMap;
0267: }
0268:
0269: public static List makeParamListWithSuffix(
0270: HttpServletRequest request, String suffix, String prefix) {
0271: return makeParamListWithSuffix(request, null, suffix, prefix);
0272: }
0273:
0274: public static List makeParamListWithSuffix(
0275: HttpServletRequest request, Map additionalFields,
0276: String suffix, String prefix) {
0277: List paramList = new ArrayList();
0278: Enumeration parameterNames = request.getParameterNames();
0279: while (parameterNames.hasMoreElements()) {
0280: String parameterName = (String) parameterNames
0281: .nextElement();
0282: if (parameterName.endsWith(suffix)) {
0283: if (prefix != null && prefix.length() > 0) {
0284: if (parameterName.startsWith(prefix)) {
0285: String value = request
0286: .getParameter(parameterName);
0287: paramList.add(value);
0288: }
0289: } else {
0290: String value = request.getParameter(parameterName);
0291: paramList.add(value);
0292: }
0293: }
0294: }
0295: if (additionalFields != null) {
0296: Iterator i = additionalFields.keySet().iterator();
0297: while (i.hasNext()) {
0298: String fieldName = (String) i.next();
0299: if (fieldName.endsWith(suffix)) {
0300: if (prefix != null && prefix.length() > 0) {
0301: if (fieldName.startsWith(prefix)) {
0302: Object value = additionalFields
0303: .get(fieldName);
0304: paramList.add(value);
0305: }
0306: } else {
0307: Object value = additionalFields.get(fieldName);
0308: paramList.add(value);
0309: }
0310: }
0311: }
0312: }
0313: return paramList;
0314: }
0315:
0316: /**
0317: * Given a request, returns the application name or "root" if deployed on root
0318: * @param request An HttpServletRequest to get the name info from
0319: * @return String
0320: */
0321: public static String getApplicationName(HttpServletRequest request) {
0322: String appName = "root";
0323: if (request.getContextPath().length() > 1) {
0324: appName = request.getContextPath().substring(1);
0325: }
0326: return appName;
0327: }
0328:
0329: /**
0330: * Put request parameters in request object as attributes.
0331: * @param request
0332: */
0333: public static void parametersToAttributes(HttpServletRequest request) {
0334: java.util.Enumeration e = request.getParameterNames();
0335: while (e.hasMoreElements()) {
0336: String name = (String) e.nextElement();
0337: request.setAttribute(name, request.getParameter(name));
0338: }
0339: }
0340:
0341: public static StringBuffer getServerRootUrl(
0342: HttpServletRequest request) {
0343: StringBuffer requestUrl = new StringBuffer();
0344: requestUrl.append(request.getScheme());
0345: requestUrl.append("://" + request.getServerName());
0346: if (request.getServerPort() != 80
0347: && request.getServerPort() != 443)
0348: requestUrl.append(":" + request.getServerPort());
0349: return requestUrl;
0350: }
0351:
0352: public static StringBuffer getFullRequestUrl(
0353: HttpServletRequest request) {
0354: StringBuffer requestUrl = UtilHttp.getServerRootUrl(request);
0355: requestUrl.append(request.getRequestURI());
0356: if (request.getQueryString() != null) {
0357: requestUrl.append("?" + request.getQueryString());
0358: }
0359: return requestUrl;
0360: }
0361:
0362: public static Locale getLocale(HttpServletRequest request,
0363: HttpSession session, Object appDefaultLocale) {
0364: // check session first, should override all if anything set there
0365: Object localeObject = session != null ? session
0366: .getAttribute("locale") : null;
0367:
0368: // next see if the userLogin has a value
0369: if (localeObject == null) {
0370: Map userLogin = (Map) session.getAttribute("userLogin");
0371: if (userLogin == null) {
0372: userLogin = (Map) session.getAttribute("autoUserLogin");
0373: }
0374:
0375: if (userLogin != null) {
0376: localeObject = userLogin.get("lastLocale");
0377: }
0378: }
0379:
0380: // no user locale? before global default try appDefaultLocale if specified
0381: if (localeObject == null
0382: && !UtilValidate.isEmpty(appDefaultLocale)) {
0383: localeObject = appDefaultLocale;
0384: }
0385:
0386: // finally request (w/ a fall back to default)
0387: if (localeObject == null) {
0388: localeObject = request != null ? request.getLocale() : null;
0389: }
0390:
0391: return UtilMisc.ensureLocale(localeObject);
0392: }
0393:
0394: /**
0395: * Get the Locale object from a session variable; if not found use the browser's default
0396: * @param request HttpServletRequest object to use for lookup
0397: * @return Locale The current Locale to use
0398: */
0399: public static Locale getLocale(HttpServletRequest request) {
0400: if (request == null)
0401: return Locale.getDefault();
0402: return UtilHttp.getLocale(request, request.getSession(), null);
0403: }
0404:
0405: /**
0406: * Get the Locale object from a session variable; if not found use the system's default.
0407: * NOTE: This method is not recommended because it ignores the Locale from the browser not having the request object.
0408: * @param session HttpSession object to use for lookup
0409: * @return Locale The current Locale to use
0410: */
0411: public static Locale getLocale(HttpSession session) {
0412: if (session == null)
0413: return Locale.getDefault();
0414: return UtilHttp.getLocale(null, session, null);
0415: }
0416:
0417: public static void setLocale(HttpServletRequest request,
0418: String localeString) {
0419: UtilHttp.setLocale(request.getSession(), UtilMisc
0420: .parseLocale(localeString));
0421: }
0422:
0423: public static void setLocale(HttpSession session, Locale locale) {
0424: session.setAttribute("locale", locale);
0425: }
0426:
0427: public static void setLocaleIfNone(HttpSession session,
0428: String localeString) {
0429: if (UtilValidate.isNotEmpty(localeString)
0430: && session.getAttribute("locale") == null) {
0431: UtilHttp.setLocale(session, UtilMisc
0432: .parseLocale(localeString));
0433: }
0434: }
0435:
0436: /**
0437: * Get the currency string from the session.
0438: * @param session HttpSession object to use for lookup
0439: * @return String The ISO currency code
0440: */
0441: public static String getCurrencyUom(HttpSession session,
0442: String appDefaultCurrencyUom) {
0443: // session, should override all if set there
0444: String iso = (String) session.getAttribute("currencyUom");
0445:
0446: // check userLogin next, ie if nothing to override in the session
0447: if (iso == null) {
0448: Map userLogin = (Map) session.getAttribute("userLogin");
0449: if (userLogin == null) {
0450: userLogin = (Map) session.getAttribute("autoUserLogin");
0451: }
0452:
0453: if (userLogin != null) {
0454: iso = (String) userLogin.get("lastCurrencyUom");
0455: }
0456: }
0457:
0458: // no user currency? before global default try appDefaultCurrencyUom if specified
0459: if (iso == null && !UtilValidate.isEmpty(appDefaultCurrencyUom)) {
0460: iso = appDefaultCurrencyUom;
0461: }
0462:
0463: // if none is set we will use the configured default
0464: if (iso == null) {
0465: try {
0466: iso = UtilProperties.getPropertyValue("general",
0467: "currency.uom.id.default", "USD");
0468: } catch (Exception e) {
0469: Debug.logWarning(
0470: "Error getting the general:currency.uom.id.default value: "
0471: + e.toString(), module);
0472: }
0473: }
0474:
0475: // if still none we will use the default for whatever locale we can get...
0476: if (iso == null) {
0477: Currency cur = Currency.getInstance(getLocale(session));
0478: iso = cur.getCurrencyCode();
0479: }
0480:
0481: return iso;
0482: }
0483:
0484: /**
0485: * Get the currency string from the session.
0486: * @param request HttpServletRequest object to use for lookup
0487: * @return String The ISO currency code
0488: */
0489: public static String getCurrencyUom(HttpServletRequest request) {
0490: return getCurrencyUom(request.getSession(), null);
0491: }
0492:
0493: /** Simple event to set the users per-session currency uom value */
0494: public static void setCurrencyUom(HttpSession session,
0495: String currencyUom) {
0496: session.setAttribute("currencyUom", currencyUom);
0497: }
0498:
0499: public static void setCurrencyUomIfNone(HttpSession session,
0500: String currencyUom) {
0501: if (UtilValidate.isNotEmpty(currencyUom)
0502: && session.getAttribute("currencyUom") == null) {
0503: session.setAttribute("currencyUom", currencyUom);
0504: }
0505: }
0506:
0507: /** URL Encodes a Map of arguements */
0508: public static String urlEncodeArgs(Map args) {
0509: return urlEncodeArgs(args, true);
0510: }
0511:
0512: /** URL Encodes a Map of arguements */
0513: public static String urlEncodeArgs(Map args,
0514: boolean useExpandedEntites) {
0515: StringBuffer buf = new StringBuffer();
0516: if (args != null) {
0517: Iterator i = args.entrySet().iterator();
0518: while (i.hasNext()) {
0519: Map.Entry entry = (Map.Entry) i.next();
0520: String name = (String) entry.getKey();
0521: Object value = entry.getValue();
0522: String valueStr = null;
0523: if (name != null && value != null) {
0524: if (value instanceof String) {
0525: valueStr = (String) value;
0526: } else {
0527: valueStr = value.toString();
0528: }
0529:
0530: if (valueStr != null && valueStr.length() > 0) {
0531: if (buf.length() > 0) {
0532: if (useExpandedEntites) {
0533: buf.append("&");
0534: } else {
0535: buf.append("&");
0536: }
0537: }
0538: try {
0539: buf
0540: .append(URLEncoder.encode(name,
0541: "UTF-8"));
0542: } catch (UnsupportedEncodingException e) {
0543: Debug.logError(e, module);
0544: }
0545: buf.append('=');
0546: try {
0547: buf.append(URLEncoder.encode(valueStr,
0548: "UTF-8"));
0549: } catch (UnsupportedEncodingException e) {
0550: Debug.logError(e, module);
0551: }
0552: }
0553: }
0554: }
0555: }
0556: return buf.toString();
0557: }
0558:
0559: public static String encodeAmpersands(String htmlString) {
0560: StringBuffer htmlBuffer = new StringBuffer(htmlString);
0561: int ampLoc = -1;
0562: while ((ampLoc = htmlBuffer.indexOf("&", ampLoc + 1)) != -1) {
0563: //NOTE: this should work fine, but if it doesn't could try making sure all characters between & and ; are letters, that would qualify as an entity
0564:
0565: // found ampersand, is it already and entity? if not change it to &
0566: int semiLoc = htmlBuffer.indexOf(";", ampLoc);
0567: if (semiLoc != -1) {
0568: // found a semi colon, if it has another & or an = before it, don't count it as an entity, otherwise it may be an entity, so skip it
0569: int eqLoc = htmlBuffer.indexOf("=", ampLoc);
0570: int amp2Loc = htmlBuffer.indexOf("&", ampLoc + 1);
0571: if ((eqLoc == -1 || eqLoc > semiLoc)
0572: && (amp2Loc == -1 || amp2Loc > semiLoc)) {
0573: continue;
0574: }
0575: }
0576:
0577: // at this point not an entity, no substitute with a &
0578: htmlBuffer.insert(ampLoc + 1, "amp;");
0579: }
0580: return htmlBuffer.toString();
0581: }
0582:
0583: public static String encodeBlanks(String htmlString) {
0584: return htmlString.replaceAll(" ", "%20");
0585: }
0586:
0587: public static String setResponseBrowserProxyNoCache(
0588: HttpServletRequest request, HttpServletResponse response) {
0589: setResponseBrowserProxyNoCache(response);
0590: return "success";
0591: }
0592:
0593: public static void setResponseBrowserProxyNoCache(
0594: HttpServletResponse response) {
0595: long nowMillis = System.currentTimeMillis();
0596: response.setDateHeader("Expires", nowMillis);
0597: response.setDateHeader("Last-Modified", nowMillis); // always modified
0598: response.setHeader("Cache-Control",
0599: "no-store, no-cache, must-revalidate"); // HTTP/1.1
0600: response.addHeader("Cache-Control",
0601: "post-check=0, pre-check=0, false");
0602: response.setHeader("Pragma", "no-cache"); // HTTP/1.0
0603: }
0604:
0605: public static String getContentTypeByFileName(String fileName) {
0606: FileNameMap mime = URLConnection.getFileNameMap();
0607: return mime.getContentTypeFor(fileName);
0608: }
0609:
0610: /**
0611: * Stream an array of bytes to the browser
0612: * This method will close the ServletOutputStream when finished
0613: *
0614: * @param response HttpServletResponse object to get OutputStream from
0615: * @param bytes Byte array of content to stream
0616: * @param contentType The content type to pass to the browser
0617: * @param fileName the fileName to tell the browser we are downloading
0618: * @throws IOException
0619: */
0620: public static void streamContentToBrowser(
0621: HttpServletResponse response, byte[] bytes,
0622: String contentType, String fileName) throws IOException {
0623: // tell the browser not the cache
0624: setResponseBrowserProxyNoCache(response);
0625:
0626: // set the response info
0627: response.setContentLength(bytes.length);
0628: if (contentType != null) {
0629: response.setContentType(contentType);
0630: }
0631: if (fileName != null) {
0632: response.setHeader("Content-Disposition",
0633: "attachment;filename=" + fileName);
0634: }
0635:
0636: // create the streams
0637: OutputStream out = response.getOutputStream();
0638: InputStream in = new ByteArrayInputStream(bytes);
0639:
0640: // stream the content
0641: try {
0642: streamContent(out, in, bytes.length);
0643: } catch (IOException e) {
0644: in.close();
0645: out.close(); // should we close the ServletOutputStream on error??
0646: throw e;
0647: }
0648:
0649: // close the input stream
0650: in.close();
0651:
0652: // close the servlet output stream
0653: out.flush();
0654: out.close();
0655: }
0656:
0657: public static void streamContentToBrowser(
0658: HttpServletResponse response, byte[] bytes,
0659: String contentType) throws IOException {
0660: streamContentToBrowser(response, bytes, contentType, null);
0661: }
0662:
0663: /**
0664: * Streams content from InputStream to the ServletOutputStream
0665: * This method will close the ServletOutputStream when finished
0666: * This method does not close the InputSteam passed
0667: *
0668: * @param response HttpServletResponse object to get OutputStream from
0669: * @param in InputStream of the actual content
0670: * @param length Size (in bytes) of the content
0671: * @param contentType The content type to pass to the browser
0672: * @throws IOException
0673: */
0674: public static void streamContentToBrowser(
0675: HttpServletResponse response, InputStream in, int length,
0676: String contentType, String fileName) throws IOException {
0677: // tell the browser not the cache
0678: setResponseBrowserProxyNoCache(response);
0679:
0680: // set the response info
0681: response.setContentLength(length);
0682: if (contentType != null) {
0683: response.setContentType(contentType);
0684: }
0685: if (fileName != null) {
0686: response.setHeader("Content-Disposition",
0687: "attachment;filename=" + fileName);
0688: }
0689:
0690: // stream the content
0691: OutputStream out = response.getOutputStream();
0692: try {
0693: streamContent(out, in, length);
0694: } catch (IOException e) {
0695: out.close();
0696: throw e;
0697: }
0698:
0699: // close the servlet output stream
0700: out.flush();
0701: out.close();
0702: }
0703:
0704: public static void streamContentToBrowser(
0705: HttpServletResponse response, InputStream in, int length,
0706: String contentType) throws IOException {
0707: streamContentToBrowser(response, in, length, contentType, null);
0708: }
0709:
0710: /**
0711: * Stream binary content from InputStream to OutputStream
0712: * This method does not close the streams passed
0713: *
0714: * @param out OutputStream content should go to
0715: * @param in InputStream of the actual content
0716: * @param length Size (in bytes) of the content
0717: * @throws IOException
0718: */
0719: public static void streamContent(OutputStream out, InputStream in,
0720: int length) throws IOException {
0721: int bufferSize = 512; // same as the default buffer size; change as needed
0722:
0723: // make sure we have something to write to
0724: if (out == null) {
0725: throw new IOException(
0726: "Attempt to write to null output stream");
0727: }
0728:
0729: // make sure we have something to read from
0730: if (in == null) {
0731: throw new IOException(
0732: "Attempt to read from null input stream");
0733: }
0734:
0735: // make sure we have some content
0736: if (length == 0) {
0737: throw new IOException(
0738: "Attempt to write 0 bytes of content to output stream");
0739: }
0740:
0741: // initialize the buffered streams
0742: BufferedOutputStream bos = new BufferedOutputStream(out,
0743: bufferSize);
0744: BufferedInputStream bis = new BufferedInputStream(in,
0745: bufferSize);
0746:
0747: byte[] buffer = new byte[length];
0748: int read = 0;
0749: try {
0750: while ((read = bis.read(buffer, 0, buffer.length)) != -1) {
0751: bos.write(buffer, 0, read);
0752: }
0753: } catch (IOException e) {
0754: Debug
0755: .logError(e, "Problem reading/writing buffers",
0756: module);
0757: bis.close();
0758: bos.close();
0759: throw e;
0760: } finally {
0761: if (bis != null) {
0762: bis.close();
0763: }
0764: if (bos != null) {
0765: bos.flush();
0766: bos.close();
0767: }
0768: }
0769: }
0770:
0771: public static String stripViewParamsFromQueryString(
0772: String queryString) {
0773: Set paramNames = new HashSet();
0774: paramNames.add("VIEW_INDEX");
0775: paramNames.add("VIEW_SIZE");
0776: paramNames.add("viewIndex");
0777: paramNames.add("viewSize");
0778: return stripNamedParamsFromQueryString(queryString, paramNames);
0779: }
0780:
0781: public static String stripNamedParamsFromQueryString(
0782: String queryString, Collection paramNames) {
0783: String retStr = null;
0784: if (UtilValidate.isNotEmpty(queryString)) {
0785: StringTokenizer queryTokens = new StringTokenizer(
0786: queryString, "&");
0787: StringBuffer cleanQuery = new StringBuffer();
0788: while (queryTokens.hasMoreTokens()) {
0789: String token = queryTokens.nextToken();
0790: if (token.startsWith("amp;")) {
0791: token = token.substring(4);
0792: }
0793: int equalsIndex = token.indexOf("=");
0794: String name = token;
0795: if (equalsIndex > 0) {
0796: name = token.substring(0, equalsIndex);
0797: }
0798: if (!paramNames.contains(name)) {
0799: cleanQuery.append(token);
0800: if (queryTokens.hasMoreTokens()) {
0801: cleanQuery.append("&");
0802: }
0803: }
0804: }
0805: retStr = cleanQuery.toString();
0806: }
0807: return retStr;
0808: }
0809:
0810: /**
0811: * Given multi form data with the ${param}_o_N notation, creates a Collection
0812: * of Maps for the submitted rows. Each Map contains the key/value pairs
0813: * of a particular row. The keys will be stripped of the _o_N suffix.
0814: * There is an additionaly key "row" for each Map that holds the
0815: * index of the row.
0816: */
0817: public static Collection parseMultiFormData(Map parameters) {
0818: FastMap rows = new FastMap(); // stores the rows keyed by row number
0819:
0820: // first loop through all the keys and create a hashmap for each ${ROW_SUBMIT_PREFIX}${N} = Y
0821: Iterator keys = parameters.keySet().iterator();
0822: while (keys.hasNext()) {
0823: String key = (String) keys.next();
0824:
0825: // skip everything that is not ${ROW_SUBMIT_PREFIX}N
0826: if (key == null || key.length() <= ROW_SUBMIT_PREFIX_LENGTH)
0827: continue;
0828: if (key.indexOf(MULTI_ROW_DELIMITER) <= 0)
0829: continue;
0830: if (!key.substring(0, ROW_SUBMIT_PREFIX_LENGTH).equals(
0831: ROW_SUBMIT_PREFIX))
0832: continue;
0833: if (!parameters.get(key).equals("Y"))
0834: continue;
0835:
0836: // decode the value of N and create a new map for it
0837: Integer n = Integer.decode(key.substring(
0838: ROW_SUBMIT_PREFIX_LENGTH, key.length()));
0839: Map m = new FastMap();
0840: m.put("row", n); // special "row" = N tuple
0841: rows.put(n, m); // key it to N
0842: }
0843:
0844: // next put all parameters with matching N in the right map
0845: keys = parameters.keySet().iterator();
0846: while (keys.hasNext()) {
0847: String key = (String) keys.next();
0848:
0849: // skip keys without DELIMITER and skip ROW_SUBMIT_PREFIX
0850: if (key == null)
0851: continue;
0852: int index = key.indexOf(MULTI_ROW_DELIMITER);
0853: if (index <= 0)
0854: continue;
0855: if (key.length() > ROW_SUBMIT_PREFIX_LENGTH
0856: && key.substring(0, ROW_SUBMIT_PREFIX_LENGTH)
0857: .equals(ROW_SUBMIT_PREFIX))
0858: continue;
0859:
0860: // get the map with index N
0861: Integer n = Integer.decode(key.substring(index
0862: + MULTI_ROW_DELIMITER_LENGTH, key.length())); // N from ${param}${DELIMITER}${N}
0863: Map map = (Map) rows.get(n);
0864: if (map == null)
0865: continue;
0866:
0867: // get the key without the <DELIMITER>N suffix and store it and its value
0868: String newKey = key.substring(0, index);
0869: map.put(newKey, parameters.get(key));
0870: }
0871: // return only the values, which is the list of maps
0872: return rows.values();
0873: }
0874:
0875: /**
0876: * Returns a new map containing all the parameters from the input map except for the
0877: * multi form parameters (usually named according to the ${param}_o_N notation).
0878: */
0879: public static Map removeMultiFormParameters(Map parameters) {
0880: FastMap filteredParameters = new FastMap();
0881: Iterator keys = parameters.keySet().iterator();
0882: while (keys.hasNext()) {
0883: String key = (String) keys.next();
0884:
0885: if (key != null
0886: && (key.indexOf(MULTI_ROW_DELIMITER) != -1
0887: || key.indexOf("_useRowSubmit") != -1 || key
0888: .indexOf("_rowCount") != -1)) {
0889: continue;
0890: }
0891:
0892: filteredParameters.put(key, parameters.get(key));
0893: }
0894: return filteredParameters;
0895: }
0896:
0897: /**
0898: * Utility to make a composite parameter from the given prefix and suffix.
0899: * The prefix should be a regular paramter name such as meetingDate. The
0900: * suffix is the composite field, such as the hour of the meeting. The
0901: * result would be meetingDate_${COMPOSITE_DELIMITER}_hour.
0902: *
0903: * @param prefix
0904: * @param suffix
0905: * @return
0906: */
0907: public static String makeCompositeParam(String prefix, String suffix) {
0908: return prefix + COMPOSITE_DELIMITER + suffix;
0909: }
0910:
0911: /**
0912: * Given the prefix of a composite parameter, recomposes a single Object from
0913: * the composite according to compositeType. For example, consider the following
0914: * form widget field,
0915: *
0916: * <field name="meetingDate">
0917: * <date-time type="timestamp" input-method="time-dropdown">
0918: * </field>
0919: *
0920: * The result in HTML is three input boxes to input the date, hour and minutes separately.
0921: * The parameter names are named meetingDate_c_date, meetingDate_c_hour, meetingDate_c_minutes.
0922: * Additionally, there will be a field named meetingDate_c_compositeType with a value of "Timestamp".
0923: * where _c_ is the COMPOSITE_DELIMITER. These parameters will then be recomposed into a Timestamp
0924: * object from the composite fields.
0925: *
0926: * @param request
0927: * @param prefix
0928: * @return Composite object from data or nulll if not supported or a parsing error occured.
0929: */
0930: public static Object makeParamValueFromComposite(
0931: HttpServletRequest request, String prefix, Locale locale) {
0932: String compositeType = request.getParameter(makeCompositeParam(
0933: prefix, "compositeType"));
0934: if (compositeType == null || compositeType.length() == 0)
0935: return null;
0936:
0937: // collect the composite fields into a map
0938: Map data = FastMap.newInstance();
0939: for (Enumeration names = request.getParameterNames(); names
0940: .hasMoreElements();) {
0941: String name = (String) names.nextElement();
0942: if (!name.startsWith(prefix + COMPOSITE_DELIMITER))
0943: continue;
0944:
0945: // extract the suffix of the composite name
0946: String suffix = name.substring(name
0947: .indexOf(COMPOSITE_DELIMITER)
0948: + COMPOSITE_DELIMITER_LENGTH);
0949:
0950: // and the value of this parameter
0951: Object value = request.getParameter(name);
0952:
0953: // key = suffix, value = parameter data
0954: data.put(suffix, value);
0955: }
0956: if (Debug.verboseOn()) {
0957: Debug.logVerbose(
0958: "Creating composite type with parameter data: "
0959: + data.toString(), module);
0960: }
0961:
0962: // handle recomposition of data into the compositeType
0963: if ("Timestamp".equals(compositeType)) {
0964: String date = (String) data.get("date");
0965: String hour = (String) data.get("hour");
0966: String minutes = (String) data.get("minutes");
0967: String ampm = (String) data.get("ampm");
0968: if (date == null || date.length() < 10)
0969: return null;
0970: if (hour == null || hour.length() == 0)
0971: return null;
0972: if (minutes == null || minutes.length() == 0)
0973: return null;
0974: boolean isTwelveHour = ((ampm == null || ampm.length() == 0) ? false
0975: : true);
0976:
0977: // create the timestamp from the data
0978: try {
0979: int h = Integer.parseInt(hour);
0980: Timestamp timestamp = Timestamp.valueOf(date.substring(
0981: 0, 10)
0982: + " 00:00:00.000");
0983: Calendar cal = Calendar.getInstance(locale);
0984: cal.setTime(timestamp);
0985: if (isTwelveHour) {
0986: boolean isAM = ("AM".equals(ampm) ? true : false);
0987: if (isAM && h == 12)
0988: h = 0;
0989: if (!isAM && h < 12)
0990: h += 12;
0991: }
0992: cal.set(Calendar.HOUR_OF_DAY, h);
0993: cal.set(Calendar.MINUTE, Integer.parseInt(minutes));
0994: return new Timestamp(cal.getTimeInMillis());
0995: } catch (IllegalArgumentException e) {
0996: Debug.logWarning(
0997: "User input for composite timestamp was invalid: "
0998: + e.getMessage(), module);
0999: return null;
1000: }
1001: }
1002:
1003: // we don't support any other compositeTypes (yet)
1004: return null;
1005: }
1006:
1007: /** Obtains the session ID from the request, or "unknown" if no session pressent. */
1008: public static String getSessionId(HttpServletRequest request) {
1009: HttpSession session = request.getSession();
1010: return (session == null ? "unknown" : session.getId());
1011: }
1012: }
|