1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
50
51 final private Broker _broker;
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
172
173
174
175
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 }