KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > portal > layout > impl > DefaultLayoutFactory


1 /*
2  * Copyright 1999-2002,2004 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.portal.layout.impl;
17
18 import java.util.ArrayList JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23
24 import org.apache.avalon.framework.CascadingRuntimeException;
25 import org.apache.avalon.framework.activity.Disposable;
26 import org.apache.avalon.framework.activity.Initializable;
27 import org.apache.avalon.framework.component.Component;
28 import org.apache.avalon.framework.configuration.Configurable;
29 import org.apache.avalon.framework.configuration.Configuration;
30 import org.apache.avalon.framework.configuration.ConfigurationException;
31 import org.apache.avalon.framework.logger.AbstractLogEnabled;
32 import org.apache.avalon.framework.service.ServiceException;
33 import org.apache.avalon.framework.service.ServiceManager;
34 import org.apache.avalon.framework.service.ServiceSelector;
35 import org.apache.avalon.framework.service.Serviceable;
36 import org.apache.avalon.framework.thread.ThreadSafe;
37 import org.apache.cocoon.ProcessingException;
38 import org.apache.cocoon.portal.PortalComponentManager;
39 import org.apache.cocoon.portal.PortalService;
40 import org.apache.cocoon.portal.aspect.AspectDataHandler;
41 import org.apache.cocoon.portal.aspect.AspectDataStore;
42 import org.apache.cocoon.portal.aspect.AspectDescription;
43 import org.apache.cocoon.portal.aspect.impl.DefaultAspectDataHandler;
44 import org.apache.cocoon.portal.aspect.impl.DefaultAspectDescription;
45 import org.apache.cocoon.portal.coplet.CopletFactory;
46 import org.apache.cocoon.portal.event.Event;
47 import org.apache.cocoon.portal.event.EventManager;
48 import org.apache.cocoon.portal.event.LayoutEvent;
49 import org.apache.cocoon.portal.event.Receiver;
50 import org.apache.cocoon.portal.event.impl.FullScreenCopletEvent;
51 import org.apache.cocoon.portal.event.impl.LayoutRemoveEvent;
52 import org.apache.cocoon.portal.layout.CompositeLayout;
53 import org.apache.cocoon.portal.layout.Item;
54 import org.apache.cocoon.portal.layout.Layout;
55 import org.apache.cocoon.portal.layout.LayoutFactory;
56 import org.apache.cocoon.portal.layout.renderer.Renderer;
57 import org.apache.cocoon.portal.profile.ProfileManager;
58 import org.apache.cocoon.util.ClassUtils;
59
60 /**
61  *
62  * <h2>Configuration</h2>
63  * <table><tbody>
64  * <tr><th>layouts</th>
65  * <td>List of layouts.</td>
66  * <td>req</td>
67  * <td>Configuration</td>
68  * <td><code>null</code></td>
69  * </tr>
70  * <tr>
71  * <th>layouts/layout</th>
72  * <td>Multiple configured layouts.
73  * </td>
74  * <td>req</td>
75  * <td>Configuration</td>
76  * <td><code>null</code></td>
77  * </tr>
78  * <tr>
79  * <th>layouts/layout/attribute::name</th>
80  * <td>Unique layout name.</td>
81  * <td>req</td>
82  * <td>String</td>
83  * <td><code>null</code></td>
84  * </tr>
85  * <tr>
86  * <th>layouts/layout/attribute::create-id</th>
87  * <td></td>
88  * <td></td>
89  * <td>boolean</td>
90  * <td><code>false</code></td>
91  * </tr>
92  * <tr>
93  * <th>layouts/layout/renderers/attribute::default</th>
94  * <td></td>
95  * <td>req</td>
96  * <td>String</td>
97  * <td><code>null</code></td>
98  * </tr>
99  * <tr>
100  * <th>layouts/layout/renderers/renderer</th>
101  * <td></td>
102  * <td>req</td>
103  * <td>Configuration</td>
104  * <td><code>null</code></td>
105  * </tr>
106  * <tr>
107  * <th>layouts/layout/renderers/renderer/attribute::name</th>
108  * <td></td>
109  * <td>req</td>
110  * <td>String</td>
111  * <td><code>null</code></td>
112  * </tr>
113  * <tr>
114  * <th>layouts/layout/aspects/aspect</th>
115  * <td></td>
116  * <td>req</td>
117  * <td>String</td>
118  * <td><code>null</code></td>
119  * </tr>
120  * </tbody></table>
121  *
122  * @author <a HREF="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
123  * @author <a HREF="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
124  *
125  * @version CVS $Id: DefaultLayoutFactory.java 327158 2005-10-21 12:03:28Z cziegeler $
126  */

127 public class DefaultLayoutFactory
128     extends AbstractLogEnabled
129     implements ThreadSafe,
130                  Component,
131                  LayoutFactory,
132                  Configurable,
133                  Disposable,
134                  Serviceable,
135                  Initializable,
136                  Receiver {
137
138     protected Map JavaDoc layouts = new HashMap JavaDoc();
139     
140     protected List JavaDoc descriptions = new ArrayList JavaDoc();
141     
142     protected ServiceSelector storeSelector;
143     
144     protected ServiceManager manager;
145     
146     protected Configuration[] layoutsConf;
147
148     protected static long idCounter = System.currentTimeMillis();
149
150     /* (non-Javadoc)
151      * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
152      */

153     public void service(ServiceManager manager) throws ServiceException {
154         this.manager = manager;
155         this.storeSelector = (ServiceSelector)this.manager.lookup( AspectDataStore.ROLE+"Selector" );
156     }
157
158     /**
159      * Configure a layout
160      */

161     protected void configureLayout(Configuration layoutConf)
162     throws ConfigurationException {
163         DefaultLayoutDescription desc = new DefaultLayoutDescription();
164         final String JavaDoc name = layoutConf.getAttribute("name");
165                 
166         // unique test
167
if ( this.layouts.get(name) != null) {
168             throw new ConfigurationException("Layout name must be unique. Double definition for " + name);
169         }
170         desc.setName(name);
171         desc.setClassName(layoutConf.getAttribute("class"));
172         desc.setCreateId(layoutConf.getAttributeAsBoolean("create-id", false));
173         desc.setItemClassName(layoutConf.getAttribute("item-class", null));
174
175         // the renderers
176
final String JavaDoc defaultRenderer = layoutConf.getChild("renderers").getAttribute("default");
177         desc.setDefaultRendererName(defaultRenderer);
178                                 
179         final Configuration[] rendererConfs = layoutConf.getChild("renderers").getChildren("renderer");
180         if ( rendererConfs != null ) {
181             boolean found = false;
182             for(int m=0; m < rendererConfs.length; m++) {
183                 final String JavaDoc rName = rendererConfs[m].getAttribute("name");
184                 desc.addRendererName(rName);
185                 if ( defaultRenderer.equals(rName) ) {
186                     found = true;
187                 }
188             }
189             if ( !found ) {
190                 throw new ConfigurationException("Default renderer '" + defaultRenderer + "' is not configured for layout '" + name + "'");
191             }
192         } else {
193             throw new ConfigurationException("Default renderer '" + defaultRenderer + "' is not configured for layout '" + name + "'");
194         }
195         
196         // and now the aspects
197
final Configuration[] aspectsConf = layoutConf.getChild("aspects").getChildren("aspect");
198         if (aspectsConf != null) {
199             for(int m=0; m < aspectsConf.length; m++) {
200                 AspectDescription adesc = DefaultAspectDescription.newInstance(aspectsConf[m]);
201                 desc.addAspectDescription( adesc );
202             }
203         }
204         // now query all configured renderers for their aspects
205
PortalService service = null;
206         try {
207             service = (PortalService)this.manager.lookup(PortalService.ROLE);
208             PortalComponentManager pcManager = service.getComponentManager();
209             
210             Iterator JavaDoc rendererIterator = desc.getRendererNames();
211             while (rendererIterator.hasNext()) {
212                 final String JavaDoc rendererName = (String JavaDoc)rendererIterator.next();
213                 Renderer renderer = pcManager.getRenderer( rendererName );
214                 
215                 Iterator JavaDoc aspectIterator = renderer.getAspectDescriptions();
216                 while (aspectIterator.hasNext()) {
217                     final AspectDescription adesc = (AspectDescription) aspectIterator.next();
218                     desc.addAspectDescription( adesc );
219                 }
220             }
221         } catch (ServiceException ce ) {
222             throw new ConfigurationException("Unable to lookup renderer selector.", ce);
223         } finally {
224             this.manager.release( service );
225         }
226         
227         // set the aspect data handler
228
DefaultAspectDataHandler handler = new DefaultAspectDataHandler(desc, this.storeSelector);
229         this.layouts.put(desc.getName(), new Object JavaDoc[] {desc, handler});
230         this.descriptions.add(desc);
231     }
232
233     /* (non-Javadoc)
234      * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
235      */

236     public void configure(Configuration configuration)
237     throws ConfigurationException {
238         this.layoutsConf = configuration.getChild("layouts").getChildren("layout");
239     }
240
241     protected void init() {
242         // FIXME when we switch to another container we can remove
243
// the lazy evaluation
244
if ( this.layoutsConf != null ) {
245             synchronized (this) {
246                 if ( this.layoutsConf != null ) {
247                     for(int i=0; i < layoutsConf.length; i++ ) {
248                         try {
249                             this.configureLayout( layoutsConf[i] );
250                         } catch (ConfigurationException ce) {
251                             throw new CascadingRuntimeException("Unable to configure layout.", ce);
252                         }
253                     }
254                     this.layoutsConf = null;
255                 }
256             }
257         }
258     }
259     
260     /* (non-Javadoc)
261      * @see org.apache.cocoon.portal.layout.LayoutFactory#prepareLayout(org.apache.cocoon.portal.layout.Layout)
262      */

263     public void prepareLayout(Layout layout)
264     throws ProcessingException {
265         if ( layout != null ) {
266             
267             this.init();
268      
269             final String JavaDoc layoutName = layout.getName();
270             if ( layoutName == null ) {
271                 throw new ProcessingException("Layout '"+layout.getId()+"' has no associated name.");
272             }
273             Object JavaDoc[] o = (Object JavaDoc[]) this.layouts.get( layoutName );
274             
275             if ( o == null ) {
276                 throw new ProcessingException("LayoutDescription with name '" + layoutName + "' not found.");
277             }
278             DefaultLayoutDescription layoutDescription = (DefaultLayoutDescription)o[0];
279
280             layout.setDescription( layoutDescription );
281             layout.setAspectDataHandler((AspectDataHandler)o[1]);
282
283             // recursive
284
if ( layout instanceof CompositeLayout ) {
285                 CompositeLayout composite = (CompositeLayout)layout;
286                 composite.setItemClassName(layoutDescription.getItemClassName());
287                 
288                 Iterator JavaDoc items = composite.getItems().iterator();
289                 while ( items.hasNext() ) {
290                     this.prepareLayout( ((Item)items.next()).getLayout() );
291                 }
292             }
293         }
294     }
295
296     /* (non-Javadoc)
297      * @see org.apache.cocoon.portal.layout.LayoutFactory#newInstance(java.lang.String)
298      */

299     public Layout newInstance(String JavaDoc layoutName)
300     throws ProcessingException {
301         this.init();
302         
303         Object JavaDoc[] o = (Object JavaDoc[]) this.layouts.get( layoutName );
304             
305         if ( o == null ) {
306             throw new ProcessingException("LayoutDescription with name '" + layoutName + "' not found.");
307         }
308         DefaultLayoutDescription layoutDescription = (DefaultLayoutDescription)o[0];
309         
310         Layout layout = null;
311         try {
312             Class JavaDoc clazz = ClassUtils.loadClass( layoutDescription.getClassName() );
313             layout = (Layout)clazz.newInstance();
314             
315         } catch (Exception JavaDoc e) {
316             throw new ProcessingException("Unable to create new instance", e );
317         }
318         
319         String JavaDoc id = null;
320         if ( layoutDescription.createId() ) {
321             synchronized (this) {
322                 id = layoutName + '-' + idCounter;
323                 idCounter += 1;
324             }
325         }
326         layout.initialize( layoutName, id );
327         layout.setDescription( layoutDescription );
328         layout.setAspectDataHandler((AspectDataHandler)o[1]);
329
330         if ( layout instanceof CompositeLayout ) {
331             CompositeLayout composite = (CompositeLayout)layout;
332             composite.setItemClassName(layoutDescription.getItemClassName());
333         }
334         
335         PortalService service = null;
336         try {
337             service = (PortalService)this.manager.lookup(PortalService.ROLE);
338             service.getComponentManager().getProfileManager().register(layout);
339         } catch (ServiceException ce) {
340             throw new ProcessingException("Unable to lookup profile manager.", ce);
341         } finally {
342             this.manager.release( service );
343         }
344         return layout;
345     }
346     
347     /* (non-Javadoc)
348      * @see org.apache.cocoon.portal.layout.LayoutFactory#getLayoutDescriptions()
349      */

350     public List JavaDoc getLayoutDescriptions() {
351         this.init();
352         return this.descriptions;
353     }
354
355
356     /* (non-Javadoc)
357      * @see org.apache.avalon.framework.activity.Disposable#dispose()
358      */

359     public void dispose() {
360         if ( this.manager != null ) {
361             EventManager eventManager = null;
362             try {
363                 eventManager = (EventManager)this.manager.lookup(EventManager.ROLE);
364                 eventManager.unsubscribe( this );
365             } catch (Exception JavaDoc ignore) {
366                 // ignore
367
} finally {
368                 this.manager.release( eventManager );
369             }
370             this.manager.release( this.storeSelector );
371             this.storeSelector = null;
372             this.manager = null;
373         }
374
375     }
376
377     /* (non-Javadoc)
378      * @see org.apache.avalon.framework.activity.Initializable#initialize()
379      */

380     public void initialize() throws Exception JavaDoc {
381         EventManager eventManager = null;
382         try {
383             eventManager = (EventManager)this.manager.lookup(EventManager.ROLE);
384             eventManager.subscribe( this );
385         } finally {
386             this.manager.release( eventManager );
387         }
388     }
389
390     /**
391      * @see Receiver
392      */

393     public void inform(LayoutEvent event, PortalService service) {
394         Layout layout = (Layout)event.getTarget();
395         if ( event instanceof LayoutRemoveEvent ) {
396             try {
397                 this.remove( layout );
398             } catch (ProcessingException pe) {
399                 throw new CascadingRuntimeException("Exception during removal.", pe);
400             }
401         }
402     }
403
404     /* (non-Javadoc)
405      * @see org.apache.cocoon.portal.layout.LayoutFactory#remove(org.apache.cocoon.portal.layout.Layout)
406      */

407     public void remove(Layout layout)
408     throws ProcessingException {
409         if ( layout != null ) {
410             this.init();
411             if ( layout instanceof CompositeLayout ) {
412                 final CompositeLayout cl = (CompositeLayout)layout;
413                 while ( cl.getItems().size() > 0 ) {
414                     final Item i = cl.getItem(0);
415                     this.remove( i.getLayout() );
416                 }
417             }
418             Item parent = layout.getParent();
419             if ( parent != null && parent.getParent() != null) {
420                 parent.getParent().removeItem( parent );
421             }
422             
423             PortalService service = null;
424             EventManager eventManager = null;
425             try {
426                 service = (PortalService)this.manager.lookup(PortalService.ROLE);
427                 ProfileManager profileManager = service.getComponentManager().getProfileManager();
428                 if ( layout instanceof CopletLayout ) {
429                     // full screen?
430
if ( layout.equals(service.getEntryLayout(null)) ) {
431                         Event event = new FullScreenCopletEvent(((CopletLayout)layout).getCopletInstanceData(), null);
432                         eventManager = (EventManager)this.manager.lookup(EventManager.ROLE);
433                         eventManager.send(event);
434                         service.getComponentManager().getLinkService().addEventToLink(event);
435                     }
436                     CopletFactory factory = service.getComponentManager().getCopletFactory();
437                     factory.remove( ((CopletLayout)layout).getCopletInstanceData());
438                 }
439                 profileManager.unregister(layout);
440             } catch (ServiceException ce) {
441                 throw new ProcessingException("Unable to lookup portal service.", ce);
442             } finally {
443                 this.manager.release( service );
444                 this.manager.release(eventManager);
445             }
446         }
447     }
448 }
449
Popular Tags