Coverage report

  %line %branch
org.apache.jetspeed.velocity.JetspeedVelocityViewServlet
0% 
0% 

 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.jetspeed.velocity;
 18  
 
 19  
 import java.io.File;
 20  
 import java.util.Locale;
 21  
 import java.util.Map;
 22  
 
 23  
 import javax.portlet.PortletConfig;
 24  
 import javax.portlet.PortletMode;
 25  
 import javax.portlet.PortletRequest;
 26  
 import javax.portlet.RenderRequest;
 27  
 import javax.portlet.RenderResponse;
 28  
 import javax.portlet.WindowState;
 29  
 import javax.servlet.ServletConfig;
 30  
 import javax.servlet.ServletException;
 31  
 import javax.servlet.http.HttpServletRequest;
 32  
 import javax.servlet.http.HttpServletResponse;
 33  
 
 34  
 import org.apache.commons.collections.ExtendedProperties;
 35  
 import org.apache.commons.collections.map.LRUMap;
 36  
 import org.apache.commons.configuration.Configuration;
 37  
 import org.apache.commons.configuration.ConfigurationException;
 38  
 import org.apache.commons.configuration.PropertiesConfiguration;
 39  
 import org.apache.commons.logging.Log;
 40  
 import org.apache.commons.logging.LogFactory;
 41  
 import org.apache.jetspeed.Jetspeed;
 42  
 import org.apache.jetspeed.PortalReservedParameters;
 43  
 import org.apache.jetspeed.capabilities.CapabilityMap;
 44  
 import org.apache.jetspeed.components.ComponentManager;
 45  
 import org.apache.jetspeed.desktop.JetspeedDesktopContext;
 46  
 import org.apache.jetspeed.locator.LocatorDescriptor;
 47  
 import org.apache.jetspeed.locator.TemplateDescriptor;
 48  
 import org.apache.jetspeed.locator.TemplateLocator;
 49  
 import org.apache.jetspeed.locator.TemplateLocatorException;
 50  
 import org.apache.jetspeed.om.page.Fragment;
 51  
 import org.apache.jetspeed.om.page.Page;
 52  
 import org.apache.jetspeed.request.RequestContext;
 53  
 import org.apache.pluto.Constants;
 54  
 import org.apache.portals.bridges.velocity.BridgesVelocityViewServlet;
 55  
 import org.apache.velocity.Template;
 56  
 import org.apache.velocity.app.VelocityEngine;
 57  
 import org.apache.velocity.app.event.EventCartridge;
 58  
 import org.apache.velocity.app.event.NullSetEventHandler;
 59  
 import org.apache.velocity.context.Context;
 60  
 import org.apache.velocity.exception.ParseErrorException;
 61  
 import org.apache.velocity.exception.ResourceNotFoundException;
 62  
 import org.apache.velocity.runtime.RuntimeConstants;
 63  
 import org.apache.velocity.tools.generic.log.LogSystemCommonsLog;
 64  
 import org.apache.velocity.tools.view.servlet.WebappLoader;
 65  
 
 66  
 /**
 67  
  * @version $Id: JetspeedVelocityViewServlet.java 550655 2007-06-26 01:41:35Z taylor $
 68  
  */
 69  0
 public class JetspeedVelocityViewServlet extends BridgesVelocityViewServlet
 70  
 {
 71  
     /** logging */
 72  0
     private static final Log log = LogFactory.getLog(JetspeedVelocityViewServlet.class);
 73  
 
 74  
     /** default cache size */
 75  
     private static final long DEFAULT_CACHE_SIZE = 50;
 76  
 
 77  
     /** default cache validation interval */
 78  
     private static final String CACHE_SIZE_PARAMETER = "org.apache.jetspeed.cache.size";
 79  
 
 80  
     /** default cache validation interval */
 81  
     private static final long DEFAULT_CACHE_VALIDATION_INTERVAL = 10000;
 82  
 
 83  
     /** default cache validation interval */
 84  
     private static final String CACHE_VALIDATION_INTERVAL_PARAMETER = "org.apache.jetspeed.cache.validation.interval";
 85  
 
 86  
     /** TLS for Context propagation */
 87  0
     private static ThreadLocal handlingRequestContext = new ThreadLocal();
 88  
 
 89  
     /** decoration locators */
 90  
     private TemplateLocator decorationLocator;
 91  
 
 92  
     /** velocity engine configuration caching object */
 93  0
     private class VelocityEngineConfig
 94  
     {
 95  
         public String decoration;
 96  
         public String type;
 97  
         public String mediaType;
 98  
         public String language;
 99  
         public String country;
 100  
 
 101  
         public File macros;
 102  
         public long macrosLastModified;
 103  
         public long lastValidated;
 104  
 
 105  
         public VelocityEngineConfig(String decoration, String type, String mediaType, String language, String country)
 106  
         {
 107  
             this.decoration = decoration;
 108  
             this.type = type;
 109  
             this.mediaType = mediaType;
 110  
             this.language = language;
 111  
             this.country = country;
 112  
             
 113  
             this.macrosLastModified = -1;
 114  
             this.lastValidated = System.currentTimeMillis();
 115  
         }
 116  
     }
 117  
 
 118  
     /** VelocityEngine configuration cache by decoration */
 119  
     private Map velocityEngineConfigCache;
 120  
 
 121  
     /** VelocityEngine cache by macros locators */
 122  
     private Map velocityEngineCache;
 123  
 
 124  
     /** cache validation interval */
 125  
     private long cacheValidationInterval;
 126  
 
 127  
     /** default velocity engine */
 128  
     private VelocityEngine defaultVelocityEngine;
 129  
     
 130  
     /** Velocity EventCartridge for handling event */
 131  
     EventCartridge eventCartridge;
 132  
 
 133  
     /**
 134  
      * Initialize servlet, BridgesVelocityViewServlet, and VelocityViewServlet.
 135  
      *
 136  
      * @see org.apache.velocity.tools.view.servlet.VelocityViewServlet.init()
 137  
      *
 138  
      * @param config servlet configuation
 139  
      */
 140  
     public void init(ServletConfig config) throws ServletException
 141  
     {
 142  
         // initialize
 143  0
         super.init(config);
 144  
 
 145  
         // get jetspeed component manager configuration for decorations
 146  0
         ComponentManager cm = Jetspeed.getComponentManager();
 147  0
         int count =0;
 148  0
         while(cm == null) {
 149  
             try {
 150  0
                 Thread.sleep(200);
 151  0
             } catch(InterruptedException ie) {
 152  
                 
 153  0
             }
 154  0
             cm = Jetspeed.getComponentManager();
 155  0
             if( count > 5 ) {
 156  0
                 if (null == cm)
 157  0
                     throw new ServletException("Could not get Jetspeed Component Manager after "+count+"tries");
 158  
             }
 159  0
             count++;
 160  
         
 161  
         }
 162  0
         decorationLocator = (TemplateLocator) cm.getComponent("DecorationLocator");
 163  
 
 164  
         // initialize thread safe velocity engine cache
 165  0
         int cacheSize = (class="keyword">int) getLongInitParameter(config, CACHE_SIZE_PARAMETER, DEFAULT_CACHE_SIZE);
 166  0
         velocityEngineConfigCache = new LRUMap(cacheSize);
 167  0
         velocityEngineCache = new LRUMap(cacheSize/2);
 168  
         
 169  0
         eventCartridge = new EventCartridge();
 170  
         // setup NullSetEventHandler to ignore those pesky "ERROR velocity - RHS of #set statement is null. Context will not be modified."
 171  0
         eventCartridge.addEventHandler(new NullSetEventHandler()
 172  
         {
 173  
             public boolean shouldLogOnNullSet(String lhs, String rhs) { return false; }
 174  
         });
 175  
 
 176  
         // initialize velocity engine cache validation interval
 177  0
         cacheValidationInterval = getLongInitParameter(config, CACHE_VALIDATION_INTERVAL_PARAMETER, DEFAULT_CACHE_VALIDATION_INTERVAL);
 178  0
     }
 179  
 
 180  
     /**
 181  
      * overriding VelocityViewServlet initialization of global Velocity to properly provide our own velocity.properties
 182  
      * so to prevent an ERROR logging for not finding the default global VM_global_library.vm (which isn't available).
 183  
      */
 184  
     protected void initVelocity(ServletConfig config) throws ServletException
 185  
     {
 186  0
         VelocityEngine velocity = new VelocityEngine();
 187  0
         setVelocityEngine(velocity);
 188  
 
 189  
         // register this engine to be the default handler of log messages
 190  
         // if the user points commons-logging to the LogSystemCommonsLog
 191  0
         LogSystemCommonsLog.setVelocityEngine(velocity);
 192  
 
 193  0
         velocity.setApplicationAttribute(SERVLET_CONTEXT_KEY, getServletContext());
 194  
 
 195  
         // default to servletlogger, which logs to the servlet engines log
 196  0
         velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.tools.view.servlet.ServletLogger");
 197  
 
 198  
         // by default, load resources with webapp resource loader
 199  0
         velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "webapp");
 200  0
         velocity.setProperty("webapp.resource.loader.class", 
 201  
                              WebappLoader.class.getName());
 202  
 
 203  
         // Try reading an overriding Velocity configuration
 204  
         try
 205  
         {
 206  0
             ExtendedProperties p = loadConfiguration(config);
 207  0
             p.addProperty("velocimacro.library", "/WEB-INF/jetspeed_macros.vm");
 208  0
             p.setProperty("file.resource.loader.path", getServletContext().getRealPath("/"));
 209  0
             velocity.setExtendedProperties(p);
 210  
         }
 211  0
         catch(Exception e)
 212  
         {
 213  0
             getServletContext().log("VelocityViewServlet: Unable to read Velocity configuration file: "+e);
 214  0
             getServletContext().log("VelocityViewServlet: Using default Velocity configuration.");
 215  0
         }   
 216  
 
 217  
         // now all is ready - init Velocity
 218  
         try
 219  
         {
 220  0
             velocity.init();
 221  
         }
 222  0
         catch(Exception e)
 223  
         {
 224  0
             getServletContext().log("VelocityViewServlet: PANIC! unable to init() - "+e);
 225  0
             throw new ServletException(e);
 226  0
         }
 227  0
     }
 228  
     
 229  
     /**
 230  
      * Handle the template processing request.
 231  
      *
 232  
      * @see org.apache.velocity.tools.view.servlet.VelocityViewServlet.handleRequest()
 233  
      *
 234  
      * @param request client request
 235  
      * @param response client response
 236  
      * @param ctx  VelocityContext to fill
 237  
      * @return Velocity Template object or null
 238  
      */
 239  
     protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) throws Exception
 240  
     {
 241  0
         RequestContext requestContext = (RequestContext)request.getAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE);
 242  0
         if(requestContext == null)
 243  
         {
 244  0
             throw new IllegalStateException("JetspeedVelocityViewServlet unable to handle request because there is no RequestContext in "+
 245  
                    "the HttpServletRequest.");
 246  
         }
 247  
         
 248  
         // hook up eventHandlers to the context, specifically our own IgnoringNullSetEventHandling
 249  0
         eventCartridge.attachToContext(ctx);
 250  
         
 251  0
         JetspeedDesktopContext desktopContext = (JetspeedDesktopContext)request.getAttribute(JetspeedDesktopContext.DESKTOP_CONTEXT_ATTRIBUTE);
 252  0
         if (desktopContext != null)
 253  
         {
 254  
             // standard render request and response also available in context
 255  0
             ctx.put(JetspeedDesktopContext.DESKTOP_CONTEXT_ATTRIBUTE, desktopContext);
 256  0
             ctx.put("JS2RequestContext", requestContext);
 257  
             
 258  
             // setup TLS for Context propagation
 259  0
             handlingRequestContext.set(ctx);            
 260  0
             return super.handleRequest(request, response, ctx);            
 261  
         }
 262  
         // configure velocity context
 263  0
         PortletRequest renderRequest = (PortletRequest) request.getAttribute(Constants.PORTLET_REQUEST);
 264  0
         RenderResponse renderResponse = (RenderResponse) request.getAttribute(Constants.PORTLET_RESPONSE);
 265  0
         PortletConfig portletConfig = (PortletConfig) request.getAttribute(Constants.PORTLET_CONFIG);
 266  0
         if (renderRequest != null)
 267  
         {
 268  0
             renderRequest.setAttribute(VELOCITY_CONTEXT_ATTR, ctx);
 269  
         }
 270  
                 
 271  0
         JetspeedVelocityPowerTool jpt = (JetspeedVelocityPowerTool) renderRequest.getAttribute(PortalReservedParameters.JETSPEED_POWER_TOOL_REQ_ATTRIBUTE);
 272  0
         if(jpt == null)
 273  
         {
 274  0
             throw new IllegalStateException("JetspeedVelocityViewServlet unable to handle request because there is no JetspeedPowerTool in "+
 275  
                    "the HttpServletRequest.");
 276  
         }
 277  
         
 278  0
         jpt.setVelocityContext(ctx);
 279  0
         ctx.put("jetspeed", jpt);  
 280  0
         ctx.put("JS2RequestContext", requestContext);
 281  0
         ctx.put("renderRequest", renderRequest);
 282  0
         ctx.put("renderResponse", renderResponse);
 283  0
         ctx.put("portletConfig", portletConfig);
 284  0
         ctx.put("portletModeView", PortletMode.VIEW);
 285  0
         ctx.put("portletModeEdit", PortletMode.EDIT);
 286  0
         ctx.put("portletModeHelp", PortletMode.HELP);
 287  0
         ctx.put("windowStateNormal", WindowState.NORMAL);
 288  0
         ctx.put("windowStateMinimized", WindowState.MINIMIZED);
 289  0
         ctx.put("windowStateMaximized", WindowState.MAXIMIZED);
 290  0
         ctx.put("rco", requestContext.getObjects());
 291  0
         StringBuffer appRoot = new StringBuffer();
 292  0
         if (!requestContext.getPortalURL().isRelativeOnly())
 293  
         {
 294  0
             appRoot.append(request.getScheme()).append("://").append(request.getServerName()).append(":").append(request.getServerPort());
 295  
         }
 296  0
         appRoot.append(renderRequest.getContextPath());
 297  0
         ctx.put("appRoot", appRoot.toString());        
 298  
         
 299  
         
 300  
         // setup TLS for Context propagation
 301  0
         handlingRequestContext.set(ctx);
 302  
 
 303  
         // handle request normally        
 304  0
         return super.handleRequest(request, response, ctx);
 305  
     }
 306  
 
 307  
     /**
 308  
      * Retrieves the requested template.
 309  
      *
 310  
      * @see org.apache.velocity.tools.view.servlet.VelocityViewServlet.getTemplate()
 311  
      *
 312  
      * @param name The file name of the template to retrieve relative to the template root.
 313  
      * @return The requested template.
 314  
      * @throws ResourceNotFoundException if template not found from any available source.
 315  
      * @throws ParseErrorException if template cannot be parsed due to syntax (or other) error.
 316  
      * @throws Exception if an error occurs in template initialization
 317  
      */
 318  
     public Template getTemplate(String name)
 319  
         throws ResourceNotFoundException, ParseErrorException, Exception
 320  
     {
 321  
         // retrieve Context to lookup appropriate velocity engine
 322  0
         Context ctx = (Context) handlingRequestContext.get();
 323  0
         if (ctx != null)
 324  
         {
 325  
             // create or lookup cached velocity engine
 326  0
             VelocityEngine velocity = getVelocityEngine(ctx);
 327  0
             if (velocity != null)
 328  
             {
 329  
                 // get template from velocity engine
 330  0
                 return velocity.getTemplate(name);
 331  
             }
 332  
         }
 333  
 
 334  
         // no velocity engine available
 335  0
         throw new Exception("No velocity engine available for request context.");
 336  
     }
 337  
 
 338  
     /**
 339  
      * Retrieves the requested template with the specified character encoding.
 340  
      *
 341  
      * @see org.apache.velocity.tools.view.servlet.VelocityViewServlet.getTemplate()
 342  
      *
 343  
      * @param name The file name of the template to retrieve relative to the template root.
 344  
      * @param encoding the character encoding of the template
 345  
      * @return The requested template.
 346  
      * @throws ResourceNotFoundException if template not found from any available source.
 347  
      * @throws ParseErrorException if template cannot be parsed due to syntax (or other) error.
 348  
      * @throws Exception if an error occurs in template initialization
 349  
      */
 350  
     public Template getTemplate(String name, String encoding)
 351  
         throws ResourceNotFoundException, ParseErrorException, Exception
 352  
     {
 353  
         // retrieve Context to lookup appropriate velocity engine
 354  0
         Context ctx = (Context) handlingRequestContext.get();
 355  0
         if (ctx != null)
 356  
         {
 357  
             // create or lookup cached velocity engine
 358  0
             VelocityEngine velocity = getVelocityEngine(ctx);
 359  0
             if (velocity != null)
 360  
             {
 361  
                 // get template from velocity engine
 362  0
                 return velocity.getTemplate(name, encoding);
 363  
             }
 364  
         }
 365  
 
 366  
         // no velocity engine available
 367  0
         throw new Exception("No velocity engine available for request context.");
 368  
     }
 369  
 
 370  
     /**
 371  
      * Get VelocityEngine for template access.
 372  
      *
 373  
      * @param ctx the velocity context.
 374  
      * @return The VelocityEngine or null.
 375  
      */
 376  
     private VelocityEngine getVelocityEngine(Context ctx)
 377  
     {
 378  0
         RequestContext requestContext = (RequestContext) ctx.get("JS2RequestContext");        
 379  0
         JetspeedDesktopContext desktopContext = (JetspeedDesktopContext)requestContext.getRequest().getAttribute(JetspeedDesktopContext.DESKTOP_CONTEXT_ATTRIBUTE);        
 380  0
         if (desktopContext != null)
 381  
         {
 382  0
             if (defaultVelocityEngine == null)
 383  
             {
 384  0
                 defaultVelocityEngine = initVelocity((TemplateDescriptor)null);
 385  
             }
 386  0
             return defaultVelocityEngine;            
 387  
         }                
 388  
         // get render request and request context from Context
 389  0
         RenderRequest renderRequest = (RenderRequest) ctx.get("renderRequest");
 390  0
         JetspeedVelocityPowerTool jpt = (JetspeedVelocityPowerTool) ctx.get("jetspeed");
 391  0
         if ((renderRequest != null) && (requestContext != class="keyword">null))
 392  
         {
 393  
             // get layout type and decoration, fallback to
 394  
             // page default decorations
 395  0
             Fragment layout = (Fragment) renderRequest.getAttribute(JetspeedVelocityPowerTool.LAYOUT_ATTR);
 396  0
             if (layout == null)
 397  
             {
 398  
                // layout = (Fragment) renderRequest.getAttribute(JetspeedPowerTool.FRAGMENT_ATTR);
 399  0
                 layout = jpt.getCurrentFragment();
 400  
             }
 401  0
             String layoutType = layout.getType();
 402  0
             String layoutDecoration = layout.getDecorator();
 403  0
             if (layoutDecoration == null)
 404  
             {
 405  
                 //Page page = (Page) renderRequest.getAttribute(PortalReservedParameters.PAGE_ATTRIBUTE_KEY);
 406  0
                 Page page = requestContext.getPage();
 407  0
                 layoutDecoration = page.getEffectiveDefaultDecorator(layoutType);
 408  
             }
 409  
             
 410  
             // get layout capabilites and locale
 411  0
             CapabilityMap capabilityMap = requestContext.getCapabilityMap();
 412  0
             Locale locale = requestContext.getLocale();
 413  0
             String layoutMediaType = capabilityMap.getPreferredMediaType().getName();
 414  0
             String layoutLanguage = locale.getLanguage();
 415  0
             String layoutCountry = locale.getCountry();
 416  
             
 417  
             // lookup cache config based on decoration cache key
 418  0
             String cacheKey = layoutDecoration + ":" + layoutType + ":" + layoutMediaType + ":" + layoutLanguage + ":" + layoutCountry;
 419  0
             VelocityEngineConfig config = null;
 420  0
             synchronized (velocityEngineConfigCache)
 421  
             {
 422  0
                config = (VelocityEngineConfig) velocityEngineConfigCache.get(cacheKey);
 423  0
             }
 424  
             
 425  
             // validate cached configuration and return VelocityEngine if cached
 426  0
             long now = System.currentTimeMillis();
 427  0
             if ((config != null) && ((cacheValidationInterval == -1) || (now <= (config.lastValidated + cacheValidationInterval)))) 
 428  
             {
 429  0
                 if (config.macros != null)
 430  
                 {
 431  0
                     synchronized (velocityEngineCache)
 432  
                     {
 433  
                         // use cached velocity engine if available
 434  0
                         VelocityEngine velocity = (VelocityEngine) velocityEngineCache.get(config.macros.getAbsolutePath());
 435  0
                         if (velocity != null)
 436  
                         {
 437  0
                             return velocity;
 438  
                         }
 439  0
                     }
 440  
                 }
 441  
                 else
 442  
                 {
 443  
                     // use default velocity engine
 444  0
                     synchronized (this)
 445  
                     {
 446  
                         // construct and cache default velocity engine
 447  0
                         if (defaultVelocityEngine == null)
 448  
                         {
 449  0
                             defaultVelocityEngine = initVelocity((TemplateDescriptor)null);
 450  
                         }
 451  0
                         return defaultVelocityEngine;
 452  0
                     }
 453  
                 }
 454  
             }
 455  
            
 456  
             // load and/or verify decorator macros configuration
 457  0
             TemplateDescriptor macrosDescriptor = null;
 458  
             
 459  
             // create reusable decoration base descriptor
 460  0
             LocatorDescriptor descriptor = null;
 461  
             try
 462  
             {
 463  0
                 descriptor = decorationLocator.createLocatorDescriptor(null);
 464  
             }
 465  0
             catch (TemplateLocatorException tle)
 466  
             {
 467  0
                 log.error("getVelocityEngine(): unable create base descriptor", tle);
 468  0
             }
 469  0
             descriptor.setMediaType(layoutMediaType);
 470  0
             descriptor.setCountry(layoutCountry);
 471  0
             descriptor.setLanguage(layoutLanguage);
 472  0
             descriptor.setType(layoutType);
 473  
             
 474  
             // get decoration configuration properties descriptor
 475  0
             descriptor.setName(layoutDecoration + "/" + JetspeedVelocityPowerTool.DECORATOR_TYPE + ".properties");
 476  0
             TemplateDescriptor propertiesDescriptor = null;
 477  
             try
 478  
             {
 479  0
                 propertiesDescriptor = decorationLocator.locateTemplate(descriptor);
 480  
             }
 481  0
             catch (TemplateLocatorException tle)
 482  
             {
 483  
                 // fallback to generic template type
 484  
                 try
 485  
                 {
 486  0
                     descriptor.setType(JetspeedVelocityPowerTool.GENERIC_TEMPLATE_TYPE);
 487  0
                     propertiesDescriptor = decorationLocator.locateTemplate(descriptor);
 488  
                 }
 489  0
                 catch (TemplateLocatorException tleFallback)
 490  
                 {
 491  0
                 }
 492  0
             }
 493  
             // load configuration properties
 494  0
             Configuration configuration = null;
 495  0
             if (propertiesDescriptor != null)
 496  
             {
 497  
                 try
 498  
                 {
 499  0
                     configuration = new PropertiesConfiguration(propertiesDescriptor.getAbsolutePath());
 500  
                 }
 501  0
                 catch (ConfigurationException ce)
 502  
                 {
 503  0
                     log.warn("getVelocityEngine(): unable read decorator properties from " + propertiesDescriptor.getAbsolutePath(), ce);
 504  0
                 }
 505  
             }
 506  0
             if (configuration != null)
 507  
             {
 508  
                 // get decoration template macros extension and suffix
 509  0
                 String ext = configuration.getString("template.extension");
 510  0
                 String macros = configuration.getString("template.macros");
 511  
                 
 512  
                 // get decoration template macros descriptor if defined
 513  0
                 if ((ext != null) && (ext.length() > 0) && (macros != class="keyword">null) && (macros.length() > 0))
 514  
                 {
 515  0
                     descriptor.setName(layoutDecoration + "/" + JetspeedVelocityPowerTool.DECORATOR_TYPE + macros + ext);
 516  
                     try
 517  
                     {
 518  0
                         macrosDescriptor = decorationLocator.locateTemplate(descriptor);
 519  
                     }
 520  0
                     catch (TemplateLocatorException tle)
 521  
                     {
 522  
                         // fallback to extends decoration, (assume macros named the
 523  
                         // same in the parent decoration as configured here)
 524  
                         try
 525  
                         {
 526  0
                             String parent = configuration.getString("extends");
 527  0
                             if ((parent != null) && (parent.length() > 0))
 528  
                             {
 529  0
                                 descriptor.setName(parent + "/" + JetspeedVelocityPowerTool.DECORATOR_TYPE + macros + ext);
 530  0
                                 macrosDescriptor = decorationLocator.locateTemplate(descriptor);
 531  
                             }
 532  
                         }
 533  0
                         catch (TemplateLocatorException tleExtends)
 534  
                         {
 535  0
                         }
 536  0
                     }
 537  
                 }
 538  
             }
 539  
             
 540  
             // compare located macros file with cached version
 541  
             // to validate/refresh cached config and velocity engine
 542  0
             boolean newVelocityEngineConfig = false;
 543  0
             boolean forceVelocityEngineRefresh = false;
 544  0
             if (config == null)
 545  
             {
 546  0
                 config = new VelocityEngineConfig(layoutDecoration, layoutType, layoutMediaType, layoutLanguage, layoutCountry);
 547  0
                 synchronized (velocityEngineConfigCache)
 548  
                 {
 549  0
                     velocityEngineConfigCache.put(cacheKey, config);
 550  0
                 }
 551  0
                 newVelocityEngineConfig = true;
 552  
             }
 553  0
             if (((macrosDescriptor == null) && (config.macros != class="keyword">null)) ||
 554  
                 ((macrosDescriptor != null) && (config.macros == class="keyword">null)) ||
 555  
                 ((macrosDescriptor != null) && (config.macros != class="keyword">null) &&
 556  
                  (!macrosDescriptor.getAbsolutePath().equals(config.macros.getAbsolutePath()) ||
 557  
                   (config.macros.lastModified() != config.macrosLastModified))))
 558  
             {
 559  
                 // set or reset configuration cache entry
 560  0
                 config.lastValidated = now;
 561  0
                 if (macrosDescriptor != null)
 562  
                 {
 563  
                     // save macros file
 564  0
                     config.macros = new File(macrosDescriptor.getAbsolutePath());
 565  0
                     config.macrosLastModified = config.macros.lastModified();
 566  
                 }
 567  
                 else
 568  
                 {
 569  
                     // clear macros file
 570  0
                     config.macros = null;
 571  0
                     config.macrosLastModified = -1;
 572  
                 }
 573  
 
 574  
                 // aggressively force creation of new velocity engine
 575  
                 // if any configuration change detected
 576  0
                 forceVelocityEngineRefresh = !newVelocityEngineConfig;
 577  
             }
 578  
             else
 579  
             {
 580  
                 // config validated
 581  0
                 config.lastValidated = now;
 582  
             }
 583  
 
 584  
             // get or create new velocity engine intialized with
 585  
             // validated macros configuration
 586  0
             VelocityEngine velocity = null;
 587  0
             if ((macrosDescriptor != null) && (config.macros != class="keyword">null))
 588  
             {
 589  0
                 synchronized (velocityEngineCache)
 590  
                 {
 591  0
                     if (!forceVelocityEngineRefresh)
 592  
                     {
 593  
                         // use cached velocity engine
 594  0
                         velocity = (VelocityEngine) velocityEngineCache.get(config.macros.getAbsolutePath());
 595  
                     }
 596  0
                     if (velocity == null)
 597  
                     {
 598  
                         // create and cache new velocity engine
 599  0
                         velocity = initVelocity(macrosDescriptor);
 600  0
                         if (velocity != null)
 601  
                         {
 602  0
                             velocityEngineCache.put(config.macros.getAbsolutePath(), velocity);
 603  
                         }
 604  
                     }
 605  0
                 }
 606  
             }
 607  
 
 608  
             // fallback to default velocity engine
 609  0
             if (velocity == null)
 610  
             {
 611  0
                 synchronized (this)
 612  
                 {
 613  
                     // construct and cache default velocity engine
 614  0
                     if (defaultVelocityEngine == null)
 615  
                     {
 616  0
                         defaultVelocityEngine = initVelocity((TemplateDescriptor)null);
 617  
                     }
 618  0
                     velocity = defaultVelocityEngine;
 619  0
                 }
 620  
             }
 621  
             
 622  
             // return velocity engine for validated configuration
 623  0
             return velocity;
 624  
         }
 625  0
         return null;
 626  
     }
 627  
 
 628  
     /**
 629  
      * Initialize new velocity instance using specified macros template.
 630  
      *
 631  
      * @see org.apache.velocity.tools.view.servlet.VelocityViewServlet.initVelocity()
 632  
      *
 633  
      * @param macros template descriptor.
 634  
      * @return new VelocityEngine instance.
 635  
      */
 636  
     private VelocityEngine initVelocity(TemplateDescriptor macros)
 637  
     {
 638  
         try
 639  
         {
 640  
             // create new instance to initialize
 641  0
             VelocityEngine velocity = new VelocityEngine();
 642  
             
 643  
             // initialize new instance as is done with the default
 644  
             // velocity singleton, appending macros template to the
 645  
             // base configuration velocimacro.library property
 646  0
             velocity.setApplicationAttribute(SERVLET_CONTEXT_KEY, getServletContext());
 647  0
             velocity.setProperty(VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.tools.view.servlet.ServletLogger");
 648  0
             ExtendedProperties configuration = loadConfiguration(getServletConfig());
 649  0
             if (macros != null)
 650  
             {
 651  0
                 configuration.addProperty("velocimacro.library", macros.getAppRelativePath());
 652  
             }
 653  0
             configuration.setProperty("file.resource.loader.path", getServletContext().getRealPath("/"));
 654  0
             velocity.setExtendedProperties(configuration);
 655  
 
 656  
             // initialize and return velocity engine
 657  0
             velocity.init();
 658  0
             if (macros != null)
 659  
             {
 660  0
                 log.debug("initVelocity(): create new VelocityEngine instance to support " + macros.getAppRelativePath() + " decoration template macros");
 661  
             }
 662  
             else
 663  
             {
 664  0
                 log.debug("initVelocity(): create new default VelocityEngine instance");
 665  
             }
 666  0
             return velocity;
 667  
         }
 668  0
         catch (Exception e)
 669  
         {
 670  0
             log.error("initVelocity(): unable to initialize velocity engine instance, using default singleton", e);
 671  
         }
 672  0
         return null;
 673  
     }
 674  
 
 675  
     /**
 676  
      * Utility to get long init parameters.
 677  
      *
 678  
      * @param config servlet config
 679  
      * @param name of init parameter
 680  
      * @param defaultValue value
 681  
      * @return parameter value
 682  
      */
 683  
     private long getLongInitParameter(ServletConfig config, String name, class="keyword">long defaultValue)
 684  
     {
 685  0
         String value = config.getInitParameter(name);
 686  0
         if ((value == null) || (value.length() == 0))
 687  
         {
 688  0
             value = config.getServletContext().getInitParameter(name);
 689  
         }
 690  0
         if ((value != null) && (value.length() > 0))
 691  
         {
 692  
             try
 693  
             {
 694  0
                 return Long.parseLong(value);
 695  
             }
 696  0
             catch (Exception e)
 697  
             {
 698  
             }
 699  
         }
 700  0
         return defaultValue;
 701  
     }
 702  
     
 703  
     protected void error(HttpServletRequest request, 
 704  
             HttpServletResponse response, 
 705  
             Exception e)
 706  
     throws ServletException
 707  
     {
 708  
         try
 709  
         {
 710  0
             StringBuffer html = new StringBuffer();
 711  0
             html.append("<b>\n");
 712  0
             html.append("Content is not available");
 713  0
             html.append("<b>\n");
 714  0
             getResponseWriter(response).write(html.toString());
 715  0
             log.error("Error processing vm template ", e);
 716  
         }
 717  0
         catch (Exception e2)
 718  
         {
 719  0
             log.error("Error writing error message to vm template ", e2);            
 720  0
         }        
 721  0
     }
 722  
     
 723  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.