001 package org.apache.myfaces.tobago.config; 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.lang.ClassUtils; 021 import org.apache.commons.logging.Log; 022 import org.apache.commons.logging.LogFactory; 023 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_IN; 024 import org.apache.myfaces.tobago.component.ComponentUtil; 025 import org.apache.myfaces.tobago.context.ClientProperties; 026 import org.apache.myfaces.tobago.context.ResourceManager; 027 import org.apache.myfaces.tobago.context.ResourceManagerFactory; 028 import org.apache.myfaces.tobago.renderkit.RendererBase; 029 030 import javax.faces.component.UIComponent; 031 import javax.faces.component.UIInput; 032 import javax.faces.component.UIViewRoot; 033 import javax.faces.context.FacesContext; 034 import javax.faces.render.Renderer; 035 import java.util.Locale; 036 import java.util.Map; 037 038 public class ThemeConfig { 039 040 private static final Log LOG = LogFactory.getLog(ThemeConfig.class); 041 042 public static final String THEME_CONFIG_CACHE 043 = "org.apache.myfaces.tobago.config.ThemeConfig.CACHE"; 044 045 public static int getValue(FacesContext facesContext, UIComponent component, 046 String name) { 047 048 CacheKey key = new CacheKey(facesContext.getViewRoot(), component, name); 049 Map<CacheKey, Integer> cache 050 = (Map<CacheKey, Integer>) facesContext.getExternalContext().getApplicationMap().get(THEME_CONFIG_CACHE); 051 052 Integer value = cache.get(key); 053 if (value == null) { 054 value = createValue(facesContext, component, name); 055 cache.put(key, value); 056 } 057 if (value != null) { 058 return value; 059 } else { 060 // todo: remove condition, is only temporary to ignore wml errors. 061 if (!ClientProperties.getInstance(facesContext.getViewRoot()).getContentType().equals("wml")) { 062 throw new NullPointerException("No value configured"); 063 } 064 // todo: remove, is only temporary to ignore wml errors. 065 return 0; 066 } 067 } 068 069 public static boolean hasValue(FacesContext facesContext, UIComponent component, 070 String name) { 071 try { 072 getValue(facesContext, component, name); 073 return true; 074 } catch (NullPointerException e) { 075 return false; 076 } 077 } 078 079 private static Integer createValue(FacesContext facesContext, 080 UIComponent component, String name) { 081 String family; 082 String rendererType; 083 if (component != null) { 084 family = component.getFamily(); 085 rendererType = component.getRendererType(); 086 } else { 087 family = UIInput.COMPONENT_FAMILY; 088 rendererType = RENDERER_TYPE_IN; 089 } 090 Renderer renderer = ComponentUtil.getRenderer(facesContext, family, rendererType); 091 092 Class clazz = renderer.getClass(); 093 if (LOG.isDebugEnabled()) { 094 LOG.debug("search for '" + name + "' in '" + clazz.getName() + "'"); 095 } 096 ResourceManager resourceManager 097 = ResourceManagerFactory.getResourceManager(facesContext); 098 UIViewRoot viewRoot = facesContext.getViewRoot(); 099 while (clazz != null) { 100 String tag = getTagName(clazz); 101 if (LOG.isDebugEnabled()) { 102 LOG.debug("try " + tag); 103 } 104 105 String property = resourceManager.getThemeProperty(viewRoot, 106 "tobago-theme-config", tag + "." + name); 107 108 if (property != null && property.length() > 0) { 109 if (LOG.isDebugEnabled()) { 110 LOG.debug("found " + property); 111 } 112 return new Integer(property); 113 } 114 clazz = clazz.getSuperclass(); 115 } 116 // todo: remove condition, is only temporary to ignore wml errors. 117 if (!ClientProperties.getInstance(viewRoot).getContentType().equals("wml")) { 118 LOG.error("Theme property not found for renderer: " + renderer.getClass() 119 + " with clientProperties='" + ClientProperties.getInstance(viewRoot).getId() + "'" 120 + " and locale='" + viewRoot.getLocale() + "'"); 121 } 122 return null; 123 } 124 125 private static String getTagName(Class clazz) { 126 String className = ClassUtils.getShortClassName(clazz); 127 if (className.equals(ClassUtils.getShortClassName(RendererBase.class))) { 128 return "Tobago"; 129 } else if (className.endsWith("Renderer")) { 130 return className.substring(0, className.lastIndexOf("Renderer")); 131 } else if (className.endsWith("RendererBase")) { 132 return className.substring(0, className.lastIndexOf("RendererBase")) + "Base"; 133 } 134 return null; 135 } 136 137 138 private static class CacheKey { 139 private String clientProperties; 140 private Locale locale; 141 private String rendererType; 142 private String name; 143 144 public CacheKey(UIViewRoot viewRoot, UIComponent component, String name) { 145 this.clientProperties = ClientProperties.getInstance(viewRoot).getId(); 146 this.locale = viewRoot.getLocale(); 147 if (component != null) { 148 rendererType = component.getRendererType(); 149 } else { 150 rendererType = "DEFAULT"; 151 } 152 this.name = name; 153 } 154 155 public boolean equals(Object o) { 156 if (this == o) { 157 return true; 158 } 159 if (o == null || getClass() != o.getClass()) { 160 return false; 161 } 162 163 final CacheKey cacheKey = (CacheKey) o; 164 165 if (!clientProperties.equals(cacheKey.clientProperties)) { 166 return false; 167 } 168 if (!locale.equals(cacheKey.locale)) { 169 return false; 170 } 171 if (!name.equals(cacheKey.name)) { 172 return false; 173 } 174 if (!rendererType.equals(cacheKey.rendererType)) { 175 return false; 176 } 177 178 return true; 179 } 180 181 public int hashCode() { 182 int result; 183 result = clientProperties.hashCode(); 184 result = 29 * result + locale.hashCode(); 185 result = 29 * result + rendererType.hashCode(); 186 result = 29 * result + name.hashCode(); 187 return result; 188 } 189 } 190 191 }