/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2010-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.web.api; import java.io.UnsupportedEncodingException; import java.lang.reflect.UndeclaredThrowableException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URLDecoder; import java.net.URLEncoder; import java.net.UnknownHostException; import java.text.DateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.servlet.http.HttpServletRequest; import org.opennms.core.resource.Vault; import org.opennms.core.utils.InetAddressUtils; import org.opennms.core.utils.WebSecurityUtils; import org.opennms.netmgt.model.events.EventProxy; import org.opennms.netmgt.utils.TcpEventProxy; /** * Provides convenience functions for web-based interfaces. * * @author <A HREF="mailto:larry@opennms.org">Lawrence Karnowski </A> * @author <A HREF="http://www.opennms.org/">OpenNMS </A> */ public abstract class Util extends Object { private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static final HashMap<String, Object> EMPTY_HASH_MAP = new HashMap<String,Object>(); /** * Return a string that represents the fully qualified URL for our servlet * context, suitable for use in the HTML <em>base</em> tag. * * <p> * As an example, suppose your host was www.mycompany.com, you are serving * from port 80, and your web application name was "opennms," then this * method would return: <code>http://www.mycompany.com:80/opennms/</code> * </p> * * <p> * If this guess is wrong, you can override it by setting the property * <code>opennms.web.base-url</code> in opennms.properties * (for embedded Jetty) or WEB-INF/configuration.properties (for Tomcat). * </p> * * @param request * the servlet request you are servicing * @return a {@link java.lang.String} object. */ public static String calculateUrlBase(final HttpServletRequest request) { if (request == null) { throw new IllegalArgumentException("Cannot take null parameters."); } String tmpl = Vault.getProperty("opennms.web.base-url"); if (tmpl == null) { tmpl = "%s://%x%c/"; } final String retval = substituteUrl(request, tmpl); if (retval.endsWith("/")) { return retval; } else { return retval + "/"; } } public static String calculateUrlBase(final HttpServletRequest request, final String path) { if (request == null || path == null) { throw new IllegalArgumentException("Cannot take null parameters."); } String tmpl = Vault.getProperty("opennms.web.base-url"); if (tmpl == null) { tmpl = "%s://%x%c"; } return substituteUrl(request, tmpl).replaceAll("/+$", "") + "/" + path.replaceAll("^/+", ""); } /** Constant <code>substKeywords={ 's', 'h', 'p', 'x', 'c' }</code> */ protected static final char[] substKeywords = { 's', 'h', 'p', 'x', 'c' }; /** * <p>substituteUrl</p> * * @param request a {@link javax.servlet.http.HttpServletRequest} object. * @param tmpl a {@link java.lang.String} object. * @return a {@link java.lang.String} object. */ protected static String substituteUrl(final HttpServletRequest request, final String tmpl) { final String[] replacements = { request.getScheme(), // %s request.getServerName(), // %h Integer.toString(request.getServerPort()), // %p getHostHeader(request), // %x request.getContextPath() // %c }; final StringBuffer out = new StringBuffer(48); for (int i = 0; i < tmpl.length();) { final char c = tmpl.charAt(i++); if (c == '%' && i < tmpl.length()) { final char d = tmpl.charAt(i++); for (int key = 0; key < substKeywords.length; ++key) { if (d == substKeywords[key]) { out.append(replacements[key]); break; } } } else { out.append(c); } } return out.toString(); } protected static final String[] hostHeaders = { "X-Forwarded-Host", // Apache ProxyPass "X-Host", // lighttpd "Host" // unproxied }; /** * Obtains the host and port used by the end user. * * @param request a {@link javax.servlet.http.HttpServletRequest} object. * @return a {@link java.lang.String} object. */ public static String getHostHeader(final HttpServletRequest request) { for (int i = 0; i < hostHeaders.length; ++i) { final String ret = request.getHeader(hostHeaders[i]); if (ret != null) { return ret; } } return request.getServerName() + ":" + Integer.toString(request.getServerPort()); } /** * Encapsulate the deprecated encode method to fix it in one place. * * @param string * string to be encoded * @return encoded string */ public static String encode(final String string) { try { return URLEncoder.encode(string, "UTF-8"); } catch (final UnsupportedEncodingException e) { // UTF-8 should *never* throw this throw new UndeclaredThrowableException(e); } } /** * Encapsulate the deprecated decode method to fix it in one place. * * @param string * string to be decoded * @return decoded string */ public static String decode(final String string) { try { return URLDecoder.decode(string, "UTF-8"); } catch (UnsupportedEncodingException e) { // UTF-8 should *never* throw this throw new UndeclaredThrowableException(e); } } /** * Creates hidden tags for all the parameters given in the request. * * @param request * the <code>HttpServletRequest</code> to read the parameters * from * @return A string containing an HTML <input type="hidden" name=" * <code>paramName</code>" value=" <code>paramValue</code>" * /> tag for each parameter. */ public static String makeHiddenTags(final HttpServletRequest request) { return (makeHiddenTags(request, EMPTY_HASH_MAP, EMPTY_STRING_ARRAY)); } /** * Creates hidden tags for all the parameters given in the request. * * @param request * the <code>HttpServletRequest</code> to read the parameters * from * @param additions * a map of extra parameters to create hidden tags for * @return A string containing an HTML <input type="hidden" name=" * <code>paramName</code>" value=" <code>paramValue</code>" * /> tag for each parameter. */ public static String makeHiddenTags(final HttpServletRequest request, final Map<String,Object> additions) { return (makeHiddenTags(request, additions, EMPTY_STRING_ARRAY)); } /** * Creates hidden tags for all the parameters given in the request. * * @param request * the <code>HttpServletRequest</code> to read the parameters * from * @param ignores * A string array containing request parameters to ignore * @return A string containing an HTML <input type="hidden" name=" * <code>paramName</code>" value=" <code>paramValue</code>" * /> tag for each parameter. */ public static String makeHiddenTags(final HttpServletRequest request, final String[] ignores) { return (makeHiddenTags(request, EMPTY_HASH_MAP, ignores)); } /** * Creates hidden tags for all the parameters given in the request plus the * additions, except for the parameters and additions listed in the ignore * list. * * @param request * the <code>HttpServletRequest</code> to read the parameters * from * @param additions * a map of extra parameters to create hidden tags for * @param ignores * the list of parameters not to create a hidden tag for * @return A string containing an HTML <input type="hidden" name=" * <code>paramName</code>" value=" <code>paramValue</code>" * /> tag for each parameter not in the ignore list. */ public static String makeHiddenTags(final HttpServletRequest request, final Map<String,Object> additions, final String[] ignores) { return (makeHiddenTags(request, additions, ignores, IgnoreType.BOTH)); } /** * Creates hidden tags for all the parameters given in the request plus the * additions, except for the parmeters listed in the ignore list. * * @param request * the <code>HttpServletRequest</code> to read the parameters * from * @param additions * a map of extra parameters to create hidden tags for * @param ignores * the list of parameters not to create a hidden tag for * @param ignoreType * whether the ignore list applies to the request parameters, * values in the additions map, or both * @return A string containing an HTML <input type="hidden" name=" * <code>paramName</code>" value=" <code>paramValue</code>" * /> tag for each parameter not in the ignore list. */ public static String makeHiddenTags(final HttpServletRequest request, final Map<String,Object> additions, final String[] ignores, final IgnoreType ignoreType) { if (request == null || additions == null || ignores == null || ignoreType == null) { throw new IllegalArgumentException("Cannot take null parameters."); } final StringBuffer buffer = new StringBuffer(); final ArrayList<String> ignoreList = new ArrayList<String>(); for (int i = 0; i < ignores.length; i++) { ignoreList.add(ignores[i]); } @SuppressWarnings("unchecked") final Enumeration<String> names = request.getParameterNames(); while (names.hasMoreElements()) { final String name = names.nextElement(); final String[] values = request.getParameterValues(name); if ((ignoreType == IgnoreType.ADDITIONS_ONLY || !ignoreList.contains(name)) && values != null) { for (final String value : values) { buffer.append("<input type=\"hidden\" name=\""); buffer.append(WebSecurityUtils.sanitizeString(name)); buffer.append("\" value=\""); buffer.append(WebSecurityUtils.sanitizeString(value)); buffer.append("\" />"); buffer.append("\n"); } } } for (final String name : additions.keySet()) { // handle both a String value or a String[] value final Object tmp = additions.get(name); final String[] values = (tmp instanceof String[]) ? ((String[]) tmp) : (new String[] { (String) tmp }); if ((ignoreType == IgnoreType.REQUEST_ONLY || !ignoreList.contains(name)) && values != null) { for (final String value : values) { buffer.append("<input type=\"hidden\" name=\""); buffer.append(WebSecurityUtils.sanitizeString(name)); buffer.append("\" value=\""); buffer.append(WebSecurityUtils.sanitizeString(value)); buffer.append("\" />"); buffer.append("\n"); } } } return (buffer.toString()); } /** * Creates a query string of the format "key1=value1&key2=value2" for * each parameter in the given <code>HttpServletRequest</code>. * * @see #makeQueryString( HttpServletRequest, Map, String[] ) * @param request a {@link javax.servlet.http.HttpServletRequest} object. * @return a {@link java.lang.String} object. */ public static String makeQueryString(final HttpServletRequest request) { return (makeQueryString(request, EMPTY_HASH_MAP, EMPTY_STRING_ARRAY)); } /** * Creates a query string of the format "key1=value1&key2=value2" for * each parameter in the given <code>HttpServletRequest</code> and key in * given <code>Map</code>. * * @see #makeQueryString( HttpServletRequest, Map, String[] ) * @param request a {@link javax.servlet.http.HttpServletRequest} object. * @param additions a {@link java.util.Map} object. * @return a {@link java.lang.String} object. */ public static String makeQueryString(final HttpServletRequest request, final Map<String,Object> additions) { return (makeQueryString(request, additions, EMPTY_STRING_ARRAY)); } /** * Creates a query string of the format "key1=value1&key2=value2" for * each parameter in the given <code>HttpServletRequest</code> that is not * listed in the ignore list. * * @see #makeQueryString( HttpServletRequest, Map, String[] ) * @param request a {@link javax.servlet.http.HttpServletRequest} object. * @param ignores an array of {@link java.lang.String} objects. * @return a {@link java.lang.String} object. */ public static String makeQueryString(final HttpServletRequest request, final String[] ignores) { return (makeQueryString(request, EMPTY_HASH_MAP, ignores)); } /** * Creates a query string of the format "key1=value1&key2=value2" for * each parameter in the given <code>HttpServletRequest</code> and key in * given <code>Map</code> that is not listed in the ignore list. * * @param request * the <code>HttpServletRequest</code> to read the parameters * from * @param additions * a mapping of strings to strings or string arrays to be * included in the query string * @param ignores * the list of parameters and map entries not to include * @return A string in the <em>x-www-form-urlencoded</em> format that is * suitable for adding to a URL as a query string. */ public static String makeQueryString(final HttpServletRequest request, final Map<String,Object> additions, final String[] ignores) { return (makeQueryString(request, additions, ignores, IgnoreType.BOTH)); } /** * Creates a query string of the format "key1=value1&key2=value2" for * each parameter in the given <code>HttpServletRequest</code> and key in * given <code>Map</code> that is not listed in the ignore list. * * @param request * the <code>HttpServletRequest</code> to read the parameters * from * @param additions * a mapping of strings to strings or string arrays to be * included in the query string * @param ignores * the list of parameters and map entries not to include * @return A string in the <em>x-www-form-urlencoded</em> format that is * suitable for adding to a URL as a query string. * @param ignoreType a {@link org.opennms.web.api.Util.IgnoreType} object. */ public static String makeQueryString(final HttpServletRequest request, final Map<String,Object> additions, final String[] ignores, final IgnoreType ignoreType) { if (request == null || additions == null || ignores == null || ignoreType == null) { throw new IllegalArgumentException("Cannot take null parameters."); } final StringBuffer buffer = new StringBuffer(); final ArrayList<String> ignoreList = new ArrayList<String>(); for (int i = 0; i < ignores.length; i++) { ignoreList.add(ignores[i]); } @SuppressWarnings("unchecked") final Enumeration<String> names = request.getParameterNames(); while (names.hasMoreElements()) { final String name = (String) names.nextElement(); final String[] values = request.getParameterValues(name); if ((ignoreType == IgnoreType.ADDITIONS_ONLY || !ignoreList.contains(name)) && values != null) { for (int i = 0; i < values.length; i++) { buffer.append("&"); buffer.append(name); buffer.append("="); buffer.append(Util.encode(values[i])); } } } for (final String name : additions.keySet()) { // handle both a String value or a String[] value final Object tmp = additions.get(name); final String[] values; if (tmp instanceof String[]) { values = (String[]) tmp; } else if (tmp instanceof String) { values = new String[] { (String) tmp }; } else { throw new IllegalArgumentException("addition \"" + name + "\" is not of type String or String[], but is of type: " + tmp.getClass().getName()); } if ((ignoreType == IgnoreType.REQUEST_ONLY || !ignoreList.contains(name)) && values != null) { for (int i = 0; i < values.length; i++) { buffer.append("&"); buffer.append(name); buffer.append("="); buffer.append(Util.encode(values[i])); } } } // removes the first & from the buffer if (buffer.length() > 0 && buffer.charAt(0) == '&') { buffer.deleteCharAt(0); } return buffer.toString(); } public static enum IgnoreType { REQUEST_ONLY, ADDITIONS_ONLY, BOTH } /** * <p>getOrderedMap</p> * * @param names an array of {@link java.lang.String} objects. * @return a {@link java.util.Map} object. */ public static SortedMap<String, String> getOrderedMap(final String names[][]) { final TreeMap<String, String> orderedMap = new TreeMap<String, String>(); for (int i = 0; i < names.length; i++) { orderedMap.put(names[i][1], names[i][0]); } return Collections.unmodifiableSortedMap(orderedMap); } /** * <p>htmlify</p> * * @param input a {@link java.lang.String} object. * @return a {@link java.lang.String} object. */ public static String htmlify(final String input) { return (input == null ? null : input.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">")); } /** * <p>createEventProxy</p> * * @return a {@link org.opennms.netmgt.model.events.EventProxy} object. */ public static EventProxy createEventProxy() { /* * Rather than defaulting to localhost all the time, give an option in properties */ final String vaultHost = Vault.getProperty("opennms.rtc.event.proxy.host"); final String vaultPort = Vault.getProperty("opennms.rtc.event.proxy.port"); final String vaultTimeout = Vault.getProperty("opennms.rtc.event.proxy.timeout"); final String proxyHostName = vaultHost == null ? "127.0.0.1" : vaultHost; final String proxyHostPort = vaultPort == null ? Integer.toString(TcpEventProxy.DEFAULT_PORT) : vaultPort; final String proxyHostTimeout = vaultTimeout == null ? Integer.toString(TcpEventProxy.DEFAULT_TIMEOUT) : vaultTimeout; InetAddress proxyAddr = null; EventProxy proxy = null; proxyAddr = InetAddressUtils.addr(proxyHostName); if (proxyAddr == null) { try { proxy = new TcpEventProxy(); } catch (final UnknownHostException e) { // XXX Ewwww! We should just let the first UnknownException bubble up. throw new UndeclaredThrowableException(e); } } else { proxy = new TcpEventProxy(new InetSocketAddress(proxyAddr, Integer.parseInt(proxyHostPort)), Integer.parseInt(proxyHostTimeout)); } return proxy; } /** * An utility method to format a 'Date' into a string in the local specific * DEFALUT DateFormat style for both the date and time. This is used by the * webui and a change here should get all time display in the webui changed. * * @see java.text.DateFormat * @param date a {@link java.util.Date} object. * @return a {@link java.lang.String} object. * @deprecated We should use the <code>fmt:formatDate</code> taglib at the JSP level * instead of converting {@link Date} instances into {@link String} instances inside * the model code. */ public static final String formatDateToUIString(final Date date) { return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM).format(date); } /** * <p>convertToJsSafeString</p> * * @param str a {@link java.lang.String} object. * @return a {@link java.lang.String} object. */ public static String convertToJsSafeString(final String str){ return str .replace("\\", "\\\\") .replace("\"", "\\\"") .replace("\t", "\\t") .replace("\r", "\\r") .replace("\n", "\\n") .replace("\b", "\\b"); } }