1
7 package org.hibernate.validator.messageinterpolation;
8
9 import java.lang.invoke.MethodHandles;
10 import java.security.AccessController;
11 import java.security.PrivilegedAction;
12 import java.util.Collections;
13 import java.util.Locale;
14 import java.util.Set;
15
16 import javax.el.ELManager;
17 import javax.el.ExpressionFactory;
18
19 import org.hibernate.validator.Incubating;
20 import org.hibernate.validator.internal.engine.messageinterpolation.DefaultLocaleResolver;
21 import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTerm;
22 import org.hibernate.validator.internal.util.logging.Log;
23 import org.hibernate.validator.internal.util.logging.LoggerFactory;
24 import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader;
25 import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader;
26 import org.hibernate.validator.spi.messageinterpolation.LocaleResolver;
27 import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator;
28
29
39 public class ResourceBundleMessageInterpolator extends AbstractMessageInterpolator {
40
41 private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
42
43 private final ExpressionFactory expressionFactory;
44
45 public ResourceBundleMessageInterpolator() {
46 this( Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false );
47 }
48
49 public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator) {
50 this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false );
51 }
52
53 public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator,
54 ResourceBundleLocator contributorResourceBundleLocator) {
55 this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false );
56 }
57
58 public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator,
59 ResourceBundleLocator contributorResourceBundleLocator,
60 boolean cachingEnabled) {
61 this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(),
62 false, cachingEnabled );
63 }
64
65 public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, boolean cachingEnabled) {
66 this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false, cachingEnabled );
67 }
68
69 public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator,
70 boolean cachingEnabled,
71 ExpressionFactory expressionFactory) {
72 this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false, cachingEnabled );
73 }
74
75
78 @Incubating
79 public ResourceBundleMessageInterpolator(Set<Locale> locales, Locale defaultLocale, LocaleResolver localeResolver, boolean preloadResourceBundles) {
80 super( locales, defaultLocale, localeResolver, preloadResourceBundles );
81 this.expressionFactory = buildExpressionFactory();
82 }
83
84
87 @Incubating
88 public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator,
89 Set<Locale> locales,
90 Locale defaultLocale,
91 LocaleResolver localeResolver,
92 boolean preloadResourceBundles) {
93 super( userResourceBundleLocator, locales, defaultLocale, localeResolver, preloadResourceBundles );
94 this.expressionFactory = buildExpressionFactory();
95 }
96
97
100 @Incubating
101 public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator,
102 ResourceBundleLocator contributorResourceBundleLocator,
103 Set<Locale> locales,
104 Locale defaultLocale,
105 LocaleResolver localeResolver,
106 boolean preloadResourceBundles) {
107 super( userResourceBundleLocator, contributorResourceBundleLocator, locales, defaultLocale, localeResolver, preloadResourceBundles );
108 this.expressionFactory = buildExpressionFactory();
109 }
110
111
114 @Incubating
115 public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator,
116 ResourceBundleLocator contributorResourceBundleLocator,
117 Set<Locale> locales,
118 Locale defaultLocale,
119 LocaleResolver localeResolver,
120 boolean preloadResourceBundles,
121 boolean cachingEnabled) {
122 super( userResourceBundleLocator, contributorResourceBundleLocator, locales, defaultLocale, localeResolver, preloadResourceBundles,
123 cachingEnabled );
124 this.expressionFactory = buildExpressionFactory();
125 }
126
127
130 @Incubating
131 public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator,
132 Set<Locale> locales,
133 Locale defaultLocale,
134 LocaleResolver localeResolver,
135 boolean preloadResourceBundles,
136 boolean cachingEnabled) {
137 super( userResourceBundleLocator, null, locales, defaultLocale, localeResolver, preloadResourceBundles, cachingEnabled );
138 this.expressionFactory = buildExpressionFactory();
139 }
140
141
144 @Incubating
145 public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator,
146 Set<Locale> locales,
147 Locale defaultLocale,
148 LocaleResolver localeResolver,
149 boolean preloadResourceBundles,
150 boolean cachingEnabled,
151 ExpressionFactory expressionFactory) {
152 super( userResourceBundleLocator, null, locales, defaultLocale, localeResolver, preloadResourceBundles, cachingEnabled );
153 this.expressionFactory = expressionFactory;
154 }
155
156 @Override
157 public String interpolate(Context context, Locale locale, String term) {
158 InterpolationTerm expression = new InterpolationTerm( term, locale, expressionFactory );
159 return expression.interpolate( context );
160 }
161
162
168 private static ExpressionFactory buildExpressionFactory() {
169
170 if ( canLoadExpressionFactory() ) {
171 ExpressionFactory expressionFactory = ELManager.getExpressionFactory();
172 LOG.debug( "Loaded expression factory via original TCCL" );
173 return expressionFactory;
174 }
175
176 final ClassLoader originalContextClassLoader = run( GetClassLoader.fromContext() );
177
178 try {
179
180
181 run( SetContextClassLoader.action( ResourceBundleMessageInterpolator.class.getClassLoader() ) );
182
183 if ( canLoadExpressionFactory() ) {
184 ExpressionFactory expressionFactory = ELManager.getExpressionFactory();
185 LOG.debug( "Loaded expression factory via HV classloader" );
186 return expressionFactory;
187 }
188
189
190
191 run( SetContextClassLoader.action( ELManager.class.getClassLoader() ) );
192 if ( canLoadExpressionFactory() ) {
193 ExpressionFactory expressionFactory = ELManager.getExpressionFactory();
194 LOG.debug( "Loaded expression factory via EL classloader" );
195 return expressionFactory;
196 }
197 }
198 catch (Throwable e) {
199 throw LOG.getUnableToInitializeELExpressionFactoryException( e );
200 }
201 finally {
202 run( SetContextClassLoader.action( originalContextClassLoader ) );
203 }
204
205
206 throw LOG.getUnableToInitializeELExpressionFactoryException( null );
207 }
208
209
214 private static boolean canLoadExpressionFactory() {
215 try {
216 ExpressionFactory.newInstance();
217 return true;
218 }
219 catch (Throwable e) {
220 LOG.debugv( e, "Failed to load expression factory via classloader {0}",
221 run( GetClassLoader.fromContext() ) );
222 return false;
223 }
224 }
225
226
232 private static <T> T run(PrivilegedAction<T> action) {
233 return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run();
234 }
235 }
236