001/* 002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Anahide Tchertchian 018 */ 019package org.nuxeo.ecm.webapp.seam.messages; 020 021import static org.jboss.seam.annotations.Install.APPLICATION; 022 023import java.util.AbstractMap; 024import java.util.Collections; 025import java.util.Enumeration; 026import java.util.HashMap; 027import java.util.HashSet; 028import java.util.Map; 029import java.util.MissingResourceException; 030import java.util.ResourceBundle; 031import java.util.Set; 032 033import org.jboss.seam.ScopeType; 034import org.jboss.seam.annotations.Install; 035import org.jboss.seam.annotations.Name; 036import org.jboss.seam.annotations.Scope; 037import org.jboss.seam.annotations.intercept.BypassInterceptors; 038import org.jboss.seam.core.SeamResourceBundle; 039import org.jboss.seam.international.Messages; 040 041/** 042 * Factory for a Map that contains interpolated messages defined in the Seam ResourceBundle. 043 * <p> 044 * Overriden to add a control over reload of bundle for hot reload 045 * 046 * @see org.jboss.seam.core.SeamResourceBundle 047 * @author Gavin King 048 * @since 5.6 049 */ 050@Scope(ScopeType.STATELESS) 051@BypassInterceptors 052@Name("org.jboss.seam.international.messagesFactory") 053// XXX: since debug mode cannot be set by using nuxeo debug/dev mode, make 054// sure this component is deployed even in production => debug = false 055@Install(precedence = APPLICATION, debug = false) 056public class HotReloadMessages extends Messages { 057 058 @Override 059 @SuppressWarnings("rawtypes") 060 // mostly copy/pasted from parent class 061 protected Map createMap() { 062 063 // AbstractMap uses the implementation of entrySet to perform all its 064 // operations - for a resource bundle this is very inefficient for keys 065 return new AbstractMap<String, String>() { 066 067 private ResourceBundle seamResourceBundle = getSeamResourceBundle(); 068 069 /** 070 * Returns usual seam bundle, but with a custom resource control 071 */ 072 protected ResourceBundle getSeamResourceBundle() { 073 ResourceBundle.Control control = HotReloadResourceBundleControl.instance(); 074 return ResourceBundle.getBundle(SeamResourceBundle.class.getName(), 075 org.jboss.seam.core.Locale.instance(), Thread.currentThread().getContextClassLoader(), control); 076 } 077 078 @Override 079 public String get(Object key) { 080 if (key instanceof String) { 081 String resourceKey = (String) key; 082 String resource = null; 083 ResourceBundle bundle = seamResourceBundle; 084 if (bundle != null) { 085 try { 086 resource = bundle.getString(resourceKey); 087 } catch (MissingResourceException mre) { 088 // Just swallow 089 } 090 } 091 return resource == null ? resourceKey : resource; 092 } else { 093 return null; 094 } 095 } 096 097 @Override 098 public Set<Map.Entry<String, String>> entrySet() { 099 ResourceBundle bundle = seamResourceBundle; 100 Enumeration<String> keys = bundle.getKeys(); 101 Map<String, String> map = new HashMap<String, String>(); 102 while (keys.hasMoreElements()) { 103 String key = keys.nextElement(); 104 map.put(key, get(key)); 105 } 106 return Collections.unmodifiableSet(map.entrySet()); 107 } 108 109 @Override 110 public boolean containsKey(Object key) { 111 return get(key) != null; 112 } 113 114 @Override 115 public Set<String> keySet() { 116 ResourceBundle bundle = seamResourceBundle; 117 Enumeration<String> keys = bundle.getKeys(); 118 return new HashSet<String>(Collections.list(keys)); 119 } 120 121 @Override 122 public int size() { 123 return keySet().size(); 124 } 125 126 }; 127 } 128 129}