Coverage report

  %line %branch
org.apache.jetspeed.container.state.impl.JetspeedNavigationalStateCodec
0% 
0% 

 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.jetspeed.container.state.impl;
 18  
 
 19  
 import java.io.UnsupportedEncodingException;
 20  
 import java.util.ArrayList;
 21  
 import java.util.Iterator;
 22  
 import java.util.Map;
 23  
 
 24  
 import javax.portlet.PortletMode;
 25  
 import javax.portlet.WindowState;
 26  
 
 27  
 import org.apache.commons.codec.binary.Base64;
 28  
 import org.apache.commons.logging.Log;
 29  
 import org.apache.commons.logging.LogFactory;
 30  
 import org.apache.jetspeed.JetspeedActions;
 31  
 import org.apache.jetspeed.PortalContext;
 32  
 import org.apache.jetspeed.PortalReservedParameters;
 33  
 import org.apache.jetspeed.container.window.PortletWindowAccessor;
 34  
 import org.apache.pluto.om.window.PortletWindow;
 35  
 
 36  
 /**
 37  
  * JetspeedNavigationalStateCodec
 38  
  *
 39  
  * @author <a href="mailto:ate@apache.org">Ate Douma</a>
 40  
  * @version $Id: JetspeedNavigationalStateCodec.java 554926 2007-07-10 13:12:26Z ate $
 41  
  */
 42  
 public class JetspeedNavigationalStateCodec implements NavigationalStateCodec
 43  
 {
 44  
     /** Commons logging */
 45  0
     protected final static Log log = LogFactory.getLog(JetspeedNavigationalStateCodec.class);
 46  
 
 47  
     protected static final char PARAMETER_SEPARATOR = '|';
 48  
     protected static final char PARAMETER_ELEMENT_SEPARATOR = '=';    
 49  
     protected static final char RENDER_WINDOW_ID_KEY = 'a';
 50  
     protected static final char ACTION_WINDOW_ID_KEY = 'b';
 51  
     protected static final char MODE_KEY = 'c';
 52  
     protected static final char STATE_KEY = 'd';
 53  
     protected static final char PARAM_KEY = 'e';
 54  
     protected static final char CLEAR_PARAMS_KEY = 'f';
 55  
     protected static final char RESOURCE_WINDOW_ID_KEY = 'g';
 56  
     
 57  
     protected static final String keytable = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
 58  
     protected final PortletMode[] portletModes;
 59  
     protected final WindowState[] windowStates;
 60  
     private final PortletWindowAccessor windowAccessor;
 61  
     
 62  
     public JetspeedNavigationalStateCodec(PortalContext portalContext, PortletWindowAccessor windowAccessor)
 63  0
     {
 64  0
         ArrayList list = new ArrayList();
 65  0
         this.windowAccessor = windowAccessor;
 66  
         
 67  
         // ensure standard modes will be first in the portletModeNames array
 68  
         // this ensures those modes are never lost from a bookmarked url when new modes are added somewhere in the
 69  
         // middle
 70  0
         list.addAll(JetspeedActions.getStandardPortletModes());
 71  0
         list.addAll(JetspeedActions.getExtendedPortletModes());
 72  
         
 73  0
         portletModes = (PortletMode[])list.toArray(new PortletMode[list.size()]);
 74  0
         if (portletModes.length > keytable.length())
 75  
         {
 76  0
             throw new UnsupportedOperationException("Too many supported PortletModes found. Can only handle max: "+keytable.length());
 77  
         }
 78  
         
 79  0
         list.clear();
 80  
         
 81  
         // ensure standard states will be first in the windowStateNames array
 82  
         // this ensures those states are never lost from a bookmarked url when new states are added somewhere in the
 83  
         // middle
 84  0
         list.addAll(JetspeedActions.getStandardWindowStates());
 85  0
         list.addAll(JetspeedActions.getExtendedWindowStates());
 86  
         
 87  0
         windowStates = (WindowState[])list.toArray(new WindowState[list.size()]);        
 88  0
         if (windowStates.length > keytable.length())
 89  
         {
 90  0
             throw new UnsupportedOperationException("Too many supported WindowModes found. Can only handle max: "+keytable.length());
 91  
         }
 92  0
     }
 93  
     
 94  
     public PortletWindowRequestNavigationalStates decode(String parameters, String characterEncoding)
 95  
     throws UnsupportedEncodingException
 96  
     {
 97  0
         PortletWindowRequestNavigationalStates states = new PortletWindowRequestNavigationalStates(characterEncoding);
 98  0
         if ( parameters != null && parameters.length() > 0 ) 
 99  
         {
 100  0
             String decodedParameters = decodeParameters(parameters, characterEncoding);
 101  
             
 102  0
             int position = 0;
 103  0
             StringBuffer buffer = new StringBuffer();
 104  
             
 105  0
             PortletWindowRequestNavigationalState currentState = null;
 106  
             String parameter;
 107  0
             while ( (position = decodeArgument(position, decodedParameters, buffer, PARAMETER_SEPARATOR )) != -1 )
 108  
             {
 109  0
                 parameter = buffer.toString();
 110  0
                 currentState = decodeParameter( windowAccessor, states, currentState, parameter);
 111  
             }
 112  
             
 113  0
             if ( log.isDebugEnabled() )
 114  
             {
 115  0
                 logDecode(states, buffer);
 116  0
                 if ( buffer.length() > 0 )
 117  
                 {
 118  0
                     buffer.append("]");
 119  0
                     log.debug("navstate decoded="+buffer.toString());
 120  
                 }
 121  
             }
 122  
         }
 123  0
         return states;
 124  
     }
 125  
 
 126  
     private void logDecode(PortletWindowRequestNavigationalStates states, StringBuffer buffer)
 127  
     {
 128  
         PortletWindowRequestNavigationalState currentState;
 129  0
         buffer.setLength(0);
 130  0
         String actionWindowId = states.getActionWindow() != null ? states.getActionWindow().getId().toString() : "";
 131  0
         Iterator iter = states.getWindowIdIterator();
 132  0
         while ( iter.hasNext() )
 133  
         {
 134  0
             if ( buffer.length() == 0 )
 135  
             {
 136  0
                 buffer.append("[[");
 137  
             }
 138  
             else
 139  
             {
 140  0
                 buffer.append(",[");
 141  
             }
 142  0
             currentState = states.getPortletWindowNavigationalState((String)iter.next());
 143  0
             buffer.append("window:"+currentState.getWindowId());
 144  
             
 145  0
             if ( currentState.getWindowId().equals(actionWindowId))
 146  
             {
 147  0
                 buffer.append(",action:true");
 148  
             }
 149  0
             if (currentState.getPortletMode() != null) 
 150  
             {
 151  0
                 buffer.append(",mode:"+currentState.getPortletMode());
 152  
             }
 153  0
             if (currentState.getWindowState() != null )
 154  
             {
 155  0
                 buffer.append(",state:"+currentState.getWindowState());
 156  
             }
 157  0
             if (!currentState.isClearParameters())
 158  
             {
 159  0
                 if (currentState.getParametersMap() != null)
 160  
                 {
 161  0
                     buffer.append(",parameters:[");
 162  0
                     boolean first = true;
 163  0
                     Iterator parIter = currentState.getParametersMap().keySet().iterator();
 164  0
                     while ( parIter.hasNext() ) 
 165  
                     {
 166  0
                         if ( first )
 167  
                         {
 168  0
                             first = false;
 169  
                         }
 170  
                         else
 171  
                         {
 172  0
                             buffer.append(",");
 173  
                         }
 174  0
                         String name = (String)parIter.next();
 175  0
                         buffer.append(name+":[");
 176  0
                         String[] values = (String[])currentState.getParametersMap().get(name);
 177  0
                         for ( int i = 0; i < values.length; i++ )
 178  
                         {
 179  0
                             if ( i > 0 )
 180  
                             {
 181  0
                                 buffer.append(",");
 182  
                             }                                    
 183  0
                             buffer.append(values[i]);
 184  
                         }
 185  0
                         buffer.append("]");
 186  0
                     }
 187  
                 }
 188  
             }
 189  0
             buffer.append("]");
 190  
         }
 191  0
     }
 192  
     
 193  
     public String encode(PortletWindowRequestNavigationalStates states, PortletWindow window, PortletMode portletMode, 
 194  
             WindowState windowState, boolean navParamsStateFull, class="keyword">boolean renderParamsStateFull)
 195  
     throws UnsupportedEncodingException
 196  
     {
 197  0
         String windowId = window.getId().toString();
 198  0
         PortletWindowRequestNavigationalState currentState = states.getPortletWindowNavigationalState(windowId);
 199  0
         PortletWindowRequestNavigationalState targetState = new PortletWindowRequestNavigationalState(windowId);
 200  0
         targetState.setPortletMode(portletMode != null ? portletMode : currentState != class="keyword">null ? currentState.getPortletMode() : class="keyword">null);
 201  0
         targetState.setWindowState(windowState != null ? windowState : currentState != class="keyword">null ? currentState.getWindowState() : class="keyword">null);
 202  
 
 203  
         // never retain actionRequest parameters nor session stored renderParameters
 204  0
         if ( currentState != null && !renderParamsStateFull )
 205  
         {
 206  
             // retain current request parameters if any
 207  0
             if ( currentState.getParametersMap() != null )
 208  
             {
 209  0
                 Iterator parametersIter = currentState.getParametersMap().entrySet().iterator();
 210  
                 Map.Entry entry;
 211  0
                 while ( parametersIter.hasNext())
 212  
                 {
 213  0
                     entry = (Map.Entry)parametersIter.next();
 214  0
                     targetState.setParameters((String)entry.getKey(), (String[])entry.getValue());
 215  
                 }
 216  
             }
 217  
         }
 218  
         // encode as requestURL parameters
 219  0
         return encode(states, windowId, targetState, false, false, navParamsStateFull, renderParamsStateFull);
 220  
     }
 221  
 
 222  
     public String encode(PortletWindowRequestNavigationalStates states, PortletWindow window, Map parameters, 
 223  
             PortletMode portletMode, WindowState windowState, boolean action, class="keyword">boolean navParamsStateFull, 
 224  
             boolean renderParamsStateFull)
 225  
     throws UnsupportedEncodingException
 226  
     {
 227  0
         String windowId = window.getId().toString();
 228  0
         PortletWindowRequestNavigationalState currentState = states.getPortletWindowNavigationalState(windowId);
 229  0
         PortletWindowRequestNavigationalState targetState = new PortletWindowRequestNavigationalState(windowId);
 230  0
         targetState.setPortletMode(portletMode != null ? portletMode : currentState != class="keyword">null ? currentState.getPortletMode() : class="keyword">null);
 231  0
         targetState.setWindowState(windowState != null ? windowState : currentState != class="keyword">null ? currentState.getWindowState() : class="keyword">null);
 232  
         
 233  0
         Iterator parametersIter = parameters.entrySet().iterator();
 234  
         
 235  0
         boolean resource = false;
 236  
 
 237  
         Map.Entry entry;
 238  
         String parameter;
 239  
         // fill in the new parameters
 240  0
         while ( parametersIter.hasNext())
 241  
         {
 242  0
             entry = (Map.Entry)parametersIter.next();
 243  0
             parameter = (String)entry.getKey();
 244  0
             if (!resource && !action && PortalReservedParameters.PORTLET_RESOURCE_URL_REQUEST_PARAMETER.equals(parameter))
 245  
             {
 246  0
                 resource = true;
 247  0
                 navParamsStateFull = true;
 248  0
                 renderParamsStateFull = true;
 249  
             }
 250  
             else
 251  
             {
 252  0
                 targetState.setParameters(parameter, (String[])entry.getValue());
 253  
             }
 254  
         }
 255  0
         if ( renderParamsStateFull && targetState.getParametersMap() == null )
 256  
         {
 257  
             // Indicate that the saved (in the session) render parameters for this PortletWindow must be cleared
 258  
             // and not copied when synchronizing the state (encoded as CLEAR_PARAMS_KEY)
 259  0
             targetState.setClearParameters(true);
 260  
         }
 261  0
         return encode(states, windowId, targetState, action, resource, navParamsStateFull, renderParamsStateFull);
 262  
     }
 263  
 
 264  
     public String encode(PortletWindowRequestNavigationalStates states, boolean navParamsStateFull, class="keyword">boolean renderParamsStateFull)
 265  
     throws UnsupportedEncodingException
 266  
     {
 267  0
         return encode(states, null, class="keyword">null, false, false, navParamsStateFull, renderParamsStateFull);
 268  
     }
 269  
     protected String encode(PortletWindowRequestNavigationalStates states, String targetWindowId, 
 270  
             PortletWindowRequestNavigationalState targetState, boolean action, class="keyword">boolean resource, class="keyword">boolean navParamsStateFull, 
 271  
             boolean renderParamsStateFull)
 272  
     throws UnsupportedEncodingException
 273  
     {
 274  0
         StringBuffer buffer = new StringBuffer();
 275  
         String encodedState;
 276  0
         boolean haveState = false;
 277  
         
 278  
         // skip other states if all non-targeted PortletWindow states are kept in the session
 279  0
         if ( !navParamsStateFull || !renderParamsStateFull )
 280  
         {
 281  
             PortletWindowRequestNavigationalState pwfns;
 282  
             String windowId;
 283  0
             Iterator iter = states.getWindowIdIterator();
 284  0
             while ( iter.hasNext() )
 285  
             {
 286  0
                 windowId = (String)iter.next();
 287  0
                 pwfns = states.getPortletWindowNavigationalState(windowId);
 288  0
                 if ( targetWindowId != null && windowId.equals(targetWindowId))
 289  
                 {
 290  
                     // skip it for now, it will be encoded as the last one below
 291  
                 }
 292  
                 else
 293  
                 {
 294  0
                     encodedState = encodePortletWindowNavigationalState(windowId, pwfns, false, false, navParamsStateFull, 
 295  
                             renderParamsStateFull);
 296  0
                     if ( encodedState.length() > 0 )
 297  
                     {
 298  0
                         if ( !haveState )
 299  
                         {
 300  0
                             haveState = true;
 301  
                         }
 302  
                         else
 303  
                         {
 304  0
                             buffer.append(PARAMETER_SEPARATOR);
 305  
                         }
 306  0
                         buffer.append(encodedState);
 307  
                     }
 308  
                 }
 309  
             }
 310  
         }
 311  0
         if (targetWindowId != null)
 312  
         {
 313  0
             encodedState = encodePortletWindowNavigationalState(targetWindowId, targetState, action, resource, false, false); 
 314  0
             if ( encodedState.length() > 0 )
 315  
             {
 316  0
                 if ( !haveState )
 317  
                 {
 318  0
                     haveState = true;
 319  
                 }
 320  
                 else
 321  
                 {
 322  0
                     buffer.append(PARAMETER_SEPARATOR);
 323  
                 }
 324  0
                 buffer.append(encodedState);
 325  
             }
 326  
         }
 327  0
         String encodedNavState = null;
 328  0
         if ( haveState )
 329  
         {
 330  0
             encodedNavState = encodeParameters(buffer.toString(), states.getCharacterEncoding());
 331  
         }
 332  0
         return encodedNavState;
 333  
     }
 334  
     
 335  
     protected String encodePortletWindowNavigationalState(String windowId, PortletWindowRequestNavigationalState state, 
 336  
             boolean action, class="keyword">boolean resource, class="keyword">boolean navParamsStateFull, class="keyword">boolean renderParamsStateFull)
 337  
     {
 338  0
         StringBuffer buffer = new StringBuffer();
 339  0
         buffer.append(action ? ACTION_WINDOW_ID_KEY : resource? RESOURCE_WINDOW_ID_KEY: RENDER_WINDOW_ID_KEY);
 340  0
         buffer.append(windowId);
 341  0
         boolean encoded = action || resource;
 342  
         
 343  0
         if ( action || !navParamsStateFull )
 344  
         {
 345  0
             if (state.getPortletMode() != null)
 346  
             {
 347  0
                 buffer.append(PARAMETER_SEPARATOR);
 348  0
                 buffer.append(MODE_KEY);
 349  0
                 buffer.append(encodePortletMode(state.getPortletMode()));
 350  0
                 encoded = true;
 351  
             }
 352  
 
 353  0
             if (state.getWindowState() != null)
 354  
             {
 355  0
                 buffer.append(PARAMETER_SEPARATOR);
 356  0
                 buffer.append(STATE_KEY);
 357  0
                 buffer.append(encodeWindowState(state.getWindowState()));
 358  0
                 encoded = true;
 359  
             }
 360  
         }
 361  
 
 362  0
         if (state.getParametersMap() != null && (action || !renderParamsStateFull) )
 363  
         {
 364  
             Map.Entry entry;
 365  
             String   parameterName;
 366  
             String[] parameterValues;
 367  
 
 368  0
             StringBuffer paramBuffer = new StringBuffer();
 369  0
             Iterator iter = state.getParametersMap().entrySet().iterator();
 370  0
             while ( iter.hasNext() )
 371  
             {
 372  0
                 encoded = true;
 373  0
                 entry = (Map.Entry)iter.next();
 374  0
                 parameterName = (String)entry.getKey();
 375  0
                 parameterValues = (String[])entry.getValue();
 376  
                
 377  0
                 buffer.append(PARAMETER_SEPARATOR);
 378  0
                 buffer.append(PARAM_KEY);
 379  
                 
 380  0
                 paramBuffer.setLength(0);
 381  0
                 paramBuffer.append(encodeArgument(parameterName, PARAMETER_ELEMENT_SEPARATOR));
 382  0
                 paramBuffer.append(PARAMETER_ELEMENT_SEPARATOR);
 383  0
                 paramBuffer.append(Integer.toHexString(parameterValues.length));
 384  0
                 for ( int i = 0; i < parameterValues.length; i++ )
 385  
                 {
 386  0
                     paramBuffer.append(PARAMETER_ELEMENT_SEPARATOR);
 387  0
                     paramBuffer.append(encodeArgument(parameterValues[i], PARAMETER_ELEMENT_SEPARATOR));
 388  
                 }
 389  
                 
 390  0
                 buffer.append(encodeArgument(paramBuffer.toString(),PARAMETER_SEPARATOR));
 391  
             }
 392  0
         }
 393  0
         else if ( state.isClearParameters() )
 394  
         {
 395  
             // Special case: for a targeted PortletWindow for which no parameters are specified 
 396  
             // indicate its saved (in the session) request parameters must be cleared instead of copying them when
 397  
             // synchronizing the state.
 398  
             // During decoding this CLEAR_PARAMS_KEY will set the clearParameters flag of the PortletWindowRequestNavigationalState.
 399  0
             buffer.append(PARAMETER_SEPARATOR);
 400  0
             buffer.append(CLEAR_PARAMS_KEY);            
 401  0
             encoded = true;
 402  
         }
 403  0
         return encoded ? buffer.toString() : "";
 404  
     }
 405  
     
 406  
     protected PortletWindowRequestNavigationalState decodeParameter(PortletWindowAccessor accessor, PortletWindowRequestNavigationalStates states, PortletWindowRequestNavigationalState currentState, String parameter)
 407  
     {
 408  0
         char parameterType = parameter.class="keyword">charAt(0);
 409  0
         if (parameterType == RENDER_WINDOW_ID_KEY || parameterType == ACTION_WINDOW_ID_KEY || parameterType == RESOURCE_WINDOW_ID_KEY )
 410  
         {            
 411  0
             String windowId = parameter.substring(1);
 412  0
             currentState = states.getPortletWindowNavigationalState(windowId);
 413  0
             if ( currentState == null )
 414  
             {
 415  0
                 PortletWindow window = accessor.getPortletWindow(windowId);
 416  0
                 if ( window == null )
 417  
                 {
 418  0
                     window = accessor.createPortletWindow(windowId);
 419  
                 }
 420  0
                 currentState = new PortletWindowRequestNavigationalState(windowId);
 421  0
                 states.addPortletWindowNavigationalState(windowId, currentState);
 422  0
                 if ( parameterType == ACTION_WINDOW_ID_KEY )
 423  
                 {
 424  0
                     states.setActionWindow(window);
 425  
                 }
 426  0
                 else if (parameterType == RESOURCE_WINDOW_ID_KEY )
 427  
                 {
 428  0
                     states.setResourceWindow(window);
 429  
                 }
 430  
             }
 431  0
         }
 432  0
         else if ( currentState != null )
 433  
         {
 434  0
             switch ( parameterType )
 435  
             {
 436  
                 case MODE_KEY:
 437  
                 {
 438  0
                     PortletMode portletMode = decodePortletMode(parameter.charAt(1));
 439  0
                     if ( portletMode != null )
 440  
                     {
 441  0
                         currentState.setPortletMode(portletMode);
 442  
                     }
 443  
                     break;
 444  
                 }
 445  
                 case STATE_KEY:
 446  
                 {
 447  0
                     WindowState windowState = decodeWindowState(parameter.charAt(1));
 448  0
                     if ( windowState != null )
 449  
                     {
 450  0
                         currentState.setWindowState(windowState);
 451  0
                         if (windowState.equals(WindowState.MAXIMIZED) || windowState.equals(JetspeedActions.SOLO_STATE))
 452  
                         {
 453  0
                             PortletWindow window = accessor.getPortletWindow(currentState.getWindowId());
 454  0
                             if ( window == null )
 455  
                             {
 456  0
                                 window = accessor.createPortletWindow(currentState.getWindowId());
 457  
                             }                                    
 458  0
                             states.setMaximizedWindow(window);
 459  0
                         }
 460  
                     }
 461  
                     break;
 462  
                 }
 463  
                 case PARAM_KEY:
 464  
                 {
 465  0
                     int position = 1;
 466  0
                     StringBuffer buffer = new StringBuffer();
 467  0
                     String parameterName = null;
 468  0
                     int parameterValueCount = -1;
 469  0
                     String parameterValues[] = null;
 470  0
                     int parameterValueIndex = -1;
 471  0
                     while ( (position = decodeArgument(position, parameter, buffer, PARAMETER_ELEMENT_SEPARATOR)) != -1 )
 472  
                     {
 473  0
                         if ( parameterName == null )
 474  
                         {
 475  0
                             parameterName = buffer.toString();
 476  0
                             parameterValueCount = -1;                        
 477  
                         }
 478  0
                         else if ( parameterValueCount == -1 )
 479  
                         {
 480  0
                             parameterValueCount = Integer.parseInt(buffer.toString(), 16);
 481  0
                             parameterValues = new String[parameterValueCount];
 482  0
                             parameterValueIndex = 0;
 483  
                         }
 484  
                         else
 485  
                         {
 486  0
                             parameterValues[parameterValueIndex++] = buffer.toString();
 487  0
                             parameterValueCount--;
 488  0
                             if ( parameterValueCount == 0 )
 489  
                             {
 490  0
                                 currentState.setParameters(parameterName, parameterValues);
 491  0
                                 break;
 492  
                             }
 493  
                         }
 494  
                     }
 495  
                     break;
 496  
                 }
 497  
                 case CLEAR_PARAMS_KEY:
 498  
                 {
 499  0
                     currentState.setClearParameters(true);
 500  
                 }
 501  
             }
 502  
         }
 503  0
         return currentState;
 504  
         
 505  
     }
 506  
     
 507  
     protected PortletMode decodePortletMode(char mode)
 508  
     {
 509  0
         PortletMode portletMode = null;
 510  0
         int index = keytable.indexOf(mode);
 511  0
         if (index > -1 && index < portletModes.length)
 512  
         {
 513  0
             portletMode = portletModes[index];
 514  
         }
 515  0
         return portletMode;
 516  
     }
 517  
     
 518  
     protected char encodePortletMode(PortletMode portletMode)
 519  
     {
 520  0
         for ( int i = 0; i < portletModes.length; i++ )
 521  
         {
 522  0
             if (portletModes[i].equals(portletMode))
 523  0
                 return keytable.charAt(i);
 524  
         }
 525  0
         throw new IllegalArgumentException("Unsupported PortletMode: "+portletMode);
 526  
     }
 527  
     
 528  
     protected WindowState decodeWindowState(char state)
 529  
     {
 530  0
         WindowState windowState = null;
 531  0
         int index = keytable.indexOf(state);
 532  0
         if (index > -1 && index < windowStates.length)
 533  
         {
 534  0
             windowState = windowStates[index];
 535  
         }
 536  0
         return windowState;
 537  
     }
 538  
     
 539  
     protected char encodeWindowState(WindowState windowState)
 540  
     {
 541  0
         for ( int i = 0; i < windowStates.length; i++ )
 542  
         {
 543  0
             if (windowStates[i].equals(windowState))
 544  0
                 return keytable.charAt(i);
 545  
         }
 546  0
         throw new IllegalArgumentException("Unsupported WindowState: "+windowState);
 547  
     }
 548  
     
 549  
     /** 
 550  
      * Decodes a Base64 encoded string.
 551  
      * 
 552  
      * Because the encoded string is used in an URL
 553  
      * the two '/' and '=' which has some significance in an URL
 554  
      * are encoded on top of the Base64 encoding and are first translated back before decoding.
 555  
      * 
 556  
      * @param value
 557  
      * @param characterEncoding String containing the name of the chararacter encoding
 558  
      * @return decoded string
 559  
      */
 560  
     protected String decodeParameters(String value, String characterEncoding)
 561  
     throws UnsupportedEncodingException
 562  
     {
 563  0
         value = value.replace('-','/').replace('_','=');
 564  0
         if ( characterEncoding != null )
 565  
         {
 566  0
             return new String(Base64.decodeBase64(value.getBytes(characterEncoding)), characterEncoding);
 567  
         }
 568  
         else
 569  
         {
 570  0
             return new String(Base64.decodeBase64(value.getBytes()));
 571  
         }
 572  
     }
 573  
 
 574  
     /** 
 575  
      * Encodes a string with Base64.
 576  
      * 
 577  
      * Because the encoded string is used in an URL
 578  
      * the two '/' and '=' which has some significance in an URL
 579  
      * are encoded on top of/after the Base64 encoding
 580  
      *  
 581  
      * @param value
 582  
      * @return encoded string
 583  
      */
 584  
     protected String encodeParameters(String value, String characterEncoding)
 585  
     throws UnsupportedEncodingException
 586  
     {
 587  0
         if ( characterEncoding != null )
 588  
         {
 589  0
             value = new String(Base64.encodeBase64(value.getBytes(characterEncoding)));
 590  
         }
 591  
         else
 592  
         {
 593  0
             value = new String(Base64.encodeBase64(value.getBytes()));
 594  
         }
 595  0
         return value.replace('/','-').replace('=','_');
 596  
     }
 597  
 
 598  
     protected String encodeArgument( String argument, char escape )
 599  
     {
 600  0
         int length = argument.length();
 601  0
         StringBuffer buffer = new StringBuffer(length);
 602  0
         buffer.setLength(0);
 603  
         char c;
 604  0
         for ( int i = 0; i < length; i++ )
 605  
         {
 606  0
             c = argument.charAt(i);
 607  0
             buffer.append(c);
 608  0
             if ( c == escape )
 609  
             {
 610  0
                 buffer.append(c);
 611  
             }
 612  
         }
 613  0
         return buffer.toString();
 614  
     }
 615  
     
 616  
     protected int decodeArgument(class="keyword">int position, String arguments, StringBuffer buffer, char escape)
 617  
     {
 618  0
         int maxLength = arguments.length();
 619  0
         buffer.setLength(0);
 620  
         char c;
 621  0
         for ( ; position < maxLength; position++ )
 622  
         {
 623  0
             c = arguments.charAt(position);
 624  0
             if ( c != escape )
 625  
             {
 626  0
                 buffer.append(c);
 627  
             }
 628  
             else 
 629  
             {
 630  0
                 if ( c == escape && position < maxLength-1 && arguments.charAt(position+1) == escape )
 631  
                 {
 632  0
                     buffer.append(c);
 633  0
                     position++;
 634  
                 }
 635  
                 else
 636  
                 {
 637  0
                     position++;
 638  0
                     break;
 639  
                 }
 640  
             }
 641  
         }
 642  0
         return buffer.length() > 0 ? position : -1; 
 643  
     }
 644  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.