View Javadoc

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.Map;
25  
26  import javax.servlet.ServletConfig;
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpServletResponse;
29  
30  import org.apache.commons.configuration.Configuration;
31  
32  import org.apache.turbine.services.InitializationException;
33  import org.apache.turbine.services.TurbineBaseService;
34  import org.apache.turbine.services.pool.PoolService;
35  import org.apache.turbine.services.pool.TurbinePool;
36  import org.apache.turbine.util.RunData;
37  import org.apache.turbine.util.ServerData;
38  import org.apache.turbine.util.TurbineException;
39  import org.apache.turbine.util.parser.CookieParser;
40  import org.apache.turbine.util.parser.DefaultCookieParser;
41  import org.apache.turbine.util.parser.DefaultParameterParser;
42  import org.apache.turbine.util.parser.ParameterParser;
43  
44  /***
45   * The RunData Service provides the implementations for RunData and
46   * related interfaces required by request processing. It supports
47   * different configurations of implementations, which can be selected
48   * by specifying a configuration key. It may use pooling, in which case
49   * the implementations should implement the Recyclable interface.
50   *
51   * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
52   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
53   * @version $Id: TurbineRunDataService.java 534527 2007-05-02 16:10:59Z tv $
54   */
55  public class TurbineRunDataService
56      extends TurbineBaseService
57      implements RunDataService
58  {
59      /*** @deprecated Use RunDataService.RUN_DATA_KEY */
60      public static final String RUN_DATA =
61          RunDataService.RUN_DATA_KEY;
62  
63      /*** @deprecated Use RunDataService.PARAMETER_PARSER_KEY */
64      public static final String PARAMETER_PARSER =
65          RunDataService.PARAMETER_PARSER_KEY;
66  
67      /*** @deprecated Use RunDataService.COOKIE_PARSER_KEY */
68      public static final String COOKIE_PARSER =
69          RunDataService.COOKIE_PARSER_KEY;
70  
71      /*** The default implementation of the RunData object*/
72      private static final String DEFAULT_RUN_DATA =
73          DefaultTurbineRunData.class.getName();
74  
75      /*** The default implementation of the Parameter Parser object */
76      private static final String DEFAULT_PARAMETER_PARSER =
77          DefaultParameterParser.class.getName();
78  
79      /*** The default implementation of the Cookie parser object */
80      private static final String DEFAULT_COOKIE_PARSER =
81          DefaultCookieParser.class.getName();
82  
83      /*** The map of configurations. */
84      private Map configurations = new HashMap();
85  
86      /*** Private reference to the pool service for object recycling */
87      private PoolService pool = null;
88  
89      /***
90       * Constructs a RunData Service.
91       */
92      public TurbineRunDataService()
93      {
94      }
95  
96      /***
97       * Initializes the service by setting the pool capacity.
98       *
99       * @throws InitializationException if initialization fails.
100      */
101     public void init()
102             throws InitializationException
103     {
104         // Create a default configuration.
105         String[] def = new String[]
106         {
107             DEFAULT_RUN_DATA,
108             DEFAULT_PARAMETER_PARSER,
109             DEFAULT_COOKIE_PARSER
110         };
111         configurations.put(DEFAULT_CONFIG, def.clone());
112 
113         // Check other configurations.
114         Configuration conf = getConfiguration();
115         if (conf != null)
116         {
117             String key,value;
118             String[] config;
119             String[] plist = new String[]
120             {
121                 RUN_DATA_KEY,
122                 PARAMETER_PARSER_KEY,
123                 COOKIE_PARSER_KEY
124             };
125             for (Iterator i = conf.getKeys(); i.hasNext();)
126             {
127                 key = (String) i.next();
128                 value = conf.getString(key);
129                 for (int j = 0; j < plist.length; j++)
130                 {
131                     if (key.endsWith(plist[j]) &&
132                             (key.length() > (plist[j].length() + 1)))
133                     {
134                         key = key.substring(0, key.length() - plist[j].length() - 1);
135                         config = (String[]) configurations.get(key);
136                         if (config == null)
137                         {
138                             config = (String[]) def.clone();
139                             configurations.put(key, config);
140                         }
141                         config[j] = value;
142                         break;
143                     }
144                 }
145             }
146         }
147         pool = TurbinePool.getService();
148 
149         if (pool == null)
150         {
151             throw new InitializationException("RunData Service requires"
152                 + " configured Pool Service!");
153         }
154 
155         setInit(true);
156     }
157 
158     /***
159      * Gets a default RunData object.
160      *
161      * @param req a servlet request.
162      * @param res a servlet response.
163      * @param config a servlet config.
164      * @return a new or recycled RunData object.
165      * @throws TurbineException if the operation fails.
166      */
167     public RunData getRunData(HttpServletRequest req,
168                               HttpServletResponse res,
169                               ServletConfig config)
170             throws TurbineException
171     {
172         return getRunData(DEFAULT_CONFIG, req, res, config);
173     }
174 
175     /***
176      * Gets a RunData instance from a specific configuration.
177      *
178      * @param key a configuration key.
179      * @param req a servlet request.
180      * @param res a servlet response.
181      * @param config a servlet config.
182      * @return a new or recycled RunData object.
183      * @throws TurbineException if the operation fails.
184      * @throws IllegalArgumentException if any of the parameters are null.
185      */
186     public RunData getRunData(String key,
187                               HttpServletRequest req,
188                               HttpServletResponse res,
189                               ServletConfig config)
190             throws TurbineException,
191             IllegalArgumentException
192     {
193         // The RunData object caches all the information that is needed for
194         // the execution lifetime of a single request. A RunData object
195         // is created/recycled for each and every request and is passed
196         // to each and every module. Since each thread has its own RunData
197         // object, it is not necessary to perform syncronization for
198         // the data within this object.
199         if ((req == null)
200             || (res == null)
201             || (config == null))
202         {
203             throw new IllegalArgumentException("HttpServletRequest, "
204                 + "HttpServletResponse or ServletConfig was null.");
205         }
206 
207         // Get the specified configuration.
208         String[] cfg = (String[]) configurations.get(key);
209         if (cfg == null)
210         {
211             throw new TurbineException("RunTime configuration '" + key + "' is undefined");
212         }
213 
214         TurbineRunData data;
215         try
216         {
217             data = (TurbineRunData) pool.getInstance(cfg[0]);
218             data.setParameterParser((ParameterParser) pool.getInstance(cfg[1]));
219             data.setCookieParser((CookieParser) pool.getInstance(cfg[2]));
220         }
221         catch (ClassCastException x)
222         {
223             throw new TurbineException("RunData configuration '" + key + "' is illegal", x);
224         }
225 
226         // Set the request and response.
227         data.setRequest(req);
228         data.setResponse(res);
229 
230         // Set the servlet configuration.
231         data.setServletConfig(config);
232 
233         // Set the ServerData.
234         data.setServerData(new ServerData(req));
235 
236         return data;
237     }
238 
239     /***
240      * Puts the used RunData object back to the factory for recycling.
241      *
242      * @param data the used RunData object.
243      * @return true, if pooling is supported and the object was accepted.
244      */
245     public boolean putRunData(RunData data)
246     {
247         if (data instanceof TurbineRunData)
248         {
249             pool.putInstance(((TurbineRunData) data).getParameterParser());
250             pool.putInstance(((TurbineRunData) data).getCookieParser());
251 
252             return pool.putInstance(data);
253         }
254         else
255         {
256             return false;
257         }
258     }
259 }