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, UIComponent component, String name) { 080 String family; 081 String rendererType; 082 if (component != null) { 083 family = component.getFamily(); 084 rendererType = component.getRendererType(); 085 } else { 086 family = UIInput.COMPONENT_FAMILY; 087 rendererType = RENDERER_TYPE_IN; 088 } 089 Renderer renderer = ComponentUtil.getRenderer(facesContext, family, rendererType); 090 091 Class clazz = renderer.getClass(); 092 if (LOG.isDebugEnabled()) { 093 LOG.debug("search for '" + name + "' in '" + clazz.getName() + "'"); 094 } 095 ResourceManager resourceManager 096 = ResourceManagerFactory.getResourceManager(facesContext); 097 UIViewRoot viewRoot = facesContext.getViewRoot(); 098 while (clazz != null) { 099 String tag = getTagName(clazz); 100 if (LOG.isDebugEnabled()) { 101 LOG.debug("try " + tag); 102 } 103 104 String property = resourceManager.getThemeProperty(viewRoot, "tobago-theme-config", tag + "." + name); 105 106 if (property != null && property.length() > 0) { 107 if (LOG.isDebugEnabled()) { 108 LOG.debug("found " + property); 109 } 110 return new Integer(property); 111 } 112 clazz = clazz.getSuperclass(); 113 } 114 // todo: remove condition, is only temporary to ignore wml errors. 115 if (!ClientProperties.getInstance(viewRoot).getContentType().equals("wml")) { 116 LOG.error("Theme property '" + name + "' not found for renderer: " + renderer.getClass() 117 + " with clientProperties='" + ClientProperties.getInstance(viewRoot).getId() + "'" 118 + " and locale='" + viewRoot.getLocale() + "'"); 119 } 120 return null; 121 } 122 123 private static String getTagName(Class clazz) { 124 String className = ClassUtils.getShortClassName(clazz); 125 if (className.equals(ClassUtils.getShortClassName(RendererBase.class))) { 126 return "Tobago"; 127 } else if (className.endsWith("Renderer")) { 128 return className.substring(0, className.lastIndexOf("Renderer")); 129 } else if (className.endsWith("RendererBase")) { 130 return className.substring(0, className.lastIndexOf("RendererBase")) + "Base"; 131 } 132 return null; 133 } 134 135 136 private static class CacheKey { 137 private String clientProperties; 138 private Locale locale; 139 private String rendererType; 140 private String name; 141 142 public CacheKey(UIViewRoot viewRoot, UIComponent component, String name) { 143 this.clientProperties = ClientProperties.getInstance(viewRoot).getId(); 144 this.locale = viewRoot.getLocale(); 145 if (component != null) { 146 rendererType = component.getRendererType(); 147 } else { 148 rendererType = "DEFAULT"; 149 } 150 this.name = name; 151 } 152 153 public boolean equals(Object o) { 154 if (this == o) { 155 return true; 156 } 157 if (o == null || getClass() != o.getClass()) { 158 return false; 159 } 160 161 final CacheKey cacheKey = (CacheKey) o; 162 163 if (!clientProperties.equals(cacheKey.clientProperties)) { 164 return false; 165 } 166 if (!locale.equals(cacheKey.locale)) { 167 return false; 168 } 169 if (!name.equals(cacheKey.name)) { 170 return false; 171 } 172 if (!rendererType.equals(cacheKey.rendererType)) { 173 return false; 174 } 175 176 return true; 177 } 178 179 public int hashCode() { 180 int result; 181 result = clientProperties.hashCode(); 182 result = 29 * result + locale.hashCode(); 183 result = 29 * result + rendererType.hashCode(); 184 result = 29 * result + name.hashCode(); 185 return result; 186 } 187 } 188 189 }