##### Coverage Report - org.apache.turbine.services.rundata.TurbineRunDataService

Classes in this File | Line Coverage | Branch Coverage | Complexity
TurbineRunDataService |
79% | 63/79
60% | 17/28
| 6.4;6,4

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.http.HttpServletRequest;
29 |  |
     import javax.servlet.http.HttpServletResponse;
30 |  |
31 |  |
     import org.apache.commons.configuration.Configuration;
32 |  |
     import org.apache.fulcrum.parser.CookieParser;
33 |  |
     import org.apache.fulcrum.parser.DefaultCookieParser;
34 |  |
     import org.apache.fulcrum.parser.DefaultParameterParser;
35 |  |
     import org.apache.fulcrum.parser.ParameterParser;
36 |  |
     import org.apache.fulcrum.parser.ParserService;
37 |  |
     import org.apache.fulcrum.pool.PoolException;
38 |  |
     import org.apache.fulcrum.pool.PoolService;
39 |  |
     import org.apache.turbine.Turbine;
40 |  |
     import org.apache.turbine.services.InitializationException;
41 |  |
     import org.apache.turbine.services.TurbineBaseService;
42 |  |
     import org.apache.turbine.services.TurbineServices;
43 |  |
     import org.apache.turbine.util.RunData;
44 |  |
     import org.apache.turbine.util.ServerData;
45 |  |
     import org.apache.turbine.util.TurbineException;
46 |  |
47 |  |
     /**
48 |  |
      * The RunData Service provides the implementations for RunData and
49 |  |
      * related interfaces required by request processing. It supports
50 |  |
      * different configurations of implementations, which can be selected
51 |  |
      * by specifying a configuration key. It may use pooling, in which case
52 |  |
      * the implementations should implement the Recyclable interface.
53 |  |
      *
54 |  |
      * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
55 |  |
      * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
56 |  |
      * @version $Id: TurbineRunDataService.java 1078552 2011-03-06 19:58:46Z tv $
57 |  |
      */
58 |  |
     public class TurbineRunDataService
59 |  |
         extends TurbineBaseService
60 |  |
         implements RunDataService
61 |  |
     {
62 |  |
63 |  |
         /** The default implementation of the RunData object*/
64 | 58 |
         private static final String DEFAULT_RUN_DATA =
65 |  |
             DefaultTurbineRunData.class.getName();
66 |  |
67 |  |
         /** The default implementation of the Parameter Parser object */
68 | 58 |
         private static final String DEFAULT_PARAMETER_PARSER =
69 |  |
             DefaultParameterParser.class.getName();
70 |  |
71 |  |
         /** The default implementation of the Cookie parser object */
72 | 58 |
         private static final String DEFAULT_COOKIE_PARSER =
73 |  |
             DefaultCookieParser.class.getName();
74 |  |
75 |  |
         /** The map of configurations. */
76 | 58 |
         private final Map<String, Object> configurations = new HashMap<String, Object>();
77 |  |
78 |  |
         /** Private reference to the pool service for object recycling */
79 | 58 |
         private PoolService pool = null;
80 |  |
81 |  |
         /** Private reference to the parser service for parser recycling */
82 | 58 |
         private ParserService parserService = null;
83 |  |
84 |  |
         /**
85 |  |
          * Constructs a RunData Service.
86 |  |
          */
87 |  |
         public TurbineRunDataService()
88 |  |
         {
89 | 58 |
             super();
90 | 58 |
         }
91 |  |
92 |  |
         /**
93 |  |
          * Initializes the service by setting the pool capacity.
94 |  |
          *
95 |  |
          * @throws InitializationException if initialization fails.
96 |  |
          */
97 |  |
         @SuppressWarnings("unchecked")
98 |  |
         @Override
99 |  |
         public void init()
100 |  |
                 throws InitializationException
101 |  |
         {
102 |  |
             // Create a default configuration.
103 | 94 |
             String[] def = new String[]
104 |  |
             {
105 |  |
                 DEFAULT_RUN_DATA,
106 |  |
                 DEFAULT_PARAMETER_PARSER,
107 |  |
                 DEFAULT_COOKIE_PARSER
108 |  |
             };
109 | 94 |
             configurations.put(DEFAULT_CONFIG, def.clone());
110 |  |
111 |  |
             // Check other configurations.
112 | 94 |
             Configuration conf = getConfiguration();
113 | 94 |
             if (conf != null)
114 |  |
             {
115 |  |
                 String key,value;
116 |  |
                 String[] config;
117 | 94 |
                 String[] plist = new String[]
118 |  |
                 {
119 |  |
                     RUN_DATA_KEY,
120 |  |
                     PARAMETER_PARSER_KEY,
121 |  |
                     COOKIE_PARSER_KEY
122 |  |
                 };
123 | 94 |
                 for (Iterator<String> i = conf.getKeys(); i.hasNext();)
124 |  |
                 {
125 | 328 |
                     key = i.next();
126 | 328 |
                     value = conf.getString(key);
127 | 844 |
                     for (int j = 0; j < plist.length; j++)
128 |  |
                     {
129 | 750 |
                         if (key.endsWith(plist[j]) &&
130 |  |
                                 (key.length() > (plist[j].length() + 1)))
131 |  |
                         {
132 | 234 |
                             key = key.substring(0, key.length() - plist[j].length() - 1);
133 | 234 |
                             config = (String[]) configurations.get(key);
134 | 234 |
                             if (config == null)
135 |  |
                             {
136 | 0 |
                                 config = def.clone();
137 | 0 |
                                 configurations.put(key, config);
138 |  |
                             }
139 | 234 |
                             config[j] = value;
140 | 234 |
                             break;
141 |  |
                         }
142 |  |
                     }
143 |  |
                 }
144 |  |
             }
145 |  |
146 | 94 |
                     pool = (PoolService)TurbineServices.getInstance().getService(PoolService.ROLE);
147 |  |
148 | 94 |
             if (pool == null)
149 |  |
             {
150 | 0 |
                 throw new InitializationException("RunData Service requires"
151 |  |
                     + " configured Pool Service!");
152 |  |
             }
153 |  |
154 | 94 |
             parserService = (ParserService)TurbineServices.getInstance().getService(ParserService.ROLE);
155 |  |
156 | 94 |
             if (parserService == null)
157 |  |
             {
158 | 0 |
                 throw new InitializationException("RunData Service requires"
159 |  |
                     + " configured Parser Service!");
160 |  |
             }
161 |  |
162 | 94 |
             setInit(true);
163 | 94 |
         }
164 |  |
165 |  |
         /**
166 |  |
          * Gets a default RunData object.
167 |  |
          *
168 |  |
          * @param req a servlet request.
169 |  |
          * @param res a servlet response.
170 |  |
          * @param config a servlet config.
171 |  |
          * @return a new or recycled RunData object.
172 |  |
          * @throws TurbineException if the operation fails.
173 |  |
          */
174 |  |
         public RunData getRunData(HttpServletRequest req,
175 |  |
                                   HttpServletResponse res,
176 |  |
                                   ServletConfig config)
177 |  |
                 throws TurbineException
178 |  |
         {
179 | 52 |
             return getRunData(DEFAULT_CONFIG, req, res, config);
180 |  |
         }
181 |  |
182 |  |
         /**
183 |  |
          * Gets a RunData instance from a specific configuration.
184 |  |
          *
185 |  |
          * @param key a configuration key.
186 |  |
          * @param req a servlet request.
187 |  |
          * @param res a servlet response.
188 |  |
          * @param config a servlet config.
189 |  |
          * @return a new or recycled RunData object.
190 |  |
          * @throws TurbineException if the operation fails.
191 |  |
          * @throws IllegalArgumentException if any of the parameters are null.
192 |  |
          * @todo The "key" parameter should be removed in favor of just looking up what class via the roleConfig avalon file.
193 |  |
          */
194 |  |
         public RunData getRunData(String key,
195 |  |
                                   HttpServletRequest req,
196 |  |
                                   HttpServletResponse res,
197 |  |
                                   ServletConfig config)
198 |  |
                 throws TurbineException,
199 |  |
                 IllegalArgumentException
200 |  |
         {
201 |  |
             // a map to hold information to be added to pipelineData
202 | 52 |
             Map<Class<?>, Object> pipelineDataMap = new HashMap<Class<?>, Object>();
203 |  |
             // The RunData object caches all the information that is needed for
204 |  |
             // the execution lifetime of a single request. A RunData object
205 |  |
             // is created/recycled for each and every request and is passed
206 |  |
             // to each and every module. Since each thread has its own RunData
207 |  |
             // object, it is not necessary to perform syncronization for
208 |  |
             // the data within this object.
209 | 52 |
             if ((req == null)
210 |  |
                 || (res == null)
211 |  |
                 || (config == null))
212 |  |
             {
213 | 0 |
                 throw new IllegalArgumentException("HttpServletRequest, "
214 |  |
                     + "HttpServletResponse or ServletConfig was null.");
215 |  |
             }
216 |  |
217 |  |
             // Get the specified configuration.
218 | 52 |
             String[] cfg = (String[]) configurations.get(key);
219 | 52 |
             if (cfg == null)
220 |  |
             {
221 | 0 |
                 throw new TurbineException("RunTime configuration '" + key + "' is undefined");
222 |  |
             }
223 |  |
224 |  |
             TurbineRunData data;
225 |  |
             try
226 |  |
             {
227 | 52 |
                         Class<?> runDataClazz = Class.forName(cfg[0]);
228 | 52 |
                         Class<?> parameterParserClazz = Class.forName(cfg[1]);
229 | 52 |
                         Class<?> cookieParserClazz = Class.forName(cfg[2]);
230 |  |
231 | 52 |
                 data = (TurbineRunData) pool.getInstance(runDataClazz);
232 | 52 |
                 ParameterParser pp = (ParameterParser) parserService.getParser(parameterParserClazz);
233 | 52 |
                 data.setParameterParser(pp);
234 | 52 |
                 CookieParser cp = (CookieParser) parserService.getParser(cookieParserClazz);
235 | 52 |
                 data.setCookieParser(cp);
236 |  |
                 // also copy data directly into pipelineData
237 | 52 |
                 pipelineDataMap.put(ParameterParser.class, pp);
238 | 52 |
                 pipelineDataMap.put(CookieParser.class, cp);
239 |  |
240 | 52 |
                 Locale locale = req.getLocale();
241 |  |
242 | 52 |
                 if (locale == null)
243 |  |
                 {
244 |  |
                     // get the default from the Turbine configuration
245 | 0 |
                     locale = data.getLocale();
246 |  |
                 }
247 |  |
248 |  |
                 // set the locale detected and propagate it to the parsers
249 | 52 |
                 data.setLocale(locale);
250 |  |
             }
251 | 0 |
             catch (PoolException pe)
252 |  |
             {
253 | 0 |
                 throw new TurbineException("RunData configuration '" + key + "' is illegal caused a pool exception", pe);
254 |  |
             }
255 | 0 |
             catch (ClassNotFoundException x)
256 |  |
             {
257 | 0 |
                 throw new TurbineException("RunData configuration '" + key + "' is illegal", x);
258 |  |
             }
259 | 0 |
             catch (ClassCastException x)
260 |  |
             {
261 | 0 |
                 throw new TurbineException("RunData configuration '" + key + "' is illegal", x);
262 |  |
             }
263 | 0 |
             catch (InstantiationException e)
264 |  |
             {
265 | 0 |
                 throw new TurbineException("RunData configuration '" + key + "' is illegal", e);
266 | 52 |
             }
267 |  |
268 |  |
             // Set the request and response.
269 | 52 |
             data.setRequest(req);
270 | 52 |
             data.setResponse(res);
271 |  |
             // also copy data directly into pipelineData
272 | 52 |
             pipelineDataMap.put(HttpServletRequest.class, req);
273 | 52 |
             pipelineDataMap.put(HttpServletResponse.class, res);
274 |  |
275 |  |
             // Set the servlet configuration.
276 | 52 |
             data.setServletConfig(config);
277 |  |
             // also copy data directly into pipelineData
278 | 52 |
             pipelineDataMap.put(ServletConfig.class, config);
279 |  |
280 |  |
             // Set the ServerData.
281 | 52 |
             ServerData sd = new ServerData(req);
282 | 52 |
             data.setServerData(sd);
283 |  |
             // also copy data directly into pipelineData
284 | 52 |
             pipelineDataMap.put(ServerData.class, sd);
285 |  |
286 |  |
             // finally put the pipelineDataMap into the pipelineData object
287 | 52 |
             data.put(Turbine.class, pipelineDataMap);
288 | 52 |
             return data;
289 |  |
         }
290 |  |
291 |  |
         /**
292 |  |
          * Puts the used RunData object back to the factory for recycling.
293 |  |
          *
294 |  |
          * @param data the used RunData object.
295 |  |
          * @return true, if pooling is supported and the object was accepted.
296 |  |
          */
297 |  |
         public boolean putRunData(RunData data)
298 |  |
         {
299 | 2 |
             if (data instanceof TurbineRunData)
300 |  |
             {
301 | 2 |
                 parserService.putParser(((TurbineRunData) data).getParameterParser());
302 | 2 |
                 parserService.putParser(((TurbineRunData) data).getCookieParser());
303 |  |
304 | 2 |
                 return pool.putInstance(data);
305 |  |
             }
306 |  |
             else
307 |  |
             {
308 | 0 |
                 return false;
309 |  |
             }
310 |  |
         }
311 |  |
     }