{
//record the begining of the portlet creation
long begin = System.currentTimeMillis();
Portlet portlet = null;
Class portletClass = null;
String handle = null;
try
{
portletClass = Class.forName(classname);
}
catch (Exception e)
{
throw new PortletException( "PortletFactory: Unable to load class " + classname );
}
if (enableCache)
{
try
{
// try to invoke a static getHandle() for this class
Class[] signatureParams = { Object.class };
Object[] methodParams = { pc };
handle = (String)portletClass.getMethod("getHandle",signatureParams)
.invoke(null,methodParams);
// make sure the handle is differenciated by class
handle = String.valueOf(classname.hashCode())+handle;
}
catch (NoSuchMethodException e)
{
// ignore, this simply means the portlet is not cacheable
}
catch (Exception e)
{
// invocation failed or security exception, in both case
// log the error and treat the class as non cacheable
logger.error("PortletFactory: failed to get cache handle",e);
}
}
try {
if (enableCache && (handle != null))
{
portlet = (Portlet)PortletCache.getCacheable( handle );
//portlet in cache but expired, remove it from cache
if ((portlet!=null) && ((Cacheable)portlet).getExpire().isExpired() )
{
logger.info( "The portlet (" + handle + ") is expired" );
PortletCache.removeCacheable(handle);
if ( logger.isDebugEnabled() )
{
logger.debug( "After removal of object(" + handle + ")." );
}
portlet = null;
}
}
// we found a portlet in the cache
if ( (portlet != null)
&& ( portlet instanceof Cacheable )
&& (! ((Cacheable)portlet).getExpire().isExpired()) )
{
// update the config for the portlet to the current one
// Note: this is what was used to find the cached portlet.
// Note: the init params may have changed in the psml since caching,
// this will update the portlet to use them.
portlet.setPortletConfig( pc );
portlet.setID( id );
portlet.setName( pc.getName() );
//FIXME: we now avoid to override metainfo when nothing is set
//in the markup, so that cached portlets can keep their metainfo
//This may lead to an incorrect metainfo retrieved if the first
//instance of the portlet, which is put in the cache, has some
//special metainfo defined in the markup
MetaData meta = pc.getMetainfo();
if ( meta != null)
{
if (! MetaData.DEFAULT_TITLE.equals( meta.getTitle() ) )
{
portlet.setTitle( meta.getTitle() );
}
if (! MetaData.DEFAULT_DESCRIPTION.equals( meta.getDescription() ) )
{
portlet.setDescription( meta.getDescription() );
}
}
//FIXME: Notice here we are putting the portlet without wrapper
//in the cache, and we must wrap it on return.
//Security implications: the portletcache should not be
//publicly accessible.
//Alternative: we could wrap the portlet before putting
//it in the cache.
//now compute the time it took to instantate and log it...
// time in millis, sugested by Thomas Schaeck (schaeck@de.ibm.com)
long milliseconds = ( System.currentTimeMillis() - begin );
if (logger.isDebugEnabled())
logger.debug( "PortletFactory.getPortlet(): found in cache in "
+ milliseconds + " ms - handle: " + handle );
return PortletWrapper.wrap( portlet );
}
// if not found in the cache, instanciate a new Portlet
portlet = (Portlet)portletClass.newInstance();
}
catch ( Throwable t )
{
logger.error("Throwable", t);
throw new PortletException( t.getMessage() );
}
// save the current meta-info
String title = null;
String description = null;
MetaData metainfo = pc.getMetainfo();
if ( metainfo != null ) {
title=metainfo.getTitle();
description=metainfo.getDescription();
}
// init the portlet, it may override its PSML defined markup if
// it doesn't check for it
portlet.setID( id );
portlet.setName( pc.getName() );
portlet.setPortletConfig( pc );
portlet.setCreationTime( System.currentTimeMillis() );
portlet.init();
//force the title and description from markup metadata
//in case the portlet overwrote some values
if ( metainfo != null)
{
if (!MetaData.DEFAULT_TITLE.equals(title) )
{
portlet.setTitle( title );
}
if (!MetaData.DEFAULT_DESCRIPTION.equals(description) )
{
portlet.setDescription( description );
}
}
if (enableCache && (portlet instanceof Cacheable))
{