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.myfaces.tobago.application.ProjectStage;
021    import org.apache.myfaces.tobago.context.RenderersConfig;
022    import org.apache.myfaces.tobago.context.Theme;
023    import org.apache.myfaces.tobago.internal.util.Deprecation;
024    import org.apache.myfaces.tobago.internal.util.JndiUtils;
025    import org.slf4j.Logger;
026    import org.slf4j.LoggerFactory;
027    
028    import javax.faces.context.FacesContext;
029    import javax.naming.Context;
030    import javax.naming.InitialContext;
031    import javax.naming.NamingException;
032    import javax.servlet.ServletContext;
033    import java.util.ArrayList;
034    import java.util.Collections;
035    import java.util.List;
036    import java.util.Map;
037    
038    public class TobagoConfig {
039    
040      private static final Logger LOG = LoggerFactory.getLogger(TobagoConfig.class);
041    
042      public static final String TOBAGO_CONFIG = "org.apache.myfaces.tobago.config.TobagoConfig";
043    
044      private List<Theme> supportedThemes;
045      private List<String> supportedThemeNames;
046      private Theme defaultTheme;
047      private String defaultThemeName;
048      private List<String> resourceDirs;
049      private Map<String, Theme> availableThemes;
050      private RenderersConfig renderersConfig;
051      private ProjectStage projectStage;
052      private boolean createSessionSecret;
053      private boolean checkSessionSecret;
054    
055      public TobagoConfig() {
056        supportedThemeNames = new ArrayList<String>();
057        supportedThemes = new ArrayList<Theme>();
058        resourceDirs = new ArrayList<String>();
059        createSessionSecret = true;
060        checkSessionSecret = true;
061      }
062    
063      public void addSupportedThemeName(String name) {
064        supportedThemeNames.add(name);
065      }
066      // TODO one init method
067      public void resolveThemes() {
068        if (defaultThemeName != null) {
069          defaultTheme = availableThemes.get(defaultThemeName);
070          checkThemeIsAvailable(defaultThemeName, defaultTheme);
071          if (LOG.isDebugEnabled()) {
072            LOG.debug("name = '{}'", defaultThemeName);
073            LOG.debug("defaultTheme = '{}'", defaultTheme);
074          }
075        } else {
076          int deep = 0;
077          for (Map.Entry<String, Theme> entry : availableThemes.entrySet()) {
078            Theme theme = entry.getValue();
079            if (theme.getFallbackList().size() > deep) {
080              defaultTheme = theme;
081              deep = theme.getFallbackList().size();
082            }
083          }
084          if (defaultTheme == null) {
085            String error = "Did not found any theme! "
086                + "Please ensure you have a tobago-theme.xml file in your "
087                + "theme jar. Please add a theme jar to your WEB-INF/lib";
088            LOG.error(error);
089            throw new RuntimeException(error);
090          } else {
091            if (LOG.isInfoEnabled()) {
092              LOG.info("Using default Theme {}", defaultTheme.getName());
093            }
094          }
095        }
096        if (!supportedThemeNames.isEmpty()) {
097          for (String name : supportedThemeNames) {
098            Theme theme = availableThemes.get(name);
099            checkThemeIsAvailable(name, theme);
100            supportedThemes.add(theme);
101            if (LOG.isDebugEnabled()) {
102              LOG.debug("name = '{}'",  name);
103              LOG.debug("supportedThemes.last() = '{}'", supportedThemes.get(supportedThemes.size() - 1));
104            }
105          }
106        }
107      }
108    
109      private void checkThemeIsAvailable(String name, Theme theme) {
110        if (theme == null) {
111          String error = "Theme not found! name: '" + name + "'. "
112              + "Please ensure you have a tobago-theme.xml file in your "
113              + "theme jar. Found the following themes: " + availableThemes.keySet();
114          LOG.error(error);
115          throw new RuntimeException(error);
116        }
117      }
118    
119      public static TobagoConfig getInstance(FacesContext facesContext) {
120        return (TobagoConfig) facesContext.getExternalContext().getApplicationMap().get(TOBAGO_CONFIG);
121      }
122    
123      public static TobagoConfig getInstance(ServletContext servletContext) {
124        return (TobagoConfig) servletContext.getAttribute(TOBAGO_CONFIG);
125      }
126    
127      public Theme getTheme(String name) {
128        if (name == null) {
129          LOG.debug("searching theme: null");
130          return defaultTheme;
131        }
132        if (defaultTheme.getName().equals(name)) {
133          return defaultTheme;
134        }
135        for (Theme theme : supportedThemes) {
136          if (theme.getName().equals(name)) {
137            return theme;
138          }
139        }
140        LOG.debug("searching theme '{}' not found. Using default: {}", name, defaultTheme);
141        return defaultTheme;
142      }
143    
144      public void setDefaultThemeName(String defaultThemeName) {
145        this.defaultThemeName = defaultThemeName;
146      }
147    
148      public List<Theme> getSupportedThemes() {
149        return Collections.unmodifiableList(supportedThemes);
150      }
151    
152      public void addResourceDir(String resourceDir) {
153        if (!resourceDirs.contains(resourceDir)) {
154          if (LOG.isInfoEnabled()) {
155            LOG.info("adding resourceDir = '{}'", resourceDir);
156          }
157          resourceDirs.add(resourceDir);
158        }
159      }
160    
161      public List<String> getResourceDirs() {
162        return resourceDirs;
163      }
164    
165      /** @deprecated */
166      @Deprecated
167      public boolean isAjaxEnabled() {
168        Deprecation.LOG.warn("Ajax is always enabled!");
169        return true;
170      }
171    
172      /** @deprecated */
173      @Deprecated
174      public void setAjaxEnabled(String value) {
175        Deprecation.LOG.error("Ajax is always enabled!");
176      }
177    
178      public Theme getDefaultTheme() {
179        return defaultTheme;
180      }
181    
182      public void setAvailableThemes(Map<String, Theme> availableThemes) {
183        this.availableThemes = availableThemes;
184        for (Theme theme : this.availableThemes.values()) {
185          addResourceDir(theme.getResourcePath());
186        }
187      }
188    
189      public RenderersConfig getRenderersConfig() {
190        return renderersConfig;
191      }
192    
193      public void setRenderersConfig(RenderersConfig renderersConfig) {
194        this.renderersConfig = renderersConfig;
195      }
196    
197      public ProjectStage getProjectStage() {
198        return projectStage;
199      }
200      // TODO one init method
201      public void initProjectState(ServletContext servletContext) {
202        String stageName = null;
203        try {
204          Context ctx = new InitialContext();
205          Object obj = JndiUtils.getJndiProperty(ctx, "jsf", "ProjectStage");
206          if (obj != null) {
207            if (obj instanceof String) {
208              stageName = (String) obj;
209            } else {
210              LOG.warn("JNDI lookup for key {} should return a java.lang.String value",
211                  ProjectStage.PROJECT_STAGE_JNDI_NAME);
212            }
213          }
214        } catch (NamingException e) {
215          // ignore
216        }
217    
218        if (stageName == null) {
219          stageName = servletContext.getInitParameter(ProjectStage.PROJECT_STAGE_PARAM_NAME);
220        }
221    
222        if (stageName == null) {
223          stageName = System.getProperty("org.apache.myfaces.PROJECT_STAGE");
224        }
225    
226        if (stageName != null) {
227          try {
228            projectStage = ProjectStage.valueOf(stageName);
229          } catch (IllegalArgumentException e) {
230            LOG.error("Couldn't discover the current project stage", e);
231          }
232        }
233        if (projectStage == null) {
234          if (LOG.isInfoEnabled()) {
235            LOG.info("Couldn't discover the current project stage, using {}", ProjectStage.Production);
236          }
237          projectStage = ProjectStage.Production;
238        }
239      }
240    
241      public boolean isCreateSessionSecret() {
242        return createSessionSecret;
243      }
244    
245      public void setCreateSessionSecret(String createSessionSecret) {
246        this.createSessionSecret = Boolean.valueOf(createSessionSecret);
247      }
248    
249      public boolean isCheckSessionSecret() {
250        return checkSessionSecret;
251      }
252    
253      public void setCheckSessionSecret(String checkSessionSecret) {
254        this.checkSessionSecret = Boolean.valueOf(checkSessionSecret);
255      }
256    
257      @Deprecated
258      public void setFixResourceOrder(String value) {
259        Deprecation.LOG.error("Config fix-resource-order not longer supported. (Is always activated).");
260      }
261    
262      @Deprecated
263      public void setFixLayoutTransparency(String value) {
264        Deprecation.LOG.error("Config fix-layout-transparency not longer supported. (Is always activated).");
265      }
266    }