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