View Javadoc
1   /*
2    * $Source$
3    * $Revision$
4    *
5    * Copyright (C) 2000 Tim Joyce
6    *
7    * Part of Melati (http://melati.org), a framework for the rapid
8    * development of clean, maintainable web applications.
9    *
10   * Melati is free software; Permission is granted to copy, distribute
11   * and/or modify this software under the terms either:
12   *
13   * a) the GNU General Public License as published by the Free Software
14   *    Foundation; either version 2 of the License, or (at your option)
15   *    any later version,
16   *
17   *    or
18   *
19   * b) any version of the Melati Software License, as published
20   *    at http://melati.org
21   *
22   * You should have received a copy of the GNU General Public License and
23   * the Melati Software License along with this program;
24   * if not, write to the Free Software Foundation, Inc.,
25   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26   * GNU General Public License and visit http://melati.org to obtain the
27   * Melati Software License.
28   *
29   * Feel free to contact the Developers of Melati (http://melati.org),
30   * if you would like to work out a different arrangement than the options
31   * outlined here.  It is our intention to allow Melati to be used by as
32   * wide an audience as possible.
33   *
34   * This program is distributed in the hope that it will be useful,
35   * but WITHOUT ANY WARRANTY; without even the implied warranty of
36   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37   * GNU General Public License for more details.
38   *
39   * Contact details for copyright holder:
40   *
41   *     Tim Joyce <timj At paneris.org>
42   *     http://paneris.org/
43   *     68 Sandbanks Rd, Poole, Dorset. BH14 8BY. UK
44   */
45  
46  package org.melati;
47  
48  import java.io.FileNotFoundException;
49  import java.io.IOException;
50  import java.util.List;
51  import java.util.Properties;
52  import java.util.Vector;
53  
54  import org.melati.login.AccessHandler;
55  import org.melati.poem.PoemLocale;
56  import org.melati.poem.util.EnumUtils;
57  import org.melati.servlet.FormDataAdaptorFactory;
58  import org.melati.template.ClassNameTempletLoader;
59  import org.melati.template.ServletTemplateEngine;
60  import org.melati.template.SimpleDateAdaptor;
61  import org.melati.template.TemplateEngine;
62  import org.melati.template.TempletLoader;
63  import org.melati.template.YMDDateAdaptor;
64  import org.melati.template.YMDHMSTimestampAdaptor;
65  import org.melati.util.ConfigException;
66  import org.melati.util.HttpHeader;
67  import org.melati.util.PropertiesUtils;
68  
69  /**
70   * A MelatiConfig loads and provides access to the configuration parameters for
71   * Melati. These are held in <TT>org.melati.MelatiConfig.properties</TT>.
72   */
73  public class MelatiConfig {
74  
75    private Properties configuration = null;
76    private String propertiesPrefix = "org.melati.MelatiConfig";
77  
78    private AccessHandler accessHandler = null;
79    private FormDataAdaptorFactory fdaFactory = null;
80    private TempletLoader templetLoader = null;
81    private TemplateEngine templateEngine = null;
82    private static PoemLocale poemLocale = null;
83    private Vector<String> preferredCharsets = null; 
84    private String javascriptLibraryURL = null;
85    private String staticURL = null;
86    private String templatePath = null;
87    private static String loginPageServletClassName = "org.melati.login.Login";
88    private static String logoutPageServletClassName = "org.melati.login.Logout";
89  
90    private static String realPath = null;
91    
92    /**
93     * Allows creation of a <code>MelatiConfig</code> with default config
94     * params.
95     */
96    public MelatiConfig() {
97      propertiesPrefix = getClass().getCanonicalName();
98      try {
99        configuration = PropertiesUtils.fromResource(getClass(), propertiesPrefix + ".properties");
100     }
101     catch (FileNotFoundException e) {
102       configuration = new Properties();
103       // TimJ: i think that if we don't have a properties file, it is pretty fatal
104       // TimP: Naah
105     }
106     catch (IOException e) {
107       throw new ConfigException("The file " + propertiesPrefix + ".properties" +
108                                 " could not be read.", e);
109     }
110     init(propertiesPrefix);
111   }
112 
113   /**
114    * Allows creation of a <code>MelatiConfig</code> with a specified
115    * properties file.
116    * 
117    * @param propertiesFilename
118    *        the name of a properties file
119    */
120   public MelatiConfig(String propertiesFilename) {
121     configuration = getProperties(propertiesFilename);
122     init(propertiesFilename);
123   }
124 
125   /**
126    * Constructor from a given Properties object.
127    * @param properties the properties object to look in 
128    */
129   public MelatiConfig(Properties properties) {
130     configuration = properties;
131     init(propertiesPrefix);
132   }
133 
134   
135   public static Properties getProperties() {
136     return getProperties(MelatiConfig.class.getCanonicalName());
137   }
138   public static Properties getProperties(String propertiesName) {
139     try {
140       return PropertiesUtils.fromResource(MelatiConfig.class, propertiesName + ".properties");
141     }
142     catch (FileNotFoundException e) {
143       throw new ConfigException("The file " + propertiesName + "properties" +
144                                 " could not be found." +
145                                 " Is it in your CLASSPATH?", e);
146     }
147     catch (IOException e) {
148       throw new ConfigException("The file " + propertiesName + ".properties" +
149                                 " could not be read.", e);
150     }
151     
152   }
153   @SuppressWarnings("unchecked")
154   void init(String propertiesNameIn) {
155     this.propertiesPrefix = propertiesNameIn;
156     String pref = propertiesPrefix + ".";
157     
158     String accessHandlerProp              = pref + "accessHandler";
159     String fdaFactoryProp                 = pref + "formDataAdaptorFactory";
160     String templetLoaderProp              = pref + "templetLoader";
161     String templateEngineProp             = pref + "templateEngine";
162     String templatePathProp               = pref + "templatePath";
163     String javascriptLibraryURLProp       = pref + "javascriptLibraryURL";
164     String staticURLProp                  = pref + "staticURL";
165     String melatiLocaleProp               = pref + "locale";
166     String preferredCharsetsProp          = pref + "preferredCharsets";
167     String loginPageServletClassNameProp  = pref + "loginPageServletClassName";
168     String logoutPageServletClassNameProp = pref + "logoutPageServletClassName";
169 
170     try {
171       setAccessHandler((AccessHandler)PropertiesUtils.
172           instanceOfNamedClass(
173               configuration,
174               accessHandlerProp,
175               "org.melati.login.AccessHandler",
176               "org.melati.login.OpenAccessHandler"));
177 
178       setFdaFactory((FormDataAdaptorFactory)PropertiesUtils.
179           instanceOfNamedClass(
180                        configuration,
181                        fdaFactoryProp,
182                        "org.melati.servlet.FormDataAdaptorFactory",
183                        "org.melati.servlet.MemoryFormDataAdaptorFactory"));
184 
185       String templetLoaderClassName =  (String)configuration.get(templetLoaderProp);
186       if(templetLoaderClassName == null || 
187          templetLoaderClassName.equals("org.melati.template.ClassNameTempletLoader")) {
188         setTempletLoader(ClassNameTempletLoader.getInstance());
189       } else
190         setTempletLoader((TempletLoader)PropertiesUtils.
191           instanceOfNamedClass(
192                           configuration,
193                           templetLoaderProp,
194                           "org.melati.template.TempletLoader",
195                           "org.melati.template.ClassNameTempletLoader"));
196 
197       setTemplateEngine((TemplateEngine)PropertiesUtils.
198           instanceOfNamedClass(
199                            configuration,
200                            templateEngineProp,
201                            "org.melati.template.TemplateEngine",
202                            "org.melati.template.NoTemplateEngine"));
203 
204       String languageTag = PropertiesUtils.getOrDefault(configuration,
205                                                         melatiLocaleProp,
206                                                         "en-gb");
207 
208       setPoemiLocale(PoemLocale.fromLanguageTag(languageTag));
209       if (poemLocale == null)
210           throw new ConfigException(languageTag +
211                               " is not a valid language tag for " +
212                               melatiLocaleProp);
213 
214       // This is a fancy way of splitting, trimming and checking for
215       // errors such as spaces within fields. 
216       // It reflects the fact that the config file format 
217       // is like a quoteless Http header field.
218       setPreferredCharsets(
219         EnumUtils.vectorOf(
220             new HttpHeader(PropertiesUtils.getOrDefault(
221                                configuration,
222                                preferredCharsetsProp,
223                                "ISO-8859-1, UTF-8, UTF-16")).wordIterator()));
224 
225       setJavascriptLibraryURL(PropertiesUtils.getOrDefault(
226               configuration,
227               javascriptLibraryURLProp,
228               "/melati-static/admin/"));
229 
230       setStaticURL(PropertiesUtils.getOrDefault(
231               configuration, 
232               staticURLProp,
233               "/melati-static/"
234               ));
235 
236       setTemplatePath(PropertiesUtils.getOrDefault(configuration,
237           templatePathProp, "."));
238 
239       setLoginPageServletClassName(PropertiesUtils.getOrDefault(configuration,
240           loginPageServletClassNameProp, loginPageServletClassName));
241 
242       setLogoutPageServletClassName(PropertiesUtils.getOrDefault(configuration,
243           logoutPageServletClassNameProp, logoutPageServletClassName));
244     }
245     catch (Exception e) {
246       throw new ConfigException("Melati could not be configured", e);
247     }
248 
249   }
250 
251   /**
252    * @return {@link ServletTemplateEngine} in use.
253    */
254   public ServletTemplateEngine getServletTemplateEngine() {
255     return (ServletTemplateEngine)templateEngine;
256   }
257 
258   /**
259    * @return {@link TemplateEngine} in use.
260    */
261   public TemplateEngine getTemplateEngine() {
262     return templateEngine;
263   }
264 
265   /**
266    * Set the {@link TemplateEngine} to use.
267    * 
268    * @param templateEngine
269    *        a {@link TemplateEngine}
270    */
271   public void setTemplateEngine(TemplateEngine templateEngine) {
272     this.templateEngine = templateEngine;
273   }
274 
275   /**
276    * @return the configured {@link AccessHandler}
277    */
278   public AccessHandler getAccessHandler() {
279     return accessHandler;
280   }
281 
282   /**
283    * Set the <code>AccessHandler</code> for use by this Melati.
284    * 
285    * @param accessHandler
286    *        a {@link AccessHandler}
287    */
288   public void setAccessHandler(AccessHandler accessHandler) {
289     this.accessHandler = accessHandler;
290   }
291 
292   /**
293    * @return the configured {@link TempletLoader}
294    */
295   public TempletLoader getTempletLoader() {
296     return templetLoader;
297   }
298 
299   /**
300    * Set the {@link TempletLoader} for use by this Melati.
301    * 
302    * @param templetLoader
303    *        a {@link TempletLoader}
304    */
305   public void setTempletLoader(TempletLoader templetLoader) {
306     this.templetLoader = templetLoader;
307   }
308 
309   /**
310    * @return the configured {@link FormDataAdaptorFactory}
311    */
312   public FormDataAdaptorFactory getFormDataAdaptorFactory() {
313     return fdaFactory;
314   }
315 
316   /**
317    * Set the {@link FormDataAdaptorFactory} for use by this Melati.
318    * 
319    * @param fdaf
320    *        a {@link FormDataAdaptorFactory}
321    */
322   public void setFormDataAdaptorFactory(FormDataAdaptorFactory fdaf) {
323     fdaFactory = fdaf;
324   }
325 
326   /**
327    * @return the location of javascript for this site.
328    */
329   public String getJavascriptLibraryURL() {
330     return javascriptLibraryURL;
331   }
332 
333   /**
334    * Set the <code>JavascriptLibraryURL</code> for use by this Melati.
335    * 
336    * @param url
337    *        a URL to the directory containing the JavaScript for this site
338    */
339   public void setJavascriptLibraryURL(String url) {
340     this.javascriptLibraryURL = url;
341   }
342 
343   /**
344    * Normally set to <code>melati-static</code>.
345    * 
346    * @return the location of static content for this site.
347    */
348   public String getStaticURL() {
349     return staticURL;
350   }
351 
352   /**
353    * Set the <code>StaticURL</code> for use by this Melati.
354    * 
355    * @param url
356    *        a URL to the directory containing the static content
357    */
358   public void setStaticURL(String url) {
359     this.staticURL = url;
360   }
361 
362   /**
363    * @return the location of templates.
364    */
365   public String getTemplatePath() {
366     return templatePath;
367   }
368 
369   /**
370    * @param templatePath
371    *        The templatePath to set.
372    */
373   public void setTemplatePath(String templatePath) {
374     this.templatePath = templatePath;
375   }
376 
377   /**
378    * @return the class name of the logout servlet
379    */
380   public static String getLogoutPageServletClassName() {
381     return logoutPageServletClassName;
382   }
383 
384   /**
385    * @param logoutPageServletClassName
386    *        The logoutPageServletClassName to set.
387    */
388   public static void setLogoutPageServletClassName(
389       String logoutPageServletClassName) {
390     MelatiConfig.logoutPageServletClassName = logoutPageServletClassName;
391   }
392 
393   /**
394    * @return the class name of the login servlet
395    */
396   public static String getLoginPageServletClassName() {
397     return loginPageServletClassName;
398   }
399 
400   /**
401    * @param loginPageServletClassName
402    *        The loginPageServletClassName to set.
403    */
404   public static void setLoginPageServletClassName(
405       String loginPageServletClassName) {
406     MelatiConfig.loginPageServletClassName = loginPageServletClassName;
407   }
408 
409   /**
410    * @return The configured locale, defaults to British English melati locale.
411    */
412   public static PoemLocale getPoemLocale() {
413     if (poemLocale == null)
414       poemLocale = PoemLocale.HERE;
415     return poemLocale;
416   }
417 
418   /**
419    * @param poemLocale
420    *        The PoemLocale to set.
421    */
422   public void setPoemiLocale(PoemLocale poemLocale) {
423     MelatiConfig.poemLocale = poemLocale;
424   }
425 
426 
427   /**
428    * Return the set encodings that the server prefers and supports.
429    * 
430    * @return List of encoding names or aliases.
431    */
432   public List<String> getPreferredCharsets() {
433     return preferredCharsets;
434   }
435 
436   /**
437    * @param preferredCharsets
438    *        The preferredCharsets to set.
439    */
440   public void setPreferredCharsets(Vector<String> preferredCharsets) {
441     this.preferredCharsets = preferredCharsets;
442   }
443 
444   /**
445    * @return Returns the fdaFactory.
446    */
447   public FormDataAdaptorFactory getFdaFactory() {
448     return fdaFactory;
449   }
450 
451   /**
452    * @param fdaFactory
453    *        The fdaFactory to set.
454    */
455   public void setFdaFactory(FormDataAdaptorFactory fdaFactory) {
456     this.fdaFactory = fdaFactory;
457   }
458   
459   //
460   // Non configurable but here to make them available in a template context.
461   //
462   
463   /**
464    * Called from within templets using 
465    * <code>
466    * #set $yearField = $melati.Config.YMDDateAdaptor.yearField($field)
467    * </code>
468    * idiom.
469    * Perhaps this should be elsewhere.
470    * @return the adaptor for rendering dates as drop-downs.
471    */
472   public static YMDDateAdaptor getYMDDateAdaptor() {
473     return YMDDateAdaptor.it;
474   }
475 
476   /**
477    * Called from within templets using 
478    * <code>
479    * #set $secondField = $melati.Config.YMDHMSTimestampAdaptor.secondField($field)
480    * </code>
481    * idiom.
482    * Perhaps this should be elsewhere.
483    * @return the adaptor for rendering timestamps as drop-downs.
484    */
485   public static YMDHMSTimestampAdaptor getYMDHMSTimestampAdaptor() {
486     return YMDHMSTimestampAdaptor.getIt();
487   }
488 
489   /**
490    * Called from within templets.
491    * Perhaps this should be elsewhere.
492    * @return the adaptor for rendering dates as normal.
493    */
494   public static SimpleDateAdaptor getSimpleDateAdaptor() {
495     return SimpleDateAdaptor.it;
496   }
497 
498   /**
499    * @param realPathP the path to set 
500    */
501   public void setRealPath(String realPathP) {
502     realPath = realPathP;
503   }
504   /**
505    * @return the real path, if set null otherwise
506    */
507   public String getRealPath() {
508     return realPath;
509   }
510 
511 }