Coverage Report - org.apache.turbine.services.rundata.DefaultTurbineRunData
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultTurbineRunData
52%
118/225
37%
25/66
0
 
 1  
 package org.apache.turbine.services.rundata;
 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.IOException;
 23  
 import java.io.PrintWriter;
 24  
 import java.util.ArrayList;
 25  
 import java.util.HashMap;
 26  
 import java.util.List;
 27  
 import java.util.Locale;
 28  
 import java.util.Map;
 29  
 
 30  
 import javax.naming.Context;
 31  
 import javax.servlet.ServletConfig;
 32  
 import javax.servlet.ServletContext;
 33  
 import javax.servlet.http.HttpServletRequest;
 34  
 import javax.servlet.http.HttpServletResponse;
 35  
 import javax.servlet.http.HttpSession;
 36  
 
 37  
 import org.apache.commons.lang3.StringUtils;
 38  
 import org.apache.fulcrum.parser.CookieParser;
 39  
 import org.apache.fulcrum.parser.ParameterParser;
 40  
 import org.apache.fulcrum.security.acl.AccessControlList;
 41  
 import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
 42  
 import org.apache.logging.log4j.LogManager;
 43  
 import org.apache.logging.log4j.Logger;
 44  
 import org.apache.turbine.Turbine;
 45  
 import org.apache.turbine.TurbineConstants;
 46  
 import org.apache.turbine.om.security.User;
 47  
 import org.apache.turbine.pipeline.DefaultPipelineData;
 48  
 import org.apache.turbine.services.TurbineServices;
 49  
 import org.apache.turbine.services.template.TemplateService;
 50  
 import org.apache.turbine.util.FormMessages;
 51  
 import org.apache.turbine.util.LocaleUtils;
 52  
 import org.apache.turbine.util.ServerData;
 53  
 import org.apache.turbine.util.SystemError;
 54  
 import org.apache.turbine.util.template.TemplateInfo;
 55  
 
 56  
 /**
 57  
  * DefaultTurbineRunData is the default implementation of the
 58  
  * TurbineRunData interface, which is distributed by the Turbine
 59  
  * RunData service, if another implementation is not defined in
 60  
  * the default or specified RunData configuration.
 61  
  * TurbineRunData is an extension to RunData, which
 62  
  * is an interface to run-rime information that is passed
 63  
  * within Turbine. This provides the threading mechanism for the
 64  
  * entire system because multiple requests can potentially come in
 65  
  * at the same time.  Thus, there is only one RunData implementation
 66  
  * for each request that is being serviced.
 67  
  *
 68  
  * <p>DefaultTurbineRunData implements the Recyclable interface making
 69  
  * it possible to pool its instances for recycling.
 70  
  *
 71  
  * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
 72  
  * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
 73  
  * @author <a href="mailto:bhoeneis@ee.ethz.ch">Bernie Hoeneisen</a>
 74  
  * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
 75  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 76  
  * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
 77  
  * @version $Id: DefaultTurbineRunData.java 1854787 2019-03-04 18:30:25Z tv $
 78  
  */
 79  
 public class DefaultTurbineRunData
 80  
         extends DefaultPipelineData
 81  
         implements TurbineRunData
 82  
 {
 83  
     /**
 84  
      * The disposed flag.
 85  
      */
 86  
     private boolean disposed;
 87  
 
 88  
     /** Cached action name to execute for this request. */
 89  
     private String action;
 90  
 
 91  
     /** This is the layout that the page will use to render the screen. */
 92  
     private String layout;
 93  
 
 94  
     /** Cached screen name to execute for this request. */
 95  
     private String screen;
 96  
 
 97  
     /** The character encoding of template files. */
 98  
     private String templateEncoding;
 99  
 
 100  
     /** This is what will build the <title></title> of the document. */
 101  
     private String title;
 102  
 
 103  
     /** Determines if there is information in the outputstream or not. */
 104  
     private boolean outSet;
 105  
 
 106  
     /**
 107  
      * Cache the output stream because it can be used in many
 108  
      * different places.
 109  
      */
 110  
     private PrintWriter out;
 111  
 
 112  
     /** The HTTP charset. */
 113  
     private String charSet;
 114  
 
 115  
     /** The HTTP content type to return. */
 116  90
     private String contentType = "text/html";
 117  
 
 118  
     /** If this is set, also set the status code to 302. */
 119  
     private String redirectURI;
 120  
 
 121  
     /** The HTTP status code to return. */
 122  90
     private int statusCode = HttpServletResponse.SC_OK;
 123  
 
 124  
     /** This is a List to hold critical system errors. */
 125  90
     private final List<SystemError> errors = new ArrayList<SystemError>();
 126  
 
 127  
     /** JNDI Contexts. */
 128  
     private Map<String, Context> jndiContexts;
 129  
 
 130  
     /** @see #getRemoteAddr() */
 131  
     private String remoteAddr;
 132  
 
 133  
     /** @see #getRemoteHost() */
 134  
     private String remoteHost;
 135  
 
 136  
     /** @see #getUserAgent() */
 137  
     private String userAgent;
 138  
 
 139  
     /** A holder for stack trace. */
 140  
     private String stackTrace;
 141  
 
 142  
     /** A holder for stack trace exception. */
 143  
     private Throwable stackTraceException;
 144  
 
 145  
     /**
 146  
      * Put things here and they will be shown on the default Error
 147  
      * screen.  This is great for debugging variable values when an
 148  
      * exception is thrown.
 149  
      */
 150  90
     private final Map<String, Object> debugVariables = new HashMap<String, Object>();
 151  
 
 152  
     /** Logging */
 153  39
     private static final Logger log = LogManager.getLogger(DefaultTurbineRunData.class);
 154  
 
 155  
     /**
 156  
      * Attempts to get the User object from the session.  If it does
 157  
      * not exist, it returns null.
 158  
      *
 159  
      * @param session An HttpSession.
 160  
      *
 161  
      * @param <T> a type extending {@link User}
 162  
      *
 163  
      * @return A User.
 164  
      */
 165  
     public static <T extends User> T getUserFromSession(HttpSession session)
 166  
     {
 167  
         try
 168  
         {
 169  
             @SuppressWarnings("unchecked")
 170  12
             T user = (T) session.getAttribute(User.SESSION_KEY);
 171  12
             return user;
 172  
         }
 173  0
         catch (ClassCastException e)
 174  
         {
 175  0
             return null;
 176  
         }
 177  
     }
 178  
 
 179  
     /**
 180  
      * Allows one to invalidate the user in a session.
 181  
      *
 182  
      * @param session An HttpSession.
 183  
      * @return True if user was invalidated.
 184  
      */
 185  
     public static boolean removeUserFromSession(HttpSession session)
 186  
     {
 187  
         try
 188  
         {
 189  0
             session.removeAttribute(User.SESSION_KEY);
 190  
         }
 191  0
         catch (Exception e)
 192  
         {
 193  0
             return false;
 194  0
         }
 195  0
         return true;
 196  
     }
 197  
 
 198  
     /**
 199  
      * Constructs a run data object.
 200  
      */
 201  
     public DefaultTurbineRunData()
 202  
     {
 203  90
         super();
 204  
 
 205  
         // a map to hold information to be added to pipelineData
 206  90
         put(Turbine.class, new HashMap<Class<?>, Object>());
 207  90
         recycle();
 208  90
     }
 209  
 
 210  
     /**
 211  
      * Recycles the object by removing its disposed flag.
 212  
      */
 213  
     @Override
 214  
     public void recycle()
 215  
     {
 216  90
         disposed = false;
 217  90
     }
 218  
 
 219  
     /**
 220  
      * Disposes a run data object.
 221  
      */
 222  
     @Override
 223  
     public void dispose()
 224  
     {
 225  
         // empty pipelinedata map
 226  3
         get(Turbine.class).clear();
 227  
 
 228  3
         action = null;
 229  3
         layout = null;
 230  3
         screen = null;
 231  3
         templateEncoding = null;
 232  3
         title = null;
 233  3
         outSet = false;
 234  3
         out = null;
 235  3
         charSet = null;
 236  3
         contentType = "text/html";
 237  3
         redirectURI = null;
 238  3
         statusCode = HttpServletResponse.SC_OK;
 239  3
         errors.clear();
 240  3
         jndiContexts = null;
 241  3
         remoteAddr = null;
 242  3
         remoteHost = null;
 243  3
         userAgent = null;
 244  3
         stackTrace = null;
 245  3
         stackTraceException = null;
 246  3
         debugVariables.clear();
 247  3
     }
 248  
 
 249  
     // ***************************************
 250  
     // Implementation of the RunData interface
 251  
     // ***************************************
 252  
 
 253  
     /**
 254  
      * Gets the parameters.
 255  
      *
 256  
      * @return a parameter parser.
 257  
      */
 258  
     @Override
 259  
     public ParameterParser getParameters()
 260  
     {
 261  
         // Parse the parameters first, if not yet done.
 262  111
         ParameterParser parameters = getParameterParser();
 263  111
         HttpServletRequest request = getRequest();
 264  
 
 265  111
         if (parameters != null && parameters.getRequest() != request)
 266  
         {
 267  42
             parameters.setRequest(request);
 268  
         }
 269  
 
 270  111
         return parameters;
 271  
     }
 272  
 
 273  
     /**
 274  
      * Gets the cookies.
 275  
      *
 276  
      * @return a cookie parser.
 277  
      */
 278  
     @Override
 279  
     public CookieParser getCookies()
 280  
     {
 281  
         // Parse the cookies first, if not yet done.
 282  0
         CookieParser cookies = getCookieParser();
 283  0
         HttpServletRequest request = getRequest();
 284  
 
 285  0
         if (cookies != null && cookies.getRequest() != request)
 286  
         {
 287  0
             cookies.setData(request, getResponse());
 288  
         }
 289  
 
 290  0
         return cookies;
 291  
     }
 292  
 
 293  
     /**
 294  
      * Gets the servlet request.
 295  
      *
 296  
      * @return the request.
 297  
      */
 298  
     @Override
 299  
     public HttpServletRequest getRequest()
 300  
     {
 301  285
         return get(Turbine.class, HttpServletRequest.class);
 302  
     }
 303  
 
 304  
     /**
 305  
      * Gets the servlet response.
 306  
      *
 307  
      * @return the response.
 308  
      */
 309  
     @Override
 310  
     public HttpServletResponse getResponse()
 311  
     {
 312  66
         return get(Turbine.class, HttpServletResponse.class);
 313  
     }
 314  
 
 315  
     /**
 316  
      * Gets the servlet session information.
 317  
      *
 318  
      * @return the session.
 319  
      */
 320  
     @Override
 321  
     public HttpSession getSession()
 322  
     {
 323  135
         return getRequest().getSession();
 324  
     }
 325  
 
 326  
     /**
 327  
      * Gets the servlet configuration used during servlet init.
 328  
      *
 329  
      * @return the configuration.
 330  
      */
 331  
     @Override
 332  
     public ServletConfig getServletConfig()
 333  
     {
 334  0
         return get(Turbine.class, ServletConfig.class);
 335  
     }
 336  
 
 337  
     /**
 338  
      * Gets the servlet context used during servlet init.
 339  
      *
 340  
      * @return the context.
 341  
      */
 342  
     @Override
 343  
     public ServletContext getServletContext()
 344  
     {
 345  0
         return get(Turbine.class, ServletContext.class);
 346  
     }
 347  
 
 348  
     /**
 349  
      * Gets the access control list.
 350  
      *
 351  
      * @return the access control list.
 352  
      */
 353  
     @Override
 354  
     public <A extends AccessControlList> A getACL()
 355  
     {
 356  
         @SuppressWarnings("unchecked")
 357  9
         A acl = (A)get(Turbine.class, TurbineAccessControlList.class);
 358  9
         return acl;
 359  
     }
 360  
 
 361  
     /**
 362  
      * Sets the access control list.
 363  
      *
 364  
      * To delete ACL from session use key {@link TurbineConstants#ACL_SESSION_KEY}.
 365  
      * Invalidate session, if session persist.
 366  
      *
 367  
      * @param acl an access control list.
 368  
      */
 369  
     @Override
 370  
     public void setACL(AccessControlList acl)
 371  
     {
 372  6
         get(Turbine.class).put(TurbineAccessControlList.class, acl);
 373  6
     }
 374  
 
 375  
     /**
 376  
      * Whether or not an action has been defined.
 377  
      *
 378  
      * @return true if an action has been defined.
 379  
      */
 380  
     @Override
 381  
     public boolean hasAction()
 382  
     {
 383  168
         return StringUtils.isNotEmpty(this.action)
 384  63
           && !this.action.equalsIgnoreCase("null");
 385  
     }
 386  
 
 387  
     /**
 388  
      * Gets the action. It returns an empty string if null so
 389  
      * that it is easy to do conditionals on it based on the
 390  
      * equalsIgnoreCase() method.
 391  
      *
 392  
      * @return a string, "" if null.
 393  
      */
 394  
     @Override
 395  
     public String getAction()
 396  
     {
 397  57
         return hasAction() ? this.action : "";
 398  
     }
 399  
 
 400  
     /**
 401  
      * Sets the action for the request.
 402  
      *
 403  
      * @param action a string.
 404  
      */
 405  
     @Override
 406  
     public void setAction(String action)
 407  
     {
 408  54
         this.action = action;
 409  54
     }
 410  
 
 411  
     /**
 412  
      * If the Layout has not been defined by the screen then set the
 413  
      * layout to be "DefaultLayout".  The screen object can also
 414  
      * override this method to provide intelligent determination of
 415  
      * the Layout to execute.  You can also define that logic here as
 416  
      * well if you want it to apply on a global scale.  For example,
 417  
      * if you wanted to allow someone to define layout "preferences"
 418  
      * where they could dynamically change the layout for the entire
 419  
      * site.
 420  
      *
 421  
      * @return a string.
 422  
      */
 423  
 
 424  
     @Override
 425  
     public String getLayout()
 426  
     {
 427  24
         if (this.layout == null)
 428  
         {
 429  
             /*
 430  
              * This will return something if the template
 431  
              * services are running. If we get nothing we
 432  
              * will fall back to the ECS layout.
 433  
              */
 434  9
             TemplateService templateService = (TemplateService)TurbineServices.getInstance().getService(TemplateService.SERVICE_NAME);
 435  9
             layout = templateService.getDefaultLayoutName(this);
 436  
 
 437  9
             if (layout == null)
 438  
             {
 439  0
                 layout = "DefaultLayout";
 440  
             }
 441  
         }
 442  
 
 443  24
         return this.layout;
 444  
     }
 445  
 
 446  
     /**
 447  
      * Set the layout for the request.
 448  
      *
 449  
      * @param layout a string.
 450  
      */
 451  
     @Override
 452  
     public void setLayout(String layout)
 453  
     {
 454  6
         this.layout = layout;
 455  6
     }
 456  
 
 457  
     /**
 458  
      * Convenience method for a template info that
 459  
      * returns the layout template being used.
 460  
      *
 461  
      * @return a string.
 462  
      */
 463  
     @Override
 464  
     public String getLayoutTemplate()
 465  
     {
 466  0
         return getTemplateInfo().getLayoutTemplate();
 467  
     }
 468  
 
 469  
     /**
 470  
      * Modifies the layout template for the screen. This convenience
 471  
      * method allows for a layout to be modified from within a
 472  
      * template. For example;
 473  
      *
 474  
      *    $data.setLayoutTemplate("NewLayout.vm")
 475  
      *
 476  
      * @param layout a layout template.
 477  
      */
 478  
     @Override
 479  
     public void setLayoutTemplate(String layout)
 480  
     {
 481  0
         getTemplateInfo().setLayoutTemplate(layout);
 482  0
     }
 483  
 
 484  
     /**
 485  
      * Whether or not a screen has been defined.
 486  
      *
 487  
      * @return true if a screen has been defined.
 488  
      */
 489  
     @Override
 490  
     public boolean hasScreen()
 491  
     {
 492  66
         return StringUtils.isNotEmpty(this.screen);
 493  
     }
 494  
 
 495  
     /**
 496  
      * Gets the screen to execute.
 497  
      *
 498  
      * @return a string.
 499  
      */
 500  
     @Override
 501  
     public String getScreen()
 502  
     {
 503  39
         return hasScreen() ? this.screen : "";
 504  
     }
 505  
 
 506  
     /**
 507  
      * Sets the screen for the request.
 508  
      *
 509  
      * @param screen a string.
 510  
      */
 511  
     @Override
 512  
     public void setScreen(String screen)
 513  
     {
 514  24
         this.screen = screen;
 515  24
     }
 516  
 
 517  
     /**
 518  
      * Convenience method for a template info that
 519  
      * returns the name of the template being used.
 520  
      *
 521  
      * @return a string.
 522  
      */
 523  
     @Override
 524  
     public String getScreenTemplate()
 525  
     {
 526  0
         return getTemplateInfo().getScreenTemplate();
 527  
     }
 528  
 
 529  
     /**
 530  
      * Sets the screen template for the request. For
 531  
      * example;
 532  
      *
 533  
      *    $data.setScreenTemplate("NewScreen.vm")
 534  
      *
 535  
      * @param screen a screen template.
 536  
      */
 537  
     @Override
 538  
     public void setScreenTemplate(String screen)
 539  
     {
 540  6
         getTemplateInfo().setScreenTemplate(screen);
 541  6
     }
 542  
 
 543  
     /**
 544  
      * Gets the character encoding to use for reading template files.
 545  
      *
 546  
      * @return the template encoding or null if not specified.
 547  
      */
 548  
     @Override
 549  
     public String getTemplateEncoding()
 550  
     {
 551  12
         return templateEncoding;
 552  
     }
 553  
 
 554  
     /**
 555  
      * Sets the character encoding to use for reading template files.
 556  
      *
 557  
      * @param encoding the template encoding.
 558  
      */
 559  
     @Override
 560  
     public void setTemplateEncoding(String encoding)
 561  
     {
 562  0
         templateEncoding = encoding;
 563  0
     }
 564  
 
 565  
     /**
 566  
      * Gets the template info. Creates a new one if needed.
 567  
      *
 568  
      * @return a template info.
 569  
      */
 570  
     @Override
 571  
     public TemplateInfo getTemplateInfo()
 572  
     {
 573  198
         TemplateInfo templateInfo = get(Turbine.class, TemplateInfo.class);
 574  
 
 575  198
         if (templateInfo == null)
 576  
         {
 577  39
             templateInfo = new TemplateInfo(this);
 578  39
             get(Turbine.class).put(TemplateInfo.class, templateInfo);
 579  
         }
 580  
 
 581  198
         return templateInfo;
 582  
     }
 583  
 
 584  
     /**
 585  
      * Whether or not a message has been defined.
 586  
      *
 587  
      * @return true if a message has been defined.
 588  
      */
 589  
     @Override
 590  
     public boolean hasMessage()
 591  
     {
 592  0
         StringBuilder message = get(Turbine.class, StringBuilder.class);
 593  0
         return message != null && message.length() > 0;
 594  
     }
 595  
 
 596  
     /**
 597  
      * Gets the results of an action or another message
 598  
      * to be displayed as a string.
 599  
      *
 600  
      * @return a string.
 601  
      */
 602  
     @Override
 603  
     public String getMessage()
 604  
     {
 605  0
         StringBuilder message = get(Turbine.class, StringBuilder.class);
 606  0
         return message == null ? null : message.toString();
 607  
     }
 608  
 
 609  
     /**
 610  
      * Sets the message for the request as a string.
 611  
      *
 612  
      * @param msg a string.
 613  
      */
 614  
     @Override
 615  
     public void setMessage(String msg)
 616  
     {
 617  3
         get(Turbine.class).put(StringBuilder.class, new StringBuilder(msg));
 618  3
     }
 619  
 
 620  
     /**
 621  
      * Adds the string to message. If message has prior messages from
 622  
      * other actions or screens, this method can be used to chain them.
 623  
      *
 624  
      * @param msg a string.
 625  
      */
 626  
     @Override
 627  
     public void addMessage(String msg)
 628  
     {
 629  0
         StringBuilder message = get(Turbine.class, StringBuilder.class);
 630  0
         if (message == null)
 631  
         {
 632  0
             setMessage(msg);
 633  
         }
 634  
         else
 635  
         {
 636  0
             message.append(msg);
 637  
         }
 638  0
     }
 639  
 
 640  
     /**
 641  
      * Gets the results of an action or another message
 642  
      * to be displayed as a string (never null).
 643  
      *
 644  
      * @return a string element.
 645  
      */
 646  
     @Override
 647  
     public String getMessageAsHTML()
 648  
     {
 649  0
         String message = getMessage();
 650  0
         return message == null ? "" : message;
 651  
     }
 652  
 
 653  
     /**
 654  
      * Unsets the message for the request.
 655  
      */
 656  
     @Override
 657  
     public void unsetMessage()
 658  
     {
 659  0
         get(Turbine.class).remove(StringBuilder.class);
 660  0
     }
 661  
 
 662  
     /**
 663  
      * Gets a FormMessages object where all the messages to the
 664  
      * user should be stored.
 665  
      *
 666  
      * @return a FormMessages.
 667  
      */
 668  
     @Override
 669  
     public FormMessages getMessages()
 670  
     {
 671  0
         FormMessages messages = get(Turbine.class, FormMessages.class);
 672  0
         if (messages == null)
 673  
         {
 674  0
             messages = new FormMessages();
 675  0
             setMessages(messages);
 676  
         }
 677  
 
 678  0
         return messages;
 679  
     }
 680  
 
 681  
     /**
 682  
      * Sets the FormMessages object for the request.
 683  
      *
 684  
      * @param msgs A FormMessages.
 685  
      */
 686  
     @Override
 687  
     public void setMessages(FormMessages msgs)
 688  
     {
 689  0
         get(Turbine.class).put(FormMessages.class, msgs);
 690  0
     }
 691  
 
 692  
     /**
 693  
      * Gets the title of the page.
 694  
      *
 695  
      * @return a string.
 696  
      */
 697  
     @Override
 698  
     public String getTitle()
 699  
     {
 700  0
         return this.title == null ? "" : this.title;
 701  
     }
 702  
 
 703  
     /**
 704  
      * Sets the title of the page.
 705  
      *
 706  
      * @param title a string.
 707  
      */
 708  
     @Override
 709  
     public void setTitle(String title)
 710  
     {
 711  0
         this.title = title;
 712  0
     }
 713  
 
 714  
     /**
 715  
      * Checks if a user exists in this session.
 716  
      *
 717  
      * @return true if a user exists in this session.
 718  
      */
 719  
     @Override
 720  
     public boolean userExists()
 721  
     {
 722  0
         User user = getUserFromSession();
 723  
 
 724  
         // TODO: Check if this side effect is reasonable
 725  0
         get(Turbine.class).put(User.class, user);
 726  
 
 727  0
         return (user != null);
 728  
     }
 729  
 
 730  
     /**
 731  
      * Gets the user.
 732  
      *
 733  
      * @param <T> a type extending {@link User}
 734  
      *
 735  
      * @return a user.
 736  
      */
 737  
     @Override
 738  
     public <T extends User> T getUser()
 739  
     {
 740  
         @SuppressWarnings("unchecked")
 741  84
         T user = (T)get(Turbine.class, User.class);
 742  84
         return user;
 743  
     }
 744  
 
 745  
     /**
 746  
      * Sets the user.
 747  
      *
 748  
      * @param user a user.
 749  
      */
 750  
     @Override
 751  
     public void setUser(User user)
 752  
     {
 753  21
         log.debug("user set: {}", user::getName);
 754  21
         get(Turbine.class).put(User.class, user);
 755  21
     }
 756  
 
 757  
     /**
 758  
      * Attempts to get the user from the session. If it does
 759  
      * not exist, it returns null.
 760  
      *
 761  
      * @return a user.
 762  
      */
 763  
     @Override
 764  
     public <T extends User> T getUserFromSession()
 765  
     {
 766  12
         return getUserFromSession(getSession());
 767  
     }
 768  
 
 769  
     /**
 770  
      * Allows one to invalidate the user in the default session.
 771  
      *
 772  
      * @return true if user was invalidated.
 773  
      */
 774  
     @Override
 775  
     public boolean removeUserFromSession()
 776  
     {
 777  0
         return removeUserFromSession(getSession());
 778  
     }
 779  
 
 780  
     /**
 781  
      * Checks to see if out is set.
 782  
      *
 783  
      * @return true if out is set.
 784  
      * @deprecated no replacement planned, response writer will not be cached
 785  
      */
 786  
     @Override
 787  
     @Deprecated
 788  
     public boolean isOutSet()
 789  
     {
 790  0
         return outSet;
 791  
     }
 792  
 
 793  
     /**
 794  
      * Gets the print writer. First time calling this
 795  
      * will set the print writer via the response.
 796  
      *
 797  
      * @return a print writer.
 798  
      * @throws IOException on failure getting the PrintWriter
 799  
      */
 800  
     @Override
 801  
     public PrintWriter getOut()
 802  
             throws IOException
 803  
     {
 804  
         // Check to see if null first.
 805  0
         if (this.out == null)
 806  
         {
 807  0
             setOut(getResponse().getWriter());
 808  
         }
 809  0
         outSet = true;
 810  0
         return this.out;
 811  
     }
 812  
 
 813  
     /**
 814  
      * Declares that output will be direct to the response stream,
 815  
      * even though getOut() may never be called.  Useful for response
 816  
      * mechanisms that may call res.getWriter() themselves
 817  
      * (such as JSP.)
 818  
      */
 819  
     @Override
 820  
     public void declareDirectResponse()
 821  
     {
 822  0
         outSet = true;
 823  0
     }
 824  
 
 825  
     /**
 826  
      * Gets the locale. If it has not already been defined with
 827  
      * setLocale(), then  properties named "locale.default.lang"
 828  
      * and "locale.default.country" are checked from the Resource
 829  
      * Service and the corresponding locale is returned. If these
 830  
      * properties are undefined, JVM's default locale is returned.
 831  
      *
 832  
      * @return the locale.
 833  
      */
 834  
     @Override
 835  
     public Locale getLocale()
 836  
     {
 837  6
         Locale locale = get(Turbine.class, Locale.class);
 838  6
         if (locale == null)
 839  
         {
 840  0
             locale = LocaleUtils.getDefaultLocale();
 841  
         }
 842  6
         return locale;
 843  
     }
 844  
 
 845  
     /**
 846  
      * Sets the locale.
 847  
      *
 848  
      * @param locale the new locale.
 849  
      */
 850  
     @Override
 851  
     public void setLocale(Locale locale)
 852  
     {
 853  90
         get(Turbine.class).put(Locale.class, locale);
 854  
 
 855  
         // propagate the locale to the parsers
 856  90
         ParameterParser parameters = get(Turbine.class, ParameterParser.class);
 857  90
         CookieParser cookies = get(Turbine.class, CookieParser.class);
 858  
 
 859  90
         if (parameters != null)
 860  
         {
 861  90
             parameters.setLocale(locale);
 862  
         }
 863  
 
 864  90
         if (cookies != null)
 865  
         {
 866  90
             cookies.setLocale(locale);
 867  
         }
 868  90
     }
 869  
 
 870  
     /**
 871  
      * Gets the charset. If it has not already been defined with
 872  
      * setCharSet(), then a property named "locale.default.charset"
 873  
      * is checked from the Resource Service and returned. If this
 874  
      * property is undefined, the default charset of the locale
 875  
      * is returned. If the locale is undefined, null is returned.
 876  
      *
 877  
      * @return the name of the charset or null.
 878  
      */
 879  
     @Override
 880  
     public String getCharSet()
 881  
     {
 882  18
         log.debug("getCharSet()");
 883  
 
 884  18
         if (StringUtils.isEmpty(charSet))
 885  
         {
 886  6
             log.debug("Charset was null!");
 887  6
             charSet =  LocaleUtils.getDefaultCharSet();
 888  
         }
 889  
 
 890  18
         return charSet;
 891  
     }
 892  
 
 893  
     /**
 894  
      * Sets the charset.
 895  
      *
 896  
      * @param charSet the name of the new charset.
 897  
      */
 898  
     @Override
 899  
     public void setCharSet(String charSet)
 900  
     {
 901  9
         log.debug("setCharSet({})", charSet);
 902  9
         this.charSet = charSet;
 903  9
     }
 904  
 
 905  
     /**
 906  
      * Gets the HTTP content type to return. If a charset
 907  
      * has been specified, it is included in the content type.
 908  
      * If the charset has not been specified and the main type
 909  
      * of the content type is "text", the default charset is
 910  
      * included. If the default charset is undefined, but the
 911  
      * default locale is defined and it is not the US locale,
 912  
      * a locale specific charset is included.
 913  
      *
 914  
      * @return the content type or an empty string.
 915  
      */
 916  
     @Override
 917  
     public String getContentType()
 918  
     {
 919  6
         if (StringUtils.isNotEmpty(contentType))
 920  
         {
 921  6
             if (StringUtils.isEmpty(charSet))
 922  
             {
 923  0
                 if (contentType.startsWith("text/"))
 924  
                 {
 925  0
                     return contentType + "; charset=" + LocaleUtils.getDefaultCharSet();
 926  
                 }
 927  
 
 928  0
                 return contentType;
 929  
             }
 930  
             else
 931  
             {
 932  6
                 return contentType + "; charset=" + charSet;
 933  
             }
 934  
         }
 935  
 
 936  0
         return "";
 937  
     }
 938  
 
 939  
     /**
 940  
      * Sets the HTTP content type to return.
 941  
      *
 942  
      * @param contentType a string.
 943  
      */
 944  
     @Override
 945  
     public void setContentType(String contentType)
 946  
     {
 947  0
         this.contentType = contentType;
 948  0
     }
 949  
 
 950  
     /**
 951  
      * Gets the redirect URI. If this is set, also make sure to set
 952  
      * the status code to 302.
 953  
      *
 954  
      * @return a string, "" if null.
 955  
      */
 956  
     @Override
 957  
     public String getRedirectURI()
 958  
     {
 959  12
         return (this.redirectURI == null ? "" : redirectURI);
 960  
     }
 961  
 
 962  
     /**
 963  
      * Sets the redirect uri. If this is set, also make sure to set
 964  
      * the status code to 302.
 965  
      *
 966  
      * @param ruri a string.
 967  
      */
 968  
     @Override
 969  
     public void setRedirectURI(String ruri)
 970  
     {
 971  0
         this.redirectURI = ruri;
 972  0
     }
 973  
 
 974  
     /**
 975  
      * Gets the HTTP status code to return.
 976  
      *
 977  
      * @return the status.
 978  
      */
 979  
     @Override
 980  
     public int getStatusCode()
 981  
     {
 982  0
         return statusCode;
 983  
     }
 984  
 
 985  
     /**
 986  
      * Sets the HTTP status code to return.
 987  
      *
 988  
      * @param statusCode the status.
 989  
      */
 990  
     @Override
 991  
     public void setStatusCode(int statusCode)
 992  
     {
 993  0
         this.statusCode = statusCode;
 994  0
     }
 995  
 
 996  
     /**
 997  
      * Gets an array of system errors.
 998  
      *
 999  
      * @return a SystemError[].
 1000  
      */
 1001  
     @Override
 1002  
     public SystemError[] getSystemErrors()
 1003  
     {
 1004  0
         SystemError[] result = new SystemError[errors.size()];
 1005  0
         errors.toArray(result);
 1006  0
         return result;
 1007  
     }
 1008  
 
 1009  
     /**
 1010  
      * Adds a critical system error.
 1011  
      *
 1012  
      * @param err a system error.
 1013  
      */
 1014  
     @Override
 1015  
     public void setSystemError(SystemError err)
 1016  
     {
 1017  0
         this.errors.add(err);
 1018  0
     }
 1019  
 
 1020  
     /**
 1021  
      * Gets JNDI Contexts.
 1022  
      *
 1023  
      * @return a hashmap.
 1024  
      */
 1025  
     @Override
 1026  
     public Map<String, Context> getJNDIContexts()
 1027  
     {
 1028  0
         if (jndiContexts == null)
 1029  
         {
 1030  0
             jndiContexts = new HashMap<String, Context>();
 1031  
         }
 1032  0
         return jndiContexts;
 1033  
     }
 1034  
 
 1035  
     /**
 1036  
      * Sets JNDI Contexts.
 1037  
      *
 1038  
      * @param contexts a hashmap.
 1039  
      */
 1040  
     @Override
 1041  
     public void setJNDIContexts(Map<String, Context> contexts)
 1042  
     {
 1043  0
         this.jndiContexts = contexts;
 1044  0
     }
 1045  
 
 1046  
     /**
 1047  
      * Gets the cached server scheme.
 1048  
      *
 1049  
      * @return a string.
 1050  
      */
 1051  
     @Override
 1052  
     public String getServerScheme()
 1053  
     {
 1054  0
         return getServerData().getServerScheme();
 1055  
     }
 1056  
 
 1057  
     /**
 1058  
      * Gets the cached server name.
 1059  
      *
 1060  
      * @return a string.
 1061  
      */
 1062  
     @Override
 1063  
     public String getServerName()
 1064  
     {
 1065  0
         return getServerData().getServerName();
 1066  
     }
 1067  
 
 1068  
     /**
 1069  
      * Gets the cached server port.
 1070  
      *
 1071  
      * @return an int.
 1072  
      */
 1073  
     @Override
 1074  
     public int getServerPort()
 1075  
     {
 1076  0
         return getServerData().getServerPort();
 1077  
     }
 1078  
 
 1079  
     /**
 1080  
      * Gets the cached context path.
 1081  
      *
 1082  
      * @return a string.
 1083  
      */
 1084  
     @Override
 1085  
     public String getContextPath()
 1086  
     {
 1087  0
         return getServerData().getContextPath();
 1088  
     }
 1089  
 
 1090  
     /**
 1091  
      * Gets the cached script name.
 1092  
      *
 1093  
      * @return a string.
 1094  
      */
 1095  
     @Override
 1096  
     public String getScriptName()
 1097  
     {
 1098  0
         return getServerData().getScriptName();
 1099  
     }
 1100  
 
 1101  
     /**
 1102  
      * Gets the server data ofy the request.
 1103  
      *
 1104  
      * @return server data.
 1105  
      */
 1106  
     @Override
 1107  
     public ServerData getServerData()
 1108  
     {
 1109  54
         return get(Turbine.class, ServerData.class);
 1110  
     }
 1111  
 
 1112  
     /**
 1113  
      * Gets the IP address of the client that sent the request.
 1114  
      *
 1115  
      * @return a string.
 1116  
      */
 1117  
     @Override
 1118  
     public String getRemoteAddr()
 1119  
     {
 1120  0
         if (this.remoteAddr == null)
 1121  
         {
 1122  0
             this.remoteAddr = this.getRequest().getRemoteAddr();
 1123  
         }
 1124  
 
 1125  0
         return this.remoteAddr;
 1126  
     }
 1127  
 
 1128  
     /**
 1129  
      * Gets the qualified name of the client that sent the request.
 1130  
      *
 1131  
      * @return a string.
 1132  
      */
 1133  
     @Override
 1134  
     public String getRemoteHost()
 1135  
     {
 1136  0
         if (this.remoteHost == null)
 1137  
         {
 1138  0
             this.remoteHost = this.getRequest().getRemoteHost();
 1139  
         }
 1140  
 
 1141  0
         return this.remoteHost;
 1142  
     }
 1143  
 
 1144  
     /**
 1145  
      * Get the user agent for the request. The semantics here
 1146  
      * are muddled because RunData caches the value after the
 1147  
      * first invocation. This is different e.g. from getCharSet().
 1148  
      *
 1149  
      * @return a string.
 1150  
      */
 1151  
     @Override
 1152  
     public String getUserAgent()
 1153  
     {
 1154  0
         if (StringUtils.isEmpty(userAgent))
 1155  
         {
 1156  0
             userAgent = this.getRequest().getHeader("User-Agent");
 1157  
         }
 1158  
 
 1159  0
         return userAgent;
 1160  
     }
 1161  
 
 1162  
     /**
 1163  
      * Pulls a user object from the session and increments the access
 1164  
      * counter and sets the last access date for the object.
 1165  
      */
 1166  
     @Override
 1167  
     public void populate()
 1168  
     {
 1169  9
         User user = getUserFromSession();
 1170  9
         get(Turbine.class).put(User.class, user);
 1171  
 
 1172  9
         if (user != null)
 1173  
         {
 1174  3
             user.setLastAccessDate();
 1175  3
             user.incrementAccessCounter();
 1176  3
             user.incrementAccessCounterForSession();
 1177  
         }
 1178  9
     }
 1179  
 
 1180  
     /**
 1181  
      * Saves a user object into the session.
 1182  
      */
 1183  
     @Override
 1184  
     public void save()
 1185  
     {
 1186  12
         getSession().setAttribute(User.SESSION_KEY, getUser());
 1187  12
     }
 1188  
 
 1189  
     /**
 1190  
      * Gets the stack trace if set.
 1191  
      *
 1192  
      * @return the stack trace.
 1193  
      */
 1194  
     @Override
 1195  
     public String getStackTrace()
 1196  
     {
 1197  3
         return stackTrace;
 1198  
     }
 1199  
 
 1200  
     /**
 1201  
      * Gets the stack trace exception if set.
 1202  
      *
 1203  
      * @return the stack exception.
 1204  
      */
 1205  
     @Override
 1206  
     public Throwable getStackTraceException()
 1207  
     {
 1208  3
         return stackTraceException;
 1209  
     }
 1210  
 
 1211  
     /**
 1212  
      * Sets the stack trace.
 1213  
      *
 1214  
      * @param trace the stack trace.
 1215  
      * @param exp the exception.
 1216  
      */
 1217  
     @Override
 1218  
     public void setStackTrace(String trace, Throwable exp)
 1219  
     {
 1220  3
         stackTrace = trace;
 1221  3
         stackTraceException = exp;
 1222  3
     }
 1223  
 
 1224  
     /**
 1225  
      * Sets a name/value pair in an internal Map that is accessible from the
 1226  
      * Error screen.  This is a good way to get debugging information
 1227  
      * when an exception is thrown.
 1228  
      *
 1229  
      * @param name name of the variable
 1230  
      * @param value value of the variable.
 1231  
      */
 1232  
     @Override
 1233  
     public void setDebugVariable(String name, Object value)
 1234  
     {
 1235  0
         this.debugVariables.put(name, value);
 1236  0
     }
 1237  
 
 1238  
     /**
 1239  
      * Gets a Map of debug variables.
 1240  
      *
 1241  
      * @return a Map of debug variables.
 1242  
      */
 1243  
     @Override
 1244  
     public Map<String, Object> getDebugVariables()
 1245  
     {
 1246  0
         return this.debugVariables;
 1247  
     }
 1248  
 
 1249  
     // **********************************************
 1250  
     // Implementation of the TurbineRunData interface
 1251  
     // **********************************************
 1252  
 
 1253  
     /**
 1254  
      * Gets the parameter parser without parsing the parameters.
 1255  
      *
 1256  
      * @return the parameter parser.
 1257  
      * TODO Does this method make sense? Pulling the parameter out of
 1258  
      *       the run data object before setting a request (which happens
 1259  
      *       only in getParameters() leads to the Parameter parser having
 1260  
      *       no object and thus the default or even an undefined encoding
 1261  
      *       instead of the actual request character encoding).
 1262  
      */
 1263  
     @Override
 1264  
     public ParameterParser getParameterParser()
 1265  
     {
 1266  114
         return get(Turbine.class, ParameterParser.class);
 1267  
     }
 1268  
 
 1269  
     /**
 1270  
      * Gets the cookie parser without parsing the cookies.
 1271  
      *
 1272  
      * @return the cookie parser.
 1273  
      */
 1274  
     @Override
 1275  
     public CookieParser getCookieParser()
 1276  
     {
 1277  3
         return get(Turbine.class, CookieParser.class);
 1278  
     }
 1279  
 
 1280  
     // ********************
 1281  
     // Miscellanous setters
 1282  
     // ********************
 1283  
 
 1284  
     /**
 1285  
      * Sets the print writer.
 1286  
      *
 1287  
      * @param out a print writer.
 1288  
      * @deprecated no replacement planned, response writer will not be cached
 1289  
      */
 1290  
     @Deprecated
 1291  
     protected void setOut(PrintWriter out)
 1292  
     {
 1293  0
         this.out = out;
 1294  0
     }
 1295  
 
 1296  
     /**
 1297  
      * Sets the cached server scheme that is stored in the server data.
 1298  
      *
 1299  
      * @param serverScheme a string.
 1300  
      */
 1301  
     protected void setServerScheme(String serverScheme)
 1302  
     {
 1303  0
         getServerData().setServerScheme(serverScheme);
 1304  0
     }
 1305  
 
 1306  
     /**
 1307  
      * Sets the cached server same that is stored in the server data.
 1308  
      *
 1309  
      * @param serverName a string.
 1310  
      */
 1311  
     protected void setServerName(String serverName)
 1312  
     {
 1313  0
         getServerData().setServerName(serverName);
 1314  0
     }
 1315  
 
 1316  
     /**
 1317  
      * Sets the cached server port that is stored in the server data.
 1318  
      *
 1319  
      * @param port an int.
 1320  
      */
 1321  
     protected void setServerPort(int port)
 1322  
     {
 1323  0
         getServerData().setServerPort(port);
 1324  0
     }
 1325  
 
 1326  
     /**
 1327  
      * Sets the cached context path that is stored in the server data.
 1328  
      *
 1329  
      * @param contextPath a string.
 1330  
      */
 1331  
     protected void setContextPath(String contextPath)
 1332  
     {
 1333  0
         getServerData().setContextPath(contextPath);
 1334  0
     }
 1335  
 
 1336  
     /**
 1337  
      * Sets the cached script name that is stored in the server data.
 1338  
      *
 1339  
      * @param scriptName a string.
 1340  
      */
 1341  
     protected void setScriptName(String scriptName)
 1342  
     {
 1343  0
         getServerData().setScriptName(scriptName);
 1344  0
     }
 1345  
 
 1346  
     /**
 1347  
      * Checks whether the object is disposed.
 1348  
      *
 1349  
      * @return true, if the object is disposed.
 1350  
      */
 1351  
     @Override
 1352  
     public boolean isDisposed()
 1353  
     {
 1354  0
         return disposed;
 1355  
     }
 1356  
 
 1357  
 }