KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > forrest > locationmap > lm > LocationMap


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation or its licensors,
3  * as applicable.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.forrest.locationmap.lm;
18
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.component.WrapperComponentManager;
24 import org.apache.avalon.framework.configuration.Configuration;
25 import org.apache.avalon.framework.configuration.ConfigurationException;
26 import org.apache.avalon.framework.container.ContainerUtil;
27 import org.apache.avalon.framework.logger.AbstractLogEnabled;
28 import org.apache.avalon.framework.logger.Logger;
29 import org.apache.avalon.framework.service.DefaultServiceManager;
30 import org.apache.avalon.framework.service.DefaultServiceSelector;
31 import org.apache.avalon.framework.service.ServiceManager;
32 import org.apache.cocoon.components.treeprocessor.InvokeContext;
33 import org.apache.cocoon.matching.Matcher;
34 import org.apache.cocoon.selection.Selector;
35
36 /**
37  * A LocationMap defines a mapping from requests to locations.
38  * <p>
39  * The syntax of the locationmap is similar to the way a sitemap
40  * maps requests to pipelines. In the locationmap's case
41  * Matchers and Selectors are not used to identify pipelines but
42  * location strings.
43  * </p>
44  * <p>
45  * The locationmap was conceived to:
46  * <ul>
47  * <li>
48  * Provide a tool for more powerful virtual linking.
49  * </li>
50  * <li>
51  * Enable Forrest with a standard configuration override mechanism.
52  * </li>
53  * </ul>
54  * </p>
55  */

56 public final class LocationMap extends AbstractLogEnabled {
57     
58     /**
59      * The locationmap namespace:
60      * <code>http://apache.org/forrest/locationmap/1.0</code>
61      */

62     public static final String JavaDoc URI = "http://apache.org/forrest/locationmap/1.0";
63     
64     /**
65      * Name of the special anchor map passed into the VariableContext.
66      * The value is <code>lm</code> .
67      * <p>
68      * This makes it possible to use special locationmap variables
69      * inside the locationmap definition.
70      * </p>
71      * <p>
72      * Special locationmap parameters are available through this anchor map.
73      * For instance the hint parameter defined below can be accessed in
74      * the locationmap definition as follows: <code>{#lm:hint}</code>
75      * </p>
76      * All anchor map parameters are also passed implicitly into each selector
77      * and matcher at run-time.
78      */

79     public static final String JavaDoc ANCHOR_NAME = "lm";
80     
81     /**
82      * Special anchor map key holding the 'hint' or 'argument' the LocationMap was
83      * called with.
84      *
85      * <p>
86      * The value is <code>hint</code>.
87      * </p>
88      */

89     public static final String JavaDoc HINT_KEY = "hint";
90     
91     /**
92      * The hint's parameter name.
93      */

94     public static final String JavaDoc HINT_PARAM = "#" + ANCHOR_NAME + ":" + HINT_KEY;
95     
96     /** Component manager containing the locationmap components */
97     private LocationMapServiceManager m_manager;
98     
99     /** default matcher */
100     private String JavaDoc m_defaultMatcher;
101     
102     /** default selector */
103     private String JavaDoc m_defaultSelector;
104     
105     /** list of LocatorNodes */
106     private LocatorNode[] m_locatorNodes;
107     
108     
109     public LocationMap(ServiceManager manager) {
110         m_manager = new LocationMapServiceManager(manager);
111     }
112     
113     /**
114      * Build the LocationMap by creating the components and recursively building
115      * the LocatorNodes.
116      */

117     public void build(final Configuration configuration) throws ConfigurationException {
118
119         // components
120
final Configuration components = configuration.getChild("components");
121
122         // matchers
123
Configuration child = components.getChild("matchers",false);
124         if (child != null) {
125             final DefaultServiceSelector matcherSelector = new DefaultServiceSelector();
126             m_defaultMatcher = child.getAttribute("default");
127             final Configuration[] matchers = child.getChildren("matcher");
128             for (int i = 0; i < matchers.length; i++) {
129                 String JavaDoc name = matchers[i].getAttribute("name");
130                 String JavaDoc src = matchers[i].getAttribute("src");
131                 Matcher matcher = (Matcher) createComponent(src, matchers[i]);
132                 matcherSelector.put(name, matcher);
133             }
134             matcherSelector.makeReadOnly();
135             if (!matcherSelector.isSelectable(m_defaultMatcher)) {
136                 throw new ConfigurationException("Default matcher is not defined.");
137             }
138             m_manager.put(Matcher.ROLE+"Selector", matcherSelector);
139         }
140
141         // selectors
142
child = components.getChild("selectors",false);
143         if (child != null) {
144             final DefaultServiceSelector selectorSelector = new DefaultServiceSelector();
145             m_defaultSelector = child.getAttribute("default");
146             final Configuration[] selectors = child.getChildren("selector");
147             for (int i = 0; i < selectors.length; i++) {
148                 String JavaDoc name = selectors[i].getAttribute("name");
149                 String JavaDoc src = selectors[i].getAttribute("src");
150                 Selector selector = (Selector) createComponent(src,selectors[i]);
151                 selectorSelector.put(name,selector);
152             }
153             selectorSelector.makeReadOnly();
154             if (!selectorSelector.isSelectable(m_defaultSelector)) {
155                 throw new ConfigurationException("Default selector is not defined.");
156             }
157             m_manager.put(Selector.ROLE+"Selector",selectorSelector);
158         }
159
160         m_manager.makeReadOnly();
161
162         // locators
163
final Configuration[] children = configuration.getChildren("locator");
164         m_locatorNodes = new LocatorNode[children.length];
165         for (int i = 0; i < children.length; i++) {
166             m_locatorNodes[i] = new LocatorNode(this, m_manager);
167             m_locatorNodes[i].enableLogging(getLogger());
168             m_locatorNodes[i].build(children[i]);
169         }
170     }
171     
172     /**
173      * Creates a LocationMap component.
174      * <p>
175      * supported component creation lifecycles that are:
176      * - LogEnabled
177      * - Configurable
178      * - Initializable
179      * </p>
180      */

181     private Object JavaDoc createComponent(String JavaDoc src, Configuration config) throws ConfigurationException {
182         Object JavaDoc component = null;
183         try {
184             component = Class.forName(src).newInstance();
185             ContainerUtil.enableLogging(component,getLogger());
186             if (config != null) {
187                 ContainerUtil.configure(component, config);
188             }
189             ContainerUtil.initialize(component);
190         } catch (Exception JavaDoc e) {
191             throw new ConfigurationException("Couldn't create object of type " + src,e);
192         }
193         return component;
194     }
195     
196     public void dispose() {
197         final Iterator JavaDoc components = m_manager.getObjects();
198         while(components.hasNext()) {
199             ContainerUtil.dispose(components.next());
200         }
201         m_manager = null;
202         m_locatorNodes = null;
203     }
204     
205     /**
206      * Loop through the list of locator nodes invoking
207      * the <code>locate()</code> method on each and return
208      * the first non-null result.
209      */

210     public String JavaDoc locate(String JavaDoc hint, Map JavaDoc om) throws Exception JavaDoc {
211
212         String JavaDoc location = null;
213
214         final InvokeContext context = new InvokeContext();
215         final Logger contextLogger = getLogger().getChildLogger("ctx");
216
217         ContainerUtil.enableLogging(context, contextLogger);
218         ContainerUtil.compose(context, new WrapperComponentManager(m_manager));
219         ContainerUtil.service(context, m_manager);
220
221         final Map JavaDoc anchorMap = new HashMap JavaDoc(2);
222         anchorMap.put(HINT_KEY,hint);
223         context.pushMap(ANCHOR_NAME,anchorMap);
224
225         for (int i = 0; i < m_locatorNodes.length; i++) {
226             location = m_locatorNodes[i].locate(om,context);
227             if (location != null) {
228                 break;
229             }
230         }
231         
232         ContainerUtil.dispose(context);
233
234         if (getLogger().isDebugEnabled() && location == null) {
235             getLogger().debug("No location matched request with hint " + hint);
236         }
237
238         return location;
239     }
240     
241     /**
242      * Expose the default Matcher to LocatorNodes
243      */

244     String JavaDoc getDefaultMatcher() {
245         return m_defaultMatcher;
246     }
247     
248     /**
249      * Expose the default Selector to LocatorNodes
250      */

251     String JavaDoc getDefaultSelector() {
252         return m_defaultSelector;
253     }
254     
255     /**
256      * Overide DefaultComponentManager to access the list of all
257      * components.
258      */

259     private static class LocationMapServiceManager extends DefaultServiceManager {
260         
261         LocationMapServiceManager(ServiceManager parent) {
262             super(parent);
263         }
264         
265         Iterator JavaDoc getObjects() {
266             return super.getObjectMap().values().iterator();
267         }
268
269     }
270
271 }
272
Popular Tags