001package org.apache.turbine.services.pull;
002
003
004/*
005 * Licensed to the Apache Software Foundation (ASF) under one
006 * or more contributor license agreements.  See the NOTICE file
007 * distributed with this work for additional information
008 * regarding copyright ownership.  The ASF licenses this file
009 * to you under the Apache License, Version 2.0 (the
010 * "License"); you may not use this file except in compliance
011 * with the License.  You may obtain a copy of the License at
012 *
013 *   http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing,
016 * software distributed under the License is distributed on an
017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
018 * KIND, either express or implied.  See the License for the
019 * specific language governing permissions and limitations
020 * under the License.
021 */
022
023
024import java.util.ArrayList;
025import java.util.Iterator;
026import java.util.List;
027
028import org.apache.commons.configuration2.Configuration;
029import org.apache.fulcrum.pool.PoolService;
030import org.apache.fulcrum.security.model.turbine.TurbineUserManager;
031import org.apache.logging.log4j.LogManager;
032import org.apache.logging.log4j.Logger;
033import org.apache.turbine.Turbine;
034import org.apache.turbine.annotation.AnnotationProcessor;
035import org.apache.turbine.om.security.User;
036import org.apache.turbine.pipeline.PipelineData;
037import org.apache.turbine.services.InitializationException;
038import org.apache.turbine.services.TurbineBaseService;
039import org.apache.turbine.services.TurbineServices;
040import org.apache.turbine.services.velocity.VelocityService;
041import org.apache.turbine.util.RunData;
042import org.apache.velocity.context.Context;
043
044/**
045 * This is the concrete implementation of the Turbine
046 * Pull Service.
047 * <p>
048 * These are tools that are placed in the context by the service
049 * These tools will be made available to all your
050 * templates. You list the tools in the following way:
051 * </p>
052 * <pre>
053 * tool.&lt;scope&gt;.&lt;id&gt; = &lt;classname&gt;
054 *
055 * &lt;scope&gt;      is the tool scope: global, request, session,
056 *              authorized or persistent (see below for more details)
057 * &lt;id&gt;         is the name of the tool in the context
058 *
059 * You can configure the tools in this way:
060 * tool.&lt;id&gt;.&lt;parameter&gt; = &lt;value&gt;
061 *
062 * So if you find "global", "request", "session" or "persistent" as second
063 * part, it is a configuration to put a tool into the toolbox, else it is a
064 * tool specific configuration.
065 *
066 * For example:
067 *
068 * tool.global.ui    = org.apache.turbine.util.pull.UIManager
069 * tool.global.mm    = org.apache.turbine.util.pull.MessageManager
070 * tool.request.link = org.apache.turbine.services.pull.tools.TemplateLink
071 * tool.request.page = org.apache.turbine.util.template.TemplatePageAttributes
072 *
073 * Then:
074 *
075 * tool.ui.skin = default
076 *
077 * configures the value of "skin" for the "ui" tool.
078 *
079 * Tools are accessible in all templates by the &lt;id&gt; given
080 * to the tool. So for the above listings the UIManager would
081 * be available as $ui, the MessageManager as $mm, the TemplateLink
082 * as $link and the TemplatePageAttributes as $page.
083 *
084 * You should avoid using tool names called "global", "request",
085 * "session" or "persistent" because of clashes with the possible Scopes.
086 *
087 * Scopes:
088 *
089 *  global:     tool is instantiated once and that instance is available
090 *              to all templates for all requests. Tool must be threadsafe.
091 *
092 *  request:    tool is instantiated once for each request (although the
093 *              PoolService is used to recycle instances). Tool need not
094 *              be threadsafe.
095 *
096 *  session:    tool is instantiated once for each user session, and is
097 *              stored in the session.  These tools do not need to be
098 *              threadsafe.
099 *
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$
120 */
121public 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<>();
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.getDeclaredConstructor().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}