001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *   http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    package org.apache.myfaces.tobago.application;
021    
022    import org.apache.commons.logging.Log;
023    import org.apache.commons.logging.LogFactory;
024    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_CLIENT_PROPERTIES;
025    import org.apache.myfaces.tobago.component.ComponentUtil;
026    import org.apache.myfaces.tobago.context.ClientProperties;
027    import org.apache.myfaces.tobago.util.RequestUtils;
028    
029    import javax.faces.FacesException;
030    import javax.faces.application.ViewHandler;
031    import javax.faces.component.UIViewRoot;
032    import javax.faces.context.FacesContext;
033    import java.io.IOException;
034    import java.util.Locale;
035    
036    public class ViewHandlerImpl extends ViewHandler {
037    
038      private static final Log LOG = LogFactory.getLog(ViewHandlerImpl.class);
039    
040      public static final String PAGE_ID = "tobago::page-id";
041    
042      private ViewHandler base;
043    
044      public ViewHandlerImpl(ViewHandler base) {
045        if (LOG.isInfoEnabled()) {
046          LOG.info("Hiding RI base implemation: " + base);
047        }
048        this.base = base;
049      }
050    
051      public Locale calculateLocale(FacesContext facesContext) {
052        return base.calculateLocale(facesContext);
053      }
054    
055      public String calculateRenderKitId(FacesContext facesContext) {
056        return base.calculateRenderKitId(facesContext);
057      }
058    
059      public UIViewRoot createView(FacesContext facesContext, String viewId) {
060        if (LOG.isDebugEnabled()) {
061          LOG.debug("creating new view with viewId:        '" + viewId + "'");
062        }
063        UIViewRoot viewRoot = base.createView(facesContext, viewId);
064        // ensure tobago UIViewRoot RI don't create the component via application
065        if (!(viewRoot instanceof org.apache.myfaces.tobago.component.UIViewRoot)) {
066          UIViewRoot tobagoViewRoot = (UIViewRoot)
067              facesContext.getApplication().createComponent(UIViewRoot.COMPONENT_TYPE);
068          if (!(tobagoViewRoot instanceof org.apache.myfaces.tobago.component.UIViewRoot)) {
069            LOG.warn("Application creating wrong UIViewRoot, forcing Tobago");
070            tobagoViewRoot = new org.apache.myfaces.tobago.component.UIViewRoot();
071          }
072          tobagoViewRoot.setLocale(viewRoot.getLocale());
073          tobagoViewRoot.setViewId(viewId);
074          tobagoViewRoot.setRenderKitId(viewRoot.getRenderKitId());
075          viewRoot = tobagoViewRoot;
076        }
077        ensureClientProperties(facesContext, viewRoot);
078    
079        return viewRoot;
080      }
081    
082      private void ensureClientProperties(FacesContext facesContext,
083          UIViewRoot viewRoot) {
084        if (viewRoot != null) {
085          ClientProperties clientProperties
086              = ClientProperties.getInstance(facesContext);
087          viewRoot.getAttributes().put(ATTR_CLIENT_PROPERTIES, clientProperties);
088        }
089      }
090    
091      public String getActionURL(FacesContext facesContext, String viewId) {
092        return base.getActionURL(facesContext, viewId);
093      }
094    
095      public String getResourceURL(FacesContext facesContext, String path) {
096        return base.getResourceURL(facesContext, path);
097      }
098    
099      public void renderView(FacesContext facesContext, UIViewRoot viewRoot)
100          throws IOException, FacesException {
101        // standard
102        if (LOG.isDebugEnabled()) {
103          LOG.debug("renderView - view id '"
104              + (viewRoot != null ? viewRoot.getViewId() : "N/A")
105              + "'; view root: '" + viewRoot + "'");
106        }
107        base.renderView(facesContext, viewRoot);
108    
109        if (LOG.isDebugEnabled()) {
110          LOG.debug("VIEW");
111          LOG.debug(ComponentUtil.toString(facesContext.getViewRoot(), 0));
112        }
113      }
114    
115      public UIViewRoot restoreView(FacesContext facesContext, String viewId) {
116        if (LOG.isDebugEnabled()) {
117          LOG.debug("restore view with viewId:             '" + viewId + "'");
118        }
119        // this is only needed in the first request, the later will be handled by faces
120        // TODO: maybe find a way to make this unneeded
121        RequestUtils.ensureEncoding(facesContext);
122        UIViewRoot viewRoot = base.restoreView(facesContext, viewId);
123        ensureClientProperties(facesContext, viewRoot);
124        return viewRoot;
125      }
126    
127      public void writeState(FacesContext facesContext) throws IOException {
128        base.writeState(facesContext);
129      }
130    
131    }
132