KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jetspeed > services > portletfactory > JetspeedPortletFactoryService


1 /*
2  * Copyright 2000-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
17 package org.apache.jetspeed.services.portletfactory;
18
19 //jetspeed stuff
20
import org.apache.jetspeed.portal.Portlet;
21 import org.apache.jetspeed.portal.PortletConfig;
22 import org.apache.jetspeed.portal.PortletException;
23 import org.apache.jetspeed.portal.BasePortletConfig;
24
25 import org.apache.jetspeed.portal.security.portlets.PortletWrapper;
26
27 import org.apache.jetspeed.om.SecurityReference;
28 import org.apache.jetspeed.om.profile.Entry;
29 import org.apache.jetspeed.om.profile.Parameter;
30 import org.apache.jetspeed.om.profile.MetaInfo;
31 import org.apache.jetspeed.services.JetspeedSecurity;
32 import org.apache.jetspeed.services.Registry;
33 import org.apache.jetspeed.services.PortalToolkit;
34 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
35 import org.apache.jetspeed.services.logging.JetspeedLogger;
36 import org.apache.jetspeed.services.portletcache.PortletCache;
37 import org.apache.jetspeed.services.portletcache.Cacheable;
38 import org.apache.jetspeed.om.registry.PortletEntry;
39 import org.apache.jetspeed.om.profile.Profile;
40 import org.apache.jetspeed.util.MetaData;
41 import org.apache.jetspeed.services.rundata.JetspeedRunDataService;
42 import org.apache.jetspeed.services.rundata.JetspeedRunData;
43
44 import org.apache.turbine.services.TurbineServices;
45 import org.apache.turbine.services.TurbineBaseService;
46 import org.apache.turbine.services.InitializationException;
47 import org.apache.turbine.services.resources.ResourceService;
48 import org.apache.turbine.services.rundata.RunDataService;
49
50 import java.util.Hashtable JavaDoc;
51 import java.util.Iterator JavaDoc;
52 import java.util.Map JavaDoc;
53 import java.util.HashMap JavaDoc;
54 import javax.servlet.ServletConfig JavaDoc;
55
56 /**
57  * Simple implementation of the PortalFactoryService.
58  *
59  * @author <a HREF="mailto:raphael@apache.org">Raphaël Luta</a>
60  * @author <a HREF="mailto:weaver@apache.org">Scott T. Weaver</a>
61  * @version $Id: JetspeedPortletFactoryService.java,v 1.23 2004/02/23 03:36:42 jford Exp $
62  */

63 public class JetspeedPortletFactoryService extends TurbineBaseService
64     implements PortletFactoryService
65 {
66     /**
67      * Static initialization of the logger for this class
68      */

69     private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedPortletFactoryService.class.getName());
70     
71     /** The default control to use when none is specified */
72     private boolean enableCache = false;
73
74     /** The JetspeedRunData Service. */
75     private JetspeedRunDataService runDataService = null;
76     
77     /**
78      * This is the early initialization method called by the
79      * Turbine <code>Service</code> framework
80      */

81     public void init( ServletConfig JavaDoc conf ) throws InitializationException
82     {
83
84         ResourceService serviceConf = ((TurbineServices)TurbineServices.getInstance())
85                                                      .getResources(PortletFactoryService.SERVICE_NAME);
86
87         this.enableCache = serviceConf.getBoolean("enable.cache",true);
88         
89         // get the runData service
90
this.runDataService =
91             (JetspeedRunDataService)TurbineServices.getInstance()
92                 .getService(RunDataService.SERVICE_NAME);
93
94         setInit(true);
95     }
96             
97     /**
98      * Given a PSML Entry return an instanciated Portlet.
99      *
100      * @param entry a PSML Entry describing a portlet
101      * @param id the PSML entry's portlet id
102      * @return an instanciated portlet corresponding to this entry
103      */

104     public Portlet getPortlet( Entry entry ) throws PortletException
105     {
106         PortletEntry regEntry = (PortletEntry)Registry.getEntry(Registry.PORTLET,
107                                                                 entry.getParent() );
108         if (regEntry == null)
109         {
110             throw new PortletException("PortletFactory: unknown portlet entry in Registry: "+entry.getParent());
111         }
112         
113         if (PortletEntry.TYPE_ABSTRACT.equals(regEntry.getType()))
114         {
115             throw new PortletException("PortletFactory: can't instanciate abstract registry entry: "+regEntry.getName());
116         }
117             
118         PortletConfig pc = getPortletConfig(regEntry, entry.getId());
119
120         // Set portlet config with values from PSML Entry
121
pc.getInitParameters().putAll(getParameters(entry));
122         pc.setPortletSkin( PortalToolkit.getSkin( entry.getSkin() ) );
123         pc.setSecurityRef( getSecurityReference(entry, regEntry));
124
125         return getPortlet( getClassname(regEntry), pc, entry.getId() );
126     }
127
128     /**
129      * Given a Portlet registry entry name, instanciate it
130      *
131      * @param name the name of a portlet in the registry
132      * @return an instanciated portlet corresponding to this entry
133      */

134     public Portlet getPortlet( String JavaDoc name, String JavaDoc id ) throws PortletException
135     {
136         PortletEntry regEntry = (PortletEntry)Registry.getEntry(Registry.PORTLET, name );
137
138         if (regEntry == null)
139         {
140             throw new PortletException("PortletFactory: unknown portlet entry in Registry: "+name);
141         }
142         
143         if (PortletEntry.TYPE_ABSTRACT.equals(regEntry.getType()))
144         {
145             throw new PortletException("PortletFactory: can't instanciate abstract registry entry: "+name);
146         }
147             
148         PortletConfig pc = getPortletConfig(regEntry, id);
149         
150         return getPortlet( getClassname(regEntry), pc, null );
151     }
152     
153     /**
154      * Instanciates or retrieve from memory cache a portlet corresponding to the
155      * passed parameters
156      *
157      * @param classname the classname of the portlet to instanciate
158      * @param pc the PortletConfig object to be associated with this object
159      * @param id the PSML entry's portlet id
160      * @return the Portlet created or retrieve from cache
161      */

162     protected Portlet getPortlet( String JavaDoc classname, PortletConfig pc, String JavaDoc id )
163         throws PortletException
164     {
165
166         //record the begining of the portlet creation
167
long begin = System.currentTimeMillis();
168
169         Portlet portlet = null;
170         Class JavaDoc portletClass = null;
171         String JavaDoc handle = null;
172         
173         try
174         {
175             portletClass = Class.forName(classname);
176         }
177         catch (Exception JavaDoc e)
178         {
179             throw new PortletException( "PortletFactory: Unable to load class " + classname );
180         }
181         
182         if (enableCache)
183         {
184             try
185             {
186                 // try to invoke a static getHandle() for this class
187
Class JavaDoc[] signatureParams = { Object JavaDoc.class };
188                 Object JavaDoc[] methodParams = { pc };
189                 handle = (String JavaDoc)portletClass.getMethod("getHandle",signatureParams)
190                                              .invoke(null,methodParams);
191                 // make sure the handle is differenciated by class
192
handle = String.valueOf(classname.hashCode())+handle;
193             }
194             catch (NoSuchMethodException JavaDoc e)
195             {
196                 // ignore, this simply means the portlet is not cacheable
197
}
198             catch (Exception JavaDoc e)
199             {
200                 // invocation failed or security exception, in both case
201
// log the error and treat the class as non cacheable
202
logger.error("PortletFactory: failed to get cache handle",e);
203             }
204         }
205         
206         try {
207
208             if (enableCache && (handle != null))
209             {
210                 portlet = (Portlet)PortletCache.getCacheable( handle );
211
212                 //portlet in cache but expired, remove it from cache
213
if ((portlet!=null) && ((Cacheable)portlet).getExpire().isExpired() )
214                 {
215                     logger.info( "The portlet (" + handle + ") is expired" );
216                     PortletCache.removeCacheable(handle);
217                     if ( logger.isDebugEnabled() )
218                     {
219                         logger.debug( "After removal of object(" + handle + ")." );
220                     }
221                     portlet = null;
222                 }
223             }
224
225             // we found a portlet in the cache
226
if ( (portlet != null)
227                  && ( portlet instanceof Cacheable )
228                  && (! ((Cacheable)portlet).getExpire().isExpired()) )
229             {
230                 // update the config for the portlet to the current one
231
// Note: this is what was used to find the cached portlet.
232
// Note: the init params may have changed in the psml since caching,
233
// this will update the portlet to use them.
234
portlet.setPortletConfig( pc );
235                 portlet.setID( id );
236                 portlet.setName( pc.getName() );
237
238                 //FIXME: we now avoid to override metainfo when nothing is set
239
//in the markup, so that cached portlets can keep their metainfo
240
//This may lead to an incorrect metainfo retrieved if the first
241
//instance of the portlet, which is put in the cache, has some
242
//special metainfo defined in the markup
243

244                 MetaData meta = pc.getMetainfo();
245                 
246                 if ( meta != null)
247                 {
248
249                     if (! MetaData.DEFAULT_TITLE.equals( meta.getTitle() ) )
250                     {
251                         portlet.setTitle( meta.getTitle() );
252                     }
253     
254                     if (! MetaData.DEFAULT_DESCRIPTION.equals( meta.getDescription() ) )
255                     {
256                         portlet.setDescription( meta.getDescription() );
257                     }
258                 }
259
260                 //FIXME: Notice here we are putting the portlet without wrapper
261
//in the cache, and we must wrap it on return.
262
//Security implications: the portletcache should not be
263
//publicly accessible.
264
//Alternative: we could wrap the portlet before putting
265
//it in the cache.
266

267                 //now compute the time it took to instantate and log it...
268
// time in millis, sugested by Thomas Schaeck (schaeck@de.ibm.com)
269
long milliseconds = ( System.currentTimeMillis() - begin );
270         
271                 if (logger.isDebugEnabled())
272                     logger.debug( "PortletFactory.getPortlet(): found in cache in "
273                         + milliseconds + " ms - handle: " + handle );
274
275                 return PortletWrapper.wrap( portlet );
276             }
277
278             // if not found in the cache, instanciate a new Portlet
279
portlet = (Portlet)portletClass.newInstance();
280
281         }
282         catch ( Throwable JavaDoc t )
283         {
284             logger.error("Throwable", t);
285             throw new PortletException( t.getMessage() );
286         }
287
288         // save the current meta-info
289
String JavaDoc title = null;
290         String JavaDoc description = null;
291         MetaData metainfo = pc.getMetainfo();
292         
293         if ( metainfo != null ) {
294             title=metainfo.getTitle();
295             description=metainfo.getDescription();
296         }
297         
298         
299         // init the portlet, it may override its PSML defined markup if
300
// it doesn't check for it
301
portlet.setID( id );
302         portlet.setName( pc.getName() );
303         portlet.setPortletConfig( pc );
304         portlet.setCreationTime( System.currentTimeMillis() );
305         portlet.init();
306
307         //force the title and description from markup metadata
308
//in case the portlet overwrote some values
309

310         if ( metainfo != null)
311         {
312             if (!MetaData.DEFAULT_TITLE.equals(title) )
313             {
314                 portlet.setTitle( title );
315             }
316
317             if (!MetaData.DEFAULT_DESCRIPTION.equals(description) )
318             {
319                 portlet.setDescription( description );
320             }
321         }
322
323         if (enableCache && (portlet instanceof Cacheable))
324         {
325             //place this portlet in a cache...
326
((Cacheable)portlet).setHandle( handle );
327             PortletCache.addCacheable( ((Cacheable)portlet) );
328             //Expiration should be added to the portlet now, so that
329
//the watcher is created before file changes on disk.
330
((Cacheable)portlet).getExpire();
331
332         }
333
334         //now compute the time it took to instantate and log it...
335
// time in millis, sugested by Thomas Schaeck (schaeck@de.ibm.com)
336
long milliseconds = ( System.currentTimeMillis() - begin );
337
338         if (logger.isDebugEnabled())
339             logger.debug( "PortletFactory.getPortlet(): constructed in "
340                 + milliseconds + " ms - handle: " + handle );
341
342         return PortletWrapper.wrap( portlet );
343
344     }
345
346     /**
347      * Given a Registry Entry, get the value of what its PortletConfig would be.
348      *
349      * @param entry the PSML Entry containing the config
350      * @param portletId the PSML entry's portlet id
351      * @return the newly created PortletConfig object
352      */

353     protected PortletConfig getPortletConfig( PortletEntry portletEntry, String JavaDoc id)
354     {
355         Map JavaDoc map = new HashMap JavaDoc();
356         map.putAll(portletEntry.getParameterMap());
357         
358         PortletConfig pc = new BasePortletConfig();
359         pc.setName( portletEntry.getName() );
360         addParentInitParameters(portletEntry, map);
361         pc.setInitParameters( map );
362         pc.setMetainfo( getMetaData( portletEntry ) );
363         pc.setURL( portletEntry.getURL() );
364         pc.setCachedOnURL( portletEntry.isCachedOnURL() );
365         //pc.setSecurityRef(portletEntry.getSecurityRef());
366
pc.setSecurityRef(getSecurityReference(null, portletEntry));
367
368         if (runDataService != null)
369         {
370             JetspeedRunData rundata = runDataService.getCurrentRunData();
371             if (rundata != null)
372             {
373                 Profile profile = rundata.getProfile();
374                 if (profile != null)
375                 {
376                     pc.setPageId(profile.getId());
377                 }
378             }
379         }
380         pc.setPortletId(id);
381
382         return pc;
383     }
384     
385     
386     /**
387      * Fetches the parameters out of a PSML Entry
388      *
389      * @param entry the Entry to check for parameters
390      * @return a Map containing the parameters names/values, an empty Map
391      * is returned if there are no parameters
392      */

393     protected static Map JavaDoc getParameters( Entry entry )
394     {
395         Hashtable JavaDoc hash = new Hashtable JavaDoc();
396         
397         Parameter[] props = entry.getParameter();
398         
399         for(int i = 0; i < props.length; ++i)
400         {
401             hash.put(props[i].getName(), props[i].getValue() );
402         }
403         
404         return hash;
405     }
406
407     /**
408     Create a MetaData object from a PSML Metainfo object
409     
410     @param meta the Metainfo to copy
411
412     @return the new MetaData object, empty if meta is null
413     */

414     protected static MetaData getMetaData(Entry entry)
415     {
416         MetaData data = new MetaData();
417         MetaInfo meta = entry.getMetaInfo();
418
419         if ( meta != null )
420         {
421             if ( meta.getTitle() != null )
422                 data.setTitle( meta.getTitle() );
423
424             if ( meta.getDescription() != null )
425                 data.setDescription( meta.getDescription() );
426
427             if ( meta.getImage() != null )
428                 data.setImage( meta.getImage() );
429         }
430
431         if ( entry.getParent() != null )
432         {
433
434             PortletEntry parent = (PortletEntry)Registry
435                 .getEntry( Registry.PORTLET, entry.getParent() );
436
437             if (parent != null)
438             {
439                 MetaData parentData = getMetaData( parent );
440                 parentData.merge(data);
441                 return parentData;
442             }
443             
444         }
445
446         return data;
447
448     }
449
450     /**
451     Create a MetaData object from a registry Metainfo object
452     
453     @param meta the Metainfo to copy
454
455     @return the new MetaData object, empty if meta is null
456     */

457     protected static MetaData getMetaData(PortletEntry entry)
458     {
459         MetaData data = new MetaData();
460
461         if ( entry.getTitle() != null )
462             data.setTitle( entry.getTitle() );
463
464         if ( entry.getDescription() != null )
465             data.setDescription( entry.getDescription() );
466             
467         if ( entry.getMetaInfo() != null && entry.getMetaInfo().getImage() != null )
468             data.setImage( entry.getMetaInfo().getImage() );
469             
470         return data;
471     }
472     
473     /**
474      * @param Entry entry Entry whose parent we want
475      * @return PortletEntry Parent of Entry
476      * @author <a HREF="mailto:weaver@apache.org">Scott T. Weaver</a>
477      */

478     protected static PortletEntry getParentEntry(PortletEntry entry)
479     {
480         PortletEntry result = null;
481         String JavaDoc parent = entry.getParent();
482         if (parent != null)
483         {
484             result = (PortletEntry) Registry.getEntry(Registry.PORTLET, parent);
485         }
486
487         return result;
488     }
489     
490     /**
491      * Retruns the classname defined for this PortletEntry.
492      * If no classname was defined, the parent is queried
493      * @author <a HREF="mailto:weaver@apache.org">Scott T. Weaver</a>
494      */

495     protected String JavaDoc getClassname(PortletEntry entry)
496     {
497         String JavaDoc className = entry.getClassname();
498         if (className == null)
499         {
500             PortletEntry parent = getParentEntry(entry);
501             if (parent != null)
502             {
503                 // We must walk up the hierarchy just to be safe
504
className = getClassname(parent);
505             }
506         }
507
508         return className;
509     }
510     
511     /**
512      * Maps all parameters, not found within the <code>entry</code>, from
513      * the <code>entry</code>'s parent into the entry
514      * @author <a HREF="mailto:weaver@apache.org">Scott T. Weaver</a>
515      */

516     protected void addParentInitParameters(PortletEntry entry, Map JavaDoc hash)
517     {
518         // Now map any parameters from the parent that the child does not have
519
PortletEntry parent = getParentEntry(entry);
520         if (parent != null)
521         {
522             Map JavaDoc parentMap = parent.getParameterMap();
523             Iterator JavaDoc names = parent.getParameterNames();
524
525             while (names.hasNext())
526             {
527                 String JavaDoc key = (String JavaDoc) names.next();
528                 if (!hash.containsKey(key))
529                 {
530                     hash.put(key, parentMap.get(key));
531                 }
532             }
533             
534             // Always make sure to get the entire inheritence chain
535
addParentInitParameters(parent, hash);
536         }
537     }
538     
539     /**
540      * Figures out how to produce a security reference for
541      * this portlet.
542      */

543     protected SecurityReference getSecurityReference(Entry entry, PortletEntry pEntry)
544     {
545         // If something happended during init() that prevented this
546
if (runDataService == null)
547         {
548             this.runDataService =
549                 (JetspeedRunDataService) TurbineServices.getInstance().getService(
550                     RunDataService.SERVICE_NAME);
551         }
552         JetspeedRunData rundata = runDataService.getCurrentRunData();
553         
554         return JetspeedSecurity.getSecurityReference(entry, rundata);
555     }
556
557 }
558
Popular Tags