001    package org.apache.myfaces.tobago.context;
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.slf4j.Logger;
021    import org.slf4j.LoggerFactory;
022    import org.apache.myfaces.tobago.config.TobagoConfig;
023    import org.apache.myfaces.tobago.internal.context.ClientPropertiesKey;
024    import org.apache.myfaces.tobago.layout.Measure;
025    import org.apache.myfaces.tobago.util.VariableResolverUtils;
026    
027    import javax.faces.component.UIViewRoot;
028    import javax.faces.context.ExternalContext;
029    import javax.faces.context.FacesContext;
030    import java.io.Serializable;
031    import java.util.ArrayList;
032    import java.util.List;
033    import java.util.Locale;
034    
035    /**
036     * The ClientProperties contains data, which are individual for each user.
037     * It is stored in the session by default, but the application can override this in the faces-config.xml.
038     * <p/>
039     * The managed bean name which is Tobago using for the instance is {@link #MANAGED_BEAN_NAME}.
040     * <p/>
041     * Please use {@link org.apache.myfaces.tobago.util.VariableResolverUtils#resolveClientProperties(FacesContext)}
042     * to access to the users client properties.
043     */
044    
045    public class ClientProperties implements Serializable {
046    
047      /**
048       * The name of the managed bean
049       */
050      public static final String MANAGED_BEAN_NAME = "tobagoClientProperties";
051    
052      private static final long serialVersionUID = 2L;
053    
054      private static final Logger LOG = LoggerFactory.getLogger(ClientProperties.class);
055    
056      private String contentType = "html";
057      private Theme theme;
058      private UserAgent userAgent = UserAgent.DEFAULT;
059      private boolean debugMode;
060    
061      private Locale locale;
062    
063      private Measure verticalScrollbarWeight;
064      private Measure horizontalScrollbarWeight;
065    
066      /** 
067       * managed bean constructor
068       */
069      public ClientProperties() {
070        this(FacesContext.getCurrentInstance());
071      }
072    
073      /**
074       * @deprecated since 1.5.
075       */
076      private ClientProperties(TobagoConfig tobagoConfig) {
077        theme = tobagoConfig.getDefaultTheme();
078        reset();
079      }
080    
081      private ClientProperties(FacesContext facesContext) {
082    
083        ExternalContext externalContext = facesContext.getExternalContext();
084    
085        // content type
086        String accept = (String) externalContext.getRequestHeaderMap().get("Accept");
087        if (accept != null) {
088          if (accept.indexOf("text/vnd.wap.wml") > -1) {
089            contentType = "wml";
090          }
091        }
092        if (LOG.isInfoEnabled()) {
093          LOG.info("contentType='" + contentType + "' from header " + "Accept='" + accept + "'");
094        }
095    
096        // user agent
097        String requestUserAgent = (String) externalContext.getRequestHeaderMap().get("User-Agent");
098        this.userAgent = UserAgent.getInstance(requestUserAgent);
099        if (LOG.isInfoEnabled()) {
100          LOG.info("userAgent='" + this.userAgent + "' from header " + "'User-Agent: " + requestUserAgent + "'");
101        }
102    
103        // theme
104        String requestTheme = (String) externalContext.getRequestParameterMap().get("tobago.theme");
105        TobagoConfig config = TobagoConfig.getInstance(facesContext);
106        // TODO log error if tobago config is not initialized
107        this.theme = config.getTheme(requestTheme);
108        if (LOG.isInfoEnabled()) {
109          LOG.info("theme='" + theme.getName() + "' from requestParameter " + "tobago.theme='" + requestTheme + "'");
110        }
111    
112        reset();
113      }
114    
115      /**
116       * @deprecated since 1.5.
117       */
118      @Deprecated
119      public static ClientProperties getDefaultInstance(FacesContext facesContext) {
120        return new ClientProperties(TobagoConfig.getInstance(facesContext));
121      }
122    
123      /**
124       * @deprecated since 1.5. Please use 
125       * {@link 
126       * org.apache.myfaces.tobago.util.VariableResolverUtils#resolveClientProperties(javax.faces.context.FacesContext)} 
127       */
128      @Deprecated
129      public static ClientProperties getInstance(UIViewRoot viewRoot) {
130        return getInstance(FacesContext.getCurrentInstance());
131      }
132    
133      /**
134       * @deprecated since 1.5. Please use 
135       * {@link 
136       * org.apache.myfaces.tobago.util.VariableResolverUtils#resolveClientProperties(javax.faces.context.FacesContext)} 
137       */
138      @Deprecated
139      public static ClientProperties getInstance(FacesContext facesContext) {
140        return (ClientProperties) VariableResolverUtils.resolveClientProperties(facesContext);
141      }
142    
143      /**
144       * @deprecated since 1.5. Please use 
145       * {@link org.apache.myfaces.tobago.util.LocaleUtils#getLocaleSuffixList(java.util.Locale)} 
146       */
147      @Deprecated
148      public static List<String> getLocaleList(Locale locale, boolean propertyPathMode) {
149        String string = locale.toString();
150        String prefix = propertyPathMode ? "" : "_";
151        List<String> locales = new ArrayList<String>(4);
152        locales.add(prefix + string);
153        int underscore;
154        while ((underscore = string.lastIndexOf('_')) > 0) {
155          string = string.substring(0, underscore);
156          locales.add(prefix + string);
157        }
158    
159        locales.add(propertyPathMode ? "default" : ""); // default suffix
160    
161        return locales;
162      }
163    
164      private void reset() {
165        ClientPropertiesKey.reset(FacesContext.getCurrentInstance());
166      }
167    
168      public String getContentType() {
169        return contentType;
170      }
171    
172      public void setContentType(String contentType) {
173        this.contentType = contentType;
174        reset();
175      }
176    
177      public Theme getTheme() {
178        return theme;
179      }
180      
181      public void setTheme(Theme theme) {
182        this.theme = theme;
183        reset();
184      }
185    
186      public UserAgent getUserAgent() {
187        return userAgent;
188      }
189    
190      public void setUserAgent(UserAgent userAgent) {
191        this.userAgent = userAgent;
192        reset();
193      }
194    
195      public boolean isDebugMode() {
196        return debugMode;
197      }
198    
199      public void setDebugMode(boolean debugMode) {
200        this.debugMode = debugMode;
201      }
202    
203      public Locale getLocale() {
204        return locale;
205      }
206    
207      /**
208       * Holds the locale of the user, which is located in the UIViewRoot.
209       * This setter should not be called from the application directly, 
210       * but via {@link UIViewRoot#setLocale(Locale locale)} 
211       */
212      public void setLocale(Locale locale) {
213        // set locale will be called "too often" from the JSF
214        if (this.locale == null && locale != null || this.locale != null && locale == null || !this.locale.equals(locale)) {
215          this.locale = locale;
216          reset();
217        }
218      }
219    
220      public Measure getVerticalScrollbarWeight() {
221        return verticalScrollbarWeight;
222      }
223    
224      public void setVerticalScrollbarWeight(Measure verticalScrollbarWeight) {
225        this.verticalScrollbarWeight = verticalScrollbarWeight;
226      }
227    
228      public Measure getHorizontalScrollbarWeight() {
229        return horizontalScrollbarWeight;
230      }
231    
232      public void setHorizontalScrollbarWeight(Measure horizontalScrollbarWeight) {
233        this.horizontalScrollbarWeight = horizontalScrollbarWeight;
234      }
235    }