Save This Page
Home » struts-2.1.8.1-src » org.apache » struts2 » components » [javadoc | source]
    1   /*
    2    * $Id: ServletUrlRenderer.java 768855 2009-04-27 02:09:35Z wesw $
    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.components;
   23   
   24   import com.opensymphony.xwork2.ActionContext;
   25   import com.opensymphony.xwork2.ActionInvocation;
   26   import com.opensymphony.xwork2.config.entities.ActionConfig;
   27   import com.opensymphony.xwork2.inject.Inject;
   28   import com.opensymphony.xwork2.util.logging.Logger;
   29   import com.opensymphony.xwork2.util.logging.LoggerFactory;
   30   import org.apache.struts2.StrutsException;
   31   import org.apache.struts2.dispatcher.mapper.ActionMapper;
   32   import org.apache.struts2.dispatcher.mapper.ActionMapping;
   33   import org.apache.struts2.views.util.UrlHelper;
   34   import org.apache.commons.lang.xwork.StringUtils;
   35   
   36   import java.io.IOException;
   37   import java.io.Writer;
   38   import java.util.Collections;
   39   import java.util.Iterator;
   40   import java.util.LinkedHashMap;
   41   import java.util.Map;
   42   
   43   /**
   44    * Implementation of the {@link UrlRenderer} interface that creates URLs suitable in a servlet environment.
   45    * 
   46    */
   47   public class ServletUrlRenderer implements UrlRenderer {
   48       /**
   49        * Provide a logging instance.
   50        */
   51       private static final Logger LOG = LoggerFactory.getLogger(ServletUrlRenderer.class);
   52   
   53       private ActionMapper actionMapper;
   54   
   55       @Inject
   56       public void setActionMapper(ActionMapper mapper) {
   57           this.actionMapper = mapper;
   58       }
   59   
   60   
   61       /**
   62   	 * {@inheritDoc}
   63   	 */
   64   	public void renderUrl(Writer writer, UrlProvider urlComponent) {
   65   		String scheme = urlComponent.getHttpServletRequest().getScheme();
   66   
   67   		if (urlComponent.getScheme() != null) {
   68   			scheme = urlComponent.getScheme();
   69   		}
   70   
   71   	       String result;
   72   	       ActionInvocation ai = (ActionInvocation) ActionContext.getContext().get(ActionContext.ACTION_INVOCATION);
   73   	        if (urlComponent.getValue() == null && urlComponent.getAction() != null) {
   74   	                result = urlComponent.determineActionURL(urlComponent.getAction(), urlComponent.getNamespace(), urlComponent.getMethod(), urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp());
   75   	        } else if (urlComponent.getValue() == null && urlComponent.getAction() == null && ai != null) {
   76   	                // both are null, we will default to the current action
   77   
   78   	                final String action = ai.getProxy().getActionName();
   79   	                final String namespace = ai.getProxy().getNamespace();
   80   	                result = urlComponent.determineActionURL(action, namespace, urlComponent.getMethod(),urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp());
   81   	        } else {
   82   	                String _value = urlComponent.getValue();
   83   
   84   	                // We don't include the request parameters cause they would have been
   85   	                // prioritised before this [in start(Writer) method]
   86   	                if (_value != null && _value.indexOf("?") > 0) {
   87   	                    _value = _value.substring(0, _value.indexOf("?"));
   88   	                }
   89   	                result = UrlHelper.buildUrl(_value, urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp());
   90   	        }
   91               String anchor = urlComponent.getAnchor();
   92   	        if (StringUtils.isNotEmpty(anchor)) {
   93   	        	result += '#' + urlComponent.findString(anchor);
   94   	        }
   95   
   96           if (urlComponent.isPutInContext()) {
   97               String var = urlComponent.getVar();
   98               if (StringUtils.isNotEmpty(var)) {
   99                   urlComponent.putInContext(result);
  100   
  101                   // add to the request and page scopes as well
  102                   urlComponent.getHttpServletRequest().setAttribute(var, result);
  103               } else {
  104                   try {
  105                       writer.write(result);
  106                   } catch (IOException e) {
  107                       throw new StrutsException("IOError: " + e.getMessage(), e);
  108                   }
  109               }
  110           } else {
  111               try {
  112                   writer.write(result);
  113               } catch (IOException e) {
  114                   throw new StrutsException("IOError: " + e.getMessage(), e);
  115               }
  116           }
  117   	}
  118   
  119   	/**
  120   	 * {@inheritDoc}
  121   	 */
  122   	public void renderFormUrl(Form formComponent) {
  123   		String namespace = formComponent.determineNamespace(formComponent.namespace, formComponent.getStack(),
  124   				formComponent.request);
  125   		String action;
  126   
  127   		if(formComponent.action != null) {
  128   			action = formComponent.findString(formComponent.action);
  129   		} else {
  130   			// no action supplied? ok, then default to the current request
  131   			// (action or general URL)
  132   			ActionInvocation ai = (ActionInvocation) formComponent.getStack().getContext().get(
  133   					ActionContext.ACTION_INVOCATION);
  134   			if (ai != null) {
  135   				action = ai.getProxy().getActionName();
  136   				namespace = ai.getProxy().getNamespace();
  137   			} else {
  138   				// hmm, ok, we need to just assume the current URL cut down
  139   				String uri = formComponent.request.getRequestURI();
  140   				action = uri.substring(uri.lastIndexOf('/'));
  141   			}
  142   		}
  143   
  144           ActionMapping nameMapping = actionMapper.getMappingFromActionName(action);
  145           String actionName = nameMapping.getName();
  146           String actionMethod = nameMapping.getMethod();
  147   
  148   		final ActionConfig actionConfig = formComponent.configuration.getRuntimeConfiguration().getActionConfig(
  149   				namespace, actionName);
  150   		if (actionConfig != null) {
  151   
  152   			ActionMapping mapping = new ActionMapping(actionName, namespace, actionMethod, formComponent.parameters);
  153   			String result = UrlHelper.buildUrl(formComponent.actionMapper.getUriFromActionMapping(mapping),
  154   					formComponent.request, formComponent.response, null);
  155   			formComponent.addParameter("action", result);
  156   
  157   			// let's try to get the actual action class and name
  158   			// this can be used for getting the list of validators
  159   			formComponent.addParameter("actionName", actionName);
  160   			try {
  161   				Class clazz = formComponent.objectFactory.getClassInstance(actionConfig.getClassName());
  162   				formComponent.addParameter("actionClass", clazz);
  163   			} catch (ClassNotFoundException e) {
  164   				// this is OK, we'll just move on
  165   			}
  166   
  167   			formComponent.addParameter("namespace", namespace);
  168   
  169   			// if the name isn't specified, use the action name
  170   			if (formComponent.name == null) {
  171   				formComponent.addParameter("name", actionName);
  172   			}
  173   
  174   			// if the id isn't specified, use the action name
  175   			if (formComponent.getId() == null  && actionName!=null ) {
  176   				formComponent.addParameter("id", formComponent.escape(actionName));
  177   			}
  178   		} else if (action != null) {
  179   			// Since we can't find an action alias in the configuration, we just
  180   			// assume the action attribute supplied is the path to be used as
  181   			// the URI this form is submitting to.
  182   
  183               // Warn user that the specified namespace/action combo
  184               // was not found in the configuration.
  185               if (namespace != null) {
  186                 LOG.warn("No configuration found for the specified action: '" + actionName + "' in namespace: '" + namespace + "'. Form action defaulting to 'action' attribute's literal value.");
  187               }
  188   
  189   			String result = UrlHelper.buildUrl(action, formComponent.request, formComponent.response, null);
  190   			formComponent.addParameter("action", result);
  191   
  192   			// namespace: cut out anything between the start and the last /
  193   			int slash = result.lastIndexOf('/');
  194   			if (slash != -1) {
  195   				formComponent.addParameter("namespace", result.substring(0, slash));
  196   			} else {
  197   				formComponent.addParameter("namespace", "");
  198   			}
  199   
  200   			// name/id: cut out anything between / and . should be the id and
  201   			// name
  202   			String id = formComponent.getId();
  203   			if (id == null) {
  204   				slash = result.lastIndexOf('/');
  205   				int dot = result.indexOf('.', slash);
  206   				if (dot != -1) {
  207   					id = result.substring(slash + 1, dot);
  208   				} else {
  209   					id = result.substring(slash + 1);
  210   				}
  211   				formComponent.addParameter("id", formComponent.escape(id));
  212   			}
  213   		}
  214   
  215   		// WW-1284
  216   		// evaluate if client-side js is to be enabled. (if validation
  217   		// interceptor does allow validation eg. method is not filtered out)
  218   		formComponent.evaluateClientSideJsEnablement(actionName, namespace, actionMethod);
  219   	}
  220   
  221   
  222   	public void beforeRenderUrl(UrlProvider urlComponent) {
  223   		if (urlComponent.getValue() != null) {
  224               urlComponent.setValue(urlComponent.findString(urlComponent.getValue()));
  225           }
  226   
  227           // no explicit url set so attach params from current url, do
  228           // this at start so body params can override any of these they wish.
  229           try {
  230               // ww-1266
  231               String includeParams = (urlComponent.getUrlIncludeParams() != null ? urlComponent.getUrlIncludeParams().toLowerCase() : UrlProvider.GET);
  232   
  233               if (urlComponent.getIncludeParams() != null) {
  234                   includeParams = urlComponent.findString(urlComponent.getIncludeParams());
  235               }
  236   
  237               if (UrlProvider.NONE.equalsIgnoreCase(includeParams)) {
  238                   mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), Collections.EMPTY_MAP);
  239               } else if (UrlProvider.ALL.equalsIgnoreCase(includeParams)) {
  240                   mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), urlComponent.getHttpServletRequest().getParameterMap());
  241   
  242                   // for ALL also include GET parameters
  243                   includeGetParameters(urlComponent);
  244                   includeExtraParameters(urlComponent);
  245               } else if (UrlProvider.GET.equalsIgnoreCase(includeParams) || (includeParams == null && urlComponent.getValue() == null && urlComponent.getAction() == null)) {
  246                   includeGetParameters(urlComponent);
  247                   includeExtraParameters(urlComponent);
  248               } else if (includeParams != null) {
  249                   LOG.warn("Unknown value for includeParams parameter to URL tag: " + includeParams);
  250               }
  251           } catch (Exception e) {
  252               LOG.warn("Unable to put request parameters (" + urlComponent.getHttpServletRequest().getQueryString() + ") into parameter map.", e);
  253           }
  254   
  255   		
  256   	}
  257   	
  258       private void includeExtraParameters(UrlProvider urlComponent) {
  259           if (urlComponent.getExtraParameterProvider() != null) {
  260               mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), urlComponent.getExtraParameterProvider().getExtraParameters());
  261           }
  262       }
  263       private void includeGetParameters(UrlProvider urlComponent) {
  264       	String query = extractQueryString(urlComponent);
  265       	mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), UrlHelper.parseQueryString(query));
  266       }
  267   
  268       private String extractQueryString(UrlProvider urlComponent) {
  269           // Parse the query string to make sure that the parameters come from the query, and not some posted data
  270           String query = urlComponent.getHttpServletRequest().getQueryString();
  271           if (query == null) {
  272               query = (String) urlComponent.getHttpServletRequest().getAttribute("javax.servlet.forward.query_string");
  273           }
  274   
  275           if (query != null) {
  276               // Remove possible #foobar suffix
  277               int idx = query.lastIndexOf('#');
  278   
  279               if (idx != -1) {
  280                   query = query.substring(0, idx);
  281               }
  282           }
  283           return query;
  284       }
  285       
  286       /**
  287        * Merge request parameters into current parameters. If a parameter is
  288        * already present, than the request parameter in the current request and value atrribute
  289        * will not override its value.
  290        *
  291        * The priority is as follows:-
  292        * <ul>
  293        *  <li>parameter from the current request (least priority)</li>
  294        *  <li>parameter form the value attribute (more priority)</li>
  295        *  <li>parameter from the param tag (most priority)</li>
  296        * </ul>
  297        *
  298        * @param value the value attribute (url to be generated by this component)
  299        * @param parameters component parameters
  300        * @param contextParameters request parameters
  301        */
  302       protected void mergeRequestParameters(String value, Map parameters, Map contextParameters){
  303   
  304           Map mergedParams = new LinkedHashMap(contextParameters);
  305   
  306           // Merge contextParameters (from current request) with parameters specified in value attribute
  307           // eg. value="someAction.action?id=someId&venue=someVenue"
  308           // where the parameters specified in value attribute takes priority.
  309   
  310           if (value != null && value.trim().length() > 0 && value.indexOf("?") > 0) {
  311               String queryString = value.substring(value.indexOf("?")+1);
  312   
  313               mergedParams = UrlHelper.parseQueryString(queryString);
  314               for (Iterator iterator = contextParameters.entrySet().iterator(); iterator.hasNext();) {
  315                   Map.Entry entry = (Map.Entry) iterator.next();
  316                   Object key = entry.getKey();
  317   
  318                   if (!mergedParams.containsKey(key)) {
  319                       mergedParams.put(key, entry.getValue());
  320                   }
  321               }
  322           }
  323   
  324   
  325           // Merge parameters specified in value attribute
  326           // eg. value="someAction.action?id=someId&venue=someVenue"
  327           // with parameters specified though param tag
  328           // eg. <param name="id" value="%{'someId'}" />
  329           // where parameters specified through param tag takes priority.
  330   
  331           for (Iterator iterator = mergedParams.entrySet().iterator(); iterator.hasNext();) {
  332               Map.Entry entry = (Map.Entry) iterator.next();
  333               Object key = entry.getKey();
  334   
  335               if (!parameters.containsKey(key)) {
  336                   parameters.put(key, entry.getValue());
  337               }
  338           }
  339       }
  340   }

Save This Page
Home » struts-2.1.8.1-src » org.apache » struts2 » components » [javadoc | source]