View Javadoc

1   /*
2    * Copyright (C) 1998-2000 Semiotek Inc.  All Rights Reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted under the terms of either of the following
6    * Open Source licenses:
7    *
8    * The GNU General Public License, version 2, or any later version, as
9    * published by the Free Software Foundation
10   * (http://www.fsf.org/copyleft/gpl.html);
11   *
12   *  or
13   *
14   * The Semiotek Public License (http://webmacro.org/LICENSE.)
15   *
16   * This software is provided "as is", with NO WARRANTY, not even the
17   * implied warranties of fitness to purpose, or merchantability. You
18   * assume all risks and liabilities associated with its use.
19   *
20   * See www.webmacro.org for more information on the WebMacro project.
21   */
22  
23  
24  package org.webmacro;
25  
26  import java.io.*;
27  import java.util.*;
28  import javax.servlet.Servlet;
29  import javax.servlet.ServletContext;
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  
33  import org.webmacro.servlet.ServletBroker;
34  import org.webmacro.servlet.WebContext;
35  
36  
37  /***
38   * This class implements the WebMacro Manager interface. You can instantiate
39   * this yourself if you want to use WebMacro in standalone mode, rather than
40   * subclassing from org.webmacro.servlet.WMServlet. This is actually the
41   * same class used by the servlet framework to manage access to the broker
42   * there, so you really don't lose much of anything by choosing to go
43   * standalone by using this object. All you have to do is come up with
44   * your own context objects.
45   */
46  public class WM implements WebMacro
47  {
48  
49      // INIT METHODS--MANAGE ACCESS TO THE BROKER
50  
51      final private Broker _broker;      // cache for rapid access
52  
53      final private Provider _tmplProvider;
54      final private Provider _urlProvider;
55      final private Log _log;
56  
57  
58      /***
59       * Constructs a WM which gets its properties (optionally) from the
60       * file WebMacro.properties, as found on the class path.  No servlet
61       * integration.  Templates will be loaded from the class path or from
62       * TemplatePath.   Most users will want to use the WM(Servlet) constructor.
63       */
64      public WM () throws InitException
65      {
66          this(Broker.getBroker());
67      }
68  
69      /***
70       * Constructs a WM which gets its properties (optionally) from the
71       * file WebMacro.properties, as found on the class path, and from properties
72       * specified in a provided Properties.  No servlet
73       * integration.  Templates will be loaded from the class path or from
74       * TemplatePath.   Most users will want to use the WM(Servlet) constructor.
75       */
76      public WM (Properties p) throws InitException
77      {
78          this(Broker.getBroker(p));
79      }
80  
81      /***
82       * Constructs a WM which gets its properties from the file specified,
83       * which must exist on the class path or be an absolute path.  No servlet
84       * integration.  Templates will be loaded from the class path or from
85       * TemplatePath.  Most users will want to use the WM(Servlet) constructor.
86       */
87      public WM (String config) throws InitException
88      {
89          this(Broker.getBroker(config));
90      }
91  
92      /***
93       * Constructs a WM is tied to a Servlet broker.  Depending on the
94       * servlet containers level of servlet support, property fetching,
95       * logging, and template fetching will be managed by the servlet broker.
96       */
97      public WM (Servlet s) throws InitException
98      {
99          this(ServletBroker.getBroker(s));
100     }
101 
102     /***
103      * Constructs a WM is tied to a Servlet broker, with an additional set of
104      * properties passed in from the caller.
105      */
106     public WM (Servlet s, Properties additionalProperties) throws InitException
107     {
108         this(ServletBroker.getBroker(s, additionalProperties));
109     }
110 
111     /***
112      * Constructs a WM is tied to a Servlet broker,
113      * with an additional set of
114      * properties passed in from the caller, using the ServletContext
115      * and ClassLoader provided.
116      * @since 2.1
117      */
118     public WM (ServletContext sc, ClassLoader cl,
119                Properties additionalProperties) throws InitException
120     {
121         this(ServletBroker.getBroker(sc, cl, additionalProperties));
122     }
123 
124     /***
125      * Constructs a WM from an arbitrary Broker.  Don't use this unless
126      * you have very specific needs and know what you are doing; constructing
127      * a properly functioning broker is not obvious.
128      */
129     public WM (Broker broker) throws InitException
130     {
131         if (broker == null)
132             throw new InitException("No Broker passed to WM()");
133 
134         _broker = broker;
135         _log = _broker.getLog("wm", "WebMacro instance lifecycle");
136         _log.notice("new " + this + " v" + WebMacro.VERSION);
137 
138         try
139         {
140             _tmplProvider = _broker.getProvider("template");
141             _urlProvider = _broker.getProvider("url");
142         }
143         catch (NotFoundException nfe)
144         {
145             _log.error("Could not load configuration", nfe);
146             throw new InitException("Could not locate provider; "
147                     + "This implies that WebMacro is badly misconfigured, you\n"
148                     + "should double check that all configuration files and\n"
149                     + "options are set up correctly. In a default install of\n"
150                     + "WebMacro this likely means your WebMacro.properties file\n"
151                     + "was not found on your CLASSPATH.", nfe);
152         }
153     }
154 
155     public String toString ()
156     {
157         return "WebMacro(" + _broker.getName() + ")";
158     }
159 
160 
161     /***
162      * This object is used to access components that have been plugged
163      * into WebMacro; it is shared between all instances of this class and
164      * its subclasses. It is created when the first instance is initialized,
165      * and deleted when the last instance is shut down. If you attempt to
166      * access it after the last servlet has been shutdown, it will either
167      * be in a shutdown state or else null.
168      */
169     final public Broker getBroker ()
170     {
171         // this method can be unsynch. because the broker manages its own
172         // state, plus the only time the _broker will be shutdown or null
173         // is after the last servlet has shutdown--so why would anyone be
174         // accessing us then? if they do the _broker will throw exceptions
175         // complaining that it has been shut down, or they'll get a null here.
176         return _broker;
177     }
178 
179     /***
180      * Get a new FastWriter.
181      * A FastWriter is used when writing templates to an output stream
182      *
183      * @param out The output stream the FastWriter should write to.  Typically
184      *           this will be your ServletOutputStream.  It can be null if
185      *           only want the fast writer to buffer the output.
186      * @param enctype the Encoding type to use
187      * @deprecated
188      */
189     final public FastWriter getFastWriter (OutputStream out, String enctype)
190             throws UnsupportedEncodingException
191     {
192         return FastWriter.getInstance(_broker, out, enctype);
193     }
194 
195 
196     /***
197      * Instantiate a new context.
198      */
199     final public Context getContext ()
200     {
201         return new Context(_broker);
202     }
203 
204     /***
205      * Instantiate a new webcontext.
206      */
207     final public WebContext getWebContext (HttpServletRequest req,
208                                            HttpServletResponse resp)
209     {
210         return new WebContext(_broker, req, resp);
211     }
212 
213 
214     /***
215      * Retrieve a template from the "template" provider.
216      * @exception NotFoundException  if the template could not be found
217      * @exception ResourceException  if the template could not be loaded
218      */
219     final public Template getTemplate (String key)
220             throws ResourceException
221     {
222         return (Template) _tmplProvider.get(key);
223     }
224 
225     /***
226      * Retrieve a URL from the "url" provider. Equivalent to
227      * getBroker().getValue("url",url)
228      * @exception NotFoundException  if the template could not be found
229      * @exception ResourceException  if the template could not be loaded
230      */
231     final public String getURL (String url)
232             throws ResourceException
233     {
234         return (String) _urlProvider.get(url);
235     }
236 
237     /***
238      * Retrieve configuration information from the "config" provider.
239      * Equivalent to getBroker().get("config",key)
240      * @exception NotFoundException could not locate requested information
241      */
242     final public String getConfig (String key)
243             throws NotFoundException
244     {
245         try
246         {
247             return (String) _broker.get("config", key);
248         }
249         catch (NotFoundException e)
250         {
251             throw e;
252         }
253         catch (ResourceException e)
254         {
255             throw new NotFoundException(e.toString(), e);
256         }
257     }
258 
259     /***
260      * Get a log to write information to. Log type names should be lower
261      * case and short. They may be printed on every line of the log
262      * file. The description is a longer explanation of the type of
263      * log messages you intend to produce with this Log object.
264      */
265     final public Log getLog (String type, String description)
266     {
267         return _broker.getLog(type, description);
268     }
269 
270     /***
271      * Get a log using the type as the description
272      */
273     final public Log getLog (String type)
274     {
275         return _broker.getLog(type, type);
276     }
277 
278     /***
279      * Convenience method for writing a template to an OutputStream.
280      * This method takes care of all the typical work involved
281      * in writing a template.<p>
282      *
283      * This method uses the default <code>TemplateOutputEncoding</code> specified in
284      * WebMacro.defaults or your custom WebMacro.properties.
285      *
286      * @param templateName name of Template to write.  Must be accessible
287      *                     via TemplatePath
288      * @param out          where the output of the template should go
289      * @param context      The Context (can be a WebContext too) used
290      *                     during the template evaluation phase
291      * @throws java.io.IOException if the template cannot be written to the
292      *                             specified output stream
293      * @throws ResourceException if the template name specified cannot be found
294      * @throws PropertyException if a fatal error occured during the Template
295      *                           evaluation phase
296      */
297     final public void writeTemplate (String templateName, java.io.OutputStream out,
298                                      Context context)
299             throws java.io.IOException, ResourceException, PropertyException
300     {
301 
302         writeTemplate(templateName, out,
303                 getConfig(WMConstants.TEMPLATE_OUTPUT_ENCODING), context);
304     }
305 
306     /***
307      * Convienence method for writing a template to an OutputStream.
308      * This method takes care of all the typical work involved
309      * in writing a template.
310      *
311      * @param templateName name of Template to write.  Must be accessible
312      *                     via TemplatePath
313      * @param out          where the output of the template should go
314      * @param encoding     character encoding to use when writing the template
315      *                     if the encoding is <code>null</code>, the default
316      *                     <code>TemplateOutputEncoding</code> is used
317      * @param context      The Context (can be a WebContext too) used
318      *                     during the template evaluation phase
319      * @throws java.io.IOException if the template cannot be written to the
320      *                             specified output stream
321      * @throws ResourceException if the template name specified cannot be found
322      * @throws PropertyException if a fatal error occured during the Template
323      *                           evaluation phase
324      */
325     final public void writeTemplate (String templateName, java.io.OutputStream out,
326                                      String encoding, Context context)
327             throws java.io.IOException, ResourceException, PropertyException
328     {
329 
330         if (encoding == null)
331             encoding = getConfig(WMConstants.TEMPLATE_OUTPUT_ENCODING);
332 
333         Template tmpl = getTemplate(templateName);
334         tmpl.write(out, encoding, context);
335     }
336 
337     /***
338      * Print the version, and quit
339      */
340     public static void main (String[] args)
341     {
342         System.out.println("WebMacro v" + WebMacro.VERSION + ".  Built " + WebMacro.BUILD_DATE);
343     }
344 
345     /***
346      * Close down this WM.  This will invoke destroy() on the Broker.
347      * @see Broker#destroy()
348      **/
349     public void destroy() 
350     {
351         getBroker().destroy();
352     }
353 }