Coverage Report - org.apache.turbine.util.uri.TurbineURI
 
Classes in this File Line Coverage Branch Coverage Complexity
TurbineURI
41%
77/184
58%
28/48
1,404
 
 1  
 package org.apache.turbine.util.uri;
 2  
 
 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  
 import java.io.UnsupportedEncodingException;
 23  
 import java.net.URLEncoder;
 24  
 import java.util.ArrayList;
 25  
 import java.util.Collection;
 26  
 import java.util.Iterator;
 27  
 import java.util.List;
 28  
 
 29  
 import org.apache.commons.lang3.StringUtils;
 30  
 import org.apache.fulcrum.parser.ParameterParser;
 31  
 import org.apache.fulcrum.parser.ParserService;
 32  
 import org.apache.logging.log4j.LogManager;
 33  
 import org.apache.logging.log4j.Logger;
 34  
 import org.apache.turbine.services.TurbineServices;
 35  
 import org.apache.turbine.util.RunData;
 36  
 import org.apache.turbine.util.ServerData;
 37  
 
 38  
 /**
 39  
  * This class allows you to keep all the information needed for a single
 40  
  * link at one place. It keeps your query data, path info, the server
 41  
  * scheme, name, port and the script path.
 42  
  *
 43  
  * If you must generate a Turbine Link, use this class.
 44  
  *
 45  
  * @author <a href="mailto:jon@clearink.com">Jon S. Stevens</a>
 46  
  * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
 47  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 48  
  * @version $Id: TurbineURI.java 1854688 2019-03-03 10:36:42Z tv $
 49  
  */
 50  
 
 51  
 public class TurbineURI
 52  
         extends BaseURI
 53  
 {
 54  
     /** Logging */
 55  12
     private static final Logger log = LogManager.getLogger(TurbineURI.class);
 56  
 
 57  
     /** Contains the PathInfo and QueryData vectors */
 58  42
     private List<URIParam> [] dataVectors = null;
 59  
 
 60  
     /** Local reference to the parser service for URI parameter folding */
 61  
     private ParserService parserService;
 62  
 
 63  
     /*
 64  
      * ========================================================================
 65  
      *
 66  
      * Constructors
 67  
      *
 68  
      * ========================================================================
 69  
      *
 70  
      */
 71  
 
 72  
     /**
 73  
      * Empty C'tor. Uses Turbine.getDefaultServerData().
 74  
      */
 75  
     public TurbineURI()
 76  
     {
 77  0
         super();
 78  0
         init();
 79  0
     }
 80  
 
 81  
     /**
 82  
      * Constructor with a RunData object.
 83  
      *
 84  
      * @param runData A RunData object
 85  
      */
 86  
     public TurbineURI(RunData runData)
 87  
     {
 88  27
         super(runData);
 89  27
         init();
 90  27
     }
 91  
 
 92  
     /**
 93  
      * Constructor, set explicit redirection.
 94  
      *
 95  
      * @param runData A RunData object
 96  
      * @param redirect True if redirection allowed.
 97  
      */
 98  
     public TurbineURI(RunData runData, boolean redirect)
 99  
     {
 100  0
         super(runData, redirect);
 101  0
         init();
 102  0
     }
 103  
 
 104  
     /**
 105  
      * Constructor, set Screen.
 106  
      *
 107  
      * @param runData A RunData object
 108  
      * @param screen A Screen Name
 109  
      */
 110  
     public TurbineURI(RunData runData, String screen)
 111  
     {
 112  0
         this(runData);
 113  0
         setScreen(screen);
 114  0
     }
 115  
 
 116  
     /**
 117  
      * Constructor, set Screen, set explicit redirection.
 118  
      *
 119  
      * @param runData A RunData object
 120  
      * @param screen A Screen Name
 121  
      * @param redirect True if redirection allowed.
 122  
      */
 123  
     public TurbineURI(RunData runData, String screen, boolean redirect)
 124  
     {
 125  0
         this(runData, redirect);
 126  0
         setScreen(screen);
 127  0
     }
 128  
 
 129  
     /**
 130  
      * Constructor, set Screen and Action.
 131  
      *
 132  
      * @param runData A RunData object
 133  
      * @param screen A Screen Name
 134  
      * @param action An Action Name
 135  
      */
 136  
     public TurbineURI(RunData runData, String screen, String action)
 137  
     {
 138  0
         this(runData, screen);
 139  0
         setAction(action);
 140  0
     }
 141  
 
 142  
     /**
 143  
      * Constructor, set Screen and Action, set explicit redirection.
 144  
      *
 145  
      * @param runData A RunData object
 146  
      * @param screen A Screen Name
 147  
      * @param action An Action Name
 148  
      * @param redirect True if redirection allowed.
 149  
      */
 150  
     public TurbineURI(RunData runData, String screen, String action, boolean redirect)
 151  
     {
 152  0
         this(runData, screen, redirect);
 153  0
         setAction(action);
 154  0
     }
 155  
 
 156  
     /**
 157  
      * Constructor with a ServerData object.
 158  
      *
 159  
      * @param serverData A ServerData object
 160  
      */
 161  
     public TurbineURI(ServerData serverData)
 162  
     {
 163  15
         super(serverData);
 164  15
         init();
 165  15
     }
 166  
 
 167  
     /**
 168  
      * Constructor, set explicit redirection.
 169  
      *
 170  
      * @param serverData A ServerData object
 171  
      * @param redirect True if redirection allowed.
 172  
      */
 173  
     public TurbineURI(ServerData serverData, boolean redirect)
 174  
     {
 175  0
         super(serverData, redirect);
 176  0
         init();
 177  0
     }
 178  
 
 179  
     /**
 180  
      * Constructor, set Screen.
 181  
      *
 182  
      * @param serverData A ServerData object
 183  
      * @param screen A Screen Name
 184  
      */
 185  
     public TurbineURI(ServerData serverData, String screen)
 186  
     {
 187  0
         this(serverData);
 188  0
         setScreen(screen);
 189  0
     }
 190  
 
 191  
     /**
 192  
      * Constructor, set Screen, set explicit redirection.
 193  
      *
 194  
      * @param serverData A ServerData object
 195  
      * @param screen A Screen Name
 196  
      * @param redirect True if redirection allowed.
 197  
      */
 198  
     public TurbineURI(ServerData serverData, String screen, boolean redirect)
 199  
     {
 200  0
         this(serverData, redirect);
 201  0
         setScreen(screen);
 202  0
     }
 203  
 
 204  
     /**
 205  
      * Constructor, set Screen and Action.
 206  
      *
 207  
      * @param serverData A ServerData object
 208  
      * @param screen A Screen Name
 209  
      * @param action An Action Name
 210  
      */
 211  
     public TurbineURI(ServerData serverData, String screen, String action)
 212  
     {
 213  0
         this(serverData, screen);
 214  0
         setAction(action);
 215  0
     }
 216  
 
 217  
     /**
 218  
      * Constructor, set Screen and Action, set explicit redirection.
 219  
      *
 220  
      * @param serverData A ServerData object
 221  
      * @param screen A Screen Name
 222  
      * @param action An Action Name
 223  
      * @param redirect True if redirection allowed.
 224  
      */
 225  
     public TurbineURI(ServerData serverData, String screen, String action,
 226  
                       boolean redirect)
 227  
     {
 228  0
         this(serverData, screen, redirect);
 229  0
         setAction(action);
 230  0
     }
 231  
 
 232  
     /**
 233  
      * Constructor, user Turbine.getDefaultServerData(), set Screen and Action.
 234  
      *
 235  
      * @param screen A Screen Name
 236  
      * @param action An Action Name
 237  
      */
 238  
     public TurbineURI(String screen, String action)
 239  
     {
 240  0
         this();
 241  0
         setScreen(screen);
 242  0
         setAction(action);
 243  0
     }
 244  
 
 245  
     /*
 246  
      * ========================================================================
 247  
      *
 248  
      * Init
 249  
      *
 250  
      * ========================================================================
 251  
      *
 252  
      */
 253  
 
 254  
     /**
 255  
      * Init the TurbineURI.
 256  
      */
 257  
     @SuppressWarnings("unchecked")
 258  
     private void init()
 259  
     {
 260  42
         dataVectors = new List[2];
 261  42
         dataVectors[PATH_INFO]  = new ArrayList<URIParam>();
 262  42
         dataVectors[QUERY_DATA] = new ArrayList<URIParam>();
 263  42
         parserService = (ParserService)TurbineServices.getInstance().getService(ParserService.ROLE);
 264  42
     }
 265  
 
 266  
     /**
 267  
      * Sets the action= value for this URL.
 268  
      *
 269  
      * By default it adds the information to the path_info instead
 270  
      * of the query data. An empty value (null or "") cleans out
 271  
      * an existing value.
 272  
      *
 273  
      * @param action A String with the action value.
 274  
      */
 275  
     public void setAction(String action)
 276  
     {
 277  0
         if(StringUtils.isNotEmpty(action))
 278  
         {
 279  0
             add(PATH_INFO, CGI_ACTION_PARAM, action);
 280  
         }
 281  
         else
 282  
         {
 283  0
             clearAction();
 284  
         }
 285  0
     }
 286  
 
 287  
     /**
 288  
      * Sets the fired eventSubmit= value for this URL.
 289  
      *
 290  
      * @param event The event to fire.
 291  
      *
 292  
      */
 293  
     public void setEvent(String event)
 294  
     {
 295  0
         add(PATH_INFO, EVENT_PREFIX + event, event);
 296  0
     }
 297  
 
 298  
     /**
 299  
      * Sets the action= and eventSubmit= values for this URL.
 300  
      *
 301  
      * By default it adds the information to the path_info instead
 302  
      * of the query data. An empty value (null or "") for the action cleans out
 303  
      * an existing value.  An empty value (null or "") for the event has no
 304  
      * effect.
 305  
      *
 306  
      * @param action A String with the action value.
 307  
      * @param event A string with the event name.
 308  
      */
 309  
     public void setActionEvent(String action, String event)
 310  
     {
 311  0
         setAction(action);
 312  0
         if(StringUtils.isNotEmpty(event))
 313  
         {
 314  0
             setEvent(event);
 315  
         }
 316  0
     }
 317  
 
 318  
     /**
 319  
      * Clears the action= value for this URL.
 320  
      */
 321  
     public void clearAction()
 322  
     {
 323  0
         removePathInfo(CGI_ACTION_PARAM);
 324  0
     }
 325  
 
 326  
     /**
 327  
      * Sets the screen= value for this URL.
 328  
      *
 329  
      * By default it adds the information to the path_info instead
 330  
      * of the query data. An empty value (null or "") cleans out
 331  
      * an existing value.
 332  
      *
 333  
      * @param screen A String with the screen value.
 334  
      */
 335  
     public void setScreen(String screen)
 336  
     {
 337  0
         if(StringUtils.isNotEmpty(screen))
 338  
         {
 339  0
             add(PATH_INFO, CGI_SCREEN_PARAM, screen);
 340  
         }
 341  
         else
 342  
         {
 343  0
             clearScreen();
 344  
         }
 345  0
     }
 346  
 
 347  
     /**
 348  
      * Clears the screen= value for this URL.
 349  
      */
 350  
     public void clearScreen()
 351  
     {
 352  0
         removePathInfo(CGI_SCREEN_PARAM);
 353  0
     }
 354  
 
 355  
     /*
 356  
      * ========================================================================
 357  
      *
 358  
      * Adding and removing Data from the Path Info and Query Data
 359  
      *
 360  
      * ========================================================================
 361  
      */
 362  
 
 363  
 
 364  
     /**
 365  
      * Adds a name=value pair for every entry in a ParameterParser
 366  
      * object to the path_info string.
 367  
      *
 368  
      * @param pp A ParameterParser.
 369  
      */
 370  
     public void addPathInfo(ParameterParser pp)
 371  
     {
 372  0
         add(PATH_INFO, pp);
 373  0
     }
 374  
 
 375  
     /**
 376  
      * Adds an existing List of URIParam objects to
 377  
      * the path_info string.
 378  
      *
 379  
      * @param list A list with URIParam objects.
 380  
      */
 381  
     public void addPathInfo(List<URIParam> list)
 382  
     {
 383  0
         add(PATH_INFO, list);
 384  0
     }
 385  
 
 386  
     /**
 387  
      * Adds a name=value pair to the path_info string.
 388  
      *
 389  
      * @param name A String with the name to add.
 390  
      * @param value An Object with the value to add.
 391  
      */
 392  
     public void addPathInfo(String name, Object value)
 393  
     {
 394  0
         add(PATH_INFO, name, null == value ? null : value.toString());
 395  0
     }
 396  
 
 397  
     /**
 398  
      * Adds a name=value pair to the path_info string.
 399  
      *
 400  
      * @param name A String with the name to add.
 401  
      * @param value A String with the value to add.
 402  
      */
 403  
     public void addPathInfo(String name, String value)
 404  
     {
 405  9
         add(PATH_INFO, name, value);
 406  9
     }
 407  
 
 408  
     /**
 409  
      * Adds a name=value pair to the path_info string.
 410  
      *
 411  
      * @param name A String with the name to add.
 412  
      * @param value A double with the value to add.
 413  
      */
 414  
     public void addPathInfo(String name, double value)
 415  
     {
 416  0
         add(PATH_INFO, name, Double.toString(value));
 417  0
     }
 418  
 
 419  
     /**
 420  
      * Adds a name=value pair to the path_info string.
 421  
      *
 422  
      * @param name A String with the name to add.
 423  
      * @param value An int with the value to add.
 424  
      */
 425  
     public void addPathInfo(String name, int value)
 426  
     {
 427  0
         add(PATH_INFO, name, Integer.toString(value));
 428  0
     }
 429  
 
 430  
     /**
 431  
      * Adds a name=value pair to the path_info string.
 432  
      *
 433  
      * @param name A String with the name to add.
 434  
      * @param value A long with the value to add.
 435  
      */
 436  
     public void addPathInfo(String name, long value)
 437  
     {
 438  0
         add(PATH_INFO, name, Long.toString(value));
 439  0
     }
 440  
 
 441  
     /**
 442  
      * Adds a name=value pair to the query string.
 443  
      *
 444  
      * @param name A String with the name to add.
 445  
      * @param value An Object with the value to add.
 446  
      */
 447  
     public void addQueryData(String name, Object value)
 448  
     {
 449  0
         add(QUERY_DATA, name, null == value ? null : value.toString());
 450  0
     }
 451  
 
 452  
     /**
 453  
      * Adds a name=value pair to the query string.
 454  
      *
 455  
      * @param name A String with the name to add.
 456  
      * @param value A String with the value to add.
 457  
      */
 458  
     public void addQueryData(String name, String value)
 459  
     {
 460  9
         add(QUERY_DATA, name, value);
 461  9
     }
 462  
 
 463  
     /**
 464  
      * Adds a name=value pair to the query string.
 465  
      *
 466  
      * @param name A String with the name to add.
 467  
      * @param value A double with the value to add.
 468  
      */
 469  
     public void addQueryData(String name, double value)
 470  
     {
 471  0
         add(QUERY_DATA, name, Double.toString(value));
 472  0
     }
 473  
 
 474  
     /**
 475  
      * Adds a name=value pair to the query string.
 476  
      *
 477  
      * @param name A String with the name to add.
 478  
      * @param value An int with the value to add.
 479  
      */
 480  
     public void addQueryData(String name, int value)
 481  
     {
 482  0
         add(QUERY_DATA, name, Integer.toString(value));
 483  0
     }
 484  
 
 485  
     /**
 486  
      * Adds a name=value pair to the query string.
 487  
      *
 488  
      * @param name A String with the name to add.
 489  
      * @param value A long with the value to add.
 490  
      */
 491  
     public void addQueryData(String name, long value)
 492  
     {
 493  0
         add(QUERY_DATA, name, Long.toString(value));
 494  0
     }
 495  
 
 496  
     /**
 497  
      * Adds a name=value pair for every entry in a ParameterParser
 498  
      * object to the query string.
 499  
      *
 500  
      * @param pp A ParameterParser.
 501  
      */
 502  
     public void addQueryData(ParameterParser pp)
 503  
     {
 504  0
         add(QUERY_DATA, pp);
 505  0
     }
 506  
 
 507  
     /**
 508  
      * Adds an existing List of URIParam objects to the query data.
 509  
      *
 510  
      * @param list A list with URIParam objects.
 511  
      */
 512  
     public void addQueryData(List<URIParam> list)
 513  
     {
 514  0
         add(QUERY_DATA, list);
 515  0
     }
 516  
 
 517  
     /**
 518  
      * Is Path Info data set in this URI?
 519  
      *
 520  
      * @return true if Path Info has values
 521  
      */
 522  
     public boolean hasPathInfo()
 523  
     {
 524  60
         return !dataVectors[PATH_INFO].isEmpty();
 525  
     }
 526  
 
 527  
     /**
 528  
      * Removes all the path info elements.
 529  
      */
 530  
     public void removePathInfo()
 531  
     {
 532  0
         dataVectors[PATH_INFO].clear();
 533  0
     }
 534  
 
 535  
     /**
 536  
      * Removes a name=value pair from the path info.
 537  
      *
 538  
      * @param name A String with the name to be removed.
 539  
      */
 540  
     public void removePathInfo(String name)
 541  
     {
 542  9
         remove(PATH_INFO, name);
 543  9
     }
 544  
 
 545  
     /**
 546  
      * Is Query data set in this URI?
 547  
      *
 548  
      * @return true if Query data has values
 549  
      */
 550  
     public boolean hasQueryData()
 551  
     {
 552  60
         return !dataVectors[QUERY_DATA].isEmpty();
 553  
     }
 554  
 
 555  
     /**
 556  
      * Removes all the query string elements.
 557  
      */
 558  
     public void removeQueryData()
 559  
     {
 560  0
         dataVectors[QUERY_DATA].clear();
 561  0
     }
 562  
 
 563  
     /**
 564  
      * Removes a name=value pair from the query string.
 565  
      *
 566  
      * @param name A String with the name to be removed.
 567  
      */
 568  
     public void removeQueryData(String name)
 569  
     {
 570  15
         remove (QUERY_DATA, name);
 571  15
     }
 572  
 
 573  
     /**
 574  
      * Template Link and friends want to be able to turn the encoding
 575  
      * of the servlet container off. After calling this method,
 576  
      * the no encoding will happen any longer. If you think, that you
 577  
      * need this outside a template context, think again.
 578  
      */
 579  
     public void clearResponse()
 580  
     {
 581  0
         setResponse(null);
 582  0
     }
 583  
 
 584  
 
 585  
     /**
 586  
      * Builds the URL with all of the data URL-encoded as well as
 587  
      * encoded using HttpServletResponse.encodeUrl(). The resulting
 588  
      * URL is absolute; it starts with http/https...
 589  
      *
 590  
      * <pre>
 591  
      * TurbineURI tui = new TurbineURI (data, "UserScreen");
 592  
      * tui.addPathInfo("user","jon");
 593  
      * tui.getAbsoluteLink();
 594  
      * </pre>
 595  
      *
 596  
      *  The above call to absoluteLink() would return the String:
 597  
      *
 598  
      * <p>
 599  
      * http://www.server.com/servlets/Turbine/screen/UserScreen/user/jon
 600  
      * </p>
 601  
      *
 602  
      * @return A String with the built URL.
 603  
      */
 604  
     public String getAbsoluteLink()
 605  
     {
 606  0
         StringBuilder output = new StringBuilder();
 607  
 
 608  0
         getSchemeAndPort(output);
 609  
 
 610  0
         buildRelativeLink(output);
 611  
 
 612  
         //
 613  
         // Encode Response does all the fixup for the Servlet Container
 614  
         //
 615  0
         return encodeResponse(output.toString());
 616  
     }
 617  
 
 618  
     /**
 619  
      * Builds the URL with all of the data URL-encoded as well as
 620  
      * encoded using HttpServletResponse.encodeUrl(). The resulting
 621  
      * URL is relative to the webserver root.
 622  
      *
 623  
      * <pre>
 624  
      * TurbineURI tui = new TurbineURI (data, "UserScreen");
 625  
      * tui.addPathInfo("user","jon");
 626  
      * tui.getRelativeLink();
 627  
      * </pre>
 628  
      *
 629  
      *  The above call to relativeLink() would return the String:
 630  
      *
 631  
      * <p>
 632  
      * /servlets/Turbine/screen/UserScreen/user/jon
 633  
      * </p>
 634  
      *
 635  
      * @return A String with the built URL.
 636  
      */
 637  
     public String getRelativeLink()
 638  
     {
 639  42
         StringBuilder output = new StringBuilder();
 640  
 
 641  42
         buildRelativeLink(output);
 642  
 
 643  
         //
 644  
         // Encode Response does all the fixup for the Servlet Container
 645  
         //
 646  42
         return encodeResponse(output.toString());
 647  
     }
 648  
 
 649  
     /**
 650  
      * Add everything needed for a relative link to the passed StringBuilder.
 651  
      *
 652  
      * @param output A Stringbuffer
 653  
      */
 654  
     private void buildRelativeLink(StringBuilder output)
 655  
     {
 656  42
         getContextAndScript(output);
 657  
 
 658  42
         if (hasPathInfo())
 659  
         {
 660  6
             output.append('/');
 661  6
             getPathInfoAsString(output);
 662  
         }
 663  
 
 664  42
         if (hasReference())
 665  
         {
 666  0
             output.append('#');
 667  0
             output.append(getReference());
 668  
         }
 669  
 
 670  42
         if (hasQueryData())
 671  
         {
 672  9
             output.append('?');
 673  9
             getQueryDataAsString(output);
 674  
         }
 675  42
     }
 676  
 
 677  
     /**
 678  
      * Gets the current Query Data List.
 679  
      *
 680  
      * @return A List which contains all query data keys. The keys
 681  
      * are URIParam objects.
 682  
      */
 683  
     public List<URIParam> getPathInfo()
 684  
     {
 685  0
         return dataVectors[PATH_INFO];
 686  
     }
 687  
 
 688  
     /**
 689  
      * Sets the Query Data List. Replaces the current query data list
 690  
      * with the one supplied. The list must contain only URIParam
 691  
      * objects!
 692  
      *
 693  
      * @param pathInfo A List with new param objects.
 694  
      */
 695  
 
 696  
     public void setPathInfo(List<URIParam> pathInfo)
 697  
     {
 698  0
         dataVectors[PATH_INFO] = pathInfo;
 699  0
     }
 700  
 
 701  
     /**
 702  
      * Gets the current Query Data List.
 703  
      *
 704  
      * @return A List which contains all query data keys. The keys
 705  
      * are URIParam objects.
 706  
      */
 707  
     public List<URIParam> getQueryData()
 708  
     {
 709  0
         return dataVectors[QUERY_DATA];
 710  
     }
 711  
 
 712  
     /**
 713  
      * Sets the Query Data List. Replaces the current query data list
 714  
      * with the one supplied. The list must contain only URIParam
 715  
      * objects!
 716  
      *
 717  
      * @param queryData A List with new param objects.
 718  
      */
 719  
 
 720  
     public void setQueryData(List<URIParam> queryData)
 721  
     {
 722  0
         dataVectors[QUERY_DATA] = queryData;
 723  0
     }
 724  
 
 725  
     /**
 726  
      * Simply calls getAbsoluteLink(). You should not use this in your
 727  
      * code unless you have to. Use getAbsoluteLink.
 728  
      *
 729  
      * @return This URI as a String
 730  
      *
 731  
      */
 732  
     @Override
 733  
     public String toString()
 734  
     {
 735  0
         return getAbsoluteLink();
 736  
     }
 737  
 
 738  
     /*
 739  
      * ========================================================================
 740  
      *
 741  
      * Protected / Private Methods
 742  
      *
 743  
      * ========================================================================
 744  
      *
 745  
      */
 746  
 
 747  
     /**
 748  
      * Returns the Path Info data as a String.
 749  
      *
 750  
      * @param output The StringBuilder that should hold the path info.
 751  
      */
 752  
     private void getPathInfoAsString(StringBuilder output)
 753  
     {
 754  6
         doEncode(output, dataVectors[PATH_INFO], '/', '/');
 755  6
     }
 756  
 
 757  
     /**
 758  
      * Returns the Query data as a String.
 759  
      *
 760  
      * @param output The StringBuilder that should hold the query data.
 761  
      */
 762  
     private void getQueryDataAsString(StringBuilder output)
 763  
     {
 764  9
         doEncode(output, dataVectors[QUERY_DATA], '&', '=');
 765  9
     }
 766  
 
 767  
     /**
 768  
      * Does the actual encoding for pathInfoAsString and queryDataAsString.
 769  
      *
 770  
      * @param output The Stringbuffer that should contain the information.
 771  
      * @param list A Collection
 772  
      * @param fieldDelim A char which is used to separate key/value pairs
 773  
      * @param valueDelim A char which is used to separate key and value
 774  
      */
 775  
     private void doEncode(StringBuilder output, Collection<URIParam> list, char fieldDelim, char valueDelim)
 776  
     {
 777  15
         if(!list.isEmpty())
 778  
         {
 779  15
                 String encoding = parserService.getParameterEncoding();
 780  
 
 781  15
             for(Iterator<URIParam> it = list.iterator(); it.hasNext();)
 782  
             {
 783  
                     try
 784  
                     {
 785  15
                                         URIParam uriParam = it.next();
 786  15
                                         String key = URLEncoder.encode(uriParam.getKey(), encoding);
 787  15
                                         String val = null == uriParam.getValue()
 788  9
                                                 ? null : String.valueOf(uriParam.getValue());
 789  
 
 790  15
                                         output.append(key);
 791  15
                                         output.append(valueDelim);
 792  
 
 793  15
                                         if(StringUtils.isEmpty(val))
 794  
                                         {
 795  15
                                             if (val == null)
 796  
                                             {
 797  6
                                             log.warn("Found a null value for {}", key);
 798  
                                                 // For backwards compatibility:
 799  6
                                                 val = "null";
 800  
                                             }
 801  15
                                             output.append(val);
 802  
                                         }
 803  
                                         else
 804  
                                         {
 805  0
                                             output.append(URLEncoder.encode(val, encoding));
 806  
                                         }
 807  
 
 808  15
                                         if (it.hasNext())
 809  
                                         {
 810  0
                                             output.append(fieldDelim);
 811  
                                         }
 812  
                                 }
 813  0
                     catch (UnsupportedEncodingException e)
 814  
                     {
 815  0
                             log.warn("Unsupported encoding {}", encoding);
 816  15
                                 }
 817  
             }
 818  
         }
 819  15
     }
 820  
 
 821  
     /**
 822  
      * If the type is PATH_INFO, then add name/value to the pathInfo
 823  
      * hashtable.
 824  
      * <p>
 825  
      * If the type is QUERY_DATA, then add name/value to the queryData
 826  
      * hashtable.
 827  
      *
 828  
      * @param type Type (PATH_INFO or QUERY_DATA) of insertion.
 829  
      * @param name A String with the name to add.
 830  
      * @param value A String with the value to add.
 831  
      */
 832  
     protected void add(int type,
 833  
             String name,
 834  
             String value)
 835  
     {
 836  21
         URIParam uriParam = new URIParam(parserService.convertAndTrim(name), value);
 837  
 
 838  21
         dataVectors[type].add(uriParam); // Code so clean you can eat from...
 839  21
     }
 840  
 
 841  
     /**
 842  
      * Method for a quick way to add all the parameters in a
 843  
      * ParameterParser.
 844  
      *
 845  
      * <p>If the type is P (0), then add name/value to the pathInfo
 846  
      * hashtable.
 847  
      *
 848  
      * <p>If the type is Q (1), then add name/value to the queryData
 849  
      * hashtable.
 850  
      *
 851  
      * @param type Type of insertion (@see #add(char type, String name, String value))
 852  
      * @param pp A ParameterParser.
 853  
      */
 854  
     protected void add(int type,
 855  
             ParameterParser pp)
 856  
     {
 857  9
         for(Iterator<?> it = pp.keySet().iterator(); it.hasNext();)
 858  
         {
 859  3
             String key = (String) it.next();
 860  
 
 861  3
             if (!key.equalsIgnoreCase(CGI_ACTION_PARAM) &&
 862  3
                     !key.equalsIgnoreCase(CGI_SCREEN_PARAM))
 863  
             {
 864  3
                 String[] values = pp.getStrings(key);
 865  3
                 if(values != null)
 866  
                 {
 867  6
                     for (int i = 0; i < values.length; i++)
 868  
                     {
 869  3
                         add(type, key, values[i]);
 870  
                     }
 871  
                 }
 872  
                 else
 873  
                 {
 874  0
                     add(type, key, "");
 875  
                 }
 876  
             }
 877  3
         }
 878  9
     }
 879  
 
 880  
     /**
 881  
      * Method for a quick way to add all the parameters in a
 882  
      * List with URIParam objects.
 883  
      *
 884  
      * <p>If the type is P (0), then add name/value to the pathInfo
 885  
      * hashtable.
 886  
      *
 887  
      * <p>If the type is Q (1), then add name/value to the queryData
 888  
      * hashtable.
 889  
      *
 890  
      * @param type Type of insertion (@see #add(char type, String name, String value))
 891  
      * @param list A List of URIParam objects
 892  
      */
 893  
     protected void add(int type, List<URIParam> list)
 894  
     {
 895  0
         for (URIParam uriParam : list)
 896  
         {
 897  0
             dataVectors[type].add(uriParam);
 898  0
         }
 899  0
     }
 900  
 
 901  
     /**
 902  
      * If the type is P (0), then remove name/value from the
 903  
      * pathInfo hashtable.
 904  
      *
 905  
      * <p>If the type is Q (1), then remove name/value from the
 906  
      * queryData hashtable.
 907  
      *
 908  
      * @param type Type (P or Q) of removal.
 909  
      * @param name A String with the name to be removed.
 910  
      */
 911  
     protected void remove (int type, String name)
 912  
     {
 913  24
         Collection<URIParam> c = dataVectors[type];
 914  24
         String key = parserService.convertAndTrim(name);
 915  
 
 916  24
         for (Iterator<URIParam> it = c.iterator(); it.hasNext();)
 917  
         {
 918  21
             URIParam uriParam = it.next();
 919  
 
 920  21
             if (key.equals(uriParam.getKey()))
 921  
             {
 922  21
                 it.remove();
 923  
             }
 924  21
         }
 925  24
     }
 926  
 }