/** * Copyright 2005-2010 hdiv.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hdiv.util; import java.net.MalformedURLException; import java.net.URL; import java.util.Locale; import java.util.Random; import java.util.regex.Pattern; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hdiv.application.IApplication; import org.hdiv.config.HDIVConfig; import org.hdiv.dataComposer.IDataComposer; import org.hdiv.exception.HDIVException; import org.hdiv.session.ISession; import org.springframework.context.MessageSource; /** * Class containing utility methods for access HDIV components: IDataComposer, * IDataValidator, IApplication, ISession. * <p> * This class is initialized from a Listener and a Filter. * </p> * * @author Roberto Velasco * @author Gorka Vicente * @author Gotzon Illarramendi */ public class HDIVUtil { /** * Commons Logging instance. */ private static Log log = LogFactory.getLog(HDIVUtil.class); public static final String APPLICATION_SERVLETCONTEXT_KEY = "APPLICATION_SERVLETCONTEXT_KEY"; public static final String MESSAGESOURCE_SERVLETCONTEXT_KEY = "MESSAGESOURCE_SERVLETCONTEXT_KEY"; public static final String HDIVCONFIG_SERVLETCONTEXT_KEY = "HDIVCONFIG_SERVLETCONTEXT_KEY"; public static final String DATACOMPOSER_REQUEST_KEY = "dataComposer"; public static final String ISESSION_SERVLETCONTEXT_KEY = "ISESSION_SERVLETCONTEXT_KEY"; public static Pattern intPattern = Pattern.compile("[0-9]+"); /** * HttpServletRequest thread local */ private static ThreadLocal httpRequest = new ThreadLocal(); /** * ThreadLocales is always guaranteed to be cleaned up when returning the * thread to the server's pool. */ public static void resetLocalData() { httpRequest.set(null); } /* DataComposer*/ /** * Returns data composer object from <code>HttpServletRequest</code> * * @param request HttpServletRequest * @return IDataComposer */ public static IDataComposer getDataComposer(HttpServletRequest request) { IDataComposer requestDataComposer = (IDataComposer) request.getAttribute(DATACOMPOSER_REQUEST_KEY); if(requestDataComposer==null){ throw new HDIVException("No se ha inicializado el objeto IDataComposer en request"); } return requestDataComposer; } /** * @return Returns data composer object */ public static IDataComposer getDataComposer() { HttpServletRequest request = getHttpServletRequest(); IDataComposer newDataComposer= getDataComposer(request); return newDataComposer; } /** * Set the <code>IDataComposer</code> * * @param newDataComposer * @param request */ public static void setDataComposer(IDataComposer newDataComposer, HttpServletRequest request) { request.setAttribute(DATACOMPOSER_REQUEST_KEY, newDataComposer); } /* IApplication*/ /** * @return Returns the servlet context wrapper object. */ public static IApplication getApplication() { ServletContext servletContext = getHttpServletRequest().getSession().getServletContext(); return getApplication(servletContext); } /** * Returns the servlet context wrapper object. * * @param servletContext * @return IApplication object */ public static IApplication getApplication(ServletContext servletContext) { IApplication app= (IApplication) servletContext.getAttribute(APPLICATION_SERVLETCONTEXT_KEY); if(app==null){ throw new HDIVException("No se ha inicializado el objeto IApplication en servletContext"); } return app; } /** * Set the <code>IApplication</code> in <code>ServletContext</code> * * @param newApplication * @param servletContext */ public static void setApplication(IApplication newApplication, ServletContext servletContext) { servletContext.setAttribute(APPLICATION_SERVLETCONTEXT_KEY, newApplication); } /* HDIVConfig*/ /** * Return the <code>HDIVConfig</code> object * * @return HDIVConfig */ public static HDIVConfig getHDIVConfig() { ServletContext servletContext = getHttpServletRequest().getSession().getServletContext(); return getHDIVConfig(servletContext); } /** * Return the <code>HDIVConfig</code> object * * @param servletContext * @return HDIVConfig */ public static HDIVConfig getHDIVConfig(ServletContext servletContext) { HDIVConfig hdivConfig = (HDIVConfig) servletContext.getAttribute(HDIVCONFIG_SERVLETCONTEXT_KEY); if (hdivConfig == null){ throw new HDIVException("HDIVConfig has not been initialized in in servlet context"); } return hdivConfig; } /** * Set the <code>HDIVConfig</code> object * * @param hdivConfig * @param servletContext */ public static void setHDIVConfig(HDIVConfig hdivConfig, ServletContext servletContext) { servletContext.setAttribute(HDIVCONFIG_SERVLETCONTEXT_KEY, hdivConfig); } /* ISession*/ /** * Return the <code>ISession</code> instance. * * @return */ public static ISession getISession() { ServletContext servletContext = getHttpServletRequest().getSession().getServletContext(); return getISession(servletContext); } /** * Return the <code>ISession</code> instance. * * @param servletContext * @return */ public static ISession getISession(ServletContext servletContext) { ISession session= (ISession) servletContext.getAttribute(ISESSION_SERVLETCONTEXT_KEY); if(session==null){ throw new HDIVException("No se ha inicializado el objeto ISession en servletContext"); } return session; } /** * Set the <code>ISession</code> instance. * * @param session * @param servletContext */ public static void setISession(ISession session, ServletContext servletContext) { servletContext.setAttribute(ISESSION_SERVLETCONTEXT_KEY, session); } /* HttpSession*/ /** * Return the <code>HttpSession</code> object. * @return */ public static HttpSession getHttpSession() { HttpServletRequest request = getHttpServletRequest(); return request.getSession(); } /* HttpServletRequest*/ /** * Return the <code>HttpServletRequest</code> object. * @return */ public static HttpServletRequest getHttpServletRequest() { HttpServletRequest request = (HttpServletRequest) httpRequest.get(); if(request == null){ throw new HDIVException("No se ha inicializado el request en threadlocal"); } return request; } /** * Set the <code>HttpServletRequest</code> instance in {@link ThreadLocal} * @param httpServletRequest */ public static void setHttpServletRequest(HttpServletRequest httpServletRequest) { httpRequest.set(httpServletRequest); } /* MessageSource*/ /** * Return the {@link MessageSource} instance. * @return */ public static MessageSource getMessageSource() { ServletContext servletContext = getHttpServletRequest().getSession().getServletContext(); return getMessageSource(servletContext); } /** * Return the {@link MessageSource} instance. * @param servletContext * @return */ public static MessageSource getMessageSource(ServletContext servletContext) { MessageSource msgSource = (MessageSource) servletContext.getAttribute(MESSAGESOURCE_SERVLETCONTEXT_KEY); if(msgSource==null){ throw new HDIVException("No se ha inicializado el MessageSource en servletContext"); } return msgSource; } /** * Set the {@link MessageSource} instance. * @param msgSource * @param servletContext */ public static void setMessageSource(MessageSource msgSource, ServletContext servletContext) { servletContext.setAttribute(MESSAGESOURCE_SERVLETCONTEXT_KEY, msgSource); } /** * Try to resolve the message. Treat as an error if the message can't be * found. * * @param key the code to lookup up, such as 'calculator.noRateSet' * @return The resolved message */ public static String getMessage(String key) { return HDIVUtil.getMessage(key, null); } /** * Try to resolve the message. Treat as an error if the message can't be * found. * * @param key the code to lookup up, such as 'calculator.noRateSet' * @param o Array of arguments that will be filled in for params within the * message (params look like "{0}", "{1,date}", "{2,time}" within * a message), or null if none. * @return The resolved message */ public static String getMessage(String key, String o) { return HDIVUtil.getMessage(key, o, Locale.getDefault()); } /** * Try to resolve the message. Treat as an error if the message can't be * found. * * @param key the code to lookup up, such as 'calculator.noRateSet' * @param o Array of arguments that will be filled in for params within the * message (params look like "{0}", "{1,date}", "{2,time}" within * a message), or null if none. * @param userLocale locale * @return The resolved message */ public static String getMessage(String key, String o, Locale userLocale) { String resolvedMessage = HDIVUtil.getMessageSource().getMessage(key, new String[] { o }, userLocale); if (log.isDebugEnabled()) { log.debug(resolvedMessage); } return resolvedMessage; } /** * Return the form action converted into an action mapping path. The value * of the <code>action</code> property is manipulated as follows in * computing the name of the requested mapping: * <ul> * <li>Any filename extension is removed (on the theory that extension * mapping is being used to select the controller servlet).</li> * <li>If the resulting value does not start with a slash, then a slash is * prepended.</li> * </ul> * * @param url URL representing the current request * @return the form action converted into an action mapping path. */ public static String getActionMappingName(String url) { String value = url; int question = url.indexOf("?"); if (question >= 0) { value = value.substring(0, question); } int pound = value.indexOf("#"); if (pound >= 0) { value = value.substring(0, pound); } // strip a servlet session ID from value = stripSession(value); int slash = value.lastIndexOf("/"); int period = value.lastIndexOf("."); // struts-examples/dir/action.do if ((period >= 0) && (period > slash)) { value = value.substring(0, value.length()); } return value.startsWith("/") ? value : ("/" + value); } /** * Strips a servlet session ID from <tt>url</tt>. The session ID is * encoded as a URL "path parameter" beginning with "jsessionid=". We thus * remove anything we find between ";jsessionid=" (inclusive) and either EOS * or a subsequent ';' (exclusive). */ public static String stripSession(String url) { if (log.isDebugEnabled()) { log.debug("Stripping jsessionid from url " + url); } StringBuffer u = new StringBuffer(url); int sessionStart; while ( ((sessionStart = u.toString().indexOf(";jsessionid=")) != -1) || ((sessionStart = u.toString().indexOf(";JSESSIONID=")) != -1) ) { int sessionEnd = u.toString().indexOf(";", sessionStart + 1); if (sessionEnd == -1) { sessionEnd = u.toString().indexOf("?", sessionStart + 1); } if (sessionEnd == -1) { // still sessionEnd = u.length(); } u.delete(sessionStart, sessionEnd); } return u.toString(); } /** * Return the URL representing the current request. * * @param request The servlet request we are processing * @return URL representing the current request * @exception Exception if a URL cannot be created */ public static String actionName(HttpServletRequest request) throws Exception { return requestURL(request).getFile(); } /** * Return the URL representing the current request. This is equivalent to * <code>HttpServletRequest.getRequestURL()</code> in Servlet 2.3. * * @param request The servlet request we are processing * @return URL representing the current request * @exception MalformedURLException if a URL cannot be created */ public static URL requestURL(HttpServletRequest request) throws MalformedURLException { //TODO Is it necessary to do this to create a URL if then only used in actionName? StringBuffer url = new StringBuffer(); String scheme = request.getScheme(); int port = request.getServerPort(); if (port < 0) { port = 80; // Work around java.net.URL bug } url.append(scheme); url.append("://"); url.append(request.getServerName()); if ((scheme.equals("http") && (port != 80)) || (scheme.equals("https") && (port != 443))) { url.append(':'); url.append(port); } url.append(request.getRequestURI()); return (new URL(HDIVUtil.stripSession(url.toString()))); } /** * Function to protect meaningful characters of regular expressions * (+,*,...) * * @param par Parameter to encode * * @return Returns par with protected characters */ public static String protectCharacters(String par) { par = par.replaceAll("\\+", "\\\\+"); par = par.replaceAll("\\*", "\\\\*"); par = par.replaceAll("\\?", "\\\\?"); par = par.replaceAll("\\$", "\\\\\\$"); par = par.replaceAll("\\^", "\\\\^"); par = par.replaceAll("\\[", "\\\\["); par = par.replaceAll("\\(", "\\\\("); par = par.replaceAll("\\)", "\\\\)"); par = par.replaceAll("\\|", "\\\\|"); return par; } /** * Generates a random number between 0 (inclusive) and n (exclusive). * * @param n the bound on the random number to be returned. Must be positive. * @return Returns a pseudorandom, uniformly distributed int value between 0 * (inclusive) and <code>n</code> (exclusive). * @since HDIV 1.1 */ public static String createRandomToken(int n) { Random r = new Random(); int i = r.nextInt(n); if (i == 0) { i = 1; } return String.valueOf(i); } }