Coverage Report - org.webmacro.servlet.Servlet22Broker
 
Classes in this File Line Coverage Branch Coverage Complexity
Servlet22Broker
70%
66/94
38%
21/54
4.3
 
 1  
 /*
 2  
  * Copyright (C) 1998-2000 Semiotek Inc.  All Rights Reserved.
 3  
  *
 4  
  * Redistribution and use in source and binary forms, with or without
 5  
  * modification, are permitted under the terms of either of the following
 6  
  * Open Source licenses:
 7  
  *
 8  
  * The GNU General Public License, version 2, or any later version, as
 9  
  * published by the Free Software Foundation
 10  
  * (http://www.fsf.org/copyleft/gpl.html);
 11  
  *
 12  
  *  or
 13  
  *
 14  
  * The Semiotek Public License (http://webmacro.org/LICENSE.)
 15  
  *
 16  
  * This software is provided "as is", with NO WARRANTY, not even the
 17  
  * implied warranties of fitness to purpose, or merchantability. You
 18  
  * assume all risks and liabilities associated with its use.
 19  
  *
 20  
  * See www.webmacro.org for more information on the WebMacro project.
 21  
  */
 22  
 
 23  
 
 24  
 package org.webmacro.servlet;
 25  
 
 26  
 import org.slf4j.Logger;
 27  
 import org.slf4j.LoggerFactory;
 28  
 
 29  
 import org.webmacro.Broker;
 30  
 import org.webmacro.InitException;
 31  
 
 32  
 import javax.servlet.Servlet;
 33  
 import javax.servlet.ServletContext;
 34  
 import java.io.File;
 35  
 import java.io.InputStream;
 36  
 import java.net.MalformedURLException;
 37  
 import java.net.URL;
 38  
 import java.util.Enumeration;
 39  
 import java.util.Properties;
 40  
 
 41  
 /**
 42  
  * An implementation of Broker tailored for Servlet 2.2
 43  
  * environments.  Loads templates and other resources from the servlet
 44  
  * context (WAR file), writes log messages to the servlet log, and loads
 45  
  * properties from the WAR file context parameters.
 46  
  * 
 47  
  * @author Brian Goetz
 48  
  * @author Marc Palmer (wj5@wangjammers.org)
 49  
  * @since 0.96
 50  
  */
 51  
 
 52  
 public class Servlet22Broker extends ServletBroker
 53  
 {
 54  
 
 55  2
     static Logger _log =  LoggerFactory.getLogger(Servlet22Broker.class);
 56  
     protected final ClassLoader _servletClassLoader;
 57  
     protected String _templatePrefix;
 58  
 
 59  
     /**
 60  
      * Creates the broker looking in WEB-INF first
 61  
      * for WebMacro.properties before looking
 62  
      * in the application root.
 63  
      */
 64  
     protected Servlet22Broker (ServletContext sc,
 65  
                              ClassLoader cl,
 66  
                              Properties additionalProperties) throws InitException
 67  
     {
 68  2
         super(sc);
 69  2
         _servletClassLoader = cl;
 70  2
         String propertySource = WEBMACRO_DEFAULTS;
 71  2
         loadDefaultSettings();
 72  2
         boolean loaded = loadSettings("WEB-INF/" + WEBMACRO_PROPERTIES, true);
 73  2
         if (loaded)
 74  0
             propertySource += ", " + "WEB-INF/" + WEBMACRO_PROPERTIES;
 75  
         else
 76  
         {
 77  2
             loadSettings(WEBMACRO_PROPERTIES, true);
 78  2
             propertySource += ", " + WEBMACRO_PROPERTIES;
 79  
         }
 80  2
         propertySource += ", (WAR file)";
 81  2
         loadServletSettings(Broker.SETTINGS_PREFIX);
 82  2
         if (additionalProperties != null && additionalProperties.keySet().size() > 0)
 83  
         {
 84  0
             propertySource += ", (additional Properties)";
 85  0
             loadSettings(additionalProperties);
 86  
         }
 87  2
         propertySource += ", (System Properties)";
 88  2
         loadSystemSettings();
 89  
 
 90  2
         _log.info("Loaded settings from " + propertySource);
 91  2
         init();
 92  2
     }
 93  
 
 94  
     protected void loadServletSettings (String prefix)
 95  
             throws InitException
 96  
     {
 97  2
         Properties p = new Properties();
 98  2
         Enumeration e = _servletContext.getInitParameterNames();
 99  2
         if (e != null)
 100  
         {
 101  2
             String dotPrefix = (prefix == null) ? "" : prefix + ".";
 102  4
             while (e.hasMoreElements())
 103  
             {
 104  2
                 String key = (String) e.nextElement();
 105  2
                 if (prefix == null)
 106  0
                     p.setProperty(key, _servletContext.getInitParameter(key));
 107  2
                 else if (key.startsWith(dotPrefix))
 108  0
                     p.setProperty(key, _servletContext.getInitParameter(key)
 109  
                             .substring(dotPrefix.length()));
 110  2
             }
 111  
         }
 112  2
         _config.load(p, prefix);
 113  2
     }
 114  
 
 115  
     protected void init () throws InitException
 116  
     {
 117  2
         super.init();
 118  2
         String s = getSetting("Servlet22Broker.TemplateLocation");
 119  2
         if (s == null || s.trim().equals(""))
 120  2
             _templatePrefix = null;
 121  
         else
 122  0
             _templatePrefix = (s.endsWith("/")) ? s : s + "/";
 123  2
     }
 124  
 
 125  
 
 126  
     public static Broker getBroker (Servlet s, Properties additionalProperties) throws InitException
 127  
     {
 128  22
         ServletContext sc = s.getServletConfig().getServletContext();
 129  22
         ClassLoader cl = s.getClass().getClassLoader();
 130  22
         return _getBroker(sc, cl, additionalProperties, true,
 131  
             s.getClass().getName());
 132  
     }
 133  
 
 134  
     /**
 135  
      * Get a Servlet API 2.2 compatible broker for the ServletContext specified.
 136  
      * 
 137  
      * @param sc The Servlet context
 138  
      * @param cl A ClassLoader to use, presumably the webapp classloader
 139  
      * @param additionalProperties
 140  
      * @return The broker for the servlet context.
 141  
      * @throws InitException
 142  
      * @since 2.1 JSDK
 143  
      */
 144  
     public static Broker getBroker(ServletContext sc, ClassLoader cl,
 145  
         Properties additionalProperties) throws InitException
 146  
     {
 147  0
         return _getBroker(sc, cl, additionalProperties, false,
 148  
             sc.toString());
 149  
     }
 150  
 
 151  
     /**
 152  
      * Get an existing instance of the Servlet 2.2 broker or create a new one.
 153  
      * 
 154  
      * Templates will be retrieved relative to the ServletContext root
 155  
      * and classes loaded from the ClassLoader passed in. 
 156  
      * 
 157  
      * NOTE: Templates will <b>not</b> be loaded from the classpath.
 158  
      * 
 159  
      * @param sc The ServletContext to template access
 160  
      * @param cl The ClassLoader for class loading, typically servlet or
 161  
      *           JSP page's class loader
 162  
      * @param additionalProperties
 163  
      * @param fromServlet true if it is actually an initialization derived from
 164  
      *                    a Servlet instance passed in - just for nicer logging output
 165  
      * @param servletOrContextName Name of the servlet or context originating this broker,
 166  
      *                             for nicer logging
 167  
      *                             
 168  
      * @throws org.webmacro.InitException
 169  
      * @since 2.1
 170  
      */
 171  
     private static Broker _getBroker(ServletContext sc, ClassLoader cl,
 172  
         Properties additionalProperties, boolean fromServlet,
 173  
         String servletOrContextName) throws InitException
 174  
     {
 175  
         Broker result;
 176  
         try
 177  
         {
 178  22
             Object key = sc;
 179  22
             if (additionalProperties != null && additionalProperties.keySet().size() > 0)
 180  0
                 key = new PropertiesPair(sc, additionalProperties);
 181  
 
 182  22
             Broker b = findBroker(key);
 183  22
             if (b == null)
 184  
             {
 185  2
                 b = new Servlet22Broker(sc, cl, additionalProperties);
 186  2
                 register(key, b);
 187  
             }
 188  
             else
 189  20
                 _log.info(
 190  
                     (fromServlet ? "Servlet " : "ServletContext ")
 191  
                     + servletOrContextName
 192  
                     + " joining Broker" + " " + b.getName());
 193  22
             result = b;
 194  
         }
 195  0
         catch (InitException e)
 196  
         {
 197  0
             _log.error("Failed to initialized WebMacro from "+
 198  
                     (fromServlet ? "Servlet " : "ServletContext ")
 199  
                     + servletOrContextName);
 200  0
             throw e;
 201  22
         }
 202  22
         return result;
 203  
     }
 204  
 
 205  
     /**
 206  
      * Get a resource (file) from the the Broker's class loader.
 207  
      */
 208  
     public URL getResource (String name)
 209  
     {
 210  
         try
 211  
         {
 212  
             // NOTE: Tomcat4 needs a leading '/'.
 213  
             // However, when loading resources from the class-loader, they
 214  
             // may _not_ start with a leading '/'. So we have to build
 215  
             // up two different names. Ugly!
 216  348
             String contextName = name;
 217  348
             if (name.startsWith("/"))
 218  
             {
 219  0
                 name = name.substring(1);
 220  
             }
 221  
             else
 222  
             {
 223  348
                 StringBuffer b = new StringBuffer(name.length() + 1);
 224  348
                 b.append("/");
 225  348
                 b.append(name);
 226  348
                 contextName = b.toString();
 227  
             }
 228  348
             URL u = _servletContext.getResource(contextName);
 229  348
             if (u != null && u.getProtocol().equals("file"))
 230  
             {
 231  0
                 File f = new File(u.getFile());
 232  0
                 if (!f.exists())
 233  0
                     u = null;
 234  
             }
 235  348
             if (u == null)
 236  
             {
 237  348
                 u = _servletClassLoader.getResource(name);
 238  
             }
 239  348
             if (u == null)
 240  180
                 u = super.getResource(name);
 241  348
             return u;
 242  
         }
 243  0
         catch (MalformedURLException e)
 244  
         {
 245  0
             _log.warn("MalformedURLException caught in " +
 246  
                     "ServletBroker.getResource for " + name);
 247  0
             return null;
 248  
         }
 249  
     }
 250  
 
 251  
     /**
 252  
      * Get a resource (file) from the Broker's class loader.
 253  
      */
 254  
     public InputStream getResourceAsStream (String name)
 255  
     {
 256  0
         InputStream is = _servletContext.getResourceAsStream(name);
 257  0
         if (is == null)
 258  0
             is = _servletClassLoader.getResourceAsStream(name);
 259  0
         if (is == null)
 260  0
             is = super.getResourceAsStream(name);
 261  0
         return is;
 262  
     }
 263  
 
 264  
     /**
 265  
      * Get a template; kind of like getting a resource, but might come
 266  
      * from a different place.
 267  
      */
 268  
     public URL getTemplate (String name)
 269  
     {
 270  344
         if (_templatePrefix == null)
 271  344
             return getResource(name);
 272  
         else
 273  
         {
 274  0
             URL u = getResource(_templatePrefix + name);
 275  0
             return (u != null) ? u : getResource(name);
 276  
         }
 277  
     }
 278  
 
 279  
     /**
 280  
      * Loads a class by name. Uses the servlet classloader to load the
 281  
      * class. If the class is not found uses the Broker classForName
 282  
      * implementation.  
 283  
      */
 284  
     public Class classForName (String name) throws ClassNotFoundException
 285  
     {
 286  92
         Class cls = null;
 287  
         try
 288  
         {
 289  92
             cls = _servletClassLoader.loadClass(name);
 290  
         }
 291  0
         catch (ClassNotFoundException e)
 292  
         {
 293  92
         }
 294  
 
 295  92
         if (cls == null)
 296  0
             cls = super.classForName(name);
 297  
 
 298  92
         return cls;
 299  
     }
 300  
 
 301  
 }