1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.objectledge.web.mvc.finders;
29
30 import java.util.HashMap;
31
32 import org.jcontainer.dna.Logger;
33 import org.objectledge.pipeline.Valve;
34 import org.objectledge.templating.Template;
35 import org.objectledge.templating.TemplateNotFoundException;
36 import org.objectledge.templating.Templating;
37 import org.objectledge.web.mvc.builders.Builder;
38 import org.objectledge.web.mvc.components.Component;
39 import org.picocontainer.MutablePicoContainer;
40
41 /***
42 * Implementation of MVC finding services.
43 *
44 * @author <a href="mailto:dgajda@caltha.pl">Damian Gajda</a>
45 * @version $Id: MVCFinder.java,v 1.36 2005/07/29 11:57:18 rafal Exp $
46 */
47 public class MVCFinder implements MVCTemplateFinder, MVCClassFinder
48 {
49 /***
50 * Different kinds of UI elements handled by the finder.
51 */
52 protected enum Kind
53 {
54 /*** View element. */
55 VIEW("views"),
56 /*** Action element. */
57 ACTION("actions"),
58 /*** Component element. */
59 COMPONENT("components");
60
61 private Kind(String infix)
62 {
63 this.infix = infix;
64 }
65
66 private final String infix;
67
68 /***
69 * Returns the path infix used by name sequences.
70 *
71 * @return the path infix used by name sequences.
72 */
73 public String getInfix()
74 {
75 return infix;
76 }
77 }
78
79 /**/package-summary/html">Internal constant for choosing "views" package name part/ *//package-summary.html">* /package-summary.html">Internal constant for choosing "views" package name part. */
80 private static final String VIEWS = "views";
81 /**/package-summary/html">Internal constant for choosing "actions" package name part/ *//package-summary.html">* /package-summary.html">Internal constant for choosing "actions" package name part. */
82 private static final String ACTIONS = "actions";
83 /**/package-summary/html">Internal constant for choosing "components" package name part/ *//package-summary.html">* /package-summary.html">Internal constant for choosing "components" package name part. */
84 private static final String COMPONENTS = "components";
85
86 private MutablePicoContainer container;
87
88 /*** the logger. */
89 private Logger logger;
90
91 /*** The Templating component. */
92 private Templating templating;
93
94 /*** The name sequence factory. */
95 private NameSequenceFactory nameSequenceFactory;
96
97 /*** The class instances cache */
98 private HashMap<String, Object> classInstanceCache = new HashMap<String, Object>();
99
100 /*** Special marker object for the classInstanceCache */
101 private static final Object MISSING = new Object();
102
103 /***
104 * Creates a MVCFinder component.
105 *
106 * @param container the container to store loaded classes.
107 * @param logger the logger to use.
108 * @param templating the templating component.
109 * @param nameSequenceFactory the name sequence factory component.
110 */
111 public MVCFinder(MutablePicoContainer container, Logger logger, Templating templating,
112 NameSequenceFactory nameSequenceFactory)
113 {
114 this.container = container;
115 this.logger = logger;
116 this.templating = templating;
117 this.nameSequenceFactory = nameSequenceFactory;
118 }
119
120
121
122
123
124 /***
125 * {@inheritDoc}
126 */
127 public MVCTemplateFinder.Result findBuilderTemplate(String view)
128 {
129 return findBuilderTemplate(view, "findBuilderTemplate");
130 }
131
132
133
134 /***
135 * {@inheritDoc}
136 */
137 public Template getComponentTemplate(String name)
138 {
139 return findTemplate(Kind.COMPONENT, name, false, "getComponentTemplate");
140 }
141
142
143
144 /***
145 * {@inheritDoc}
146 */
147 public Valve getAction(String actionName)
148 {
149 return (Valve)findObject(Kind.ACTION, actionName, false, "getAction");
150 }
151
152
153
154 /***
155 * {@inheritDoc}
156 */
157 public MVCClassFinder.Result findBuilder(String view)
158 {
159 return findBuilder(view, "findBuilder");
160 }
161
162 /***
163 * {@inheritDoc}
164 */
165 public String findEnclosingViewName(String viewName)
166 {
167 if(viewName != null && viewName.length() != 0)
168 {
169 Sequence classSequence = nameSequenceFactory.
170 getClassNameSequence(VIEWS, viewName, true, true);
171
172 Sequence templateSequence = nameSequenceFactory.
173 getTemplateNameSequence(VIEWS, viewName, true, true);
174
175 while(classSequence.hasNext() && templateSequence.hasNext())
176 {
177 String className = classSequence.next();
178 String templateName = templateSequence.next();
179 logger.debug("findEnclosingViewName: trying "+className+" and "+templateName);
180
181 if(getClassInstance(className) != null)
182 {
183 break;
184 }
185
186 if(templating.templateExists(templateName))
187 {
188 break;
189 }
190 }
191
192 String classSequenceViewName = classSequence.currentView();
193 String templateSequenceViewName = templateSequence.currentView();
194 if((classSequenceViewName == templateSequenceViewName)
195 || classSequenceViewName.equals(templateSequenceViewName))
196 {
197 return classSequenceViewName;
198 }
199 else
200 {
201 throw new IllegalStateException("Sequences produced different view names: "+
202 classSequenceViewName+" (class sequence) "+
203 templateSequenceViewName+" (template sequence)");
204 }
205 }
206 return null;
207 }
208
209
210
211 /***
212 * {@inheritDoc}
213 */
214 public Component getComponent(String componentName)
215 {
216 return (Component)
217 findObject(Kind.COMPONENT, componentName, false, "getComponent");
218 }
219
220
221
222 private Template findTemplate(Kind kind, String templateName, boolean fallback,
223 String methodName)
224 {
225 if(templateName != null && templateName.length() != 0)
226 {
227 Sequence sequence = getTemplateNameSequence(kind, templateName, fallback, false);
228 while(sequence.hasNext())
229 {
230 String name = sequence.next();
231 logger.debug(methodName+": trying "+name);
232 if(templating.templateExists(name))
233 {
234 try
235 {
236 return templating.getTemplate(name);
237 }
238 catch(TemplateNotFoundException e)
239 {
240 throw new IllegalStateException("Existing template disappeared", e);
241 }
242 }
243 }
244 }
245 return null;
246 }
247
248 private MVCTemplateFinder.Result findBuilderTemplate(String templateName, String methodName)
249 {
250 if(templateName != null && templateName.length() != 0)
251 {
252 Sequence sequence = getTemplateNameSequence(Kind.VIEW, templateName, true, false);
253 while(sequence.hasNext())
254 {
255 String name = sequence.next();
256 logger.debug(methodName+": trying "+name);
257 if(templating.templateExists(name))
258 {
259 try
260 {
261 Template template = templating.getTemplate(name);
262 return new MVCTemplateFinder.Result(
263 templateName, template, sequence.currentView());
264 }
265 catch(TemplateNotFoundException e)
266 {
267 throw new IllegalStateException("Existing template disappeared", e);
268 }
269 }
270 }
271 return new MVCTemplateFinder.Result(templateName, null, sequence.currentView());
272 }
273 return new MVCTemplateFinder.Result(templateName, null, null);
274 }
275
276 /***
277 * Return a template lookup sequence.
278 *
279 * @param kind the kind of template being looked up.
280 * @param templateName the view name.
281 * @param fallback perform fallback.
282 * @param enclosing obsolete paramter.
283 * @return a lookup sequence.
284 */
285 protected Sequence getTemplateNameSequence(Kind kind, String templateName,
286 boolean fallback, boolean enclosing)
287 {
288 return nameSequenceFactory.
289 getTemplateNameSequence(kind.getInfix(), templateName, fallback, enclosing);
290 }
291
292 private Object findObject(Kind kind, String className, boolean fallback, String methodName)
293 {
294 if(className != null && className.length() != 0)
295 {
296 Sequence sequence = nameSequenceFactory.
297 getClassNameSequence(kind.getInfix(), className, fallback, false);
298 while(sequence.hasNext())
299 {
300 String name = sequence.next();
301 logger.debug(methodName+": trying "+name);
302 Object obj = getClassInstance(name);
303 if(obj != null)
304 {
305 return obj;
306 }
307 }
308 }
309 return null;
310 }
311
312 private MVCClassFinder.Result findBuilder(String className, String methodName)
313 {
314 if(className != null && className.length() != 0)
315 {
316 Sequence sequence = nameSequenceFactory.
317 getClassNameSequence(Kind.VIEW.getInfix(), className, true, false);
318 while(sequence.hasNext())
319 {
320 String name = sequence.next();
321 logger.debug(methodName+": trying "+name);
322 Object obj = getClassInstance(name);
323 if(obj != null)
324 {
325 return new MVCClassFinder.Result(className, (Builder)obj, sequence
326 .currentView());
327 }
328 }
329 return new MVCClassFinder.Result(className, (Builder) null, sequence.currentView());
330 }
331 return new MVCClassFinder.Result(className, (Builder) null, null);
332 }
333
334 private Object getClassInstance(String className)
335 {
336 Object instance;
337 synchronized(classInstanceCache)
338 {
339 instance = classInstanceCache.get(className);
340 if(instance == MISSING)
341 {
342 return null;
343 }
344 if(instance == null)
345 {
346 try
347 {
348 Class clazz = Class.forName(className);
349 if(container.getComponentAdapter(clazz) == null)
350 {
351 container.registerComponentImplementation(clazz);
352 }
353 instance = container.getComponentInstance(clazz);
354 classInstanceCache.put(className, instance);
355 }
356 catch(ClassNotFoundException e)
357 {
358 classInstanceCache.put(className, MISSING);
359 return null;
360 }
361 }
362 return instance;
363 }
364 }
365 }