KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > ExtendedComponentSelector


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;
17
18 import org.apache.avalon.excalibur.component.ExcaliburComponentSelector;
19 import org.apache.avalon.excalibur.component.RoleManager;
20 import org.apache.avalon.framework.component.Component;
21 import org.apache.avalon.framework.component.ComponentException;
22 import org.apache.avalon.framework.configuration.Configuration;
23 import org.apache.avalon.framework.configuration.ConfigurationException;
24 import org.apache.avalon.framework.configuration.DefaultConfiguration;
25
26 /**
27  * An extension of <code>ExcaliburComponentSelector</code> that can have a parent
28  * and accepts a wider variety of configurations.
29  *
30  * @author <a HREF="mailto:sylvain@apache.org">Sylvain Wallez</a>
31  * @version CVS $Id: ExtendedComponentSelector.java 165142 2005-04-28 14:11:42Z vgritsenko $
32  */

33 public class ExtendedComponentSelector extends ExcaliburComponentSelector
34                                        implements ParentAware {
35
36     /** The role manager */
37     protected RoleManager roles;
38
39     /** The parent selector, if any */
40     protected ExtendedComponentSelector parentSelector;
41
42     /** The parent locator, if any */
43     protected ComponentLocator parentLocator;
44
45     /** The class loader to use */
46     protected ClassLoader JavaDoc classLoader;
47
48     /** The role of this selector. Set in <code>configure()</code>. */
49     protected String JavaDoc roleName;
50
51     /** The default hint */
52     protected String JavaDoc defaultHint;
53
54     /** This selector's location (used for debugging purposes) */
55     private String JavaDoc location;
56
57
58     /** Create the ComponentSelector with the Thread context ClassLoader */
59     public ExtendedComponentSelector() {
60         this.classLoader = Thread.currentThread().getContextClassLoader();
61     }
62
63     /** Create the ComponentSelector with a ClassLoader */
64     public ExtendedComponentSelector(ClassLoader JavaDoc loader) {
65         super(loader);
66
67         if (loader == null) {
68             this.classLoader = Thread.currentThread().getContextClassLoader();
69         } else {
70             this.classLoader = loader;
71         }
72     }
73
74     /**
75      * Get the name for component-instance elements (i.e. components not defined
76      * by their role shortcut. If <code>null</code>, any element having a 'class'
77      * attribute will be considered as a component instance.
78      * <p>
79      * The default here is to return <code>null</code>, and subclasses can redefine
80      * this method to return particular values.
81      *
82      * @return <code>null</code>, but can be changed by subclasses
83      */

84     protected String JavaDoc getComponentInstanceName() {
85         return null;
86     }
87
88     /**
89      * Get the name of the attribute giving the class name of a component.
90      * The default here is "class", but this can be overriden in subclasses.
91      *
92      * @return "<code>class</code>", but can be changed by subclasses
93      */

94     protected String JavaDoc getClassAttributeName() {
95         return "class";
96     }
97
98     /**
99      * Get the name of the attribute giving the default hint to use if
100      * none is given. The default here is "default", but this can be
101      * overriden in subclasses. If this method returns <code>null</code>,
102      * no default hint can be specified.
103      *
104      * @return "<code>default</code>", but can be changed by subclasses
105      */

106     protected String JavaDoc getDefaultHintAttributeName() {
107         return "default";
108     }
109
110     /**
111      * Configure the RoleManager. Redeclared only because parent member is private.
112      */

113     public void setRoleManager(RoleManager roles) {
114         super.setRoleManager(roles);
115         this.roles = roles;
116     }
117
118     /**
119      * Set the parent of this selector. This can be done after the selector is
120      * initialized, but <em>only once</em>. This allows this selector to be
121      * created by a component manager while still being able to have a parent.
122      *
123      * @param parent the parent selector
124      * @throws IllegalStateException if parent is already set
125      */

126 /* public void setParentSelector(ComponentSelector parent) {
127         if (this.parentSelector != null) {
128             throw new IllegalStateException("Parent selector is already set");
129         }
130         this.parentSelector = parent;
131         this.parentComponents = new HashSet();
132     }
133 */

134
135     /**
136      * Get the role name for this selector. This is called by <code>configure()</code>
137      * to set the value of <code>this.roleName</code>.
138      *
139      * @return the role name, or <code>null<code> if it couldn't be determined.
140      */

141     protected String JavaDoc getRoleName(Configuration config) {
142         // Get the role for this selector
143
String JavaDoc roleName = config.getAttribute("role", null);
144         if (roleName == null && this.roles != null) {
145             roleName = this.roles.getRoleForName(config.getName());
146         }
147
148         return roleName;
149     }
150
151     /**
152      * Configure this selector. This is the main difference with the parent class :
153      * <ul>
154      * <li>if {@link #getComponentInstanceName()} returns <code>null</code>,
155      * any child configurations having a attribute named as the result of
156      * {@link #getClassAttributeName()}, is considered as a component instance.
157      * </li>
158      * <li>if {@link #getComponentInstanceName()} returns a non-null value,
159      * only child configurations having this name are considered as a
160      * component instance.
161      * </li>
162      * <li>if other cases, it's name is considered to be a hint in the role manager.
163      * The behaviour is then the same as <code>ExcaliburComponentSelector</code>.
164      * </li>
165      *
166      * @param config the configuration
167      * @throws ConfigurationException if some hints aren't defined
168      */

169     public void configure(Configuration config) throws ConfigurationException {
170
171         // Store location
172
this.location = config.getLocation();
173
174         this.roleName = getRoleName(config);
175
176         // Pass a copy of the top-level object to superclass so that
177
// our name is properly initialized
178
// FIXME : could be avoided if parent m_role was protected or had protected accessors
179
DefaultConfiguration temp = new DefaultConfiguration(config.getName(), this.location);
180         if (config.getAttribute("role", null) != null) {
181             temp.setAttribute("role", this.roleName);
182         }
183         super.configure(temp);
184
185         // Get default hint
186
this.defaultHint = config.getAttribute(this.getDefaultHintAttributeName(), null);
187
188         // Add components
189
String JavaDoc compInstanceName = getComponentInstanceName();
190
191         Configuration[] instances = config.getChildren();
192
193         for (int i = 0; i < instances.length; i++) {
194             Configuration instance = instances[i];
195
196             Object JavaDoc hint = instance.getAttribute("name").trim();
197
198             String JavaDoc classAttr = instance.getAttribute(getClassAttributeName(), null);
199             String JavaDoc className;
200
201             if (compInstanceName == null) {
202                 // component-instance implicitly defined by the presence of the 'class' attribute
203
if (classAttr == null) {
204                     className = this.roles.getDefaultClassNameForHint(roleName, instance.getName());
205                 } else {
206                     className = classAttr.trim();
207                 }
208
209             } else {
210                 // component-instances names explicitly defined
211
if (compInstanceName.equals(instance.getName())) {
212                     className = (classAttr == null) ? null : classAttr.trim();
213                 } else {
214                     className = this.roles.getDefaultClassNameForHint(roleName, instance.getName());
215                 }
216             }
217
218             if (className == null) {
219                 String JavaDoc message = "Unable to determine class name for component named '" + hint +
220                     "' at " + instance.getLocation();
221
222                 getLogger().error(message);
223                 throw new ConfigurationException(message);
224             }
225
226             try {
227                 Class JavaDoc clazz = this.classLoader.loadClass(className);
228                 addComponent(hint, clazz, instance);
229
230             } catch (Exception JavaDoc e) {
231                 String JavaDoc message = "Could not load class " + className + " for component named '" +
232                                  hint + "' at " + instance.getLocation();
233
234                 getLogger().error(message, e);
235                 throw new ConfigurationException(message, e);
236             }
237         }
238     }
239
240     /**
241      * Get the default hint, if any for this selector.
242      */

243     public String JavaDoc getDefaultHint() {
244         // Inherit parent default hint if have no own
245
if (this.defaultHint == null && this.parentSelector != null) {
246             return this.parentSelector.getDefaultHint();
247         }
248
249         return this.defaultHint;
250     }
251
252     /* (non-Javadoc)
253      * @see org.apache.avalon.framework.component.ComponentSelector#select(java.lang.Object)
254      */

255     public Component select(Object JavaDoc hint) throws ComponentException {
256         if (hint == null) {
257             hint = this.defaultHint;
258         }
259
260         if (parentSelector == null) {
261             // No parent: default behaviour
262
return super.select(hint);
263         }
264
265         try {
266             // Try in this selector first
267
final Component component = super.select(hint);
268             return component;
269
270         } catch (ComponentException original) {
271             try {
272                 // Doesn't exist here: try in parent selector
273
final Component component = this.parentSelector.select(hint);
274                 return component;
275
276             } catch (ComponentException nested) {
277                 // Doesn't exist in parent too: throw exception.
278

279                 if (nested.getCause() != null) {
280                     // Nested exception has a cause; let's throw it instead of original.
281
throw nested;
282                 }
283
284                 // Throw original exception
285
throw original;
286             }
287         }
288     }
289
290     /* (non-Javadoc)
291      * @see org.apache.avalon.framework.component.ComponentSelector#release(org.apache.avalon.framework.component.Component)
292      */

293     public void release(Component component) {
294         // Was it selected on the parent ?
295
if (this.parentSelector != null && this.parentSelector.canRelease(component)) {
296             // Yes
297
this.parentSelector.release(component);
298         } else {
299             // No
300
super.release(component);
301         }
302     }
303
304     /**
305      * Does this selector or its parent have the given hint ?
306      */

307     public boolean hasComponent(Object JavaDoc hint) {
308         boolean exists = super.hasComponent(hint);
309         if (!exists && this.parentSelector != null) {
310             exists = this.parentSelector.hasComponent(hint);
311         }
312         return exists;
313     }
314
315     /**
316      * Does this selector declare a given hint? Check is performed on the components declared for this
317      * selector only, and <strong>not</strong> those potentially inherited from the parent selector.
318      *
319      * @param hint the hint to check for
320      * @return <code>true</code> if this selector has the specified hint
321      */

322     protected boolean hasDeclaredComponent(Object JavaDoc hint) {
323         return super.hasComponent(hint);
324     }
325
326     /* (non-Javadoc)
327      * @see org.apache.cocoon.components.ParentAware#setParentInformation(org.apache.avalon.framework.component.ComponentManager, java.lang.String)
328      */

329     public void setParentLocator(ComponentLocator locator)
330     throws ComponentException {
331         if (this.parentSelector != null) {
332             throw new ComponentException(null, "Parent selector is already set");
333         }
334         this.parentLocator = locator;
335         this.parentSelector = (ExtendedComponentSelector) locator.lookup();
336     }
337
338     /* (non-Javadoc)
339      * @see org.apache.avalon.framework.activity.Disposable#dispose()
340      */

341     public void dispose() {
342         super.dispose();
343         if (this.parentLocator != null) {
344             this.parentLocator.release(this.parentSelector);
345             this.parentLocator = null;
346             this.parentSelector = null;
347         }
348     }
349
350     /* (non-Javadoc)
351      * @see org.apache.avalon.excalibur.component.ExcaliburComponentSelector#canRelease(org.apache.avalon.framework.component.Component)
352      */

353     protected boolean canRelease(Component component) {
354         if (this.parentSelector != null && this.parentSelector.canRelease(component)) {
355             return true;
356         }
357
358         return super.canRelease(component);
359     }
360 }
361
Popular Tags