1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.talika.tarsis.context;
24
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.net.MalformedURLException;
28 import java.net.URL;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.Map;
33
34 import javax.servlet.ServletContext;
35 import javax.xml.parsers.ParserConfigurationException;
36 import javax.xml.parsers.SAXParserFactory;
37
38 import org.talika.tarsis.Globals;
39 import org.talika.tarsis.command.factory.CommandFactory;
40 import org.talika.tarsis.command.factory.CommandFactoryService;
41 import org.talika.tarsis.factory.Factory;
42 import org.talika.tarsis.factory.FactoryService;
43 import org.talika.tarsis.log.Logger;
44 import org.talika.tarsis.log.LoggerHandler;
45 import org.talika.tarsis.security.Authenticator;
46 import org.talika.tarsis.security.AuthenticatorService;
47 import org.talika.tarsis.security.Authorizator;
48 import org.talika.tarsis.security.AuthorizatorService;
49 import org.talika.tarsis.service.ServiceException;
50 import org.xml.sax.InputSource;
51 import org.xml.sax.SAXException;
52 import org.xml.sax.SAXParseException;
53 import org.xml.sax.XMLReader;
54
55 /**
56 * Implementation of <code>Context</code> interface.
57 *
58 * @author Jose M. Palomar
59 * @version $Revision: 118 $
60 */
61 public final class ContextImpl implements Context {
62
63
64 /**
65 * Singleton instance.
66 */
67 private static ContextImpl context;
68
69 /**
70 * Init parameters map of this context.
71 */
72 private Map initParameters;
73
74 /**
75 * <code>Authenticator</code> defined for this context.
76 */
77 private AuthenticatorService authc;
78
79 /**
80 * <code>Authorizator</code> defined for this context.
81 */
82 private AuthorizatorService authz;
83
84 /**
85 * <code>Logger</code> defined for this context.
86 */
87 private LoggerHandler logger;
88
89 /**
90 * <code>CommandFactory</code> defined for this context.
91 */
92 private CommandFactoryService commandFactory;
93
94 /**
95 * Map of <code>Factory</code> objects defined for this context.
96 */
97 private Map factories;
98
99 /**
100 * <code>ServletContext</code> of web application.
101 */
102 private ServletContext ctx;
103
104 /**
105 * Is context loaded?
106 */
107 private boolean loaded;
108
109 /**
110 * Is context initialized?
111 */
112 private boolean initialized;
113
114
115 /**
116 * Creates a new <code>ContextImpl</code> object.
117 */
118 private ContextImpl() {
119 this.initParameters = new HashMap();
120 this.factories = new HashMap();
121 this.logger = new LoggerHandler();
122 }
123
124
125 /**
126 * Returns singleton <code>ContextImpl</code> instance.
127 *
128 * @return Context singleton <code>ContextImpl</code> instance.
129 */
130 public static ContextImpl getInstance() {
131
132 if (context == null) {
133 context = new ContextImpl();
134 }
135
136 return context;
137 }
138
139
140 /**
141 * Called on starts up of the Tarsis MVC Framework and put all components in
142 * service.<br>
143 * <br>
144 * Initializing sequence is:
145 * <ol>
146 * <li>Loads context configuration file.</li>
147 * <li>Initializes loggers.</li>
148 * <li>Initializes command factory.</li>
149 * <li>Initializes authenticator and authorizator if any are configured.</li>
150 * <li>Initializes factories if any are configured.</li>
151 * </ol>
152 *
153 * @param ctx ServletContext the <code>ServletContext</code> of web application
154 * where Tarsis MVC Framework is contained.
155 * @throws ConfigException if there is any problem loading configuration.
156 * @throws ServiceException if there is any problem initializing services.
157 */
158 public void init(ServletContext ctx) throws ConfigException, ServiceException {
159
160 if (this.initialized) {
161 return;
162 }
163
164
165 this.ctx = ctx;
166
167
168 loadConfig();
169
170
171 this.logger.init(this);
172
173 this.commandFactory.init(this);
174
175 if (this.authc != null) {
176 this.authc.init(this);
177 }
178
179 if (this.authz != null) {
180 this.authz.init(this);
181 }
182
183 Iterator factoryIterator = this.factories.values().iterator();
184 while (factoryIterator.hasNext()) {
185 FactoryService service = (FactoryService) factoryIterator.next();
186 service.init(this);
187 }
188
189 this.initialized = true;
190
191 }
192
193 /**
194 * Called on shutdown of the Tarsis MVC Framework and put all components out of
195 * service.
196 */
197 public void destroy() {
198
199 if (!this.initialized) {
200 return;
201 }
202
203
204 this.commandFactory.destroy();
205
206 Iterator factoryIterator = this.factories.values().iterator();
207 while (factoryIterator.hasNext()) {
208 FactoryService service = (FactoryService) factoryIterator.next();
209 service.destroy();
210 }
211 this.factories.clear();
212
213 if (this.authc != null) {
214 this.authc.destroy();
215 this.authc = null;
216 }
217
218 if (this.authz != null) {
219 this.authz.destroy();
220 this.authz = null;
221 }
222
223 this.initParameters.clear();
224
225 this.logger.destroy();
226
227 this.ctx = null;
228 this.initialized = false;
229 }
230
231 /**
232 * Load context configuration from an XML file. The Tarsis MVC Framework
233 * configuration file is <code>/WEB-INF/tarsis-config.xml</code>.
234 *
235 * @throws ConfigException if there is any problems or errors loading config file.
236 */
237 private void loadConfig() throws ConfigException {
238
239 if (this.loaded) {
240 return;
241 }
242
243 try {
244
245 InputStream contextStream = ctx.getResourceAsStream(Globals.CONFIG_FILE);
246 if (contextStream == null) {
247 throw new ConfigException("Config file not found");
248 }
249
250 InputSource input = new InputSource(contextStream);
251
252 SAXParserFactory spf = SAXParserFactory.newInstance();
253 spf.setValidating(true);
254 spf.setNamespaceAware(false);
255
256 XMLReader parser = null;
257 parser = spf.newSAXParser().getXMLReader();
258 XmlConfigHandler handler = new XmlConfigHandler();
259 parser.setContentHandler(handler);
260 parser.setErrorHandler(handler);
261 parser.setEntityResolver(handler);
262 parser.parse(input);
263
264 this.initParameters.putAll(handler.getInitParameters());
265 this.authc = handler.getAuthenticathor();
266 this.authz = handler.getAuthorizator();
267 this.factories.putAll(handler.getFactories());
268 this.logger.addLoggers(handler.getLoggers());
269 this.commandFactory = handler.getCommandFactory();
270
271 }
272 catch (SAXParseException spe) {
273 throw new ConfigException("Error parsing context: " + spe.getMessage());
274 }
275 catch (SAXException se) {
276 if (se.getException() != null) {
277 throw new ConfigException("Error parsing context: " +
278 se.getException().getMessage());
279 }
280 else {
281 throw new ConfigException("Error parsing context: " + se.getMessage());
282 }
283 }
284 catch (ParserConfigurationException pce) {
285 throw new ConfigException("Error parsing context: " + pce.getMessage());
286 }
287 catch (IOException ioe) {
288 throw new ConfigException("Error parsing context: " + ioe.getMessage());
289 }
290
291 this.loaded = true;
292
293 }
294
295
296 /**
297 * Returns default <code>Authenticator</code> for this context.
298 *
299 * @return Authenticator default <code>Authenticator</code> for this context.
300 * @see org.talika.tarsis.context.Context#getAuthenticator()
301 */
302 public Authenticator getAuthenticator() {
303 return authc;
304 }
305
306 /**
307 * Returns default <code>Authorizator</code> for this context.
308 *
309 * @return Authorizator default <code>Authorizator</code> for this context.
310 * @see org.talika.tarsis.context.Context#getAuthorizator()
311 */
312 public Authorizator getAuthorizator() {
313 return authz;
314 }
315
316 /**
317 * Returns an init parameter of this context.
318 *
319 * @param name String name of parameter.
320 * @return String value of parameter or <code>null</code> if parameter does not
321 * exist.
322 * @see org.talika.tarsis.context.Context#getInitParameter(String)
323 */
324 public String getInitParameter(String name) {
325 return (String) initParameters.get(name);
326 }
327
328 /**
329 * Returns a map with all the init parameters of this context.
330 *
331 * @return Map map with all the init parameters of this context.
332 * @see org.talika.tarsis.context.Context#getInitParameters()
333 */
334 public Map getInitParameters() {
335 return Collections.unmodifiableMap(initParameters);
336 }
337
338 /**
339 * Returns <code>Logger</code> of this context.
340 *
341 * @return Logger <code>Logger</code> of this context.
342 * @see org.talika.tarsis.context.Context#getLogger()
343 */
344 public Logger getLogger() {
345 return logger;
346 }
347
348 /**
349 * Returns default <code>CommandFactory</code> for this context.
350 *
351 * @return CommandFactory default <code>CommandFactory</code> for this context.
352 * @see org.talika.tarsis.context.Context#getCommandFactory()
353 */
354 public CommandFactory getCommandFactory() {
355 return commandFactory;
356 }
357
358 /**
359 * Returns an object <code>Factory</code> for given name in this context.
360 *
361 * @param name String name of factory.
362 * @return Factory object <code>Factory</code> for given name in this context or
363 * <code>null</code> if does not exist.
364 * @see org.talika.tarsis.context.Context#getFactory(String)
365 */
366 public Factory getFactory(String name) {
367 return (Factory) factories.get(name);
368 }
369
370 /**
371 * Returns a URL to the resource that is mapped to a specified path.
372 *
373 * @param path String a <code>String</code> specifying the path to the resource.
374 * @return URL the resource located at the named path, or <code>null</code> if
375 * there is no resource at that path.
376 * @throws MalformedURLException if the pathname is not given in the correct form.
377 * @see javax.servlet.ServletContext#getResource(java.lang.String)
378 * @see org.talika.tarsis.context.Context#getResource(String)
379 */
380 public URL getResource(String path) throws MalformedURLException {
381 return ctx.getResource(path);
382 }
383
384 /**
385 * Returns the resource located at the named path as an <code>InputStream</code>
386 * object.
387 *
388 * @param path String a <code>String</code> specifying the path to the resource.
389 * @return InputStream the <code>InputStream</code> returned to the servlet, or
390 * <code>null</code> if no resource exists at the specified path.
391 * @see javax.servlet.ServletContext#getResourceAsStream(java.lang.String)
392 * @see org.talika.tarsis.context.Context#getResourceAsStream(String)
393 */
394 public InputStream getResourceAsStream(String path) {
395 return ctx.getResourceAsStream(path);
396 }
397
398 /**
399 * Returns a String containing the real path for a given virtual path.
400 *
401 * @param path String a <code>String</code> specifying the path to the resource.
402 * @return String a <code>String</code> specifying the real path, or
403 * <code>null</code> if the translation cannot be performed
404 * @see javax.servlet.ServletContext#getRealPath(java.lang.String)
405 * @see org.talika.tarsis.context.Context#getRealPath(String)
406 */
407 public String getRealPath(String path) {
408 return ctx.getRealPath(path);
409 }
410
411 }