View Javadoc

1   /*
2    * Copyright 2000-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.scaffold.http;
18  
19  import java.io.BufferedInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.util.Map;
23  import java.util.Properties;
24  
25  import javax.servlet.ServletException;
26  import javax.servlet.UnavailableException;
27  import javax.servlet.http.HttpServlet;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  
32  /**
33   * Base servlet for loading application resources.
34   * 
35   * @author Ted Husted
36   * @author Steve Raeburn
37   */
38  public class ResourceServlet extends HttpServlet {
39  
40      // TODO: Externalize messages using commons resources. 
41      //       Previous suggestion was to use MessageResources, but this would 
42      //       create a dependency on Struts. A better option would be to use 
43      //       Commons Resources, which Struts will eventually migrate to.
44      
45      // ------------------------------------------------------- Class variables
46  
47      /**
48       * Commons logging instance
49       */
50      private static Log log = LogFactory.getLog(ResourceServlet.class);
51  
52      // ------------------------------------------------------ Logging Messages
53  
54      private static final String INIT_FAILED_EVENT =
55          "ResourceServlet: init() failed.";
56  
57      private static final String RELOAD_EVENT = 
58          "Reloading ResourceServlet";
59  
60      private static final String DESTROY_EVENT = 
61          "Destroying ResourceServlet";
62  
63      private static final String RESOURCE_LOADING =
64          "Loading resources from path: ";
65  
66      private static final String RESOURCE_NOT_FOUND = 
67          "Resources not found";
68  
69      // --------------------------------------------------- Parameter Utilities
70  
71      /**
72       * Check for a parameter and returns a default value if not found.
73       *
74       * @param parameter The attribute name to look for
75       * @param defaultValue The default to return if the parameter is not found
76       * @return The customized value or the default value
77       */
78      public String getInitString(String parameter, String defaultValue) {
79  
80          String stringValue = getServletConfig().getInitParameter(parameter);
81          if (null == stringValue)
82              return defaultValue;
83          return stringValue;
84  
85      }
86  
87      /**
88       * Check for a parameter and returns a default value if not found,
89       * or if the value does not convert to an <code>int</code>.
90       *
91       * @param parameter The attribute name to look for
92       * @defaultValue The default to return if the parameter is not found
93       * @return The customized value or the default value
94       */
95      public int getInitInt(String parameter, int defaultValue) {
96  
97          String stringValue = null;
98          int intValue = defaultValue;
99  
100         try {
101 
102             stringValue = getServletConfig().getInitParameter(parameter);
103             intValue = Integer.parseInt(stringValue);
104 
105         } catch (Throwable t) {
106             intValue = defaultValue;
107         }
108 
109         return intValue;
110     }
111 
112     /**
113      * Return a map of this servlet's initialization parameters.
114      *
115      * @return A map of this servlet's initialization parameters.
116      * @fixme Not tested yet
117      */
118     public Map getInitParameters() {
119 
120         // :FIXME: Not tested yet.
121 
122         java.util.Enumeration names =
123             getServletConfig().getInitParameterNames();
124         java.util.HashMap map = new java.util.HashMap();
125         while (names.hasMoreElements()) {
126             String name = (String) names.nextElement();
127             String value = getServletConfig().getInitParameter(name);
128             map.put(name, value);
129         }
130         return map;
131     }
132 
133     // --------------------------------------------------- Internal Properties
134 
135     /**
136      * The parameter to check for a new path to the default properties
137      * ["default"].
138      */
139     private static final String DEFAULT_PARAMETER = "default";
140 
141     /**
142      * The default path to use if parameter is not set
143      *["resources/default.properties"].
144      */
145     private static final String DEFAULT_PATH = "resources/default.properties";
146 
147     /**
148      * The default attribute for the application properties.
149      * The properties are exposed in the servlet context
150      * under this attribute name
151      * [lang.Tokens.PROPERTIES_KEY].
152      */
153     private static final String DEFAULT_ATTRIBUTE =
154         org.apache.commons.scaffold.lang.Tokens.PROPERTIES_KEY;
155 
156     /**
157      * Our default properties object.
158      * <p>
159      * The default properties can be used to store applications
160      * settings that do not need to be localized and may
161      * not even be displayed to the user.
162      */
163     Properties properties = null;
164 
165     /**
166      * Set the default properties object.
167      */
168     public void setProperties(Properties properties) {
169         this.properties = properties;
170     }
171 
172     /**
173      * Return the default properties object.
174      *
175      * @return The default properties object
176      */
177     public Properties getProperties() {
178         return this.properties;
179     }
180 
181     /**
182      * A utility method for loading a Properties file
183      * specified by an initialization parameter.
184      *
185      * The initialization parameter should specify the
186      * package and folder for the Properties in system
187      * path format (resources/custom.properties).
188      *
189      * @param parameter The name of the initialization
190      * parameter
191      * @param defaultPath The path to use if the
192      * parameter is not found
193      * @param attribute If not null, store in
194      * application scope under this attribute name
195      */
196     public Properties loadProperties(
197         String parameter,
198         String defaultPath,
199         String attribute)
200         throws ServletException {
201 
202         String path = getInitString(parameter, defaultPath);
203 
204         if (log.isDebugEnabled()) {
205             log.debug(RESOURCE_LOADING);
206             log.debug(path);
207         }
208 
209         InputStream is = null;
210         is = this.getClass().getClassLoader().getResourceAsStream(path);
211         if (null == is)
212             throw new UnavailableException(RESOURCE_NOT_FOUND);
213 
214         Properties p = null;
215         BufferedInputStream bis = new BufferedInputStream(is);
216 
217         try {
218 
219             p = new Properties();
220             p.load(bis);
221             bis.close();
222             is.close();
223         } catch (IOException e) {
224 
225             p = null;
226 
227         } finally {
228             is = null;
229             bis = null;
230         }
231 
232         if ((null != p) && (null != attribute)) {
233 
234             this.getServletContext().setAttribute(attribute, p);
235 
236         }
237 
238         if (log.isDebugEnabled()) {
239             log.debug(p.toString());
240         }
241 
242         return p;
243     }
244 
245     /**
246      * Initialize the default properties for this application.
247      * <p>
248      * Use the <code>default</code> initialization parameter to specify
249      * another path. Otherwise ["resources/default.properties"] is used.
250      * <p>
251      * If the default properties will not be used or specified,
252      * override this method with one that does not try to load the
253      * default properties.
254      *
255      * @exception IOException if an input/output error is encountered
256      * @exception ServletException if we cannot initialize these resources
257      * @todo The PROPERTIES_KEY could be made configurable,
258      * but the BaseAction would need to be notified.
259      */
260     protected void initDefault() throws IOException, ServletException {
261 
262         setProperties(
263             loadProperties(DEFAULT_PARAMETER, DEFAULT_PATH, DEFAULT_ATTRIBUTE));
264     }
265 
266     /**
267      * Release any default resources created at initialization
268      */
269     protected void destroyDefault() {
270         setProperties(null);
271     }
272 
273     // --------------------------------------------------- HttpServlet Methods
274 
275     /**
276      * Initialize this servlet by caling three extension points:
277      * <ul>
278      * <li><code>initLogging</code></li>
279      * <li><code>initDefault</code></li>
280      * <li><code>initCustom</code></li>
281      * </ul>
282      * The main extension point is <code><b>initCustom</b></code>
283      * The default implementation does nothing.
284      * The other two methods have reasonable default behaviors that most
285      * subclasses could use as-is.
286      * This may be called again from <code>reload</code> and should be
287      * "re-enterant".
288      *
289      * @exception ServletException if we cannot configure ourselves
290      * correctly
291      */
292     public void init() throws ServletException {
293 
294         try {
295 
296             initDefault();
297             // initMessages();
298             initCustom();
299 
300         } catch (IOException e) {
301 
302             throw new UnavailableException(INIT_FAILED_EVENT);
303 
304         }
305     }
306 
307     /**
308      * Gracefully shut down this controller servlet, releasing any resources
309      * that were allocated at initialization.
310      */
311     public void destroy() {
312 
313         if (log.isDebugEnabled()) {
314             log.debug(DESTROY_EVENT);
315         }
316 
317         destroyCustom();
318         // destroyMessages();
319         destroyDefault();
320 
321     }
322 
323     // ------------------------------------------------------ Extension Points
324 
325     /**
326      * Initialize the custom properties or objects for this application.
327      *
328      * @exception IOException if an input/output error is encountered
329      * @exception ServletException if we cannot initialize these resources
330      */
331     protected void initCustom() throws IOException, ServletException {
332 
333         // Override with custom initializations
334 
335     }
336 
337     /**
338      * Release any custom resources created at initialization
339      */
340     protected void destroyCustom() {
341         // override to provide functionality if needed
342     }
343 
344     // -------------------------------------------------------- Public Methods
345 
346     /**
347      * Reload the configuration of this controller servlet from our
348      * underlying configuration files.
349      *
350      * @exception IOException if an input/output error occurs
351      * @exception ServletException if a servlet exception occurs
352      */
353     public void reload() throws IOException, ServletException {
354 
355         if (log.isDebugEnabled()) {
356             log.debug(RELOAD_EVENT);
357         }
358 
359         // Re-initialize
360         init();
361     }
362 
363 } // end ResourceServlet