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.configuration.Configuration; 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.apache.fulcrum.pool.PoolService; 032import org.apache.fulcrum.security.model.turbine.TurbineUserManager; 033import org.apache.turbine.Turbine; 034import org.apache.turbine.om.security.User; 035import org.apache.turbine.pipeline.PipelineData; 036import org.apache.turbine.services.InitializationException; 037import org.apache.turbine.services.TurbineBaseService; 038import org.apache.turbine.services.TurbineServices; 039import org.apache.turbine.services.velocity.TurbineVelocity; 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.<scope>.<id> = <classname> 054 * 055 * <scope> is the tool scope: global, request, session, 056 * authorized or persistent (see below for more details) 057 * <id> is the name of the tool in the context 058 * 059 * You can configure the tools in this way: 060 * tool.<id>.<parameter> = <value> 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 <id> 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: TurbinePullService.java 1706239 2015-10-01 13:18:35Z tv $ 120 */ 121public class TurbinePullService 122 extends TurbineBaseService 123 implements PullService 124{ 125 /** Logging */ 126 private static Log log = LogFactory.getLog(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 = TurbineVelocity.getService(); 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( 222 "TurbinePullService failed to initialize", e); 223 } 224 } 225 226 /** 227 * Initialize the pull service 228 * 229 * @exception Exception A problem happened when starting up 230 */ 231 private void initPullService() 232 throws Exception 233 { 234 // This is the per-service configuration, prefixed with services.PullService 235 Configuration conf = getConfiguration(); 236 237 // Get the resources directory that is specificed 238 // in the TR.props or default to "resources", relative to the webapp. 239 resourcesDirectory = conf.getString( 240 TOOL_RESOURCES_DIR_KEY, 241 TOOL_RESOURCES_DIR_DEFAULT); 242 243 // Should we refresh the tool box on a per 244 // request basis. 245 refreshToolsPerRequest = 246 conf.getBoolean( 247 TOOLS_PER_REQUEST_REFRESH_KEY, 248 TOOLS_PER_REQUEST_REFRESH_DEFAULT); 249 250 // Log the fact that the application tool box will 251 // be refreshed on a per request basis. 252 if (refreshToolsPerRequest) 253 { 254 log.info("Pull Model tools will " 255 + "be refreshed on a per request basis."); 256 } 257 } 258 259 /** 260 * Initialize the pull tools. At this point, the 261 * service must be marked as initialized, because the 262 * tools may call the methods of this service via the 263 * static facade class TurbinePull. 264 * 265 * @exception Exception A problem happened when starting up 266 */ 267 private void initPullTools() 268 throws Exception 269 { 270 // And for reasons I never really fully understood, 271 // the tools directive is toplevel without the service 272 // prefix. This is brain-damaged but for legacy reasons we 273 // keep this. So this is the global turbine configuration: 274 Configuration conf = Turbine.getConfiguration(); 275 276 // Grab each list of tools that are to be used (for global scope, 277 // request scope, authorized scope, session scope and persistent 278 // scope tools). They are specified respectively in the TR.props 279 // like this: 280 // 281 // tool.global.ui = org.apache.turbine.util.pull.UIManager 282 // tool.global.mm = org.apache.turbine.util.pull.MessageManager 283 // 284 // tool.request.link = org.apache.turbine.services.pull.tools.TemplateLink 285 // 286 // tool.session.basket = org.sample.util.ShoppingBasket; 287 // 288 // tool.persistent.ui = org.apache.turbine.services.pull.util.PersistentUIManager 289 290 log.debug("Global Tools:"); 291 globalTools = getTools(conf.subset(GLOBAL_TOOL)); 292 log.debug("Request Tools:"); 293 requestTools = getTools(conf.subset(REQUEST_TOOL)); 294 log.debug("Session Tools:"); 295 sessionTools = getTools(conf.subset(SESSION_TOOL)); 296 log.debug("Authorized Tools:"); 297 authorizedTools = getTools(conf.subset(AUTHORIZED_TOOL)); 298 log.debug("Persistent Tools:"); 299 persistentTools = getTools(conf.subset(PERSISTENT_TOOL)); 300 301 // Create and populate the global context right now 302 303 // This is unholy, because it entwines the VelocityService and 304 // the Pull Service even further. However, there isn't much we can 305 // do for the 2.3 release. Expect this to go post-2.3 306 globalContext = velocity.getNewContext(); 307 308 populateWithGlobalTools(globalContext); 309 } 310 311 /** 312 * Retrieve the tool names and classes for the tools definied 313 * in the configuration file with the prefix given. 314 * 315 * @param toolConfig The part of the configuration describing some tools 316 */ 317 @SuppressWarnings("unchecked") 318 private List<ToolData> getTools(Configuration toolConfig) 319 { 320 List<ToolData> tools = new ArrayList<ToolData>(); 321 322 // There might not be any tools for this prefix 323 // so return an empty list. 324 if (toolConfig == null) 325 { 326 return tools; 327 } 328 329 for (Iterator<String> it = toolConfig.getKeys(); it.hasNext();) 330 { 331 String toolName = it.next(); 332 String toolClassName = toolConfig.getString(toolName); 333 334 try 335 { 336 // Create an instance of the tool class. 337 Class<ApplicationTool> toolClass = (Class<ApplicationTool>) Class.forName(toolClassName); 338 339 // Add the tool to the list being built. 340 tools.add(new ToolData(toolName, toolClassName, toolClass)); 341 342 log.info("Tool " + toolClassName 343 + " to add to the context as '$" + toolName + "'"); 344 } 345 catch (Exception e) 346 { 347 log.error("Cannot instantiate tool class " 348 + toolClassName + ": ", e); 349 } 350 } 351 352 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 if (refreshToolsPerRequest) 365 { 366 refreshGlobalTools(); 367 } 368 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 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 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 populateWithSessionTools(sessionTools, context, data, user); 403 404 TurbineUserManager userManager = 405 (TurbineUserManager)TurbineServices 406 .getInstance() 407 .getService(TurbineUserManager.ROLE); 408 409 if (!userManager.isAnonymousUser(user)) 410 { 411 if (user.hasLoggedIn()) 412 { 413 populateWithSessionTools(authorizedTools, context, data, user); 414 populateWithPermTools(persistentTools, context, data, user); 415 } 416 } 417 } 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 RunData data = (RunData)pipelineData; 434 435 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 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 populateWithSessionTools(sessionTools, context, pipelineData, user); 454 455 TurbineUserManager userManager = 456 (TurbineUserManager)TurbineServices 457 .getInstance() 458 .getService(TurbineUserManager.ROLE); 459 460 if (!userManager.isAnonymousUser(user)) 461 { 462 if (user.hasLoggedIn()) 463 { 464 populateWithSessionTools(authorizedTools, context, pipelineData, user); 465 populateWithPermTools(persistentTools, context, pipelineData, user); 466 } 467 } 468 } 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 for (Iterator<ToolData> it = globalTools.iterator(); it.hasNext();) 478 { 479 ToolData toolData = it.next(); 480 try 481 { 482 Object tool = toolData.toolClass.newInstance(); 483 484 // global tools are init'd with a null data parameter 485 initTool(tool, null); 486 487 // put the tool in the context 488 context.put(toolData.toolName, tool); 489 } 490 catch (Exception e) 491 { 492 log.error("Could not instantiate global tool " 493 + toolData.toolName + " from a " 494 + toolData.toolClassName + " object", e); 495 } 496 } 497 } 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 for (Iterator<ToolData> it = requestTools.iterator(); it.hasNext();) 509 { 510 ToolData toolData = it.next(); 511 try 512 { 513 // Fetch Object through the Pool. 514 Object tool = pool.getInstance(toolData.toolClass); 515 516 // request tools are init'd with a RunData object 517 initTool(tool, data); 518 519 // put the tool in the context 520 context.put(toolData.toolName, tool); 521 } 522 catch (Exception e) 523 { 524 log.error("Could not instantiate request tool " 525 + toolData.toolName + " from a " 526 + toolData.toolClassName + " object", e); 527 } 528 } 529 } 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 for (Iterator<ToolData> it = requestTools.iterator(); it.hasNext();) 542 { 543 ToolData toolData = it.next(); 544 try 545 { 546 // Fetch Object through the Pool. 547 Object tool = pool.getInstance(toolData.toolClass); 548 549 initTool(tool, pipelineData); 550 551 // put the tool in the context 552 context.put(toolData.toolName, tool); 553 } 554 catch (Exception e) 555 { 556 log.error("Could not instantiate request tool " 557 + toolData.toolName + " from a " 558 + toolData.toolClassName + " object", e); 559 } 560 } 561 } 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 RunData runData = (RunData)pipelineData; 579 // Iterate the tools 580 for (Iterator<ToolData> it = tools.iterator(); it.hasNext();) 581 { 582 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 synchronized (runData.getSession()) 588 { 589 // first try and fetch the tool from the user's 590 // hashtable 591 Object tool = runData.getSession().getAttribute( 592 SESSION_TOOLS_ATTRIBUTE_PREFIX 593 + toolData.toolClassName); 594 595 if (tool == null) 596 { 597 // if not there, an instance must be fetched from 598 // the pool 599 tool = pool.getInstance(toolData.toolClass); 600 601 // session tools are init'd with the User object 602 initTool(tool, user); 603 } 604 605 // *NOT* else 606 if(tool != null) 607 { 608 // store the newly created tool in the session 609 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 if (refreshToolsPerRequest) 627 { 628 refreshTool(tool, pipelineData); 629 } 630 631 // put the tool in the context 632 log.debug("Adding " + tool + " to ctx as " 633 + toolData.toolName); 634 context.put(toolData.toolName, tool); 635 } 636 else 637 { 638 log.info("Tool " + toolData.toolName 639 + " was null, skipping it."); 640 } 641 } 642 } 643 catch (Exception e) 644 { 645 log.error("Could not instantiate session tool " 646 + toolData.toolName + " from a " 647 + toolData.toolClassName + " object", e); 648 } 649 } 650 } 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 for (Iterator<ToolData> it = tools.iterator(); it.hasNext();) 667 { 668 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 synchronized (data.getSession()) 674 { 675 // first try and fetch the tool from the user's 676 // hashtable 677 Object tool = data.getSession().getAttribute( 678 SESSION_TOOLS_ATTRIBUTE_PREFIX 679 + toolData.toolClassName); 680 681 if (tool == null) 682 { 683 // if not there, an instance must be fetched from 684 // the pool 685 tool = pool.getInstance(toolData.toolClass); 686 687 // session tools are init'd with the User object 688 initTool(tool, user); 689 } 690 691 // *NOT* else 692 if(tool != null) 693 { 694 // store the newly created tool in the session 695 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 if (refreshToolsPerRequest) 713 { 714 refreshTool(tool, data); 715 } 716 717 // put the tool in the context 718 log.debug("Adding " + tool + " to ctx as " 719 + toolData.toolName); 720 context.put(toolData.toolName, tool); 721 } 722 else 723 { 724 log.info("Tool " + toolData.toolName 725 + " was null, skipping it."); 726 } 727 } 728 } 729 catch (Exception e) 730 { 731 log.error("Could not instantiate session tool " 732 + toolData.toolName + " from a " 733 + toolData.toolClassName + " object", e); 734 } 735 } 736 } 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 for (Iterator<ToolData> it = tools.iterator(); it.hasNext();) 755 { 756 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 synchronized (user) 762 { 763 // first try and fetch the tool from the user's 764 // hashtable 765 Object tool = user.getPerm(toolData.toolClassName); 766 767 if (tool == null) 768 { 769 // if not there, an instance must be fetched from 770 // the pool 771 tool = pool.getInstance(toolData.toolClass); 772 773 // session tools are init'd with the User object 774 initTool(tool, user); 775 776 // store the newly created tool in the user's hashtable 777 user.setPerm(toolData.toolClassName, tool); 778 } 779 780 // *NOT* else 781 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 if (refreshToolsPerRequest) 797 { 798 refreshTool(tool, pipelineData); 799 } 800 801 // put the tool in the context 802 log.debug("Adding " + tool + " to ctx as " 803 + toolData.toolName); 804 log.warn("Persistent scope tools are deprecated."); 805 context.put(toolData.toolName, tool); 806 } 807 else 808 { 809 log.info("Tool " + toolData.toolName 810 + " was null, skipping it."); 811 } 812 } 813 } 814 catch (Exception e) 815 { 816 log.error("Could not instantiate perm tool " 817 + toolData.toolName + " from a " 818 + toolData.toolClassName + " object", e); 819 } 820 } 821 } 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 for (Iterator<ToolData> it = tools.iterator(); it.hasNext();) 838 { 839 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 synchronized (user) 845 { 846 // first try and fetch the tool from the user's 847 // hashtable 848 Object tool = user.getPerm(toolData.toolClassName); 849 850 if (tool == null) 851 { 852 // if not there, an instance must be fetched from 853 // the pool 854 tool = pool.getInstance(toolData.toolClass); 855 856 // session tools are init'd with the User object 857 initTool(tool, user); 858 859 // store the newly created tool in the user's hashtable 860 user.setPerm(toolData.toolClassName, tool); 861 } 862 863 // *NOT* else 864 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 if (refreshToolsPerRequest) 880 { 881 refreshTool(tool, data); 882 } 883 884 // put the tool in the context 885 log.debug("Adding " + tool + " to ctx as " 886 + toolData.toolName); 887 log.warn("Persistent scope tools are deprecated."); 888 context.put(toolData.toolName, tool); 889 } 890 else 891 { 892 log.info("Tool " + toolData.toolName 893 + " was null, skipping it."); 894 } 895 } 896 } 897 catch (Exception e) 898 { 899 log.error("Could not instantiate perm tool " 900 + toolData.toolName + " from a " 901 + toolData.toolClassName + " object", e); 902 } 903 } 904 } 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 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 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 for (Iterator<ToolData> it = globalTools.iterator(); it.hasNext();) 942 { 943 ToolData toolData = it.next(); 944 Object tool = globalContext.get(toolData.toolName); 945 refreshTool(tool, null); 946 } 947 } 948 949 /** 950 * Release the request-scope tool instances in the 951 * given Context back to the pool 952 * 953 * @param context the Velocity Context to release tools from 954 */ 955 @Override 956 public void releaseTools(Context context) 957 { 958 // only the request tools can be released - other scoped 959 // tools will have continuing references to them 960 releaseTools(context, requestTools); 961 } 962 963 /** 964 * Release the given list of tools from the context back 965 * to the pool 966 * 967 * @param context the Context containing the tools 968 * @param tools a List of ToolData objects 969 */ 970 private void releaseTools(Context context, List<ToolData> tools) 971 { 972 for (Iterator<ToolData> it = tools.iterator(); it.hasNext();) 973 { 974 ToolData toolData = it.next(); 975 Object tool = context.remove(toolData.toolName); 976 977 if (tool != null) 978 { 979 pool.putInstance(tool); 980 } 981 } 982 } 983 984 /** 985 * Initialized a given Tool with the passed init Object 986 * 987 * @param tool A Tool Object 988 * @param param The Init Parameter 989 * 990 * @throws Exception If anything went wrong. 991 */ 992 private void initTool(Object tool, Object param) 993 throws Exception 994 { 995 if (param instanceof PipelineData) 996 { 997 if (tool instanceof PipelineDataApplicationTool) 998 { 999 ((PipelineDataApplicationTool) tool).init(param); 1000 } 1001 else if (tool instanceof RunDataApplicationTool) 1002 { 1003 RunData data = getRunData((PipelineData)param); 1004 ((RunDataApplicationTool) tool).init(data); 1005 } 1006 else if (tool instanceof ApplicationTool) 1007 { 1008 RunData data = getRunData((PipelineData)param); 1009 ((ApplicationTool) tool).init(data); 1010 } 1011 } 1012 else 1013 { 1014 if (tool instanceof PipelineDataApplicationTool) 1015 { 1016 ((PipelineDataApplicationTool) tool).init(param); 1017 } 1018 else if (tool instanceof RunDataApplicationTool) 1019 { 1020 ((RunDataApplicationTool) tool).init(param); 1021 } 1022 else if (tool instanceof ApplicationTool) 1023 { 1024 ((ApplicationTool) tool).init(param); 1025 } 1026 } 1027 } 1028 1029 /** 1030 * Refresh a given Tool. 1031 * 1032 * @param tool A Tool Object 1033 * @param pipelineData The current RunData Object 1034 */ 1035 private void refreshTool(Object tool, Object dataObject) 1036 { 1037 RunData data = null; 1038 PipelineData pipelineData = null; 1039 if (dataObject instanceof PipelineData) 1040 { 1041 pipelineData = (PipelineData)dataObject; 1042 data = getRunData(pipelineData); 1043 if (tool instanceof PipelineDataApplicationTool) 1044 { 1045 ((PipelineDataApplicationTool) tool).refresh(pipelineData); 1046 } 1047 } 1048 if (tool instanceof ApplicationTool) 1049 { 1050 ((ApplicationTool) tool).refresh(); 1051 } 1052 else if (tool instanceof RunDataApplicationTool) 1053 { 1054 ((RunDataApplicationTool) tool).refresh(data); 1055 } 1056 } 1057 1058 private RunData getRunData(PipelineData pipelineData) 1059 { 1060 if(!(pipelineData instanceof RunData)){ 1061 throw new RuntimeException("Can't cast to rundata from pipeline data."); 1062 } 1063 return (RunData)pipelineData; 1064 } 1065}