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 org.apache.myfaces.tobago.component.ComponentUtil;
025    import org.apache.myfaces.tobago.context.ClientProperties;
026    import org.apache.myfaces.tobago.util.RequestUtils;
027    
028    import javax.faces.FacesException;
029    import javax.faces.application.ViewHandler;
030    import javax.faces.component.UIViewRoot;
031    import javax.faces.context.FacesContext;
032    import java.io.IOException;
033    import java.util.Locale;
034    
035    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_CLIENT_PROPERTIES;
036    
037    public class ViewHandlerImpl extends ViewHandler {
038    
039      private static final Log LOG = LogFactory.getLog(ViewHandlerImpl.class);
040    
041      public static final String PAGE_ID = "tobago::page-id";
042    
043      private ViewHandler base;
044    
045      public ViewHandlerImpl(ViewHandler base) {
046        if (LOG.isInfoEnabled()) {
047          LOG.info("Hiding RI base implementation: " + base);
048        }
049        this.base = base;
050      }
051    
052      public Locale calculateLocale(FacesContext facesContext) {
053        return base.calculateLocale(facesContext);
054      }
055    
056      public String calculateRenderKitId(FacesContext facesContext) {
057        return base.calculateRenderKitId(facesContext);
058      }
059    
060      public UIViewRoot createView(FacesContext facesContext, String viewId) {
061        if (LOG.isDebugEnabled()) {
062          LOG.debug("creating new view with viewId:        '" + viewId + "'");
063        }
064        UIViewRoot viewRoot = base.createView(facesContext, viewId);
065        // ensure tobago UIViewRoot RI don't create the component via application
066        if (!(viewRoot instanceof org.apache.myfaces.tobago.component.UIViewRoot)) {
067          UIViewRoot tobagoViewRoot = (UIViewRoot)
068              facesContext.getApplication().createComponent(UIViewRoot.COMPONENT_TYPE);
069          if (!(tobagoViewRoot instanceof org.apache.myfaces.tobago.component.UIViewRoot)) {
070            LOG.warn("Application creating wrong UIViewRoot, forcing Tobago");
071            tobagoViewRoot = new org.apache.myfaces.tobago.component.UIViewRoot();
072          }
073          tobagoViewRoot.setLocale(viewRoot.getLocale());
074          tobagoViewRoot.setViewId(viewId);
075          tobagoViewRoot.setRenderKitId(viewRoot.getRenderKitId());
076          viewRoot = tobagoViewRoot;
077        }
078        ensureClientProperties(facesContext, viewRoot);
079    
080        return viewRoot;
081      }
082    
083      private void ensureClientProperties(FacesContext facesContext,
084          UIViewRoot viewRoot) {
085        if (viewRoot != null) {
086          ClientProperties clientProperties
087              = ClientProperties.getInstance(facesContext);
088          viewRoot.getAttributes().put(ATTR_CLIENT_PROPERTIES, clientProperties);
089        }
090      }
091    
092      public String getActionURL(FacesContext facesContext, String viewId) {
093        return base.getActionURL(facesContext, viewId);
094      }
095    
096      public String getResourceURL(FacesContext facesContext, String path) {
097        return base.getResourceURL(facesContext, path);
098      }
099    
100      public void renderView(FacesContext facesContext, UIViewRoot viewRoot)
101          throws IOException, FacesException {
102        // standard
103        if (LOG.isDebugEnabled()) {
104          LOG.debug("renderView - view id '"
105              + (viewRoot != null ? viewRoot.getViewId() : "N/A")
106              + "'; view root: '" + viewRoot + "'");
107        }
108        base.renderView(facesContext, viewRoot);
109    
110        if (LOG.isDebugEnabled()) {
111          LOG.debug("VIEW");
112          LOG.debug(ComponentUtil.toString(facesContext.getViewRoot(), 0));
113        }
114      }
115    
116      public UIViewRoot restoreView(FacesContext facesContext, String viewId) {
117        if (LOG.isDebugEnabled()) {
118          LOG.debug("restore view with viewId:             '" + viewId + "'");
119        }
120        // this is only needed in the first request, the later will be handled by faces
121        // TODO: maybe find a way to make this unneeded
122        RequestUtils.ensureEncoding(facesContext);
123        UIViewRoot viewRoot = base.restoreView(facesContext, viewId);
124        ensureClientProperties(facesContext, viewRoot);
125        return viewRoot;
126      }
127    
128      public void writeState(FacesContext facesContext) throws IOException {
129        base.writeState(facesContext);
130      }
131    
132    }
133