| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.cocoon.faces; |
| |
| import org.apache.avalon.framework.activity.Initializable; |
| import org.apache.avalon.framework.configuration.Configurable; |
| import org.apache.avalon.framework.configuration.Configuration; |
| import org.apache.avalon.framework.configuration.ConfigurationException; |
| import org.apache.avalon.framework.context.ContextException; |
| import org.apache.avalon.framework.context.Contextualizable; |
| import org.apache.avalon.framework.logger.AbstractLogEnabled; |
| import org.apache.avalon.framework.parameters.Parameters; |
| import org.apache.avalon.framework.thread.ThreadSafe; |
| |
| import org.apache.cocoon.CascadingIOException; |
| import org.apache.cocoon.Constants; |
| import org.apache.cocoon.ProcessingException; |
| import org.apache.cocoon.acting.Action; |
| import org.apache.cocoon.environment.Context; |
| import org.apache.cocoon.environment.ObjectModelHelper; |
| import org.apache.cocoon.environment.Redirector; |
| import org.apache.cocoon.environment.Request; |
| import org.apache.cocoon.environment.Response; |
| import org.apache.cocoon.environment.SourceResolver; |
| import org.apache.cocoon.environment.portlet.ActionResponse; |
| import org.apache.cocoon.environment.portlet.PortletResponse; |
| |
| import javax.faces.FacesException; |
| import javax.faces.FactoryFinder; |
| import javax.faces.application.Application; |
| import javax.faces.application.ApplicationFactory; |
| import javax.faces.context.FacesContext; |
| import javax.faces.context.FacesContextFactory; |
| import javax.faces.lifecycle.Lifecycle; |
| import javax.faces.lifecycle.LifecycleFactory; |
| import javax.faces.webapp.FacesServlet; |
| import java.io.IOException; |
| import java.util.Map; |
| |
| /** |
| * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a> |
| * @version CVS $Id$ |
| */ |
| public class FacesAction extends AbstractLogEnabled |
| implements Action, ThreadSafe, Contextualizable, |
| Configurable, Initializable { |
| |
| public static final String REQUEST_REDIRECTOR_ATTRIBUTE = "org.apache.cocoon.faces.REDIRECTOR"; |
| |
| private Context context; |
| |
| private String cutPrefix; |
| private String cutSuffix; |
| private String addPrefix; |
| private String addSuffix; |
| |
| private FacesContextFactory facesContextFactory; |
| private Application application; |
| private Lifecycle lifecycle; |
| |
| |
| /** |
| * |
| */ |
| class RedirectorImpl implements FacesRedirector { |
| private Redirector redirector; |
| private Request request; |
| private Response response; |
| |
| RedirectorImpl (Redirector redirector, Request request, Response response) { |
| this.redirector = redirector; |
| this.request = request; |
| this.response = response; |
| } |
| |
| public void dispatch(String url) throws IOException { |
| // System.err.println("INFO: Dispatching to " + url); |
| try { |
| // TODO: HACK: Dependency on ActionResponse |
| if (response instanceof ActionResponse) { |
| // Can't render response. Redirect to another face. |
| redirector.redirect(true, url); |
| } else { |
| // Need to render face. Convert face URL to view URL. |
| int begin = 0; |
| int end = url.length(); |
| |
| if (cutPrefix != null && url.startsWith(cutPrefix)) { |
| begin = cutPrefix.length(); |
| } |
| if (cutSuffix != null && url.endsWith(cutSuffix)) { |
| end = end - cutSuffix.length(); |
| } |
| |
| StringBuffer buffer = new StringBuffer(); |
| if (addPrefix != null) { |
| buffer.append(addPrefix); |
| } |
| if (begin < end) { |
| buffer.append(url.substring(begin, end)); |
| } |
| if (addSuffix != null) { |
| buffer.append(addSuffix); |
| } |
| url = buffer.toString(); |
| |
| // System.err.println("INFO: Dispatching to view " + url); |
| redirector.redirect(true, "cocoon:/" + url); |
| } |
| } catch (Exception e) { |
| throw new CascadingIOException(e); |
| } |
| } |
| |
| public void redirect(String url) throws IOException { |
| // System.err.println("redirect: " + url); |
| try { |
| redirector.redirect(true, url); |
| } catch (Exception e) { |
| throw new CascadingIOException(e); |
| } |
| } |
| |
| public String encodeActionURL(String url) { |
| // System.err.println("encodeActionURL: " + url); |
| // TODO: HACK: Dependency on PortletResponse |
| if (response instanceof PortletResponse) { |
| final String context = request.getContextPath(); |
| |
| if (url.startsWith(context)) { |
| url = url.substring(context.length()); |
| // System.err.println("encodeActionURL: cut: " + url); |
| } |
| |
| return "portlet:action:" + response.encodeURL(url); |
| } else { |
| return response.encodeURL(url); |
| } |
| } |
| |
| public String encodeResourceURL(String url) { |
| // System.err.println("encodeResourceURL: " + url); |
| return response.encodeURL(url); |
| } |
| } |
| |
| |
| public void contextualize(org.apache.avalon.framework.context.Context avalonContext) throws ContextException { |
| context = (Context) avalonContext.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT); |
| } |
| |
| public void configure(Configuration configuration) throws ConfigurationException { |
| this.cutPrefix = configuration.getChild("cut-prefix").getValue(null); |
| this.cutSuffix = configuration.getChild("cut-suffix").getValue(".faces"); |
| this.addPrefix = configuration.getChild("add-prefix").getValue(null); |
| this.addSuffix = configuration.getChild("add-suffix").getValue(".view"); |
| } |
| |
| public void initialize() throws Exception { |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("Initializing FacesAction"); |
| } |
| |
| facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); |
| // facesContextFactory = new FacesContextFactoryImpl(); |
| |
| ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY); |
| application = applicationFactory.getApplication(); |
| // application.setDefaultRenderKitId("COCOON_BASIC_XHTML"); |
| |
| LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY); |
| String lifecycleID = context.getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR); |
| if (lifecycleID == null) { |
| lifecycleID = "DEFAULT"; |
| } |
| lifecycle = lifecycleFactory.getLifecycle(lifecycleID); |
| |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("Faces context factory is " + facesContextFactory.getClass().getName()); |
| getLogger().debug("Faces application factory is " + applicationFactory.getClass().getName()); |
| getLogger().debug("Faces lifecycle factory is " + lifecycleFactory.getClass().getName()); |
| } |
| } |
| |
| public Map act(Redirector redirector, |
| SourceResolver resolver, |
| Map objectModel, |
| String source, |
| Parameters parameters) |
| throws Exception { |
| Request request = ObjectModelHelper.getRequest(objectModel); |
| Response response = ObjectModelHelper.getResponse(objectModel); |
| |
| // Pass FacesRedirector to the FacesContext implementation. |
| request.setAttribute(REQUEST_REDIRECTOR_ATTRIBUTE, new RedirectorImpl(redirector, request, response)); |
| |
| FacesContext context = facesContextFactory.getFacesContext(this.context, request, response, lifecycle); |
| try { |
| lifecycle.execute(context); |
| lifecycle.render(context); |
| |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("Request processed; View root ID: " + context.getViewRoot().getId()); |
| } |
| } catch (FacesException e) { |
| throw new ProcessingException("Failed to process faces request", e); |
| } finally { |
| context.release(); |
| } |
| |
| return null; |
| } |
| } |