1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.services.portletfactory;
18
19
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;
51 import java.util.Iterator;
52 import java.util.Map;
53 import java.util.HashMap;
54 import javax.servlet.ServletConfig;
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 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
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
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 name, String 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 classname, PortletConfig pc, String id )
163 throws PortletException
164 {
165
166
167 long begin = System.currentTimeMillis();
168
169 Portlet portlet = null;
170 Class portletClass = null;
171 String handle = null;
172
173 try
174 {
175 portletClass = Class.forName(classname);
176 }
177 catch (Exception e)
178 {
179 throw new PortletException( "PortletFactory: Unable to load class " + classname );
180 }
181
182 if (enableCache)
183 {
184 try
185 {
186
187 Class[] signatureParams = { Object.class };
188 Object[] methodParams = { pc };
189 handle = (String)portletClass.getMethod("getHandle",signatureParams)
190 .invoke(null,methodParams);
191
192 handle = String.valueOf(classname.hashCode())+handle;
193 }
194 catch (NoSuchMethodException e)
195 {
196
197 }
198 catch (Exception e)
199 {
200
201
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
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
226 if ( (portlet != null)
227 && ( portlet instanceof Cacheable )
228 && (! ((Cacheable)portlet).getExpire().isExpired()) )
229 {
230
231
232
233
234 portlet.setPortletConfig( pc );
235 portlet.setID( id );
236 portlet.setName( pc.getName() );
237
238
239
240
241
242
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
261
262
263
264
265
266
267
268
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
279 portlet = (Portlet)portletClass.newInstance();
280
281 }
282 catch ( Throwable t )
283 {
284 logger.error("Throwable", t);
285 throw new PortletException( t.getMessage() );
286 }
287
288
289 String title = null;
290 String description = null;
291 MetaData metainfo = pc.getMetainfo();
292
293 if ( metainfo != null ) {
294 title=metainfo.getTitle();
295 description=metainfo.getDescription();
296 }
297
298
299
300
301 portlet.setID( id );
302 portlet.setName( pc.getName() );
303 portlet.setPortletConfig( pc );
304 portlet.setCreationTime( System.currentTimeMillis() );
305 portlet.init();
306
307
308
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
326 ((Cacheable)portlet).setHandle( handle );
327 PortletCache.addCacheable( ((Cacheable)portlet) );
328
329
330 ((Cacheable)portlet).getExpire();
331
332 }
333
334
335
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 id)
354 {
355 Map map = new HashMap();
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
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 getParameters( Entry entry )
394 {
395 Hashtable hash = new Hashtable();
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 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 getClassname(PortletEntry entry)
496 {
497 String className = entry.getClassname();
498 if (className == null)
499 {
500 PortletEntry parent = getParentEntry(entry);
501 if (parent != null)
502 {
503
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 hash)
517 {
518
519 PortletEntry parent = getParentEntry(entry);
520 if (parent != null)
521 {
522 Map parentMap = parent.getParameterMap();
523 Iterator names = parent.getParameterNames();
524
525 while (names.hasNext())
526 {
527 String key = (String) names.next();
528 if (!hash.containsKey(key))
529 {
530 hash.put(key, parentMap.get(key));
531 }
532 }
533
534
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
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 }