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
015package org.apache.tapestry.portlet;
016
017import java.io.IOException;
018import java.util.Locale;
019
020import javax.portlet.ActionRequest;
021import javax.portlet.ActionResponse;
022import javax.portlet.Portlet;
023import javax.portlet.PortletConfig;
024import javax.portlet.PortletException;
025import javax.portlet.RenderRequest;
026import javax.portlet.RenderResponse;
027
028import org.apache.hivemind.ClassResolver;
029import org.apache.hivemind.Registry;
030import org.apache.hivemind.Resource;
031import org.apache.hivemind.impl.DefaultClassResolver;
032import org.apache.hivemind.impl.RegistryBuilder;
033import org.apache.hivemind.impl.XmlModuleDescriptorProvider;
034import org.apache.tapestry.web.WebContext;
035import 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 */
047public 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}