KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > validation > impl > DefaultValidator


1 /*
2  * Copyright 1999-2005 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 package org.apache.cocoon.components.validation.impl;
17
18 import java.util.Collections JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import org.apache.avalon.framework.activity.Disposable;
24 import org.apache.avalon.framework.activity.Initializable;
25 import org.apache.avalon.framework.activity.Startable;
26 import org.apache.avalon.framework.configuration.Configurable;
27 import org.apache.avalon.framework.configuration.Configuration;
28 import org.apache.avalon.framework.configuration.ConfigurationException;
29 import org.apache.avalon.framework.context.Context;
30 import org.apache.avalon.framework.context.ContextException;
31 import org.apache.avalon.framework.context.Contextualizable;
32 import org.apache.avalon.framework.logger.LogEnabled;
33 import org.apache.avalon.framework.logger.Logger;
34 import org.apache.avalon.framework.parameters.Parameterizable;
35 import org.apache.avalon.framework.parameters.Parameters;
36 import org.apache.avalon.framework.service.ServiceException;
37 import org.apache.avalon.framework.service.ServiceManager;
38 import org.apache.avalon.framework.service.ServiceSelector;
39 import org.apache.avalon.framework.service.Serviceable;
40 import org.apache.avalon.framework.thread.ThreadSafe;
41 import org.apache.cocoon.components.validation.SchemaParser;
42 import org.apache.cocoon.components.validation.Validator;
43
44 /**
45  * <p>The default implementation of the {@link Validator} interface provides
46  * core management for a number of {@link SchemaParser} instances.</p>
47  *
48  * <p>Given the simplicity of this implementation, only {@link SchemaParser}s
49  * implementing the {@link ThreadSafe} interface can be managed, and they can be
50  * accessed directly (via its name) through the methods specified by the
51  * {@link ServiceSelector} interface.</p>
52  *
53  * <p>That said, normally selection would occur using the methods declared by the
54  * {@link AbstractValidator} class and implemented here.</p>
55  *
56  * @author <a HREF="mailto:pier@betaversion.org">Pier Fumagalli</a>
57  */

58 public class DefaultValidator extends AbstractValidator implements ServiceSelector,
59 ThreadSafe, Contextualizable, Initializable, Disposable, Configurable {
60
61     /** <p>A {@link Map} associating {@link SchemaParser}s with their names.</p> */
62     private final Map JavaDoc components = Collections.synchronizedMap(new HashMap JavaDoc());
63     /** <p>A {@link Map} associating component names with grammars.</p> */
64     private final Map JavaDoc grammars = Collections.synchronizedMap(new HashMap JavaDoc());
65
66     /** <p>The configured {@link Context} instance.</p> */
67     private Context context = null;
68     /** <p>The configured {@link Configuration} instance.</p> */
69     private Configuration conf = null;
70
71     /**
72      * <p>Create a new {@link DefaultValidator} instance.</p>
73      */

74     public DefaultValidator() {
75         super();
76     }
77
78     /**
79      * <p>Contextualize this instance.</p>
80      */

81     public void contextualize(Context context)
82     throws ContextException {
83         this.context = context;
84     }
85
86     /**
87      * <p>Configure this instance.</p>
88      */

89     public void configure(Configuration conf)
90     throws ConfigurationException {
91         this.conf = conf;
92     }
93
94     /**
95      * <p>Initialize this instance.</p>
96      */

97     public void initialize()
98     throws Exception JavaDoc {
99         this.logger.debug("Initializing " + this.getClass().getName());
100
101         if (this.logger == null) throw new IllegalStateException JavaDoc("Null logger");
102         if (this.context == null) throw new IllegalStateException JavaDoc("Null context");
103         if (this.manager == null) throw new IllegalStateException JavaDoc("Null manager");
104         if (this.conf == null) throw new IllegalStateException JavaDoc("Null configuration");
105
106         Configuration configurations[] = this.conf.getChildren("schema-parser");
107         this.logger.debug("Configuring " + configurations.length + " schema parsers"
108                           + " from " + this.conf.getLocation());
109
110         /* Iterate through all the sub-confiuration instances */
111         for (int x = 0; x < configurations.length; x++) try {
112             final Configuration configuration = configurations[x];
113             final String JavaDoc className = configuration.getAttribute("class");
114             final String JavaDoc selectionKey = configuration.getAttribute("name");
115             
116             /* Check that we don't have a duplicate schema parser name in configs */
117             if (this.components.containsKey(selectionKey)) {
118                 String JavaDoc message = "Duplicate schema parser \"" + selectionKey + "\"";
119                 throw new ConfigurationException(message, configuration);
120             }
121
122             /* Dump some debugging information, just in case */
123             this.logger.debug("Configuring schema parser " + selectionKey + " as "
124                               + className + " from " + configuration.getLocation());
125
126             /* Try to load and instantiate the SchemaParser */
127             final SchemaParser schemaParser;
128             try {
129                 /* Load the class */
130                 final Class JavaDoc clazz = Class.forName(className);
131
132                 /* ClassCastExceptions normally don't come with messages (darn) */
133                 if (! SchemaParser.class.isAssignableFrom(clazz)) {
134                     String JavaDoc message = "Class " + className + " doesn't implement the "
135                                      + SchemaParser.class.getName() + " interface";
136                     throw new ConfigurationException(message, configuration);
137                 }
138
139                 /* We only support ThreadSafe SchemaParser instances */
140                 if (! ThreadSafe.class.isAssignableFrom(clazz)) {
141                     String JavaDoc message = "Class " + className + " doesn't implement the "
142                                      + ThreadSafe.class.getName() + " interface";
143                     throw new ConfigurationException(message, configuration);
144                 }
145
146                 /* Instantiate and set up the new SchemaParser */
147                 schemaParser = (SchemaParser) clazz.newInstance();
148                 this.setupComponent(selectionKey, schemaParser, configuration);
149
150             } catch (ConfigurationException exception) {
151                 throw exception;
152             } catch (Exception JavaDoc exception) {
153                 String JavaDoc message = "Unable to instantiate SchemaParser " + className;
154                 throw new ConfigurationException(message, configuration, exception);
155             }
156
157             /* Store this instance (and report about it) */
158             this.components.put(selectionKey, schemaParser);
159             this.logger.debug("SchemaParser \"" + selectionKey + "\" instantiated" +
160                               " from class " + className);
161
162             /* Analyze the grammars provided by the current SchemaParser */
163             String JavaDoc grammars[] = schemaParser.getSupportedGrammars();
164             if (grammars == null) continue;
165
166             /* Iterate through the grammars and store them (default lookup) */
167             for (int k = 0; k < grammars.length; k++) {
168                 if (this.grammars.containsKey(grammars[k])) {
169                     if (this.logger.isDebugEnabled()) {
170                         this.logger.debug("SchemaParser \"" + selectionKey + "\" " +
171                                           "supports grammar \"" + grammars[k] +
172                                           "\" but is not the default provider");
173                     }
174                     continue;
175                 }
176
177                 /* Noone yet supports this grammar, make this the default */
178                 this.grammars.put(grammars[k], selectionKey);
179                 if (this.logger.isDebugEnabled()) {
180                     this.logger.debug("SchemaParser \"" + selectionKey + "\" is the "
181                                       + "default grammar provider for "+grammars[k]);
182                 }
183             }
184
185         } catch (Exception JavaDoc exception) {
186             /* Darn, we had an exception instantiating one of the components */
187             exception.printStackTrace();
188             this.logger.fatalError("Exception creating schema parsers", exception);
189
190             /* Dispose all previously stored component instances */
191             Iterator JavaDoc iterator = this.components.values().iterator();
192             while (iterator.hasNext()) try {
193                 this.decommissionComponent(iterator.next());
194             } catch (Exception JavaDoc nested) {
195                 this.logger.fatalError("Error decommissioning component", nested);
196             }
197
198             /* Depending on the exception type, re-throw it or wrap it */
199             if (exception instanceof ConfigurationException) {
200                 throw exception;
201             } else {
202                 Configuration configuration = configurations[x];
203                 String JavaDoc message = "Unable to setup SchemaParser declared at ";
204                 message += configuration.getLocation();
205                 throw new ConfigurationException(message, configuration, exception);
206             }
207         }
208     }
209
210     /**
211      * <p>Dispose of this instance.</p>
212      *
213      * <p>All sub-components initialized previously will be disposed of when this
214      * method is called.</p>
215      */

216     public void dispose() {
217         Iterator JavaDoc iterator = this.components.values().iterator();
218         while (iterator.hasNext()) try {
219             this.decommissionComponent(iterator.next());
220         } catch (Exception JavaDoc exception) {
221             this.logger.fatalError("Error decommissioning component", exception);
222         }
223     }
224
225     /* =========================================================================== */
226     /* IMPLEMENTATION OF METHODS SPECIFIED BY THE ABSTRACTVALIDATOR CLASS */
227     /* =========================================================================== */
228
229     /**
230      * <p>Attempt to acquire a {@link SchemaParser} interface able to understand
231      * the grammar language specified.</p>
232      *
233      * @param grammar the grammar language that must be understood by the returned
234      * {@link SchemaParser}
235      * @return a {@link SchemaParser} instance or <b>null</b> if none was found able
236      * to understand the specified grammar language.
237      */

238     protected SchemaParser lookupParserByGrammar(String JavaDoc grammar) {
239         if (this.grammars.containsKey(grammar)) {
240             return this.lookupParserByName((String JavaDoc) this.grammars.get(grammar));
241         }
242         return null;
243     }
244
245     /**
246      * <p>Attempt to acquire a {@link SchemaParser} interface associated with the
247      * specified instance name.</p>
248      *
249      * @param name the name associated with the {@link SchemaParser} to be returned.
250      * @return a {@link SchemaParser} instance or <b>null</b> if none was found.
251      */

252     protected SchemaParser lookupParserByName(String JavaDoc name) {
253         if (this.isSelectable(name)) try {
254             return (SchemaParser) this.select(name);
255         } catch (ServiceException exception) {
256             return null;
257         }
258         return null;
259     }
260
261     /**
262      * <p>Release a previously acquired {@link SchemaParser} instance back to its
263      * original component manager.</p>
264      *
265      * <p>This method is supplied in case solid implementations of this class relied
266      * on the {@link ServiceManager} to manage {@link SchemaParser}s instances.</p>
267      *
268      * @param parser the {@link SchemaParser} whose instance is to be released.
269      */

270     protected void releaseParser(SchemaParser parser) {
271         this.release(parser);
272     }
273
274     /* =========================================================================== */
275     /* IMPLEMENTATION OF THE METHODS SPECIFIED BY THE SERVICESELECTOR INTERFACE */
276     /* =========================================================================== */
277
278     /**
279      * <p>Select a subcomponent ({@link SchemaParser}) associated with the specified
280      * selection key (its configured &quot;name&quot;).</p>
281      */

282     public Object JavaDoc select(Object JavaDoc selectionKey)
283     throws ServiceException {
284         /* Look up for the specified component and return it if found */
285         if ( this.components.containsKey(selectionKey)) {
286             return this.components.get(selectionKey);
287         }
288
289         /* Fail miserably */
290         String JavaDoc message = "No component associated with " + selectionKey;
291         throw new ServiceException((String JavaDoc) selectionKey, message);
292     }
293
294     /**
295      * <p>Check whether a subcomponent ({@link SchemaParser}) associated with the
296      * specified selection key (its configured &quot;name&quot;) is selectable in
297      * this {@link ServiceSelector} instance.</p>
298      */

299     public boolean isSelectable(Object JavaDoc selectionKey) {
300         return this.components.containsKey(selectionKey);
301     }
302
303     /**
304      * <p>Release a subcomponent ({@link SchemaParser}) instance previously selected
305      * from this {@link ServiceSelector} instance.</p>
306      */

307     public void release(Object JavaDoc component) {
308         // We don't need to do anything in this method.
309
}
310
311     /* =========================================================================== */
312     /* SUBCOMPONENTS (SCHEMA PARSERS) LIFECYCLE MANAGEMENT METHODS */
313     /* =========================================================================== */
314
315     /**
316      * <p>Manage the instantiation lifecycle of a specified component.</p>
317      */

318     private Object JavaDoc setupComponent(String JavaDoc name, Object JavaDoc component, Configuration conf)
319     throws Exception JavaDoc {
320         boolean initialized = false;
321         boolean started = false;
322
323         try {
324             if (component instanceof LogEnabled) {
325                 Logger logger = this.logger.getChildLogger(name);
326                 ((LogEnabled) component).enableLogging(logger);
327             }
328     
329             if (component instanceof Contextualizable) {
330                 ((Contextualizable) component).contextualize(this.context);
331             }
332
333             if (component instanceof Serviceable) {
334                 ((Serviceable) component).service(this.manager);
335             }
336
337             if (component instanceof Configurable) {
338                 ((Configurable) component).configure(conf);
339             }
340
341             if (component instanceof Parameterizable) {
342                 Parameters parameters = Parameters.fromConfiguration(conf);
343                 ((Parameterizable) component).parameterize(parameters);
344             }
345     
346             if (component instanceof Initializable) {
347                 ((Initializable) component).initialize();
348                 initialized = true;
349             }
350
351             if (component instanceof Startable) {
352                 ((Startable) component).start();
353                 started = true;
354             }
355
356             return component;
357
358         } catch (Exception JavaDoc exception) {
359             if ((started) && (component instanceof Startable)) try {
360                 ((Startable) component).stop();
361             } catch (Exception JavaDoc nested) {
362                 this.logger.fatalError("Error stopping component", nested);
363             }
364             if ((initialized) && (component instanceof Disposable)) try {
365                 ((Disposable) component).dispose();
366             } catch (Exception JavaDoc nested) {
367                 this.logger.fatalError("Error disposing component", nested);
368             }
369             throw exception;
370         }
371     }
372
373     /**
374      * <p>Manage the distruction lifecycle of a specified component.</p>
375      */

376     private void decommissionComponent(Object JavaDoc component)
377     throws Exception JavaDoc {
378         try {
379             if (component instanceof Startable) ((Startable) component).stop();
380         } finally {
381             if (component instanceof Disposable) ((Disposable) component).dispose();
382         }
383     }
384 }
Popular Tags