public ResourceBundle getResourceBundle(Locale locale) { List<ResourceBundle> sourceBundles = new ArrayList<ResourceBundle>(); for (String oneBundleName : bundleNames) { ResourceBundleLocator oneLocator = new PlatformResourceBundleLocator(oneBundleName); ResourceBundle oneBundle = oneLocator.getResourceBundle(locale); if (oneBundle != null) { sourceBundles.add(oneBundle); } } ResourceBundle bundleFromDelegate = super.getResourceBundle(locale); if (bundleFromDelegate != null) { sourceBundles.add(bundleFromDelegate); } return sourceBundles.isEmpty() ? null : new AggregateBundle(sourceBundles); }
/** * Runs the message interpolation according to algorithm specified in the Bean Validation * specification. <br> * Note: <br> * Look-ups in user bundles is recursive whereas look-ups in default bundle are not! * * @param message the message to interpolate * @param context the context for this interpolation * @param locale the {@code Locale} to use for the resource bundle. * @return the interpolated message. */ private String interpolateMessage(String message, Context context, Locale locale) throws MessageDescriptorFormatException { LocalizedMessage localisedMessage = new LocalizedMessage(message, locale); String resolvedMessage = null; if (cachingEnabled) { resolvedMessage = resolvedMessages.get(localisedMessage); } // if the message is not already in the cache we have to run step 1-3 of the message resolution if (resolvedMessage == null) { ResourceBundle userResourceBundle = userResourceBundleLocator.getResourceBundle(locale); ResourceBundle defaultResourceBundle = defaultResourceBundleLocator.getResourceBundle(locale); String userBundleResolvedMessage; resolvedMessage = message; boolean evaluatedDefaultBundleOnce = false; do { // search the user bundle recursive (step1) userBundleResolvedMessage = interpolateBundleMessage(resolvedMessage, userResourceBundle, locale, true); // exit condition - we have at least tried to validate against the default bundle and there // was no // further replacements if (evaluatedDefaultBundleOnce && !hasReplacementTakenPlace(userBundleResolvedMessage, resolvedMessage)) { break; } // search the default bundle non recursive (step2) resolvedMessage = interpolateBundleMessage( userBundleResolvedMessage, defaultResourceBundle, locale, false); evaluatedDefaultBundleOnce = true; } while (true); } // cache resolved message if (cachingEnabled) { String cachedResolvedMessage = resolvedMessages.putIfAbsent(localisedMessage, resolvedMessage); if (cachedResolvedMessage != null) { resolvedMessage = cachedResolvedMessage; } } // resolve parameter expressions (step 4) List<Token> tokens = null; if (cachingEnabled) { tokens = tokenizedParameterMessages.get(resolvedMessage); } if (tokens == null) { TokenCollector tokenCollector = new TokenCollector(resolvedMessage, InterpolationTermType.PARAMETER); tokens = tokenCollector.getTokenList(); if (cachingEnabled) { tokenizedParameterMessages.putIfAbsent(resolvedMessage, tokens); } } resolvedMessage = interpolateExpression(new TokenIterator(tokens), context, locale); // resolve EL expressions (step 5) tokens = null; if (cachingEnabled) { tokens = tokenizedELMessages.get(resolvedMessage); } if (tokens == null) { TokenCollector tokenCollector = new TokenCollector(resolvedMessage, InterpolationTermType.EL); tokens = tokenCollector.getTokenList(); if (cachingEnabled) { tokenizedELMessages.putIfAbsent(resolvedMessage, tokens); } } resolvedMessage = interpolateExpression(new TokenIterator(tokens), context, locale); // last but not least we have to take care of escaped literals resolvedMessage = replaceEscapedLiterals(resolvedMessage); return resolvedMessage; }