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