View Javadoc

    1   /*
    2    * $Id: UrlHelper.java 508879 2007-02-18 06:32:02Z tschneider $
    3    *
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
    10   * with the License.  You may obtain a copy of the License at
    11   *
    12   *  http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing,
    15   * software distributed under the License is distributed on an
    16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    17   * KIND, either express or implied.  See the License for the
    18   * specific language governing permissions and limitations
    19   * under the License.
    20   */
    21
    22  package org.apache.struts2.views.util;
    23
    24  import java.io.UnsupportedEncodingException;
    25  import java.net.URLDecoder;
    26  import java.net.URLEncoder;
    27  import java.util.Collections;
    28  import java.util.Iterator;
    29  import java.util.LinkedHashMap;
    30  import java.util.Map;
    31
    32  import javax.servlet.http.HttpServletRequest;
    33  import javax.servlet.http.HttpServletResponse;
    34
    35  import org.apache.commons.logging.Log;
    36  import org.apache.commons.logging.LogFactory;
    37  import org.apache.struts2.ServletActionContext;
    38  import org.apache.struts2.StrutsConstants;
    39
    40  import com.opensymphony.xwork2.ActionContext;
    41  import com.opensymphony.xwork2.inject.Inject;
    42  import com.opensymphony.xwork2.util.TextParseUtil;
    43  import com.opensymphony.xwork2.util.ValueStack;
    44
    45
    46  /***
    47   * UrlHelper
    48   *
    49   */
    50  public class UrlHelper {
    51      private static final Log LOG = LogFactory.getLog(UrlHelper.class);
    52
    53      /***
    54       * Default HTTP port (80).
    55       */
    56      private static final int DEFAULT_HTTP_PORT = 80;
    57
    58      /***
    59       * Default HTTPS port (443).
    60       */
    61      private static final int DEFAULT_HTTPS_PORT = 443;
    62
    63      private static final String AMP = "&amp;";
    64
    65      private static int httpPort = DEFAULT_HTTP_PORT;
    66      private static int httpsPort = DEFAULT_HTTPS_PORT;
    67      private static String customEncoding;
    68
    69      @Inject(StrutsConstants.STRUTS_URL_HTTP_PORT)
    70      public static void setHttpPort(String val) {
    71          httpPort = Integer.parseInt(val);
    72      }
    73
    74      @Inject(StrutsConstants.STRUTS_URL_HTTPS_PORT)
    75      public static void setHttpsPort(String val) {
    76          httpsPort = Integer.parseInt(val);
    77      }
    78
    79      @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
    80      public static void setCustomEncoding(String val) {
    81          customEncoding = val;
    82      }
    83
    84      public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params) {
    85          return buildUrl(action, request, response, params, null, true, true);
    86      }
    87
    88      public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult) {
    89          return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, false);
    90      }
    91
    92      public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort) {
    93          StringBuffer link = new StringBuffer();
    94
    95          boolean changedScheme = false;
    96
    97          // only append scheme if it is different to the current scheme *OR*
    98          // if we explicity want it to be appended by having forceAddSchemeHostAndPort = true
    99          if (forceAddSchemeHostAndPort) {
    100             String reqScheme = request.getScheme();
    101             changedScheme = true;
    102             link.append(scheme != null ? scheme : reqScheme);
    103             link.append("://");
    104             link.append(request.getServerName());
    105
    106             if (scheme != null) {
    107                 if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT))
    108                 {
    109                     link.append(":");
    110                     link.append(scheme.equals("http") ? httpPort : httpsPort);
    111                 }
    112             }
    113         }
    114         else if (
    115            (scheme != null) && !scheme.equals(request.getScheme())) {
    116             changedScheme = true;
    117             link.append(scheme);
    118             link.append("://");
    119             link.append(request.getServerName());
    120
    121             if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT))
    122             {
    123                 link.append(":");
    124                 link.append(scheme.equals("http") ? httpPort : httpsPort);
    125             }
    126         }
    127
    128         if (action != null) {
    129             // Check if context path needs to be added
    130             // Add path to absolute links
    131             if (action.startsWith("/") && includeContext) {
    132                 String contextPath = request.getContextPath();
    133                 if (!contextPath.equals("/")) {
    134                     link.append(contextPath);
    135                 }
    136             } else if (changedScheme) {
    137
    138                 // (Applicable to Servlet 2.4 containers)
    139                 // If the request was forwarded, the attribute below will be set with the original URL
    140                 String uri = (String) request.getAttribute("javax.servlet.forward.request_uri");
    141
    142                 // If the attribute wasn't found, default to the value in the request object
    143                 if (uri == null) {
    144                     uri = request.getRequestURI();
    145                 }
    146
    147                 link.append(uri.substring(0, uri.lastIndexOf('/') + 1));
    148             }
    149
    150             // Add page
    151             link.append(action);
    152         } else {
    153             // Go to "same page"
    154             String requestURI = (String) request.getAttribute("struts.request_uri");
    155
    156             // (Applicable to Servlet 2.4 containers)
    157             // If the request was forwarded, the attribute below will be set with the original URL
    158             if (requestURI == null) {
    159                 requestURI = (String) request.getAttribute("javax.servlet.forward.request_uri");
    160             }
    161
    162             // If neither request attributes were found, default to the value in the request object
    163             if (requestURI == null) {
    164                 requestURI = request.getRequestURI();
    165             }
    166
    167             link.append(requestURI);
    168         }
    169
    170         //if the action was not explicitly set grab the params from the request
    171         buildParametersString(params, link);
    172
    173         String result;
    174
    175         try {
    176             result = encodeResult ? response.encodeURL(link.toString()) : link.toString();
    177         } catch (Exception ex) {
    178             // Could not encode the URL for some reason
    179             // Use it unchanged
    180             result = link.toString();
    181         }
    182
    183         return result;
    184     }
    185
    186     public static void buildParametersString(Map params, StringBuffer link) {
    187         buildParametersString(params, link, AMP);
    188     }
    189
    190     public static void buildParametersString(Map params, StringBuffer link, String paramSeparator) {
    191         if ((params != null) && (params.size() > 0)) {
    192             if (link.toString().indexOf("?") == -1) {
    193                 link.append("?");
    194             } else {
    195                 link.append(paramSeparator);
    196             }
    197
    198             // Set params
    199             Iterator iter = params.entrySet().iterator();
    200
    201             String[] valueHolder = new String[1];
    202
    203             while (iter.hasNext()) {
    204                 Map.Entry entry = (Map.Entry) iter.next();
    205                 String name = (String) entry.getKey();
    206                 Object value = entry.getValue();
    207
    208                 String[] values;
    209
    210                 if (value instanceof String[]) {
    211                     values = (String[]) value;
    212                 } else {
    213                     valueHolder[0] = value.toString();
    214                     values = valueHolder;
    215                 }
    216
    217                 for (int i = 0; i < values.length; i++) {
    218                     if (values[i] != null) {
    219                         link.append(name);
    220                         link.append('=');
    221                         link.append(translateAndEncode(values[i]));
    222                     }
    223
    224                     if (i < (values.length - 1)) {
    225                         link.append(paramSeparator);
    226                     }
    227                 }
    228
    229                 if (iter.hasNext()) {
    230                     link.append(paramSeparator);
    231                 }
    232             }
    233         }
    234     }
    235
    236     /***
    237      * Translates any script expressions using {@link com.opensymphony.xwork2.util.TextParseUtil#translateVariables} and
    238      * encodes the URL using {@link java.net.URLEncoder#encode} with the encoding specified in the configuration.
    239      *
    240      * @param input
    241      * @return the translated and encoded string
    242      */
    243     public static String translateAndEncode(String input) {
    244         String translatedInput = translateVariable(input);
    245         String encoding = getEncodingFromConfiguration();
    246
    247         try {
    248             return URLEncoder.encode(translatedInput, encoding);
    249         } catch (UnsupportedEncodingException e) {
    250             LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
    251             return translatedInput;
    252         }
    253     }
    254
    255     public static String translateAndDecode(String input) {
    256         String translatedInput = translateVariable(input);
    257         String encoding = getEncodingFromConfiguration();
    258
    259         try {
    260             return URLDecoder.decode(translatedInput, encoding);
    261         } catch (UnsupportedEncodingException e) {
    262             LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
    263             return translatedInput;
    264         }
    265     }
    266
    267     private static String translateVariable(String input) {
    268         ValueStack valueStack = ServletActionContext.getContext().getValueStack();
    269         String output = TextParseUtil.translateVariables(input, valueStack);
    270         return output;
    271     }
    272
    273     private static String getEncodingFromConfiguration() {
    274         final String encoding;
    275         if (customEncoding != null) {
    276             encoding = customEncoding;
    277         } else {
    278             encoding = "UTF-8";
    279         }
    280         return encoding;
    281     }
    282
    283     public static Map parseQueryString(String queryString) {
    284         Map queryParams = new LinkedHashMap();
    285         if (queryString != null) {
    286             String[] params = queryString.split("&");
    287             for (int a=0; a< params.length; a++) {
    288                 if (params[a].trim().length() > 0) {
    289                     String[] tmpParams = params[a].split("=");
    290                     String paramName = null;
    291                     String paramValue = "";
    292                     if (tmpParams.length > 0) {
    293                         paramName = tmpParams[0];
    294                     }
    295                     if (tmpParams.length > 1) {
    296                         paramValue = tmpParams[1];
    297                     }
    298                     if (paramName != null) {
    299                         String translatedParamValue = translateAndDecode(paramValue);
    300                         queryParams.put(paramName, translatedParamValue);
    301                     }
    302                 }
    303             }
    304         }
    305         return queryParams;
    306     }
    307 }