Coverage Report - org.apache.turbine.services.pull.TurbinePullService
 
Classes in this File Line Coverage Branch Coverage Complexity
TurbinePullService
57%
136/238
44%
41/92
3,565
TurbinePullService$ToolData
100%
5/5
N/A
3,565
 
 1  
 package org.apache.turbine.services.pull;
 2  
 
 3  
 
 4  
 /*
 5  
  * Licensed to the Apache Software Foundation (ASF) under one
 6  
  * or more contributor license agreements.  See the NOTICE file
 7  
  * distributed with this work for additional information
 8  
  * regarding copyright ownership.  The ASF licenses this file
 9  
  * to you under the Apache License, Version 2.0 (the
 10  
  * "License"); you may not use this file except in compliance
 11  
  * with the License.  You may obtain a copy of the License at
 12  
  *
 13  
  *   http://www.apache.org/licenses/LICENSE-2.0
 14  
  *
 15  
  * Unless required by applicable law or agreed to in writing,
 16  
  * software distributed under the License is distributed on an
 17  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 18  
  * KIND, either express or implied.  See the License for the
 19  
  * specific language governing permissions and limitations
 20  
  * under the License.
 21  
  */
 22  
 
 23  
 
 24  
 import java.util.ArrayList;
 25  
 import java.util.Iterator;
 26  
 import java.util.List;
 27  
 
 28  
 import org.apache.commons.configuration.Configuration;
 29  
 import org.apache.commons.logging.Log;
 30  
 import org.apache.commons.logging.LogFactory;
 31  
 import org.apache.fulcrum.pool.PoolService;
 32  
 import org.apache.fulcrum.security.model.turbine.TurbineUserManager;
 33  
 import org.apache.turbine.Turbine;
 34  
 import org.apache.turbine.annotation.AnnotationProcessor;
 35  
 import org.apache.turbine.om.security.User;
 36  
 import org.apache.turbine.pipeline.PipelineData;
 37  
 import org.apache.turbine.services.InitializationException;
 38  
 import org.apache.turbine.services.TurbineBaseService;
 39  
 import org.apache.turbine.services.TurbineServices;
 40  
 import org.apache.turbine.services.velocity.VelocityService;
 41  
 import org.apache.turbine.util.RunData;
 42  
 import org.apache.velocity.context.Context;
 43  
 
 44  
 /**
 45  
  * This is the concrete implementation of the Turbine
 46  
  * Pull Service.
 47  
  * <p>
 48  
  * These are tools that are placed in the context by the service
 49  
  * These tools will be made available to all your
 50  
  * templates. You list the tools in the following way:
 51  
  * </p>
 52  
  * <pre>
 53  
  * tool.&lt;scope&gt;.&lt;id&gt; = &lt;classname&gt;
 54  
  *
 55  
  * &lt;scope&gt;      is the tool scope: global, request, session,
 56  
  *              authorized or persistent (see below for more details)
 57  
  * &lt;id&gt;         is the name of the tool in the context
 58  
  *
 59  
  * You can configure the tools in this way:
 60  
  * tool.&lt;id&gt;.&lt;parameter&gt; = &lt;value&gt;
 61  
  *
 62  
  * So if you find "global", "request", "session" or "persistent" as second
 63  
  * part, it is a configuration to put a tool into the toolbox, else it is a
 64  
  * tool specific configuration.
 65  
  *
 66  
  * For example:
 67  
  *
 68  
  * tool.global.ui    = org.apache.turbine.util.pull.UIManager
 69  
  * tool.global.mm    = org.apache.turbine.util.pull.MessageManager
 70  
  * tool.request.link = org.apache.turbine.services.pull.tools.TemplateLink
 71  
  * tool.request.page = org.apache.turbine.util.template.TemplatePageAttributes
 72  
  *
 73  
  * Then:
 74  
  *
 75  
  * tool.ui.skin = default
 76  
  *
 77  
  * configures the value of "skin" for the "ui" tool.
 78  
  *
 79  
  * Tools are accessible in all templates by the &lt;id&gt; given
 80  
  * to the tool. So for the above listings the UIManager would
 81  
  * be available as $ui, the MessageManager as $mm, the TemplateLink
 82  
  * as $link and the TemplatePageAttributes as $page.
 83  
  *
 84  
  * You should avoid using tool names called "global", "request",
 85  
  * "session" or "persistent" because of clashes with the possible Scopes.
 86  
  *
 87  
  * Scopes:
 88  
  *
 89  
  *  global:     tool is instantiated once and that instance is available
 90  
  *              to all templates for all requests. Tool must be threadsafe.
 91  
  *
 92  
  *  request:    tool is instantiated once for each request (although the
 93  
  *              PoolService is used to recycle instances). Tool need not
 94  
  *              be threadsafe.
 95  
  *
 96  
  *  session:    tool is instantiated once for each user session, and is
 97  
  *              stored in the session.  These tools do not need to be
 98  
  *              threadsafe.
 99  
  *
 100  
  *  authorized: tool is instantiated once for each user session once the
 101  
  *              user logs in. After this, it is a normal session tool.
 102  
  *
 103  
  *  persistent: tool is instantitated once for each user session once
 104  
  *              the user logs in and is is stored in the user's permanent
 105  
  *              hashtable.
 106  
  *              This means for a logged in user the tool will be persisted
 107  
  *              in the user's objectdata. Tool should be Serializable.  These
 108  
  *              tools do not need to be threadsafe.
 109  
  *              <b>persistent scope tools are deprecated in 2.3</b>
 110  
  *
 111  
  * Defaults: none
 112  
  * </pre>
 113  
  *
 114  
  * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
 115  
  * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
 116  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 117  
  * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
 118  
  * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
 119  
  * @version $Id: TurbinePullService.java 1773378 2016-12-09 13:19:59Z tv $
 120  
  */
 121  32
 public class TurbinePullService
 122  
         extends TurbineBaseService
 123  
         implements PullService
 124  
 {
 125  
     /** Logging */
 126  32
     private static Log log = LogFactory.getLog(TurbinePullService.class);
 127  
 
 128  
     /** Reference to the pool service */
 129  32
     private PoolService pool = null;
 130  
 
 131  
     /** Reference to the templating (nee Velocity) service */
 132  32
     private VelocityService velocity = null;
 133  
 
 134  
     /**
 135  
      * This is the container for the global web application
 136  
      * tools that are used in conjunction with the
 137  
      * Turbine Pull Model. All the global tools will be placed
 138  
      * in this Context and be made accessible inside
 139  
      * templates via the tool name specified in the TR.props
 140  
      * file.
 141  
      */
 142  
     private Context globalContext;
 143  
 
 144  
     /**
 145  
      * This inner class is used in the lists below to store the
 146  
      * tool name and class for each of request, session and persistent
 147  
      * tools
 148  
      */
 149  
     private static class ToolData
 150  
     {
 151  
         String toolName;
 152  
         String toolClassName;
 153  
         Class<ApplicationTool> toolClass;
 154  
 
 155  
         public ToolData(String toolName, String toolClassName, Class<ApplicationTool> toolClass)
 156  133
         {
 157  133
             this.toolName = toolName;
 158  133
             this.toolClassName = toolClassName;
 159  133
             this.toolClass = toolClass;
 160  133
         }
 161  
     }
 162  
 
 163  
     /** Internal list of global tools */
 164  
     private List<ToolData> globalTools;
 165  
 
 166  
     /** Internal list of request tools */
 167  
     private List<ToolData> requestTools;
 168  
 
 169  
     /** Internal list of session tools */
 170  
     private List<ToolData> sessionTools;
 171  
 
 172  
     /** Internal list of authorized tools */
 173  
     private List<ToolData> authorizedTools;
 174  
 
 175  
     /** Internal list of persistent tools */
 176  
     private List<ToolData> persistentTools;
 177  
 
 178  
     /** Directory where application tool resources are stored.*/
 179  
     private String resourcesDirectory;
 180  
 
 181  
     /** Should we refresh the application tools on a per request basis? */
 182  32
     private boolean refreshToolsPerRequest = false;
 183  
 
 184  
     /**
 185  
      * Called the first time the Service is used.
 186  
      */
 187  
     @Override
 188  
     public void init()
 189  
         throws InitializationException
 190  
     {
 191  
         try
 192  
         {
 193  39
                     pool = (PoolService)TurbineServices.getInstance().getService(PoolService.ROLE);
 194  
 
 195  39
             if (pool == null)
 196  
             {
 197  0
                 throw new InitializationException("Pull Service requires"
 198  
                     + " configured Pool Service!");
 199  
             }
 200  
 
 201  39
             initPullService();
 202  
             // Make sure to setInit(true) because Tools may
 203  
             // make calls back to the TurbinePull static methods
 204  
             // which causes an init loop.
 205  39
             setInit(true);
 206  
 
 207  
             // Do _NOT_ move this before the setInit(true)
 208  39
             velocity = (VelocityService)TurbineServices.getInstance().getService(VelocityService.SERVICE_NAME);
 209  
 
 210  28
             if (velocity != null)
 211  
             {
 212  28
                 initPullTools();
 213  
             }
 214  
             else
 215  
             {
 216  0
                 log.info("Velocity Service not configured, skipping pull tools!");
 217  
             }
 218  
         }
 219  11
         catch (Exception e)
 220  
         {
 221  11
             throw new InitializationException("TurbinePullService failed to initialize", e);
 222  28
         }
 223  28
     }
 224  
 
 225  
     /**
 226  
      * Initialize the pull service
 227  
      *
 228  
      * @throws Exception A problem happened when starting up
 229  
      */
 230  
     private void initPullService()
 231  
         throws Exception
 232  
     {
 233  
         // This is the per-service configuration, prefixed with services.PullService
 234  39
         Configuration conf = getConfiguration();
 235  
 
 236  
         // Get the resources directory that is specificed
 237  
         // in the TR.props or default to "resources", relative to the webapp.
 238  39
         resourcesDirectory = conf.getString(
 239  
             TOOL_RESOURCES_DIR_KEY,
 240  
             TOOL_RESOURCES_DIR_DEFAULT);
 241  
 
 242  
         // Should we refresh the tool box on a per
 243  
         // request basis.
 244  39
         refreshToolsPerRequest =
 245  
             conf.getBoolean(
 246  
                 TOOLS_PER_REQUEST_REFRESH_KEY,
 247  
                 TOOLS_PER_REQUEST_REFRESH_DEFAULT);
 248  
 
 249  
         // Log the fact that the application tool box will
 250  
         // be refreshed on a per request basis.
 251  39
         if (refreshToolsPerRequest)
 252  
         {
 253  30
             log.info("Pull Model tools will "
 254  
                 + "be refreshed on a per request basis.");
 255  
         }
 256  39
     }
 257  
 
 258  
     /**
 259  
      * Initialize the pull tools. At this point, the
 260  
      * service must be marked as initialized, because the
 261  
      * tools may call the methods of this service via the
 262  
      * static facade class TurbinePull.
 263  
      *
 264  
      * @throws Exception A problem happened when starting up
 265  
      */
 266  
     private void initPullTools()
 267  
         throws Exception
 268  
     {
 269  
         // And for reasons I never really fully understood,
 270  
         // the tools directive is toplevel without the service
 271  
         // prefix. This is brain-damaged but for legacy reasons we
 272  
         // keep this. So this is the global turbine configuration:
 273  28
         Configuration conf = Turbine.getConfiguration();
 274  
 
 275  
         // Grab each list of tools that are to be used (for global scope,
 276  
         // request scope, authorized scope, session scope and persistent
 277  
         // scope tools). They are specified respectively in the TR.props
 278  
         // like this:
 279  
         //
 280  
         // tool.global.ui = org.apache.turbine.util.pull.UIManager
 281  
         // tool.global.mm = org.apache.turbine.util.pull.MessageManager
 282  
         //
 283  
         // tool.request.link = org.apache.turbine.services.pull.tools.TemplateLink
 284  
         //
 285  
         // tool.session.basket = org.sample.util.ShoppingBasket;
 286  
         //
 287  
         // tool.persistent.ui = org.apache.turbine.services.pull.util.PersistentUIManager
 288  
 
 289  28
         log.debug("Global Tools:");
 290  28
         globalTools     = getTools(conf.subset(GLOBAL_TOOL));
 291  28
         log.debug("Request Tools:");
 292  28
         requestTools    = getTools(conf.subset(REQUEST_TOOL));
 293  28
         log.debug("Session Tools:");
 294  28
         sessionTools    = getTools(conf.subset(SESSION_TOOL));
 295  28
         log.debug("Authorized Tools:");
 296  28
         authorizedTools = getTools(conf.subset(AUTHORIZED_TOOL));
 297  28
         log.debug("Persistent Tools:");
 298  28
         persistentTools = getTools(conf.subset(PERSISTENT_TOOL));
 299  
 
 300  
         // Create and populate the global context right now
 301  
 
 302  
         // This is unholy, because it entwines the VelocityService and
 303  
         // the Pull Service even further. However, there isn't much we can
 304  
         // do for the 2.3 release. Expect this to go post-2.3
 305  28
         globalContext = velocity.getNewContext();
 306  
 
 307  28
         populateWithGlobalTools(globalContext);
 308  28
     }
 309  
 
 310  
     /**
 311  
      * Retrieve the tool names and classes for the tools defined
 312  
      * in the configuration file with the prefix given.
 313  
      *
 314  
      * @param toolConfig The part of the configuration describing some tools
 315  
      */
 316  
     @SuppressWarnings("unchecked")
 317  
     private List<ToolData> getTools(Configuration toolConfig)
 318  
     {
 319  140
         List<ToolData> tools = new ArrayList<ToolData>();
 320  
 
 321  
         // There might not be any tools for this prefix
 322  
         // so return an empty list.
 323  140
         if (toolConfig == null)
 324  
         {
 325  0
             return tools;
 326  
         }
 327  
 
 328  140
         for (Iterator<String> it = toolConfig.getKeys(); it.hasNext();)
 329  
         {
 330  133
             String toolName = it.next();
 331  133
             String toolClassName = toolConfig.getString(toolName);
 332  
 
 333  
             try
 334  
             {
 335  
                 // Create an instance of the tool class.
 336  133
                 Class<ApplicationTool> toolClass = (Class<ApplicationTool>) Class.forName(toolClassName);
 337  
 
 338  
                 // Add the tool to the list being built.
 339  133
                 tools.add(new ToolData(toolName, toolClassName, toolClass));
 340  
 
 341  133
                 log.info("Tool " + toolClassName
 342  
                     + " to add to the context as '$" + toolName + "'");
 343  
             }
 344  
             // NoClassDefFoundError + ClassNotFoundException
 345  0
             catch (Throwable e)
 346  
             {
 347  0
                 log.error("Cannot instantiate tool class "
 348  
                     + toolClassName + ": ", e);
 349  133
             }
 350  133
         }
 351  
 
 352  140
         return tools;
 353  
     }
 354  
 
 355  
     /**
 356  
      * Return the Context which contains all global tools that
 357  
      * are to be used in conjunction with the Turbine
 358  
      * Pull Model. The tools are refreshed every time the
 359  
      * global Context is pulled.
 360  
      */
 361  
     @Override
 362  
     public Context getGlobalContext()
 363  
     {
 364  10
         if (refreshToolsPerRequest)
 365  
         {
 366  10
             refreshGlobalTools();
 367  
         }
 368  10
         return globalContext;
 369  
     }
 370  
 
 371  
     /**
 372  
      * Populate the given context with all request, session, authorized
 373  
      * and persistent scope tools (it is assumed that the context
 374  
      * already wraps the global context, and thus already contains
 375  
      * the global tools).
 376  
      *
 377  
      * @param context a Velocity Context to populate
 378  
      * @param data a RunData object for request specific data
 379  
      */
 380  
     @Override
 381  
     public void populateContext(Context context, RunData data)
 382  
     {
 383  0
         populateWithRequestTools(context, data);
 384  
 
 385  
         // session tools (whether session-only or persistent are
 386  
         // very similar, so the same method is used - the
 387  
         // boolean parameter indicates whether get/setPerm is to be used
 388  
         // rather than get/setTemp)
 389  
 
 390  
         //
 391  
         // Session Tool start right at the session once the user has been set
 392  
         // while persistent and authorized Tools are started when the user has
 393  
         // logged in
 394  
         //
 395  0
         User user = data.getUser();
 396  
 
 397  
         // Note: Session tools are currently lost after the login action
 398  
         // because the anonymous user is replaced the the real user object.
 399  
         // We should either store the session pull tools in the session or
 400  
         // make Turbine.loginAction() copy the session pull tools into the
 401  
         // new user object.
 402  0
         populateWithSessionTools(sessionTools, context, data, user);
 403  
 
 404  0
         TurbineUserManager userManager =
 405  
                 (TurbineUserManager)TurbineServices
 406  
                         .getInstance()
 407  
                         .getService(TurbineUserManager.ROLE);
 408  
 
 409  0
         if (!userManager.isAnonymousUser(user))
 410  
         {
 411  0
             if (user.hasLoggedIn())
 412  
             {
 413  0
                 populateWithSessionTools(authorizedTools, context, data, user);
 414  0
                 populateWithPermTools(persistentTools, context, data, user);
 415  
             }
 416  
         }
 417  0
     }
 418  
 
 419  
     /**
 420  
      * Populate the given context with all request, session, authorized
 421  
      * and persistent scope tools (it is assumed that the context
 422  
      * already wraps the global context, and thus already contains
 423  
      * the global tools).
 424  
      *
 425  
      * @param context a Velocity Context to populate
 426  
      * @param pipelineData a PipelineData object for request specific data
 427  
      */
 428  
     @Override
 429  
     public void populateContext(Context context, PipelineData pipelineData)
 430  
     {
 431  
        // Map runDataMap = (Map) pipelineData.get(RunData.class);
 432  
        // RunData data = (RunData)runDataMap.get(RunData.class);
 433  9
         RunData data = (RunData)pipelineData;
 434  
 
 435  9
         populateWithRequestTools(context, pipelineData);
 436  
         // session tools (whether session-only or persistent are
 437  
         // very similar, so the same method is used - the
 438  
         // boolean parameter indicates whether get/setPerm is to be used
 439  
         // rather than get/setTemp)
 440  
 
 441  
         //
 442  
         // Session Tool start right at the session once the user has been set
 443  
         // while persistent and authorized Tools are started when the user has
 444  
         // logged in
 445  
         //
 446  9
         User user = data.getUser();
 447  
 
 448  
         // Note: Session tools are currently lost after the login action
 449  
         // because the anonymous user is replaced the the real user object.
 450  
         // We should either store the session pull tools in the session or
 451  
         // make Turbine.loginAction() copy the session pull tools into the
 452  
         // new user object.
 453  9
         populateWithSessionTools(sessionTools, context, pipelineData, user);
 454  
 
 455  9
         TurbineUserManager userManager =
 456  
                 (TurbineUserManager)TurbineServices
 457  
                         .getInstance()
 458  
                         .getService(TurbineUserManager.ROLE);
 459  
 
 460  9
         if (!userManager.isAnonymousUser(user))
 461  
         {
 462  2
             if (user.hasLoggedIn())
 463  
             {
 464  2
                 populateWithSessionTools(authorizedTools, context, pipelineData, user);
 465  2
                 populateWithPermTools(persistentTools, context, pipelineData, user);
 466  
             }
 467  
         }
 468  9
     }
 469  
 
 470  
     /**
 471  
      * Populate the given context with the global tools
 472  
      *
 473  
      * @param context a Velocity Context to populate
 474  
      */
 475  
     private void populateWithGlobalTools(Context context)
 476  
     {
 477  28
         for (Iterator<ToolData> it = globalTools.iterator(); it.hasNext();)
 478  
         {
 479  19
             ToolData toolData = it.next();
 480  
             try
 481  
             {
 482  19
                 Object tool = toolData.toolClass.newInstance();
 483  
 
 484  
                 // global tools are init'd with a null data parameter
 485  19
                 initTool(tool, null);
 486  
 
 487  
                 // put the tool in the context
 488  19
                 context.put(toolData.toolName, tool);
 489  
             }
 490  0
             catch (Exception e)
 491  
             {
 492  0
                 log.error("Could not instantiate global tool "
 493  
                     + toolData.toolName + " from a "
 494  
                     + toolData.toolClassName + " object", e);
 495  19
             }
 496  19
         }
 497  28
     }
 498  
 
 499  
     /**
 500  
      * Populate the given context with the request-scope tools
 501  
      *
 502  
      * @param context a Velocity Context to populate
 503  
      * @param pipelineData a RunData instance
 504  
      */
 505  
     private void populateWithRequestTools(Context context, RunData data)
 506  
     {
 507  
         // Iterate the tools
 508  0
         for (Iterator<ToolData> it = requestTools.iterator(); it.hasNext();)
 509  
         {
 510  0
             ToolData toolData = it.next();
 511  
             try
 512  
             {
 513  
                 // Fetch Object through the Pool.
 514  0
                 Object tool = pool.getInstance(toolData.toolClass);
 515  
 
 516  
                 // request tools are init'd with a RunData object
 517  0
                 initTool(tool, data);
 518  
 
 519  
                 // put the tool in the context
 520  0
                 context.put(toolData.toolName, tool);
 521  
             }
 522  0
             catch (Exception e)
 523  
             {
 524  0
                 log.error("Could not instantiate request tool "
 525  
                     + toolData.toolName + " from a "
 526  
                     + toolData.toolClassName + " object", e);
 527  0
             }
 528  0
         }
 529  0
     }
 530  
 
 531  
 
 532  
     /**
 533  
      * Populate the given context with the request-scope tools
 534  
      *
 535  
      * @param context a Velocity Context to populate
 536  
      * @param pipelineData a RunData instance
 537  
      */
 538  
     private void populateWithRequestTools(Context context, PipelineData pipelineData)
 539  
     {
 540  
         // Iterate the tools
 541  9
         for (Iterator<ToolData> it = requestTools.iterator(); it.hasNext();)
 542  
         {
 543  45
             ToolData toolData = it.next();
 544  
             try
 545  
             {
 546  
                 // Fetch Object through the Pool.
 547  45
                 Object tool = pool.getInstance(toolData.toolClass);
 548  
 
 549  45
                 initTool(tool, pipelineData);
 550  
 
 551  
                 // put the tool in the context
 552  45
                 context.put(toolData.toolName, tool);
 553  
             }
 554  0
             catch (Exception e)
 555  
             {
 556  0
                 log.error("Could not instantiate request tool "
 557  
                     + toolData.toolName + " from a "
 558  
                     + toolData.toolClassName + " object", e);
 559  45
             }
 560  45
         }
 561  9
     }
 562  
 
 563  
     /**
 564  
      * Populate the given context with the session-scoped tools.
 565  
      *
 566  
      * @param tools The list of tools with which to populate the
 567  
      * session.
 568  
      * @param context The context to populate.
 569  
      * @param pipelineData The current RunData object
 570  
      * @param user The <code>User</code> object whose storage to
 571  
      * retrieve the tool from.
 572  
      */
 573  
     private void populateWithSessionTools(List<ToolData> tools, Context context,
 574  
             PipelineData pipelineData, User user)
 575  
     {
 576  
         //Map runDataMap = (Map)pipelineData.get(RunData.class);
 577  
         //RunData data = (RunData) runDataMap.get(RunData.class);
 578  11
         RunData runData = (RunData)pipelineData;
 579  
         // Iterate the tools
 580  11
         for (Iterator<ToolData> it = tools.iterator(); it.hasNext();)
 581  
         {
 582  9
             ToolData toolData = it.next();
 583  
             try
 584  
             {
 585  
                 // ensure that tool is created only once for a user
 586  
                 // by synchronizing against the user object
 587  9
                 synchronized (runData.getSession())
 588  
                 {
 589  
                     // first try and fetch the tool from the user's
 590  
                     // hashtable
 591  9
                     Object tool = runData.getSession().getAttribute(
 592  
                             SESSION_TOOLS_ATTRIBUTE_PREFIX
 593  
                             + toolData.toolClassName);
 594  
 
 595  9
                     if (tool == null)
 596  
                     {
 597  
                         // if not there, an instance must be fetched from
 598  
                         // the pool
 599  9
                         tool = pool.getInstance(toolData.toolClass);
 600  
 
 601  
                         // session tools are init'd with the User object
 602  9
                         initTool(tool, user);
 603  
                     }
 604  
 
 605  
                     // *NOT* else
 606  9
                     if(tool != null)
 607  
                     {
 608  
                         // store the newly created tool in the session
 609  9
                         runData.getSession().setAttribute(
 610  
                                 SESSION_TOOLS_ATTRIBUTE_PREFIX
 611  
                                 + tool.getClass().getName(), tool);
 612  
 
 613  
                         // This is a semantics change. In the old
 614  
                         // Turbine, Session tools were initialized and
 615  
                         // then refreshed every time they were pulled
 616  
                         // into the context if "refreshToolsPerRequest"
 617  
                         // was wanted.
 618  
                         //
 619  
                         // RunDataApplicationTools now have a parameter
 620  
                         // for refresh. If it is not refreshed immediately
 621  
                         // after init(), the parameter value will be undefined
 622  
                         // until the 2nd run. So we refresh all the session
 623  
                         // tools on every run, even if we just init'ed it.
 624  
                         //
 625  
 
 626  9
                         if (refreshToolsPerRequest)
 627  
                         {
 628  9
                             refreshTool(tool, pipelineData);
 629  
                         }
 630  
 
 631  
                         // put the tool in the context
 632  9
                         log.debug("Adding " + tool + " to ctx as "
 633  
                                 + toolData.toolName);
 634  9
                         context.put(toolData.toolName, tool);
 635  
                     }
 636  
                     else
 637  
                     {
 638  0
                         log.info("Tool " + toolData.toolName
 639  
                                 + " was null, skipping it.");
 640  
                     }
 641  9
                 }
 642  
             }
 643  0
             catch (Exception e)
 644  
             {
 645  0
                 log.error("Could not instantiate session tool "
 646  
                     + toolData.toolName + " from a "
 647  
                     + toolData.toolClassName + " object", e);
 648  9
             }
 649  9
         }
 650  11
     }
 651  
 
 652  
     /**
 653  
      * Populate the given context with the session-scoped tools.
 654  
      *
 655  
      * @param tools The list of tools with which to populate the
 656  
      * session.
 657  
      * @param context The context to populate.
 658  
      * @param pipelineData The current RunData object
 659  
      * @param user The <code>User</code> object whose storage to
 660  
      * retrieve the tool from.
 661  
      */
 662  
     private void populateWithSessionTools(List<ToolData> tools, Context context,
 663  
             RunData data, User user)
 664  
     {
 665  
         // Iterate the tools
 666  0
         for (Iterator<ToolData> it = tools.iterator(); it.hasNext();)
 667  
         {
 668  0
             ToolData toolData = it.next();
 669  
             try
 670  
             {
 671  
                 // ensure that tool is created only once for a user
 672  
                 // by synchronizing against the user object
 673  0
                 synchronized (data.getSession())
 674  
                 {
 675  
                     // first try and fetch the tool from the user's
 676  
                     // hashmap
 677  0
                     Object tool = data.getSession().getAttribute(
 678  
                             SESSION_TOOLS_ATTRIBUTE_PREFIX
 679  
                             + toolData.toolClassName);
 680  
 
 681  0
                     if (tool == null)
 682  
                     {
 683  
                         // if not there, an instance must be fetched from
 684  
                         // the pool
 685  0
                         tool = pool.getInstance(toolData.toolClass);
 686  
 
 687  
                         // session tools are init'd with the User object
 688  0
                         initTool(tool, user);
 689  
                     }
 690  
 
 691  
                     // *NOT* else
 692  0
                     if(tool != null)
 693  
                     {
 694  
                         // store the newly created tool in the session
 695  0
                         data.getSession().setAttribute(
 696  
                                 SESSION_TOOLS_ATTRIBUTE_PREFIX
 697  
                                 + tool.getClass().getName(), tool);
 698  
 
 699  
                         // This is a semantics change. In the old
 700  
                         // Turbine, Session tools were initialized and
 701  
                         // then refreshed every time they were pulled
 702  
                         // into the context if "refreshToolsPerRequest"
 703  
                         // was wanted.
 704  
                         //
 705  
                         // RunDataApplicationTools now have a parameter
 706  
                         // for refresh. If it is not refreshed immediately
 707  
                         // after init(), the parameter value will be undefined
 708  
                         // until the 2nd run. So we refresh all the session
 709  
                         // tools on every run, even if we just init'ed it.
 710  
                         //
 711  
 
 712  0
                         if (refreshToolsPerRequest)
 713  
                         {
 714  0
                             refreshTool(tool, data);
 715  
                         }
 716  
 
 717  
                         // put the tool in the context
 718  0
                         log.debug("Adding " + tool + " to ctx as "
 719  
                                 + toolData.toolName);
 720  0
                         context.put(toolData.toolName, tool);
 721  
                     }
 722  
                     else
 723  
                     {
 724  0
                         log.info("Tool " + toolData.toolName
 725  
                                 + " was null, skipping it.");
 726  
                     }
 727  0
                 }
 728  
             }
 729  0
             catch (Exception e)
 730  
             {
 731  0
                 log.error("Could not instantiate session tool "
 732  
                     + toolData.toolName + " from a "
 733  
                     + toolData.toolClassName + " object", e);
 734  0
             }
 735  0
         }
 736  0
     }
 737  
 
 738  
 
 739  
 
 740  
     /**
 741  
      * Populate the given context with the perm-scoped tools.
 742  
      *
 743  
      * @param tools The list of tools with which to populate the
 744  
      * session.
 745  
      * @param context The context to populate.
 746  
      * @param pipelineData The current RunData object
 747  
      * @param user The <code>User</code> object whose storage to
 748  
      * retrieve the tool from.
 749  
      */
 750  
     private void populateWithPermTools(List<ToolData> tools, Context context,
 751  
             PipelineData pipelineData, User user)
 752  
     {
 753  
         // Iterate the tools
 754  2
         for (Iterator<ToolData> it = tools.iterator(); it.hasNext();)
 755  
         {
 756  0
             ToolData toolData = it.next();
 757  
             try
 758  
             {
 759  
                 // ensure that tool is created only once for a user
 760  
                 // by synchronizing against the user object
 761  0
                 synchronized (user)
 762  
                 {
 763  
                     // first try and fetch the tool from the user's
 764  
                     // hashtable
 765  0
                     Object tool = user.getPerm(toolData.toolClassName);
 766  
 
 767  0
                     if (tool == null)
 768  
                     {
 769  
                         // if not there, an instance must be fetched from
 770  
                         // the pool
 771  0
                         tool = pool.getInstance(toolData.toolClass);
 772  
 
 773  
                         // session tools are init'd with the User object
 774  0
                         initTool(tool, user);
 775  
 
 776  
                         // store the newly created tool in the user's hashtable
 777  0
                         user.setPerm(toolData.toolClassName, tool);
 778  
                     }
 779  
 
 780  
                     // *NOT* else
 781  0
                     if(tool != null)
 782  
                     {
 783  
                         // This is a semantics change. In the old
 784  
                         // Turbine, Session tools were initialized and
 785  
                         // then refreshed every time they were pulled
 786  
                         // into the context if "refreshToolsPerRequest"
 787  
                         // was wanted.
 788  
                         //
 789  
                         // RunDataApplicationTools now have a parameter
 790  
                         // for refresh. If it is not refreshed immediately
 791  
                         // after init(), the parameter value will be undefined
 792  
                         // until the 2nd run. So we refresh all the session
 793  
                         // tools on every run, even if we just init'ed it.
 794  
                         //
 795  
 
 796  0
                         if (refreshToolsPerRequest)
 797  
                         {
 798  0
                             refreshTool(tool, pipelineData);
 799  
                         }
 800  
 
 801  
                         // put the tool in the context
 802  0
                         log.debug("Adding " + tool + " to ctx as "
 803  
                                 + toolData.toolName);
 804  0
                         log.warn("Persistent scope tools are deprecated.");
 805  0
                         context.put(toolData.toolName, tool);
 806  
                     }
 807  
                     else
 808  
                     {
 809  0
                         log.info("Tool " + toolData.toolName
 810  
                                 + " was null, skipping it.");
 811  
                     }
 812  0
                 }
 813  
             }
 814  0
             catch (Exception e)
 815  
             {
 816  0
                 log.error("Could not instantiate perm tool "
 817  
                     + toolData.toolName + " from a "
 818  
                     + toolData.toolClassName + " object", e);
 819  0
             }
 820  0
         }
 821  2
     }
 822  
 
 823  
     /**
 824  
      * Populate the given context with the perm-scoped tools.
 825  
      *
 826  
      * @param tools The list of tools with which to populate the
 827  
      * session.
 828  
      * @param context The context to populate.
 829  
      * @param pipelineData The current RunData object
 830  
      * @param user The <code>User</code> object whose storage to
 831  
      * retrieve the tool from.
 832  
      */
 833  
     private void populateWithPermTools(List<ToolData> tools, Context context,
 834  
             RunData data, User user)
 835  
     {
 836  
         // Iterate the tools
 837  0
         for (Iterator<ToolData> it = tools.iterator(); it.hasNext();)
 838  
         {
 839  0
             ToolData toolData = it.next();
 840  
             try
 841  
             {
 842  
                 // ensure that tool is created only once for a user
 843  
                 // by synchronizing against the user object
 844  0
                 synchronized (user)
 845  
                 {
 846  
                     // first try and fetch the tool from the user's
 847  
                     // hashtable
 848  0
                     Object tool = user.getPerm(toolData.toolClassName);
 849  
 
 850  0
                     if (tool == null)
 851  
                     {
 852  
                         // if not there, an instance must be fetched from
 853  
                         // the pool
 854  0
                         tool = pool.getInstance(toolData.toolClass);
 855  
 
 856  
                         // session tools are init'd with the User object
 857  0
                         initTool(tool, user);
 858  
 
 859  
                         // store the newly created tool in the user's hashtable
 860  0
                         user.setPerm(toolData.toolClassName, tool);
 861  
                     }
 862  
 
 863  
                     // *NOT* else
 864  0
                     if(tool != null)
 865  
                     {
 866  
                         // This is a semantics change. In the old
 867  
                         // Turbine, Session tools were initialized and
 868  
                         // then refreshed every time they were pulled
 869  
                         // into the context if "refreshToolsPerRequest"
 870  
                         // was wanted.
 871  
                         //
 872  
                         // RunDataApplicationTools now have a parameter
 873  
                         // for refresh. If it is not refreshed immediately
 874  
                         // after init(), the parameter value will be undefined
 875  
                         // until the 2nd run. So we refresh all the session
 876  
                         // tools on every run, even if we just init'ed it.
 877  
                         //
 878  
 
 879  0
                         if (refreshToolsPerRequest)
 880  
                         {
 881  0
                             refreshTool(tool, data);
 882  
                         }
 883  
 
 884  
                         // put the tool in the context
 885  0
                         log.debug("Adding " + tool + " to ctx as "
 886  
                                 + toolData.toolName);
 887  0
                         log.warn("Persistent scope tools are deprecated.");
 888  0
                         context.put(toolData.toolName, tool);
 889  
                     }
 890  
                     else
 891  
                     {
 892  0
                         log.info("Tool " + toolData.toolName
 893  
                                 + " was null, skipping it.");
 894  
                     }
 895  0
                 }
 896  
             }
 897  0
             catch (Exception e)
 898  
             {
 899  0
                 log.error("Could not instantiate perm tool "
 900  
                     + toolData.toolName + " from a "
 901  
                     + toolData.toolClassName + " object", e);
 902  0
             }
 903  0
         }
 904  0
     }
 905  
 
 906  
 
 907  
 
 908  
     /**
 909  
      * Return the absolute path to the resources directory
 910  
      * used by the application tools.
 911  
      *
 912  
      * @return the absolute path of the resources directory
 913  
      */
 914  
     @Override
 915  
     public String getAbsolutePathToResourcesDirectory()
 916  
     {
 917  0
         return Turbine.getRealPath(resourcesDirectory);
 918  
     }
 919  
 
 920  
     /**
 921  
      * Return the resources directory. This is
 922  
      * relative to the web context.
 923  
      *
 924  
      * @return the relative path of the resources directory
 925  
      */
 926  
     @Override
 927  
     public String getResourcesDirectory()
 928  
     {
 929  19
         return resourcesDirectory;
 930  
     }
 931  
 
 932  
     /**
 933  
      * Refresh the global tools. We can
 934  
      * only refresh those tools that adhere to
 935  
      * ApplicationTool interface because we
 936  
      * know those types of tools have a refresh
 937  
      * method.
 938  
      */
 939  
     private void refreshGlobalTools()
 940  
     {
 941  10
         if (globalTools != null)
 942  
         {
 943  10
             for (ToolData toolData : globalTools)
 944  
             {
 945  10
                 Object tool = globalContext.get(toolData.toolName);
 946  10
                 refreshTool(tool, null);
 947  10
             }
 948  
         }
 949  10
     }
 950  
 
 951  
     /**
 952  
      * Release the request-scope tool instances in the
 953  
      * given Context back to the pool
 954  
      *
 955  
      * @param context the Velocity Context to release tools from
 956  
      */
 957  
     @Override
 958  
     public void releaseTools(Context context)
 959  
     {
 960  
         // only the request tools can be released - other scoped
 961  
         // tools will have continuing references to them
 962  2
         releaseTools(context, requestTools);
 963  2
     }
 964  
 
 965  
     /**
 966  
      * Release the given list of tools from the context back
 967  
      * to the pool
 968  
      *
 969  
      * @param context the Context containing the tools
 970  
      * @param tools a List of ToolData objects
 971  
      */
 972  
     private void releaseTools(Context context, List<ToolData> tools)
 973  
     {
 974  2
         if (tools != null)
 975  
         {
 976  2
             for (ToolData toolData : tools)
 977  
             {
 978  10
                 Object tool = context.remove(toolData.toolName);
 979  
 
 980  10
                 if (tool != null)
 981  
                 {
 982  10
                     pool.putInstance(tool);
 983  
                 }
 984  10
             }
 985  
         }
 986  2
     }
 987  
 
 988  
     /**
 989  
      * Initialized a given Tool with the passed init Object
 990  
      *
 991  
      * @param tool A Tool Object
 992  
      * @param param The Init Parameter
 993  
      *
 994  
      * @throws Exception If anything went wrong.
 995  
      */
 996  
     private void initTool(Object tool, Object param)
 997  
         throws Exception
 998  
     {
 999  73
         AnnotationProcessor.process(tool);
 1000  
 
 1001  73
         if (param instanceof PipelineData)
 1002  
         {
 1003  45
             if (tool instanceof PipelineDataApplicationTool)
 1004  
             {
 1005  0
                 ((PipelineDataApplicationTool) tool).init(param);
 1006  
             }
 1007  45
             else if (tool instanceof RunDataApplicationTool)
 1008  
             {
 1009  0
                 RunData data = getRunData((PipelineData)param);
 1010  0
                 ((RunDataApplicationTool) tool).init(data);
 1011  0
             }
 1012  45
             else if (tool instanceof ApplicationTool)
 1013  
             {
 1014  45
                 RunData data = getRunData((PipelineData)param);
 1015  45
                 ((ApplicationTool) tool).init(data);
 1016  45
             }
 1017  
         }
 1018  
         else
 1019  
         {
 1020  28
             if (tool instanceof PipelineDataApplicationTool)
 1021  
             {
 1022  0
                 ((PipelineDataApplicationTool) tool).init(param);
 1023  
             }
 1024  28
             else if (tool instanceof RunDataApplicationTool)
 1025  
             {
 1026  0
                 ((RunDataApplicationTool) tool).init(param);
 1027  
             }
 1028  28
             else if (tool instanceof ApplicationTool)
 1029  
             {
 1030  28
                 ((ApplicationTool) tool).init(param);
 1031  
             }
 1032  
         }
 1033  73
     }
 1034  
 
 1035  
     /**
 1036  
      * Refresh a given Tool.
 1037  
      *
 1038  
      * @param tool A Tool Object
 1039  
      * @param pipelineData The current RunData Object
 1040  
      */
 1041  
     private void refreshTool(Object tool, Object dataObject)
 1042  
     {
 1043  19
         RunData data = null;
 1044  19
         PipelineData pipelineData = null;
 1045  19
         if (dataObject instanceof PipelineData)
 1046  
         {
 1047  9
             pipelineData = (PipelineData)dataObject;
 1048  9
             data = getRunData(pipelineData);
 1049  9
             if (tool instanceof PipelineDataApplicationTool)
 1050  
             {
 1051  0
                 ((PipelineDataApplicationTool) tool).refresh(pipelineData);
 1052  
             }
 1053  
         }
 1054  19
         if (tool instanceof ApplicationTool)
 1055  
         {
 1056  19
             ((ApplicationTool) tool).refresh();
 1057  
         }
 1058  0
         else if (tool instanceof RunDataApplicationTool)
 1059  
         {
 1060  0
             ((RunDataApplicationTool) tool).refresh(data);
 1061  
         }
 1062  19
     }
 1063  
 
 1064  
     private RunData getRunData(PipelineData pipelineData)
 1065  
     {
 1066  54
         if(!(pipelineData instanceof RunData)){
 1067  0
             throw new RuntimeException("Can't cast to rundata from pipeline data.");
 1068  
         }
 1069  54
         return (RunData)pipelineData;
 1070  
     }
 1071  
 }