001/* 002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Anahide Tchertchian 016 */ 017package org.nuxeo.ecm.webapp.seam.messages; 018 019import static org.jboss.seam.annotations.Install.APPLICATION; 020 021import java.util.AbstractMap; 022import java.util.Collections; 023import java.util.Enumeration; 024import java.util.HashMap; 025import java.util.HashSet; 026import java.util.Map; 027import java.util.MissingResourceException; 028import java.util.ResourceBundle; 029import java.util.Set; 030 031import org.jboss.seam.ScopeType; 032import org.jboss.seam.annotations.Install; 033import org.jboss.seam.annotations.Name; 034import org.jboss.seam.annotations.Scope; 035import org.jboss.seam.annotations.intercept.BypassInterceptors; 036import org.jboss.seam.core.SeamResourceBundle; 037import org.jboss.seam.international.Messages; 038 039/** 040 * Factory for a Map that contains interpolated messages defined in the Seam ResourceBundle. 041 * <p> 042 * Overriden to add a control over reload of bundle for hot reload 043 * 044 * @see org.jboss.seam.core.SeamResourceBundle 045 * @author Gavin King 046 * @since 5.6 047 */ 048@Scope(ScopeType.STATELESS) 049@BypassInterceptors 050@Name("org.jboss.seam.international.messagesFactory") 051// XXX: since debug mode cannot be set by using nuxeo debug/dev mode, make 052// sure this component is deployed even in production => debug = false 053@Install(precedence = APPLICATION, debug = false) 054public class HotReloadMessages extends Messages { 055 056 @Override 057 @SuppressWarnings("rawtypes") 058 // mostly copy/pasted from parent class 059 protected Map createMap() { 060 061 // AbstractMap uses the implementation of entrySet to perform all its 062 // operations - for a resource bundle this is very inefficient for keys 063 return new AbstractMap<String, String>() { 064 065 private ResourceBundle seamResourceBundle = getSeamResourceBundle(); 066 067 /** 068 * Returns usual seam bundle, but with a custom resource control 069 */ 070 protected ResourceBundle getSeamResourceBundle() { 071 ResourceBundle.Control control = HotReloadResourceBundleControl.instance(); 072 return ResourceBundle.getBundle(SeamResourceBundle.class.getName(), 073 org.jboss.seam.core.Locale.instance(), Thread.currentThread().getContextClassLoader(), control); 074 } 075 076 @Override 077 public String get(Object key) { 078 if (key instanceof String) { 079 String resourceKey = (String) key; 080 String resource = null; 081 ResourceBundle bundle = seamResourceBundle; 082 if (bundle != null) { 083 try { 084 resource = bundle.getString(resourceKey); 085 } catch (MissingResourceException mre) { 086 // Just swallow 087 } 088 } 089 return resource == null ? resourceKey : resource; 090 } else { 091 return null; 092 } 093 } 094 095 @Override 096 public Set<Map.Entry<String, String>> entrySet() { 097 ResourceBundle bundle = seamResourceBundle; 098 Enumeration<String> keys = bundle.getKeys(); 099 Map<String, String> map = new HashMap<String, String>(); 100 while (keys.hasMoreElements()) { 101 String key = keys.nextElement(); 102 map.put(key, get(key)); 103 } 104 return Collections.unmodifiableSet(map.entrySet()); 105 } 106 107 @Override 108 public boolean containsKey(Object key) { 109 return get(key) != null; 110 } 111 112 @Override 113 public Set<String> keySet() { 114 ResourceBundle bundle = seamResourceBundle; 115 Enumeration<String> keys = bundle.getKeys(); 116 return new HashSet<String>(Collections.list(keys)); 117 } 118 119 @Override 120 public int size() { 121 return keySet().size(); 122 } 123 124 }; 125 } 126 127}