001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.pluto.internal;
018:
019: import org.apache.pluto.PlutoConfigurationException;
020: import org.apache.pluto.PortletContainerException;
021: import org.apache.pluto.descriptors.portlet.PortletAppDD;
022: import org.apache.pluto.descriptors.services.PortletAppDescriptorService;
023: import org.apache.pluto.util.StringManager;
024:
025: import javax.servlet.ServletContext;
026: import java.io.IOException;
027: import java.io.InputStream;
028: import java.util.Map;
029: import java.util.WeakHashMap;
030:
031: /**
032: * Simple caching mechanism used to manage portlet descriptors. This mechanism
033: * takes special considerations to make sure that the cache is invalidated for
034: * any ServletContext that is destroyed, thus allowing for a the context to be
035: * redeployed.
036: *
037: * NOTE: This should only be used internally. Do not access it from embedding
038: * portals, instead, utilize the PortletRegistryService.
039: *
040: * @version 1.0
041: * @since Nov 3, 2004
042: */
043: public class PortletDescriptorRegistry {
044:
045: /** Portlet deployment descriptor location. */
046: private static final String PORTLET_XML = "/WEB-INF/portlet.xml";
047:
048: /** Exception Messages. */
049: private static final StringManager EXCEPTIONS = StringManager
050: .getManager(PortletDescriptorRegistry.class.getPackage()
051: .getName());
052:
053: /** The static singleton registry instance. */
054: private static final PortletDescriptorRegistry REGISTRY = new PortletDescriptorRegistry();
055:
056: // Private Member Variables ------------------------------------------------
057:
058: /** The portlet application descriptor service. */
059: private PortletAppDescriptorService portletDDService = null;
060:
061: /**
062: * Cache of descriptors. WeakHashMap is used so that
063: * once the context is destroyed (kinda), the cache is eliminated.
064: * Ideally we'd use a ServletContextListener, but at this
065: * point I'm wondering if we really want to add another
066: * config requirement in the servlet xml? Hmm. . .
067: */
068: private final Map cache = new WeakHashMap();
069:
070: // Constructor -------------------------------------------------------------
071:
072: /**
073: * Returns the singleton registry instance.
074: * @return the singleton registry instance.
075: */
076: public static PortletDescriptorRegistry getRegistry() {
077: return REGISTRY;
078: }
079:
080: /**
081: * Private constructor that prevents external instantiation.
082: * We must modify the context class loader in order for
083: * the Configuration utility to find the properties file.
084: * @throws PlutoConfigurationException if fail to instantiate portlet
085: * application descriptor service.
086: */
087: private PortletDescriptorRegistry()
088: throws PlutoConfigurationException {
089: String className = Configuration
090: .getPortletAppDescriptorServiceImpl();
091: try {
092: Class clazz = Class.forName(className);
093: portletDDService = (PortletAppDescriptorService) clazz
094: .newInstance();
095: } catch (ClassNotFoundException ex) {
096: throw new PlutoConfigurationException(
097: "Unable to find class " + className, ex);
098: } catch (InstantiationException ex) {
099: throw new PlutoConfigurationException(
100: "Unable to instantiate class " + className, ex);
101: } catch (IllegalAccessException ex) {
102: throw new PlutoConfigurationException(
103: "Unable to access class " + className, ex);
104: }
105: }
106:
107: // Public Methods ----------------------------------------------------------
108:
109: /**
110: * Retrieve the Portlet Application Deployment Descriptor for the given
111: * servlet context. Create it if it does not allready exist.
112: *
113: * @param servletContext the servlet context.
114: * @return The portlet application deployment descriptor.
115: * @throws PortletContainerException if the descriptor can not be found or parsed
116: */
117: public PortletAppDD getPortletAppDD(ServletContext servletContext)
118: throws PortletContainerException {
119: PortletAppDD portletAppDD = (PortletAppDD) cache
120: .get(servletContext);
121: if (portletAppDD == null) {
122: portletAppDD = createDefinition(servletContext);
123: cache.put(servletContext, portletAppDD);
124: }
125: return portletAppDD;
126: }
127:
128: // Private Methods ---------------------------------------------------------
129:
130: /**
131: * Creates the portlet.xml deployment descriptor representation.
132: *
133: * @param servletContext the servlet context for which the DD is requested.
134: * @return the Portlet Application Deployment Descriptor.
135: * @throws PortletContainerException
136: */
137: private PortletAppDD createDefinition(ServletContext servletContext)
138: throws PortletContainerException {
139: PortletAppDD portletAppDD = null;
140: try {
141: InputStream in = servletContext
142: .getResourceAsStream(PORTLET_XML);
143: portletAppDD = portletDDService.read(in);
144: } catch (IOException ex) {
145: throw new PortletContainerException(EXCEPTIONS.getString(
146: "error.context.descriptor.load",
147: new String[] { servletContext
148: .getServletContextName() }), ex);
149: }
150: return portletAppDD;
151: }
152:
153: }
|