Coverage Report - org.apache.turbine.services.rundata.TurbineRunDataService
 
Classes in this File Line Coverage Branch Coverage Complexity
TurbineRunDataService
80%
68/84
67%
23/34
6
 
 1  
 package org.apache.turbine.services.rundata;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.util.HashMap;
 23  
 import java.util.Iterator;
 24  
 import java.util.Locale;
 25  
 import java.util.Map;
 26  
 
 27  
 import javax.servlet.ServletConfig;
 28  
 import javax.servlet.ServletContext;
 29  
 import javax.servlet.http.HttpServletRequest;
 30  
 import javax.servlet.http.HttpServletResponse;
 31  
 
 32  
 import org.apache.commons.configuration.Configuration;
 33  
 import org.apache.fulcrum.parser.CookieParser;
 34  
 import org.apache.fulcrum.parser.DefaultCookieParser;
 35  
 import org.apache.fulcrum.parser.DefaultParameterParser;
 36  
 import org.apache.fulcrum.parser.ParameterParser;
 37  
 import org.apache.fulcrum.parser.ParserService;
 38  
 import org.apache.fulcrum.pool.PoolException;
 39  
 import org.apache.fulcrum.pool.PoolService;
 40  
 import org.apache.turbine.Turbine;
 41  
 import org.apache.turbine.services.InitializationException;
 42  
 import org.apache.turbine.services.TurbineBaseService;
 43  
 import org.apache.turbine.services.TurbineServices;
 44  
 import org.apache.turbine.util.RunData;
 45  
 import org.apache.turbine.util.ServerData;
 46  
 import org.apache.turbine.util.TurbineException;
 47  
 
 48  
 /**
 49  
  * The RunData Service provides the implementations for RunData and
 50  
  * related interfaces required by request processing. It supports
 51  
  * different configurations of implementations, which can be selected
 52  
  * by specifying a configuration key. It may use pooling, in which case
 53  
  * the implementations should implement the Recyclable interface.
 54  
  *
 55  
  * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
 56  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 57  
  * @version $Id: TurbineRunDataService.java 1706239 2015-10-01 13:18:35Z tv $
 58  
  */
 59  
 public class TurbineRunDataService
 60  
     extends TurbineBaseService
 61  
     implements RunDataService
 62  
 {
 63  
 
 64  
     /** The default implementation of the RunData object*/
 65  33
     private static final String DEFAULT_RUN_DATA =
 66  
         DefaultTurbineRunData.class.getName();
 67  
 
 68  
     /** The default implementation of the Parameter Parser object */
 69  33
     private static final String DEFAULT_PARAMETER_PARSER =
 70  
         DefaultParameterParser.class.getName();
 71  
 
 72  
     /** The default implementation of the Cookie parser object */
 73  33
     private static final String DEFAULT_COOKIE_PARSER =
 74  
         DefaultCookieParser.class.getName();
 75  
 
 76  
     /** The map of configurations. */
 77  33
     private final Map<String, Object> configurations = new HashMap<String, Object>();
 78  
 
 79  
     /** A class cache. */
 80  33
     private final Map<String, Class<?>> classCache = new HashMap<String, Class<?>>();
 81  
 
 82  
     /** Private reference to the pool service for object recycling */
 83  33
     private PoolService pool = null;
 84  
 
 85  
     /** Private reference to the parser service for parser recycling */
 86  33
     private ParserService parserService = null;
 87  
 
 88  
     /**
 89  
      * Constructs a RunData Service.
 90  
      */
 91  
     public TurbineRunDataService()
 92  
     {
 93  33
         super();
 94  33
     }
 95  
 
 96  
     /**
 97  
      * Initializes the service by setting the pool capacity.
 98  
      *
 99  
      * @throws InitializationException if initialization fails.
 100  
      */
 101  
     @Override
 102  
     public void init()
 103  
             throws InitializationException
 104  
     {
 105  
         // Create a default configuration.
 106  39
         String[] def = new String[]
 107  
         {
 108  
             DEFAULT_RUN_DATA,
 109  
             DEFAULT_PARAMETER_PARSER,
 110  
             DEFAULT_COOKIE_PARSER
 111  
         };
 112  39
         configurations.put(DEFAULT_CONFIG, def.clone());
 113  
 
 114  
         // Check other configurations.
 115  39
         Configuration conf = getConfiguration();
 116  39
         if (conf != null)
 117  
         {
 118  
             String key,value;
 119  
             String[] config;
 120  39
             String[] plist = new String[]
 121  
             {
 122  
                 RUN_DATA_KEY,
 123  
                 PARAMETER_PARSER_KEY,
 124  
                 COOKIE_PARSER_KEY
 125  
             };
 126  39
             for (Iterator<String> i = conf.getKeys(); i.hasNext();)
 127  
             {
 128  129
                 key = i.next();
 129  129
                 value = conf.getString(key);
 130  336
                 for (int j = 0; j < plist.length; j++)
 131  
                 {
 132  297
                     if (key.endsWith(plist[j]) &&
 133  
                             (key.length() > (plist[j].length() + 1)))
 134  
                     {
 135  90
                         key = key.substring(0, key.length() - plist[j].length() - 1);
 136  90
                         config = (String[]) configurations.get(key);
 137  90
                         if (config == null)
 138  
                         {
 139  0
                             config = def.clone();
 140  0
                             configurations.put(key, config);
 141  
                         }
 142  90
                         config[j] = value;
 143  90
                         break;
 144  
                     }
 145  
                 }
 146  
             }
 147  
         }
 148  
 
 149  39
                 pool = (PoolService)TurbineServices.getInstance().getService(PoolService.ROLE);
 150  
 
 151  39
         if (pool == null)
 152  
         {
 153  0
             throw new InitializationException("RunData Service requires"
 154  
                 + " configured Pool Service!");
 155  
         }
 156  
 
 157  39
         parserService = (ParserService)TurbineServices.getInstance().getService(ParserService.ROLE);
 158  
 
 159  39
         if (parserService == null)
 160  
         {
 161  0
             throw new InitializationException("RunData Service requires"
 162  
                 + " configured Parser Service!");
 163  
         }
 164  
 
 165  39
         setInit(true);
 166  39
     }
 167  
 
 168  
     /**
 169  
      * Shutdown the service
 170  
      *
 171  
      * @see org.apache.turbine.services.TurbineBaseService#shutdown()
 172  
      */
 173  
     @Override
 174  
     public void shutdown()
 175  
     {
 176  39
         classCache.clear();
 177  39
         super.shutdown();
 178  39
     }
 179  
 
 180  
     /**
 181  
      * Gets a default RunData object.
 182  
      *
 183  
      * @param req a servlet request.
 184  
      * @param res a servlet response.
 185  
      * @param config a servlet config.
 186  
      * @return a new or recycled RunData object.
 187  
      * @throws TurbineException if the operation fails.
 188  
      */
 189  
     @Override
 190  
     public RunData getRunData(HttpServletRequest req,
 191  
                               HttpServletResponse res,
 192  
                               ServletConfig config)
 193  
             throws TurbineException
 194  
     {
 195  28
         return getRunData(DEFAULT_CONFIG, req, res, config);
 196  
     }
 197  
 
 198  
     /**
 199  
      * Gets a RunData instance from a specific configuration.
 200  
      *
 201  
      * @param key a configuration key.
 202  
      * @param req a servlet request.
 203  
      * @param res a servlet response.
 204  
      * @param config a servlet config.
 205  
      * @return a new or recycled RunData object.
 206  
      * @throws TurbineException if the operation fails.
 207  
      * @throws IllegalArgumentException if any of the parameters are null.
 208  
      * TODO The "key" parameter should be removed in favor of just looking up what class via the roleConfig avalon file.
 209  
      */
 210  
     @Override
 211  
     public RunData getRunData(String key,
 212  
                               HttpServletRequest req,
 213  
                               HttpServletResponse res,
 214  
                               ServletConfig config)
 215  
             throws TurbineException,
 216  
             IllegalArgumentException
 217  
     {
 218  
         // The RunData object caches all the information that is needed for
 219  
         // the execution lifetime of a single request. A RunData object
 220  
         // is created/recycled for each and every request and is passed
 221  
         // to each and every module. Since each thread has its own RunData
 222  
         // object, it is not necessary to perform synchronization for
 223  
         // the data within this object.
 224  28
         if ((req == null)
 225  
             || (res == null)
 226  
             || (config == null))
 227  
         {
 228  0
             throw new IllegalArgumentException("HttpServletRequest, "
 229  
                 + "HttpServletResponse or ServletConfig was null.");
 230  
         }
 231  
 
 232  
         // Get the specified configuration.
 233  28
         String[] cfg = (String[]) configurations.get(key);
 234  28
         if (cfg == null)
 235  
         {
 236  0
             throw new TurbineException("RunTime configuration '" + key + "' is undefined");
 237  
         }
 238  
 
 239  
         TurbineRunData data;
 240  
         try
 241  
         {
 242  28
                     Class<?> runDataClazz = classCache.get(cfg[0]);
 243  28
                     if (runDataClazz == null)
 244  
                     {
 245  12
                         runDataClazz = Class.forName(cfg[0]);
 246  12
                         classCache.put(cfg[0], runDataClazz);
 247  
                     }
 248  
 
 249  28
             Class<?> parameterParserClazz = classCache.get(cfg[1]);
 250  28
             if (parameterParserClazz == null)
 251  
             {
 252  12
                 parameterParserClazz = Class.forName(cfg[1]);
 253  12
                 classCache.put(cfg[1], parameterParserClazz);
 254  
             }
 255  
 
 256  28
             Class<?> cookieParserClazz = classCache.get(cfg[2]);
 257  28
             if (cookieParserClazz == null)
 258  
             {
 259  12
                 cookieParserClazz = Class.forName(cfg[2]);
 260  12
                 classCache.put(cfg[2], cookieParserClazz);
 261  
             }
 262  
 
 263  28
             data = (TurbineRunData) pool.getInstance(runDataClazz);
 264  
             @SuppressWarnings("unchecked") // ok
 265  28
             ParameterParser pp = parserService.getParser((Class<ParameterParser>)parameterParserClazz);
 266  28
             data.get(Turbine.class).put(ParameterParser.class, pp);
 267  
 
 268  
             @SuppressWarnings("unchecked") // ok
 269  28
             CookieParser cp = parserService.getParser((Class<CookieParser>)cookieParserClazz);
 270  28
             data.get(Turbine.class).put(CookieParser.class, cp);
 271  
 
 272  28
             Locale locale = req.getLocale();
 273  
 
 274  28
             if (locale == null)
 275  
             {
 276  
                 // get the default from the Turbine configuration
 277  0
                 locale = data.getLocale();
 278  
             }
 279  
 
 280  
             // set the locale detected and propagate it to the parsers
 281  28
             data.setLocale(locale);
 282  
         }
 283  0
         catch (PoolException pe)
 284  
         {
 285  0
             throw new TurbineException("RunData configuration '" + key + "' is illegal caused a pool exception", pe);
 286  
         }
 287  0
         catch (ClassNotFoundException x)
 288  
         {
 289  0
             throw new TurbineException("RunData configuration '" + key + "' is illegal", x);
 290  
         }
 291  0
         catch (ClassCastException x)
 292  
         {
 293  0
             throw new TurbineException("RunData configuration '" + key + "' is illegal", x);
 294  
         }
 295  0
         catch (InstantiationException e)
 296  
         {
 297  0
             throw new TurbineException("RunData configuration '" + key + "' is illegal", e);
 298  28
         }
 299  
 
 300  
         // Set the request and response.
 301  28
         data.get(Turbine.class).put(HttpServletRequest.class, req);
 302  28
         data.get(Turbine.class).put(HttpServletResponse.class, res);
 303  
 
 304  
         // Set the servlet configuration.
 305  28
         data.get(Turbine.class).put(ServletConfig.class, config);
 306  28
         data.get(Turbine.class).put(ServletContext.class, config.getServletContext());
 307  
 
 308  
         // Set the ServerData.
 309  28
         data.get(Turbine.class).put(ServerData.class, new ServerData(req));
 310  
 
 311  28
         return data;
 312  
     }
 313  
 
 314  
     /**
 315  
      * Puts the used RunData object back to the factory for recycling.
 316  
      *
 317  
      * @param data the used RunData object.
 318  
      * @return true, if pooling is supported and the object was accepted.
 319  
      */
 320  
     @Override
 321  
     public boolean putRunData(RunData data)
 322  
     {
 323  1
         if (data instanceof TurbineRunData)
 324  
         {
 325  1
             parserService.putParser(((TurbineRunData) data).getParameterParser());
 326  1
             parserService.putParser(((TurbineRunData) data).getCookieParser());
 327  
 
 328  1
             return pool.putInstance(data);
 329  
         }
 330  
         else
 331  
         {
 332  0
             return false;
 333  
         }
 334  
     }
 335  
 }