/* | |
* Copyright 2004 The Apache Software Foundation | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package org.apache.pluto.internal; | |
import org.apache.pluto.PlutoConfigurationException; | |
import org.apache.pluto.PortletContainerException; | |
import org.apache.pluto.descriptors.portlet.PortletAppDD; | |
import org.apache.pluto.descriptors.services.PortletAppDescriptorService; | |
import org.apache.pluto.util.StringManager; | |
import javax.servlet.ServletContext; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.util.Map; | |
import java.util.WeakHashMap; | |
/** | |
* Simple caching mechanism used to manage portlet descriptors. This mechanism | |
* takes special considerations to make sure that the cache is invalidated for | |
* any ServletContext that is destroyed, thus allowing for a the context to be | |
* redeployed. | |
* | |
* @author <a href="mailto:ddewolf@apache.org">David H. DeWolf</a> | |
* @author <a href="mailto:zheng@apache.org">ZHENG Zhong</a> | |
* @version 1.0 | |
* @since Nov 3, 2004 | |
*/ | |
public class PortletDescriptorRegistry { | |
/** Portlet deployment descriptor location. */ | |
private static final String PORTLET_XML = "/WEB-INF/portlet.xml"; | |
/** Exception Messages. */ | |
private static final StringManager EXCEPTIONS = StringManager.getManager( | |
PortletDescriptorRegistry.class.getPackage().getName()); | |
/** The static singleton registry instance. */ | |
private static final PortletDescriptorRegistry REGISTRY = | |
new PortletDescriptorRegistry(); | |
// Private Member Variables ------------------------------------------------ | |
/** The portlet application descriptor service. */ | |
private PortletAppDescriptorService portletDDService = null; | |
/** | |
* Cache of descriptors. WeakHashMap is used so that | |
* once the context is destroyed (kinda), the cache is eliminated. | |
* Ideally we'd use a ServletContextListener, but at this | |
* point I'm wondering if we really want to add another | |
* config requirement in the servlet xml? Hmm. . . | |
*/ | |
private Map cache = new WeakHashMap(); | |
// Constructor ------------------------------------------------------------- | |
/** | |
* Returns the singleton registry instance. | |
* @return the singleton registry instance. | |
*/ | |
public static PortletDescriptorRegistry getRegistry() { | |
return REGISTRY; | |
} | |
/** | |
* Private constructor that prevents external instantiation. | |
* We must modify the context class loader in order for | |
* the Configuration utility to find the properties file. | |
* @throws PlutoConfigurationException if fail to instantiate portlet | |
* application descriptor service. | |
*/ | |
private PortletDescriptorRegistry() | |
throws PlutoConfigurationException { | |
String className = Configuration.getPortletAppDescriptorServiceImpl(); | |
try { | |
Class clazz = Class.forName(className); | |
portletDDService = (PortletAppDescriptorService) clazz.newInstance(); | |
} catch (ClassNotFoundException ex) { | |
throw new PlutoConfigurationException( | |
"Unable to find class " + className, ex); | |
} catch (InstantiationException ex) { | |
throw new PlutoConfigurationException( | |
"Unable to instantiate class " + className, ex); | |
} catch (IllegalAccessException ex) { | |
throw new PlutoConfigurationException( | |
"Unable to access class " + className, ex); | |
} | |
} | |
// Public Methods ---------------------------------------------------------- | |
/** | |
* Retrieve the Portlet Application Deployment Descriptor for the given | |
* servlet context. Create it if it does not allready exist. | |
* | |
* @param servletContext the servlet context. | |
* @return The portlet application deployment descriptor. | |
* @throws PortletContainerException | |
*/ | |
public PortletAppDD getPortletAppDD(ServletContext servletContext) | |
throws PortletContainerException { | |
PortletAppDD portletAppDD = (PortletAppDD) cache.get(servletContext); | |
if (portletAppDD == null) { | |
portletAppDD = createDefinition(servletContext); | |
cache.put(servletContext, portletAppDD); | |
} | |
return portletAppDD; | |
} | |
// Private Methods --------------------------------------------------------- | |
/** | |
* Creates the portlet.xml deployment descriptor representation. | |
* | |
* @param servletContext the servlet context for which the DD is requested. | |
* @return the Portlet Application Deployment Descriptor. | |
* @throws PortletContainerException | |
*/ | |
private PortletAppDD createDefinition(ServletContext servletContext) | |
throws PortletContainerException { | |
PortletAppDD portletAppDD = null; | |
try { | |
InputStream in = servletContext.getResourceAsStream(PORTLET_XML); | |
portletAppDD = portletDDService.read(in); | |
} catch (IOException ex) { | |
throw new PortletContainerException(EXCEPTIONS.getString( | |
"error.context.descriptor.load", | |
new String[] { servletContext.getServletContextName() }), | |
ex); | |
} | |
return portletAppDD; | |
} | |
} | |