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.getService(
074                            "tapestry.portlet.PortletApplicationInitializer",
075                            PortletApplicationInitializer.class);
076    
077            initializer.initialize(config);
078    
079            _actionRequestServicer = (ActionRequestServicer) _registry.getService(
080                    "tapestry.portlet.ActionRequestServicer",
081                    ActionRequestServicer.class);
082    
083            _renderRequestServicer = (RenderRequestServicer) _registry.getService(
084                    "tapestry.portlet.RenderRequestServicer",
085                    RenderRequestServicer.class);
086        }
087    
088        /**
089         * Constructs the Registry. The Registry is constructed from the classpath, plus two optional
090         * files:
091         * <ul>
092         * <li>WEB-INF/ <em>name</em> /hivemodule.xml</li>
093         * <li>WEB-INF/hivemodule.xml</li>
094         * </ul>.
095         * <p>
096         * Where <em>name</em> is the name of the portlet.
097         */
098    
099        protected Registry constructRegistry(PortletConfig config)
100        {
101            RegistryBuilder builder = new RegistryBuilder();
102    
103            ClassResolver resolver = new DefaultClassResolver();
104    
105            builder.addModuleDescriptorProvider(new XmlModuleDescriptorProvider(resolver));
106    
107            String name = config.getPortletName();
108            WebContext context = new PortletWebContext(config.getPortletContext());
109    
110            addModuleIfExists(builder, resolver, context, "/WEB-INF/" + name + "/hivemodule.xml");
111            addModuleIfExists(builder, resolver, context, "/WEB-INF/hivemodule.xml");
112    
113            return builder.constructRegistry(Locale.getDefault());
114        }
115    
116        /**
117         * Looks for a file in the context; if it exists, it is expected to be a HiveMind module
118         * descriptor, and is added to the builder.
119         * 
120         * @since 4.0
121         */
122    
123        protected void addModuleIfExists(RegistryBuilder builder, ClassResolver resolver,
124                WebContext context, String path)
125        {
126            Resource r = new WebContextResource(context, path);
127    
128            if (r.getResourceURL() == null)
129                return;
130    
131            builder.addModuleDescriptorProvider(new XmlModuleDescriptorProvider(resolver, r));
132        }
133    
134        public void processAction(ActionRequest request, ActionResponse response)
135                throws PortletException, IOException
136        {
137            try
138            {
139                _registry.setupThread();
140    
141                _actionRequestServicer.service(request, response);
142            }
143            catch (RuntimeException ex)
144            {
145                throw new PortletException(PortletMessages.errorProcessingAction(ex), ex);
146            }
147            finally
148            {
149                _registry.cleanupThread();
150            }
151        }
152    
153        public void render(RenderRequest request, RenderResponse response) throws PortletException,
154                IOException
155        {
156            try
157            {
158                _registry.setupThread();
159    
160                _renderRequestServicer.service(request, response);
161            }
162            catch (RuntimeException ex)
163            {
164                throw new PortletException(PortletMessages.errorProcessingRender(ex), ex);
165            }
166            finally
167            {
168                _registry.cleanupThread();
169            }
170        }
171    }