ate 2005/03/23 14:25:50 Modified: components/portlet-factory/src/java/org/apache/jetspeed/factory JetspeedPortletFactory.java Added: components/portlet-factory/src/java/org/apache/jetspeed/factory JetspeedPortletInstance.java Removed: components/portlet-factory/src/java/org/apache/jetspeed/cache PortletCache.java Log: Resolving http://issues.apache.org/jira/browse/JS2-210: Rewritten PortletFactory Revision Changes Path 1.7 +94 -105 jakarta-jetspeed-2/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletFactory.java Index: JetspeedPortletFactory.java =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletFactory.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- JetspeedPortletFactory.java 27 Jan 2005 21:27:52 -0000 1.6 +++ JetspeedPortletFactory.java 23 Mar 2005 22:25:50 -0000 1.7 @@ -15,7 +15,6 @@ */ package org.apache.jetspeed.factory; -import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Iterator; @@ -23,16 +22,14 @@ import javax.portlet.PortletConfig; import javax.portlet.PortletContext; import javax.portlet.PortletException; -import javax.servlet.ServletConfig; +import javax.portlet.UnavailableException; import javax.servlet.ServletContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.jetspeed.cache.PortletCache; import org.apache.jetspeed.container.PortalAccessor; -import org.apache.pluto.om.common.ObjectID; +import org.apache.jetspeed.om.common.portlet.PortletApplication; import org.apache.pluto.om.portlet.PortletDefinition; -import org.apache.pluto.om.portlet.PortletDefinitionCtrl; /** * <p> @@ -48,173 +45,165 @@ public class JetspeedPortletFactory implements PortletFactory { - private PortletCache portletCache; + private HashMap portletCache; private static final Log log = LogFactory.getLog(JetspeedPortletFactory.class); private final HashMap classLoaderMap; /** * */ - public JetspeedPortletFactory(PortletCache portletCache) + public JetspeedPortletFactory() { - super(); - this.portletCache = portletCache; + this.portletCache = new HashMap(); classLoaderMap = new HashMap(); } - /** - * - * <p> - * addClassLoader - * </p> - * - * Adds a ClassLoader to the search path, <code>classLoaders</code>, of the JetspeedPortletFactory. - * - * @param cl - */ - public void addClassLoader(String paId, ClassLoader cl) - { - if (paId != null && !paId.equals("")) + public void registerPortletApplication(PortletApplication pa, ClassLoader cl) { synchronized (classLoaderMap) { - if (classLoaderMap.get(paId) == null) - { - classLoaderMap.put(paId, cl); - } - } + unregisterPortletApplication(pa); + classLoaderMap.put(pa.getId().toString(), cl); } } - /** - * <p> - * loadPortletClass - * </p> - * Loads a Portlet class by first checking Thread.currentThread().getContextClassLoader() - * then by checking all of the ClassLoaders in <code>classLoaders</code> until the - * class is located or returns <code>null</code> if the Portlet class could not be found. - * - * @param className - * @return - * @throws InstantiationException - * @throws IllegalAccessException - */ - public Portlet loadPortletClass( String className ) throws InstantiationException, IllegalAccessException + public void unregisterPortletApplication(PortletApplication pa) { - Portlet portlet = null; - try + synchronized (classLoaderMap) { - portlet = (Portlet)Thread.currentThread().getContextClassLoader().loadClass(className).newInstance(); - } - catch (ClassCastException cce) + synchronized (portletCache) { - cce.printStackTrace(); - } - catch (ClassNotFoundException e) + ClassLoader cl = (ClassLoader)classLoaderMap.remove(pa.getId().toString()); + if ( cl != null ) { - synchronized (classLoaderMap) + ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader(); + + Iterator portletDefinitions = pa.getPortletDefinitions().iterator(); + while (portletDefinitions.hasNext()) { - Iterator itr = classLoaderMap.values().iterator(); - while (itr.hasNext() && portlet == null) + PortletDefinition pd = (PortletDefinition)portletDefinitions.next(); + Portlet portlet = (Portlet)portletCache.remove(pd.getId().toString()); + if ( portlet != null ) { - ClassLoader cl = (ClassLoader) itr.next(); try { - portlet = (Portlet) cl.loadClass(className).newInstance(); - if(portlet != null) + Thread.currentThread().setContextClassLoader(cl); + portlet.destroy(); + } + finally { - log.warn("Portlet class "+className+" successfuly located in classloader "+cl+". "+ - "You can safely ignore any prior messages classloading messages for this class."); + Thread.currentThread().setContextClassLoader(currentContextClassLoader); } } - catch (Exception e1) - { - // move along - log.warn("The PortletFactory did not locate class "+className+" in classloader "+cl+". "+ - "This message can be ignored if "+className+" can be located in subsequent classloaders. "+ - "This message triggered by: "+e.toString()); } - } } } - return portlet; } /** * Gets a portlet by either creating it or returning a handle to it from the portlet 'cache' * * @param portletDefinition The definition of the portlet - * @return Portlet + * @return PortletInstance * @throws PortletException */ - public Portlet getPortlet( ServletConfig servletConfig, PortletDefinition portletDefinition ) throws PortletException + public PortletInstance getPortletInstance( ServletContext servletContext, PortletDefinition pd ) throws PortletException { - Portlet portlet = null; - Class portletClass = null; - String handle = null; - String portletName = portletDefinition.getId().toString(); - //String portletName = portletDefinition.getName(); - String className = portletDefinition.getClassName(); - String paId = portletDefinition.getPortletApplicationDefinition().getWebApplicationDefinition().getId().toString(); + PortletInstance portlet = null; + String portletName = pd.getId().toString(); + PortletApplication pa = (PortletApplication)pd.getPortletApplicationDefinition(); try { - portlet = portletCache.get(portletName); + synchronized (portletCache) + { + portlet = (PortletInstance)portletCache.get(portletName); if (null != portlet) { - // ((PortletDefinitionCtrl) portletDefinition).setPortletClassLoader(portlet.getClass().getClassLoader()); return portlet; } - portlet = loadPortletClass(className); - - if(portlet == null) + ClassLoader paCl = (ClassLoader)classLoaderMap.get(pa.getId().toString()); + if ( paCl == null ) { - throw new FileNotFoundException("Could not located portlet "+className+" in any classloader."); + throw new UnavailableException("Portlet Application "+pa.getName()+" not available"); } - ClassLoader cl = (ClassLoader) classLoaderMap.get(paId); - if (cl != null) + ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader(); + + try + { + Class clazz = paCl.loadClass(pd.getClassName()); + try { - ((PortletDefinitionCtrl) portletDefinition).setPortletClassLoader(cl); + Thread.currentThread().setContextClassLoader(paCl); + // wrap new Portlet inside PortletInstance which ensures the destroy + // method will wait for all its invocation threads to complete + // and thereby releasing all its ClassLoader locks as needed for local portlets. + portlet = new JetspeedPortletInstance((Portlet)clazz.newInstance()); } - else + finally { - ((PortletDefinitionCtrl) portletDefinition).setPortletClassLoader(portlet.getClass().getClassLoader()); + Thread.currentThread().setContextClassLoader(currentContextClassLoader); + } + } + catch (Exception e) + { + String msg = "Cannot create Portlet instance "+pd.getClassName()+" for Portlet Application "+pa.getName(); + log.error(msg,e); + throw new UnavailableException(msg); } - ServletContext servletContext = servletConfig.getServletContext(); - PortletContext portletContext = - PortalAccessor.createPortletContext(servletContext, - portletDefinition.getPortletApplicationDefinition()); - PortletConfig portletConfig = PortalAccessor.createPortletConfig(servletConfig, portletContext, portletDefinition); + PortletContext portletContext = PortalAccessor.createPortletContext(servletContext, pa); + PortletConfig portletConfig = PortalAccessor.createPortletConfig(portletContext, pd); + try + { + try + { + Thread.currentThread().setContextClassLoader(paCl); portlet.init(portletConfig); - portletCache.add(portletName, portlet); - + } + finally + { + Thread.currentThread().setContextClassLoader(currentContextClassLoader); + } + } + catch (PortletException e1) + { + log.error("Failed to initialize Portlet "+pd.getClassName()+" for Portlet Application "+pa.getName(), e1); + throw e1; + } + portletCache.put(portletName, portlet); + } + } + catch (PortletException pe) + { + throw pe; } catch (Throwable e) { - log.error("PortletFactory: Failed to load portlet "+className, e); - e.printStackTrace(); - throw new PortletException( "PortletFactory: Failed to load portlet " + className +":"+e.toString(), e); + log.error("PortletFactory: Failed to load portlet "+pd.getClassName(), e); + throw new UnavailableException( "Failed to load portlet " + pd.getClassName() +": "+e.toString()); } - return portlet; } - public ClassLoader getPortletClassLoader(PortletDefinition portletDef) + public ClassLoader getPortletApplicationClassLoader(PortletApplication pa) { - String appId = portletDef.getPortletApplicationDefinition().getId().toString(); - if(classLoaderMap.containsKey(appId)) + synchronized (classLoaderMap) { - return (ClassLoader) classLoaderMap.get(appId); - } - else + if ( pa != null ) { - throw new IllegalStateException("No classloader has been defined for portlet application "+appId); + return (ClassLoader)classLoaderMap.get(pa.getId().toString()); + } + return null; } } - + + public boolean isPortletApplicationRegistered(PortletApplication pa) + { + return getPortletApplicationClassLoader(pa) != null; + } } 1.2 +145 -0 jakarta-jetspeed-2/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletInstance.java
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]