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}