| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.util.containers.ConcurrentSoftValueHashMap; |
| import com.intellij.util.containers.ConcurrentWeakFactoryMap; |
| import com.intellij.util.containers.FactoryMap; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.lang.ref.Reference; |
| import java.lang.ref.SoftReference; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.MissingResourceException; |
| import java.util.ResourceBundle; |
| |
| /** |
| * Base class for particular scoped bundles (e.g. <code>'vcs'</code> bundles, <code>'aop'</code> bundles etc). |
| * <p/> |
| * Usage pattern: |
| * <pre> |
| * <ol> |
| * <li>Create class that extends this class and provides path to the target bundle to the current class constructor;</li> |
| * <li> |
| * Optionally create static facade method at the subclass - create single shared instance and delegate |
| * to its {@link #getMessage(String, Object...)}; |
| * </li> |
| * </ol> |
| * </pre> |
| * |
| * @author Denis Zhdanov |
| * @since 8/1/11 2:37 PM |
| */ |
| public abstract class AbstractBundle { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.AbstractBundle"); |
| private Reference<ResourceBundle> myBundle; |
| @NonNls private final String myPathToBundle; |
| |
| protected AbstractBundle(@NonNls @NotNull String pathToBundle) { |
| myPathToBundle = pathToBundle; |
| } |
| |
| public String getMessage(@NotNull String key, @NotNull Object... params) { |
| return CommonBundle.message(getBundle(), key, params); |
| } |
| |
| private ResourceBundle getBundle() { |
| ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(myBundle); |
| if (bundle == null) { |
| bundle = getResourceBundle(myPathToBundle, getClass().getClassLoader()); |
| myBundle = new SoftReference<ResourceBundle>(bundle); |
| } |
| return bundle; |
| } |
| |
| @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") |
| private static final FactoryMap<ClassLoader, Map<String, ResourceBundle>> ourCache = |
| new ConcurrentWeakFactoryMap<ClassLoader, Map<String, ResourceBundle>>() { |
| @Override |
| protected Map<String, ResourceBundle> create(ClassLoader key) { |
| return new ConcurrentSoftValueHashMap<String, ResourceBundle>(); |
| } |
| }; |
| |
| public static ResourceBundle getResourceBundle(@NotNull String pathToBundle, @NotNull ClassLoader loader) { |
| Map<String, ResourceBundle> map = ourCache.get(loader); |
| ResourceBundle result = map.get(pathToBundle); |
| if (result == null) { |
| try { |
| ResourceBundle.Control control = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_PROPERTIES); |
| result = ResourceBundle.getBundle(pathToBundle, Locale.getDefault(), loader, control); |
| } |
| catch (MissingResourceException e) { |
| LOG.info("Cannot load resource bundle from *.properties file, falling back to slow class loading: " + pathToBundle); |
| ResourceBundle.clearCache(loader); |
| result = ResourceBundle.getBundle(pathToBundle, Locale.getDefault(), loader); |
| } |
| map.put(pathToBundle, result); |
| } |
| return result; |
| } |
| } |