View Javadoc

1   /*
2    * $Id: ConfiguredHttpServlet.java,v 1.18 2011/06/16 09:29:41 jbmeslin Exp $
3    * 
4    */
5   package org.rcfaces.core.internal.webapp;
6   
7   import java.util.HashMap;
8   import java.util.HashSet;
9   import java.util.Locale;
10  import java.util.Map;
11  import java.util.Set;
12  import java.util.StringTokenizer;
13  
14  import javax.servlet.ServletConfig;
15  import javax.servlet.ServletException;
16  import javax.servlet.http.HttpServletRequest;
17  import javax.servlet.http.HttpServletResponse;
18  
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  import org.rcfaces.core.internal.Constants;
22  import org.rcfaces.core.internal.util.Delay;
23  import org.rcfaces.core.internal.util.ServletTools;
24  
25  /**
26   * @author Olivier Oeuillot (latest modification by $Author: jbmeslin $)
27   * @version $Revision: 1.18 $ $Date: 2011/06/16 09:29:41 $
28   */
29  public class ConfiguredHttpServlet extends ExtendedHttpServlet {
30  
31      private static final String REVISION = "$Revision: 1.18 $";
32  
33      private static final long serialVersionUID = 8336388990583712944L;
34  
35      private static final Log LOG = LogFactory
36              .getLog(ConfiguredHttpServlet.class);
37  
38      public static final String USE_GZIP_PARAMETER = Constants
39              .getPackagePrefix()
40              + ".GZIP_SUPPORT";
41  
42      private static final String EXPIRE_PARAMETER = Constants.getPackagePrefix()
43              + ".EXPIRES";
44  
45      private static final String VERSIONED_EXPIRE_PARAMETER = Constants
46              .getPackagePrefix()
47              + ".VERSIONED_EXPIRES";
48  
49      private static final String ETAG_SUPPORT_PARAMETER = Constants
50              .getPackagePrefix()
51              + ".ETAG_SUPPORT";
52  
53      private static final String HASH_SUPPORT_PARAMETER = Constants
54              .getPackagePrefix()
55              + ".HASH_SUPPORT";
56  
57      private static final String FILTERED_LOCALES_PARAMETER = Constants
58              .getPackagePrefix()
59              + ".FILTERED_LOCALES";
60  
61      private static final String DEFAULT_LOCALE_PARAMETER = Constants
62              .getPackagePrefix()
63              + ".DEFAULT_LOCALE";
64  
65      private static final String LOCALE_SUPPORT_PARAMETER = Constants
66              .getPackagePrefix()
67              + ".LOCALE_SUPPORT";
68  
69      private static final String NONE_EXPIRATION_KEYWORD = "none";
70  
71      private boolean gZipSupport;
72  
73      private boolean etagSupport;
74  
75      private boolean hashSupport;
76  
77      private ExpirationDate expirationDate;
78  
79      private ExpirationDate versionedExpirationDate;
80  
81      private Set filtredLocales;
82  
83      protected boolean localeSupport;
84  
85      private final Map convertedLocales = new HashMap(32);
86  
87      private Locale defaultLocale;
88  
89      public void init(ServletConfig config) throws ServletException {
90  
91          super.init(config);
92  
93          String useGZIP = getParameter(USE_GZIP_PARAMETER);
94          if ("true".equalsIgnoreCase(useGZIP)) {
95              gZipSupport = true;
96  
97              LOG.info("Enable gzip support for sevlet '" + getServletName()
98                      + "'");
99          } else if ("false".equalsIgnoreCase(useGZIP)) {
100             gZipSupport = false;
101 
102             LOG.info("Disable gzip support for sevlet '" + getServletName()
103                     + "'");
104         } else {
105             gZipSupport = getDefaultGZipSupport();
106 
107             LOG.info("Use default gzip support configuration (value="
108                     + this.gZipSupport + ") for sevlet '" + getServletName()
109                     + "'");
110         }
111 
112         String etagSupport = getParameter(ETAG_SUPPORT_PARAMETER);
113         if ("true".equalsIgnoreCase(etagSupport)) {
114             this.etagSupport = true;
115 
116             LOG.info("Enable etag support for sevlet '" + getServletName()
117                     + "'");
118 
119         } else if ("false".equalsIgnoreCase(etagSupport)) {
120             this.etagSupport = false;
121 
122             LOG.info("Disable etag support for sevlet '" + getServletName()
123                     + "'");
124 
125         } else {
126             this.etagSupport = getDefaultETagSupport();
127 
128             LOG.info("Use default ETag support configuration (value="
129                     + this.etagSupport + ") for sevlet '" + getServletName()
130                     + "'");
131         }
132 
133         String hashSupport = getParameter(HASH_SUPPORT_PARAMETER);
134         if ("true".equalsIgnoreCase(hashSupport)) {
135             this.hashSupport = true;
136 
137             LOG.info("Enable hash support for sevlet '" + getServletName()
138                     + "'");
139 
140         } else if ("false".equalsIgnoreCase(hashSupport)) {
141             this.hashSupport = false;
142 
143             LOG.info("Disable hash support for sevlet '" + getServletName()
144                     + "'");
145 
146         } else {
147             this.hashSupport = getDefaultHashSupport();
148 
149             LOG.info("Use default Hash support configuration (value="
150                     + this.hashSupport + ") for sevlet '" + getServletName()
151                     + "'");
152         }
153 
154         String expires = getParameter(EXPIRE_PARAMETER);
155         if (expires != null) {
156             expirationDate = ExpirationDate.parse(getServletName(),
157                     EXPIRE_PARAMETER, expires);
158         }
159 
160         if (expirationDate == null
161                 && NONE_EXPIRATION_KEYWORD.equalsIgnoreCase(expires) == false) {
162             expirationDate = ExpirationDate
163                     .fromDelay(getDefaultExpirationDelay());
164         }
165 
166         if (LOG.isInfoEnabled() && expirationDate != null) {
167             if (expirationDate.getExpiresDate() >= 0) {
168                 LOG.info("Expire date setted to "
169                         + expirationDate.getExpiresDate() + "  for sevlet '"
170                         + getServletName() + "'.");
171             }
172 
173             if (expirationDate.getExpiresDelay() >= 0) {
174                 LOG.info("Expire delay setted to "
175                         + Delay.format(expirationDate.getExpiresDelay())
176                         + " for sevlet '" + getServletName() + "'.");
177 
178             }
179         }
180 
181         String versionedExpires = getParameter(VERSIONED_EXPIRE_PARAMETER);
182         if (versionedExpires != null) {
183             versionedExpirationDate = ExpirationDate.parse(getServletName(),
184                     VERSIONED_EXPIRE_PARAMETER, versionedExpires);
185         }
186 
187         if (versionedExpirationDate == null
188                 && NONE_EXPIRATION_KEYWORD.equalsIgnoreCase(versionedExpires) == false) {
189             versionedExpirationDate = ExpirationDate
190                     .fromDelay(getDefaultVersionedExpirationDelay());
191         }
192 
193         if (LOG.isInfoEnabled() && versionedExpirationDate != null) {
194             if (versionedExpirationDate.getExpiresDate() >= 0) {
195                 LOG.info("Versioned resources expire date detected: "
196                         + versionedExpirationDate.getExpiresDate()
197                         + "  for sevlet '" + getServletName() + "'");
198             }
199 
200             if (versionedExpirationDate.getExpiresDelay() >= 0) {
201                 LOG.info("Versioned resources expire delay setted to "
202                         + Delay.format(versionedExpirationDate
203                                 .getExpiresDelay()) + " for sevlet '"
204                         + getServletName() + "'");
205             }
206         }
207 
208         if (hasLocaleSupport()) {
209             String localeSupportProperty = getParameter(LOCALE_SUPPORT_PARAMETER);
210             if ("false".equalsIgnoreCase(localeSupportProperty)) {
211                 localeSupport = false;
212 
213                 LOG.info("LOCALE_SUPPORT is disabled for servlet '"
214                         + getServletName() + "'.");
215             } else if ("true".equalsIgnoreCase(localeSupportProperty)) {
216                 localeSupport = true;
217 
218                 LOG.info("LOCALE_SUPPORT is enabled for servlet '"
219                         + getServletName() + "'.");
220             } else {
221                 localeSupport = getDefaultLocaleSupport();
222 
223                 LOG.info("Use default value (" + localeSupport
224                         + ") for LOCALE_SUPPORT for servlet '"
225                         + getServletName() + "'.");
226             }
227 
228             if (localeSupport) {
229                 String acceptedLocaleNames = getParameter(FILTERED_LOCALES_PARAMETER);
230                 if (acceptedLocaleNames != null
231                         && acceptedLocaleNames.trim().length() > 0) {
232 
233                     StringTokenizer st = new StringTokenizer(
234                             acceptedLocaleNames, ", ");
235                     filtredLocales = new HashSet(st.countTokens());
236 
237                     for (; st.hasMoreTokens();) {
238                         String localeName = st.nextToken();
239 
240                         Locale locale = convertLocaleName(localeName, false);
241                         if (locale == null) {
242                             LOG.error("Rejected locale '" + localeName + "'.");
243                             continue;
244                         }
245 
246                         filtredLocales.add(locale);
247                     }
248 
249                     LOG.info("Accepted locale: " + filtredLocales
250                             + " for servlet '" + getServletName() + "'.");
251                 }
252 
253                 String localeName = getParameter(DEFAULT_LOCALE_PARAMETER);
254                 if (localeName != null) {
255                     defaultLocale = convertLocaleName(localeName, true);
256 
257                     if (defaultLocale != null) {
258                         LOG.info("DEFAULT_LOCALE specify default locale to '"
259                                 + defaultLocale + "'.");
260                     } else {
261                         LOG.info("DEFAULT_LOCALE value '" + localeName
262                                 + "' is not valid !");
263                     }
264                 }
265             }
266         }
267     }
268 
269     protected boolean hasLocaleSupport() {
270         return true;
271     }
272 
273     private long getDefaultVersionedExpirationDelay() {
274         return Constants.DEFAULT_VERSIONED_EXPIRATION_DELAY;
275     }
276 
277     protected boolean getDefaultLocaleSupport() {
278         return Constants.CLIENT_LOCALE_SUPPORT_DEFAULT_VALUE;
279     }
280 
281     protected long getDefaultExpirationDelay() {
282         return Constants.DEFAULT_EXPIRATION_DELAY;
283     }
284 
285     protected boolean getDefaultHashSupport() {
286         return Constants.HASH_SUPPORT;
287     }
288 
289     protected boolean getDefaultETagSupport() {
290         return Constants.ETAG_SUPPORT;
291     }
292 
293     protected boolean getDefaultGZipSupport() {
294         return Constants.GZIP_SUPPORT_DEFAULT_VALUE;
295     }
296 
297     protected ExpirationDate getDefaultExpirationDate(boolean versioned) {
298         if (versioned && versionedExpirationDate != null) {
299             return versionedExpirationDate;
300         }
301 
302         return expirationDate;
303     }
304 
305     protected boolean hasEtagSupport() {
306         return etagSupport;
307     }
308 
309     protected boolean hasHashSupport() {
310         return hashSupport;
311     }
312 
313     protected final boolean hasGZipSupport() {
314         return gZipSupport;
315     }
316 
317     protected final Locale getDefaultLocale(HttpServletRequest request,
318             HttpServletResponse response) {
319         synchronized (this) {
320             if (defaultLocale == null) {
321                 defaultLocale = ServletTools.getDefaultLocale(
322                         getServletContext(), request, response);
323             }
324         }
325 
326         return defaultLocale;
327     }
328 
329     protected final Locale convertLocaleName(String localeName, boolean accept) {
330         localeName = localeName.toLowerCase();
331 
332         Locale locale;
333         synchronized (convertedLocales) {
334             locale = (Locale) convertedLocales.get(localeName);
335         }
336 
337         if (locale != null) {
338             return locale;
339         }
340 
341         // On synchronise pas le bloc, histore de pas bloquer le reste des
342         // Threads ...
343         // Et tanpis pour les put multiple de la meme valeur !
344 
345         StringTokenizer st = new StringTokenizer(localeName, "_");
346         String language = st.nextToken().toLowerCase();
347         String country = (st.hasMoreTokens()) ? st.nextToken().toLowerCase()
348                 : "";
349         String variant = (st.hasMoreTokens()) ? st.nextToken().toLowerCase()
350                 : "";
351 
352         Locale bestLocale = null;
353         int bestHit = 0;
354 
355         Locale locales[] = Locale.getAvailableLocales();
356         for (int i = 0; i < locales.length; i++) {
357             locale = locales[i];
358             if (accept && filtredLocales != null
359                     && filtredLocales.contains(locale) == false) {
360                 continue;
361             }
362 
363             if (locale.getLanguage().equalsIgnoreCase(language) == false) {
364                 continue;
365             }
366             int hit = 1;
367 
368             String lcountry = locale.getCountry();
369             if (lcountry.equalsIgnoreCase(country)) {
370                 hit += 2;
371 
372                 String lvariant = locale.getVariant();
373                 if (lvariant.equalsIgnoreCase(variant)) {
374                     hit += 2;
375 
376                 } else if (lvariant.length() < 1) {
377                     hit++;
378                 }
379 
380             } else if (lcountry.length() < 1) {
381                 hit++;
382             }
383 
384             if (hit < bestHit) {
385                 continue;
386             }
387 
388             bestLocale = locale;
389             bestHit = hit;
390         }
391 
392         if (bestLocale == null) {
393             // On n'enregistre pas la mauvaise reponse !
394             return null;
395         }
396 
397         synchronized (convertedLocales) {
398             convertedLocales.put(localeName, bestLocale);
399 
400             return bestLocale;
401         }
402     }
403 }