001    // Copyright 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.portlet;
016    
017    import java.io.IOException;
018    import java.util.Locale;
019    
020    import javax.portlet.ActionRequest;
021    import javax.portlet.ActionResponse;
022    import javax.portlet.Portlet;
023    import javax.portlet.PortletConfig;
024    import javax.portlet.PortletException;
025    import javax.portlet.RenderRequest;
026    import javax.portlet.RenderResponse;
027    
028    import org.apache.hivemind.ClassResolver;
029    import org.apache.hivemind.Registry;
030    import org.apache.hivemind.Resource;
031    import org.apache.hivemind.impl.DefaultClassResolver;
032    import org.apache.hivemind.impl.RegistryBuilder;
033    import org.apache.hivemind.impl.XmlModuleDescriptorProvider;
034    import org.apache.tapestry.web.WebContext;
035    import org.apache.tapestry.web.WebContextResource;
036    
037    /**
038     * Portlet implementation for Tapestry Portlet applilcations. It's job is to create and manage the
039     * HiveMind registry, to use the <code>tapestry.portlet.PortletApplicationInitializer</code>
040     * service to initialize HiveMind, and the delegate requests to the
041     * <code>tapestry.portlet.ActionRequestServicer</code> and
042     * <code>tapestry.portlet.RenderRequestServicer</code> services.
043     * 
044     * @author Howard M. Lewis Ship
045     * @since 4.0
046     */
047    public class ApplicationPortlet implements Portlet
048    {
049        Registry _registry;
050    
051        ActionRequestServicer _actionRequestServicer;
052    
053        RenderRequestServicer _renderRequestServicer;
054    
055        public void destroy()
056        {
057            try
058            {
059                _registry.shutdown();
060            }
061            finally
062            {
063                _registry = null;
064                _actionRequestServicer = null;
065                _renderRequestServicer = null;
066            }
067        }
068    
069        public void init(PortletConfig config) throws PortletException
070        {
071            _registry = constructRegistry(config);
072    
073            PortletApplicationInitializer initializer = (PortletApplicationInitializer) _registry
074                    .getService(
075                            "tapestry.portlet.PortletApplicationInitializer",
076                            PortletApplicationInitializer.class);
077    
078            initializer.initialize(config);
079    
080            _actionRequestServicer = (ActionRequestServicer) _registry.getService(
081                    "tapestry.portlet.ActionRequestServicer",
082                    ActionRequestServicer.class);
083    
084            _renderRequestServicer = (RenderRequestServicer) _registry.getService(
085                    "tapestry.portlet.RenderRequestServicer",
086                    RenderRequestServicer.class);
087        }
088    
089        /**
090         * Constructs the Registry. The Registry is constructed from the classpath, plus two optional
091         * files:
092         * <ul>
093         * <li>WEB-INF/ <em>name</em> /hivemodule.xml</li>
094         * <li>WEB-INF/hivemodule.xml</li>
095         * </ul>.
096         * <p>
097         * Where <em>name</em> is the name of the portlet.
098         */
099    
100        protected Registry constructRegistry(PortletConfig config)
101        {
102            RegistryBuilder builder = new RegistryBuilder();
103    
104            ClassResolver resolver = new DefaultClassResolver();
105    
106            builder.addModuleDescriptorProvider(new XmlModuleDescriptorProvider(resolver));
107    
108            String name = config.getPortletName();
109            WebContext context = new PortletWebContext(config.getPortletContext());
110    
111            addModuleIfExists(builder, resolver, context, "/WEB-INF/" + name + "/hivemodule.xml");
112            addModuleIfExists(builder, resolver, context, "/WEB-INF/hivemodule.xml");
113    
114            return builder.constructRegistry(Locale.getDefault());
115        }
116    
117        /**
118         * Looks for a file in the context; if it exists, it is expected to be a HiveMind module
119         * descriptor, and is added to the builder.
120         * 
121         * @since 4.0
122         */
123    
124        protected void addModuleIfExists(RegistryBuilder builder, ClassResolver resolver,
125                WebContext context, String path)
126        {
127            Resource r = new WebContextResource(context, path);
128    
129            if (r.getResourceURL() == null)
130                return;
131    
132            builder.addModuleDescriptorProvider(new XmlModuleDescriptorProvider(resolver, r));
133        }
134    
135        public void processAction(ActionRequest request, ActionResponse response)
136                throws PortletException, IOException
137        {
138            try
139            {
140                _registry.setupThread();
141    
142                _actionRequestServicer.service(request, response);
143            }
144            catch (RuntimeException ex)
145            {
146                throw new PortletException(PortletMessages.errorProcessingAction(ex), ex);
147            }
148            finally
149            {
150                _registry.cleanupThread();
151            }
152        }
153    
154        public void render(RenderRequest request, RenderResponse response) throws PortletException,
155                IOException
156        {
157            try
158            {
159                _registry.setupThread();
160    
161                _renderRequestServicer.service(request, response);
162            }
163            catch (RuntimeException ex)
164            {
165                throw new PortletException(PortletMessages.errorProcessingRender(ex), ex);
166            }
167            finally
168            {
169                _registry.cleanupThread();
170            }
171        }
172    }