View Javadoc
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.configuration2.Configuration;
29  import org.apache.fulcrum.pool.PoolService;
30  import org.apache.fulcrum.security.model.turbine.TurbineUserManager;
31  import org.apache.logging.log4j.LogManager;
32  import org.apache.logging.log4j.Logger;
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 1854797 2019-03-04 20:41:39Z tv $
120  */
121 public class TurbinePullService
122         extends TurbineBaseService
123         implements PullService
124 {
125     /** Logging */
126     private static Logger log = LogManager.getLogger(TurbinePullService.class);
127 
128     /** Reference to the pool service */
129     private PoolService pool = null;
130 
131     /** Reference to the templating (nee Velocity) service */
132     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         {
157             this.toolName = toolName;
158             this.toolClassName = toolClassName;
159             this.toolClass = toolClass;
160         }
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     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 		    pool = (PoolService)TurbineServices.getInstance().getService(PoolService.ROLE);
194 
195             if (pool == null)
196             {
197                 throw new InitializationException("Pull Service requires"
198                     + " configured Pool Service!");
199             }
200 
201             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             setInit(true);
206 
207             // Do _NOT_ move this before the setInit(true)
208             velocity = (VelocityService)TurbineServices.getInstance().getService(VelocityService.SERVICE_NAME);
209 
210             if (velocity != null)
211             {
212                 initPullTools();
213             }
214             else
215             {
216                 log.info("Velocity Service not configured, skipping pull tools!");
217             }
218         }
219         catch (Exception e)
220         {
221             throw new InitializationException("TurbinePullService failed to initialize", e);
222         }
223     }
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         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         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         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         if (refreshToolsPerRequest)
252         {
253             log.info("Pull Model tools will be refreshed on a per request basis.");
254         }
255     }
256 
257     /**
258      * Initialize the pull tools. At this point, the
259      * service must be marked as initialized, because the
260      * tools may call the methods of this service via the
261      * static facade class TurbinePull.
262      *
263      * @throws Exception A problem happened when starting up
264      */
265     private void initPullTools()
266         throws Exception
267     {
268         // And for reasons I never really fully understood,
269         // the tools directive is toplevel without the service
270         // prefix. This is brain-damaged but for legacy reasons we
271         // keep this. So this is the global turbine configuration:
272         Configuration conf = Turbine.getConfiguration();
273 
274         // Grab each list of tools that are to be used (for global scope,
275         // request scope, authorized scope, session scope and persistent
276         // scope tools). They are specified respectively in the TR.props
277         // like this:
278         //
279         // tool.global.ui = org.apache.turbine.util.pull.UIManager
280         // tool.global.mm = org.apache.turbine.util.pull.MessageManager
281         //
282         // tool.request.link = org.apache.turbine.services.pull.tools.TemplateLink
283         //
284         // tool.session.basket = org.sample.util.ShoppingBasket;
285         //
286         // tool.persistent.ui = org.apache.turbine.services.pull.util.PersistentUIManager
287 
288         log.debug("Global Tools:");
289         globalTools     = getTools(conf.subset(GLOBAL_TOOL));
290         log.debug("Request Tools:");
291         requestTools    = getTools(conf.subset(REQUEST_TOOL));
292         log.debug("Session Tools:");
293         sessionTools    = getTools(conf.subset(SESSION_TOOL));
294         log.debug("Authorized Tools:");
295         authorizedTools = getTools(conf.subset(AUTHORIZED_TOOL));
296         log.debug("Persistent Tools:");
297         persistentTools = getTools(conf.subset(PERSISTENT_TOOL));
298 
299         // Create and populate the global context right now
300 
301         // This is unholy, because it entwines the VelocityService and
302         // the Pull Service even further. However, there isn't much we can
303         // do for the 2.3 release. Expect this to go post-2.3
304         globalContext = velocity.getNewContext();
305 
306         populateWithGlobalTools(globalContext);
307     }
308 
309     /**
310      * Retrieve the tool names and classes for the tools defined
311      * in the configuration file with the prefix given.
312      *
313      * @param toolConfig The part of the configuration describing some tools
314      */
315     @SuppressWarnings("unchecked")
316     private List<ToolData> getTools(Configuration toolConfig)
317     {
318         List<ToolData> tools = new ArrayList<ToolData>();
319 
320         // There might not be any tools for this prefix
321         // so return an empty list.
322         if (toolConfig == null)
323         {
324             return tools;
325         }
326 
327         for (Iterator<String> it = toolConfig.getKeys(); it.hasNext();)
328         {
329             String toolName = it.next();
330             String toolClassName = toolConfig.getString(toolName);
331 
332             try
333             {
334                 // Create an instance of the tool class.
335                 Class<ApplicationTool> toolClass = (Class<ApplicationTool>) Class.forName(toolClassName);
336 
337                 // Add the tool to the list being built.
338                 tools.add(new ToolData(toolName, toolClassName, toolClass));
339 
340                 log.info("Tool {} to add to the context as '${}'", toolClassName, toolName);
341             }
342             catch (NoClassDefFoundError | ClassNotFoundException e)
343             {
344                 log.error("Cannot instantiate tool class {}", toolClassName, e);
345             }
346         }
347 
348         return tools;
349     }
350 
351     /**
352      * Return the Context which contains all global tools that
353      * are to be used in conjunction with the Turbine
354      * Pull Model. The tools are refreshed every time the
355      * global Context is pulled.
356      */
357     @Override
358     public Context getGlobalContext()
359     {
360         if (refreshToolsPerRequest)
361         {
362             refreshGlobalTools();
363         }
364         return globalContext;
365     }
366 
367     /**
368      * Populate the given context with all request, session, authorized
369      * and persistent scope tools (it is assumed that the context
370      * already wraps the global context, and thus already contains
371      * the global tools).
372      *
373      * @param context a Velocity Context to populate
374      * @param data a RunData object for request specific data
375      */
376     @Override
377     public void populateContext(Context context, RunData data)
378     {
379         populateWithRequestTools(context, data);
380 
381         // session tools (whether session-only or persistent are
382         // very similar, so the same method is used - the
383         // boolean parameter indicates whether get/setPerm is to be used
384         // rather than get/setTemp)
385 
386         //
387         // Session Tool start right at the session once the user has been set
388         // while persistent and authorized Tools are started when the user has
389         // logged in
390         //
391         User user = data.getUser();
392 
393         // Note: Session tools are currently lost after the login action
394         // because the anonymous user is replaced the the real user object.
395         // We should either store the session pull tools in the session or
396         // make Turbine.loginAction() copy the session pull tools into the
397         // new user object.
398         populateWithSessionTools(sessionTools, context, data, user);
399 
400         TurbineUserManager userManager =
401         	(TurbineUserManager)TurbineServices
402         		.getInstance()
403         		.getService(TurbineUserManager.ROLE);
404 
405         if (!userManager.isAnonymousUser(user) && user.hasLoggedIn())
406         {
407             populateWithSessionTools(authorizedTools, context, data, user);
408             populateWithPermTools(persistentTools, context, data, user);
409         }
410     }
411 
412     /**
413      * Populate the given context with all request, session, authorized
414      * and persistent scope tools (it is assumed that the context
415      * already wraps the global context, and thus already contains
416      * the global tools).
417      *
418      * @param context a Velocity Context to populate
419      * @param pipelineData a PipelineData object for request specific data
420      */
421     @Override
422     public void populateContext(Context context, PipelineData pipelineData)
423     {
424         RunData data = pipelineData.getRunData();
425 
426         populateWithRequestTools(context, pipelineData);
427         // session tools (whether session-only or persistent are
428         // very similar, so the same method is used - the
429         // boolean parameter indicates whether get/setPerm is to be used
430         // rather than get/setTemp)
431 
432         //
433         // Session Tool start right at the session once the user has been set
434         // while persistent and authorized Tools are started when the user has
435         // logged in
436         //
437         User user = data.getUser();
438 
439         // Note: Session tools are currently lost after the login action
440         // because the anonymous user is replaced the the real user object.
441         // We should either store the session pull tools in the session or
442         // make Turbine.loginAction() copy the session pull tools into the
443         // new user object.
444         populateWithSessionTools(sessionTools, context, data, user);
445 
446         TurbineUserManager userManager =
447         	(TurbineUserManager)TurbineServices
448         		.getInstance()
449         		.getService(TurbineUserManager.ROLE);
450 
451         if (!userManager.isAnonymousUser(user) && user.hasLoggedIn())
452         {
453             populateWithSessionTools(authorizedTools, context, data, user);
454             populateWithPermTools(persistentTools, context, pipelineData, user);
455         }
456     }
457 
458     /**
459      * Populate the given context with the global tools
460      *
461      * @param context a Velocity Context to populate
462      */
463     private void populateWithGlobalTools(Context context)
464     {
465         for (ToolData toolData : globalTools)
466         {
467             try
468             {
469                 Object tool = toolData.toolClass.newInstance();
470 
471                 // global tools are init'd with a null data parameter
472                 initTool(tool, null);
473 
474                 // put the tool in the context
475                 context.put(toolData.toolName, tool);
476             }
477             catch (Exception e)
478             {
479                 log.error("Could not instantiate global tool {} from a {} object",
480                     toolData.toolName, toolData.toolClassName, e);
481             }
482         }
483     }
484 
485     /**
486      * Populate the given context with the request-scope tools
487      *
488      * @param context a Velocity Context to populate
489      * @param data a RunData or PipelineData instance
490      */
491     private void populateWithRequestTools(Context context, Object data)
492     {
493         // Iterate the tools
494         for (ToolData toolData : requestTools)
495         {
496             try
497             {
498                 // Fetch Object through the Pool.
499                 Object tool = pool.getInstance(toolData.toolClass);
500 
501                 // request tools are init'd with a RunData object
502                 initTool(tool, data);
503 
504                 // put the tool in the context
505                 context.put(toolData.toolName, tool);
506             }
507             catch (Exception e)
508             {
509                 log.error("Could not instantiate request tool {} from a {} object",
510                         toolData.toolName, toolData.toolClassName, e);
511             }
512         }
513     }
514 
515     /**
516      * Populate the given context with the session-scoped tools.
517      *
518      * @param tools The list of tools with which to populate the session.
519      * @param context The context to populate.
520      * @param data The current RunData object
521      * @param user The <code>User</code> object whose storage to
522      * retrieve the tool from.
523      */
524     private void populateWithSessionTools(List<ToolData> tools, Context context,
525             RunData data, User user)
526     {
527         // Iterate the tools
528         for (ToolData toolData : tools)
529         {
530             try
531             {
532                 // ensure that tool is created only once for a user
533                 // by synchronizing against the user object
534                 synchronized (data.getSession())
535                 {
536                     // first try and fetch the tool from the user's
537                     // hashmap
538                     Object tool = data.getSession().getAttribute(
539                             SESSION_TOOLS_ATTRIBUTE_PREFIX
540                             + toolData.toolClassName);
541 
542                     if (tool == null)
543                     {
544                         // if not there, an instance must be fetched from
545                         // the pool
546                         tool = pool.getInstance(toolData.toolClass);
547 
548                         // session tools are init'd with the User object
549                         initTool(tool, user);
550                     }
551 
552                     // *NOT* else
553                     if(tool != null)
554                     {
555                         // store the newly created tool in the session
556                         data.getSession().setAttribute(
557                                 SESSION_TOOLS_ATTRIBUTE_PREFIX
558                                 + tool.getClass().getName(), tool);
559 
560                         // This is a semantics change. In the old
561                         // Turbine, Session tools were initialized and
562                         // then refreshed every time they were pulled
563                         // into the context if "refreshToolsPerRequest"
564                         // was wanted.
565                         //
566                         // RunDataApplicationTools now have a parameter
567                         // for refresh. If it is not refreshed immediately
568                         // after init(), the parameter value will be undefined
569                         // until the 2nd run. So we refresh all the session
570                         // tools on every run, even if we just init'ed it.
571                         //
572 
573                         if (refreshToolsPerRequest)
574                         {
575                             refreshTool(tool, data);
576                         }
577 
578                         // put the tool in the context
579                         log.debug("Adding {} to ctx as {}", tool, toolData.toolName);
580                         context.put(toolData.toolName, tool);
581                     }
582                     else
583                     {
584                         log.info("Tool {} was null, skipping it.", toolData.toolName);
585                     }
586                 }
587             }
588             catch (Exception e)
589             {
590                 log.error("Could not instantiate session tool {} from a {} object",
591                         toolData.toolName, toolData.toolClassName, e);
592             }
593         }
594     }
595 
596     /**
597      * Populate the given context with the perm-scoped tools.
598      *
599      * @param tools The list of tools with which to populate the
600      * session.
601      * @param context The context to populate.
602      * @param data The current RunData or PipelineData object
603      * @param user The <code>User</code> object whose storage to
604      * retrieve the tool from.
605      */
606     private void populateWithPermTools(List<ToolData> tools, Context context,
607             Object data, User user)
608     {
609         // Iterate the tools
610         for (ToolData toolData : tools)
611         {
612             try
613             {
614                 // ensure that tool is created only once for a user
615                 // by synchronizing against the user object
616                 synchronized (user)
617                 {
618                     // first try and fetch the tool from the user's
619                     // hashtable
620                     Object tool = user.getPerm(toolData.toolClassName);
621 
622                     if (tool == null)
623                     {
624                         // if not there, an instance must be fetched from
625                         // the pool
626                         tool = pool.getInstance(toolData.toolClass);
627 
628                         // session tools are init'd with the User object
629                         initTool(tool, user);
630 
631                         // store the newly created tool in the user's hashtable
632                         user.setPerm(toolData.toolClassName, tool);
633                     }
634 
635                     // *NOT* else
636                     if (tool != null)
637                     {
638                         // This is a semantics change. In the old
639                         // Turbine, Session tools were initialized and
640                         // then refreshed every time they were pulled
641                         // into the context if "refreshToolsPerRequest"
642                         // was wanted.
643                         //
644                         // RunDataApplicationTools now have a parameter
645                         // for refresh. If it is not refreshed immediately
646                         // after init(), the parameter value will be undefined
647                         // until the 2nd run. So we refresh all the session
648                         // tools on every run, even if we just init'ed it.
649                         //
650 
651                         if (refreshToolsPerRequest)
652                         {
653                             refreshTool(tool, data);
654                         }
655 
656                         // put the tool in the context
657                         log.debug("Adding {} to ctx as {}", tool, toolData.toolName);
658                         log.warn("Persistent scope tools are deprecated.");
659                         context.put(toolData.toolName, tool);
660                     }
661                     else
662                     {
663                         log.info("Tool {} was null, skipping it.", toolData.toolName);
664                     }
665                 }
666             }
667             catch (Exception e)
668             {
669                 log.error("Could not instantiate perm tool {} from a {} object",
670                         toolData.toolName, toolData.toolClassName, e);
671             }
672         }
673     }
674 
675 
676 
677     /**
678      * Return the absolute path to the resources directory
679      * used by the application tools.
680      *
681      * @return the absolute path of the resources directory
682      */
683     @Override
684     public String getAbsolutePathToResourcesDirectory()
685     {
686         return Turbine.getRealPath(resourcesDirectory);
687     }
688 
689     /**
690      * Return the resources directory. This is
691      * relative to the web context.
692      *
693      * @return the relative path of the resources directory
694      */
695     @Override
696     public String getResourcesDirectory()
697     {
698         return resourcesDirectory;
699     }
700 
701     /**
702      * Refresh the global tools. We can
703      * only refresh those tools that adhere to
704      * ApplicationTool interface because we
705      * know those types of tools have a refresh
706      * method.
707      */
708     private void refreshGlobalTools()
709     {
710         if (globalTools != null)
711         {
712             for (ToolData toolData : globalTools)
713             {
714                 Object tool = globalContext.get(toolData.toolName);
715                 refreshTool(tool, null);
716             }
717         }
718     }
719 
720     /**
721      * Release the request-scope tool instances in the
722      * given Context back to the pool
723      *
724      * @param context the Velocity Context to release tools from
725      */
726     @Override
727     public void releaseTools(Context context)
728     {
729         // only the request tools can be released - other scoped
730         // tools will have continuing references to them
731         releaseTools(context, requestTools);
732     }
733 
734     /**
735      * Release the given list of tools from the context back
736      * to the pool
737      *
738      * @param context the Context containing the tools
739      * @param tools a List of ToolData objects
740      */
741     private void releaseTools(Context context, List<ToolData> tools)
742     {
743         if (tools != null)
744         {
745             for (ToolData toolData : tools)
746             {
747                 Object tool = context.remove(toolData.toolName);
748 
749                 if (tool != null)
750                 {
751                     pool.putInstance(tool);
752                 }
753             }
754         }
755     }
756 
757     /**
758      * Initialized a given Tool with the passed init Object
759      *
760      * @param tool A Tool Object
761      * @param param The Init Parameter
762      *
763      * @throws Exception If anything went wrong.
764      */
765     private void initTool(Object tool, Object param)
766         throws Exception
767     {
768         AnnotationProcessor.process(tool);
769 
770         if (param instanceof PipelineData)
771         {
772             if (tool instanceof PipelineDataApplicationTool)
773             {
774                 ((PipelineDataApplicationTool) tool).init(param);
775             }
776             else if (tool instanceof RunDataApplicationTool)
777             {
778                 RunData data = getRunData((PipelineData)param);
779                 ((RunDataApplicationTool) tool).init(data);
780             }
781             else if (tool instanceof ApplicationTool)
782             {
783                 RunData data = getRunData((PipelineData)param);
784                 ((ApplicationTool) tool).init(data);
785             }
786         }
787         else
788         {
789             if (tool instanceof PipelineDataApplicationTool)
790             {
791                 ((PipelineDataApplicationTool) tool).init(param);
792             }
793             else if (tool instanceof RunDataApplicationTool)
794             {
795                 ((RunDataApplicationTool) tool).init(param);
796             }
797             else if (tool instanceof ApplicationTool)
798             {
799                 ((ApplicationTool) tool).init(param);
800             }
801         }
802     }
803 
804     /**
805      * Refresh a given Tool.
806      *
807      * @param tool A Tool Object
808      * @param pipelineData The current RunData Object
809      */
810     private void refreshTool(Object tool, Object dataObject)
811     {
812         RunData data = null;
813         PipelineData pipelineData = null;
814         if (dataObject instanceof PipelineData)
815         {
816             pipelineData = (PipelineData)dataObject;
817             data = pipelineData.getRunData();
818             if (tool instanceof PipelineDataApplicationTool)
819             {
820                 ((PipelineDataApplicationTool) tool).refresh(pipelineData);
821             }
822         }
823         if (tool instanceof ApplicationTool)
824         {
825             ((ApplicationTool) tool).refresh();
826         }
827         else if (tool instanceof RunDataApplicationTool)
828         {
829             ((RunDataApplicationTool) tool).refresh(data);
830         }
831     }
832 
833     private RunData getRunData(PipelineData pipelineData)
834     {
835         if (!(pipelineData instanceof RunData))
836         {
837             throw new RuntimeException("Can't cast to rundata from pipeline data.");
838         }
839         return (RunData)pipelineData;
840     }
841 }