View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.internal.config;
21  
22  import org.apache.myfaces.tobago.application.ProjectStage;
23  import org.apache.myfaces.tobago.config.TobagoConfig;
24  import org.apache.myfaces.tobago.context.Theme;
25  import org.apache.myfaces.tobago.internal.util.Deprecation;
26  import org.apache.myfaces.tobago.internal.util.JndiUtils;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  
30  import javax.faces.application.Application;
31  import javax.faces.context.FacesContext;
32  import javax.naming.Context;
33  import javax.naming.InitialContext;
34  import javax.naming.NamingException;
35  import javax.servlet.ServletContext;
36  import java.net.URL;
37  import java.util.ArrayList;
38  import java.util.Collections;
39  import java.util.HashSet;
40  import java.util.List;
41  import java.util.Map;
42  import java.util.Set;
43  
44  public class TobagoConfigImpl extends TobagoConfig {
45  
46    private static final Logger LOG = LoggerFactory.getLogger(TobagoConfigImpl.class);
47  
48    public static final String TOBAGO_CONFIG = "org.apache.myfaces.tobago.config.TobagoConfig";
49  
50    private List<Theme> supportedThemes;
51    private List<String> supportedThemeNames;
52    private Theme defaultTheme;
53    private String defaultThemeName;
54    private List<String> resourceDirs;
55    private Map<String, Theme> availableThemes;
56    private RenderersConfig renderersConfig;
57    private ProjectStage projectStage;
58    private boolean createSessionSecret;
59    private boolean checkSessionSecret;
60    private boolean preventFrameAttacks;
61    private ContentSecurityPolicy contentSecurityPolicy;
62    private URL url;
63    private Map<String, String> defaultValidatorInfo;
64  
65    public TobagoConfigImpl() {
66      supportedThemeNames = new ArrayList<String>();
67      supportedThemes = new ArrayList<Theme>();
68      resourceDirs = new ArrayList<String>();
69      createSessionSecret = true;
70      checkSessionSecret = true;
71      preventFrameAttacks = true;
72      contentSecurityPolicy = new ContentSecurityPolicy(ContentSecurityPolicy.Mode.OFF.getValue());
73    }
74  
75    public void addSupportedThemeName(String name) {
76      supportedThemeNames.add(name);
77    }
78    // TODO one init method
79    public void resolveThemes() {
80      if (defaultThemeName != null) {
81        defaultTheme = availableThemes.get(defaultThemeName);
82        checkThemeIsAvailable(defaultThemeName, defaultTheme);
83        if (LOG.isDebugEnabled()) {
84          LOG.debug("name = '{}'", defaultThemeName);
85          LOG.debug("defaultTheme = '{}'", defaultTheme);
86        }
87      } else {
88        int deep = 0;
89        for (Map.Entry<String, Theme> entry : availableThemes.entrySet()) {
90          Theme theme = entry.getValue();
91          if (theme.getFallbackList().size() > deep) {
92            defaultTheme = theme;
93            deep = theme.getFallbackList().size();
94          }
95        }
96        if (defaultTheme == null) {
97          String error = "Did not found any theme! "
98              + "Please ensure you have a tobago-config.xml with a theme-definition in your "
99              + "theme JAR. Please add a theme JAR to your WEB-INF/lib";
100         LOG.error(error);
101         throw new RuntimeException(error);
102       } else {
103         if (LOG.isInfoEnabled()) {
104           LOG.info("Using default Theme {}", defaultTheme.getName());
105         }
106       }
107     }
108     if (!supportedThemeNames.isEmpty()) {
109       for (String name : supportedThemeNames) {
110         Theme theme = availableThemes.get(name);
111         checkThemeIsAvailable(name, theme);
112         supportedThemes.add(theme);
113         if (LOG.isDebugEnabled()) {
114           LOG.debug("name = '{}'",  name);
115           LOG.debug("supportedThemes.last() = '{}'", supportedThemes.get(supportedThemes.size() - 1));
116         }
117       }
118     }
119   }
120 
121   private void checkThemeIsAvailable(String name, Theme theme) {
122     if (theme == null) {
123       String error = "Theme not found! name: '" + name + "'. "
124           + "Please ensure you have a tobago-config.xml with a theme-definition in your "
125           + "theme JAR. Found the following themes: " + availableThemes.keySet();
126       LOG.error(error);
127       throw new RuntimeException(error);
128     }
129   }
130 
131   public Theme getTheme(String name) {
132     if (name == null) {
133       LOG.debug("searching theme: null");
134       return defaultTheme;
135     }
136     if (defaultTheme.getName().equals(name)) {
137       return defaultTheme;
138     }
139     for (Theme theme : supportedThemes) {
140       if (theme.getName().equals(name)) {
141         return theme;
142       }
143     }
144     LOG.debug("searching theme '{}' not found. Using default: {}", name, defaultTheme);
145     return defaultTheme;
146   }
147 
148   public void setDefaultThemeName(String defaultThemeName) {
149     this.defaultThemeName = defaultThemeName;
150   }
151 
152   public List<Theme> getSupportedThemes() {
153     return Collections.unmodifiableList(supportedThemes);
154   }
155 
156   public void addResourceDir(String resourceDir) {
157     if (!resourceDirs.contains(resourceDir)) {
158       if (LOG.isInfoEnabled()) {
159         LOG.info("adding resourceDir = '{}'", resourceDir);
160       }
161       resourceDirs.add(0, resourceDir);
162     }
163   }
164 
165   public List<String> getResourceDirs() {
166     return resourceDirs;
167   }
168 
169   /** @deprecated since 1.5.0 */
170   @Deprecated
171   public boolean isAjaxEnabled() {
172     Deprecation.LOG.warn("Ajax is always enabled!");
173     return true;
174   }
175 
176   public Theme getDefaultTheme() {
177     return defaultTheme;
178   }
179 
180   public void setAvailableThemes(Map<String, Theme> availableThemes) {
181     this.availableThemes = availableThemes;
182     for (Theme theme : this.availableThemes.values()) {
183       addResourceDir(theme.getResourcePath());
184     }
185   }
186 
187   public RenderersConfig getRenderersConfig() {
188     return renderersConfig;
189   }
190 
191   public void setRenderersConfig(RenderersConfig renderersConfig) {
192     this.renderersConfig = renderersConfig;
193   }
194 
195   public ProjectStage getProjectStage() {
196     return projectStage;
197   }
198   // TODO one init method
199   public void initProjectState(ServletContext servletContext) {
200     String stageName = null;
201     try {
202       Context ctx = new InitialContext();
203       Object obj = JndiUtils.getJndiProperty(ctx, "jsf", "ProjectStage");
204       if (obj != null) {
205         if (obj instanceof String) {
206           stageName = (String) obj;
207         } else {
208           LOG.warn("JNDI lookup for key {} should return a java.lang.String value",
209               ProjectStage.PROJECT_STAGE_JNDI_NAME);
210         }
211       }
212     } catch (NamingException e) {
213       // ignore
214     }
215 
216     if (stageName == null) {
217       stageName = servletContext.getInitParameter(ProjectStage.PROJECT_STAGE_PARAM_NAME);
218     }
219 
220     if (stageName == null) {
221       stageName = System.getProperty("org.apache.myfaces.PROJECT_STAGE");
222     }
223 
224     if (stageName != null) {
225       try {
226         projectStage = ProjectStage.valueOf(stageName);
227       } catch (IllegalArgumentException e) {
228         LOG.error("Couldn't discover the current project stage", e);
229       }
230     }
231     if (projectStage == null) {
232       if (LOG.isInfoEnabled()) {
233         LOG.info("Couldn't discover the current project stage, using {}", ProjectStage.Production);
234       }
235       projectStage = ProjectStage.Production;
236     }
237   }
238 
239   public synchronized void initDefaultValidatorInfo() {
240     final FacesContext facesContext = FacesContext.getCurrentInstance();
241     if (facesContext != null) {
242       try {
243         final Application application = facesContext.getApplication();
244         final Map<String, String> map = application.getDefaultValidatorInfo();
245         if (map.size() > 0) {
246           defaultValidatorInfo = Collections.unmodifiableMap(map);
247         } else {
248           defaultValidatorInfo = Collections.emptyMap();
249         }
250       } catch (Exception e) {
251         LOG.error("Can't initialize default validators (this happens with JBoss GateIn 3.6.0).", e);
252         defaultValidatorInfo = Collections.emptyMap();
253       }
254     }
255   }
256 
257   public boolean isCreateSessionSecret() {
258     return createSessionSecret;
259   }
260 
261   public void setCreateSessionSecret(boolean createSessionSecret) {
262     this.createSessionSecret = createSessionSecret;
263   }
264 
265   public boolean isCheckSessionSecret() {
266     return checkSessionSecret;
267   }
268 
269   public void setCheckSessionSecret(boolean checkSessionSecret) {
270     this.checkSessionSecret = checkSessionSecret;
271   }
272 
273 
274   public boolean isPreventFrameAttacks() {
275     return preventFrameAttacks;
276   }
277 
278   public void setPreventFrameAttacks(boolean preventFrameAttacks) {
279     this.preventFrameAttacks = preventFrameAttacks;
280   }
281 
282   public ContentSecurityPolicy getContentSecurityPolicy() {
283     return contentSecurityPolicy;
284   }
285 
286   public Map<String, String> getDefaultValidatorInfo() {
287 
288     // TODO: if the startup hasn't found a FacesContext and Application, this may depend on the order of the listeners.
289     if (defaultValidatorInfo == null) {
290       initDefaultValidatorInfo();
291     }
292     return defaultValidatorInfo;
293   }
294 
295   @Override
296   public String toString() {
297     final StringBuilder builder = new StringBuilder();
298     builder.append("TobagoConfigImpl{");
299     builder.append("\nsupportedThemes=[");
300     for (Theme supportedTheme : supportedThemes) {
301       builder.append(supportedTheme.getName());
302       builder.append(", ");
303     }
304     builder.append("], \ndefaultTheme=");
305     builder.append(defaultTheme.getName());
306     builder.append(", \nresourceDirs=");
307     builder.append(resourceDirs);
308     builder.append(", \navailableThemes=");
309     builder.append(availableThemes.keySet());
310     builder.append(", \nprojectStage=");
311     builder.append(projectStage);
312     builder.append(", \ncreateSessionSecret=");
313     builder.append(createSessionSecret);
314     builder.append(", \ncheckSessionSecret=");
315     builder.append(checkSessionSecret);
316     builder.append(", \nurl=");
317     builder.append(url);
318     // to see only different (ignore alternative names for the same theme)
319     builder.append(", \nthemes=");
320     Set<Theme> all = new HashSet<Theme>(availableThemes.values());
321     builder.append(all);
322     builder.append('}');
323     return builder.toString();
324   }
325 }