View | Details | Raw Unified | Return to bug 52998
Collapse All | Expand All

(-)java/javax/el/ExpressionFactory.java (-14 / +129 lines)
Lines 25-35 Link Here
25
import java.io.InputStream;
25
import java.io.InputStream;
26
import java.io.InputStreamReader;
26
import java.io.InputStreamReader;
27
import java.io.UnsupportedEncodingException;
27
import java.io.UnsupportedEncodingException;
28
import java.lang.ref.WeakReference;
28
import java.lang.reflect.Constructor;
29
import java.lang.reflect.Constructor;
29
import java.lang.reflect.InvocationTargetException;
30
import java.lang.reflect.InvocationTargetException;
30
import java.security.AccessController;
31
import java.security.AccessController;
31
import java.security.PrivilegedAction;
32
import java.security.PrivilegedAction;
32
import java.util.Properties;
33
import java.util.Properties;
34
import java.util.concurrent.ConcurrentHashMap;
35
import java.util.concurrent.ConcurrentMap;
36
import java.util.concurrent.locks.Lock;
37
import java.util.concurrent.locks.ReadWriteLock;
38
import java.util.concurrent.locks.ReentrantReadWriteLock;
33
39
34
/**
40
/**
35
 *
41
 *
Lines 48-53 Link Here
48
    private static final String SEP;
54
    private static final String SEP;
49
    private static final String PROPERTY_FILE;
55
    private static final String PROPERTY_FILE;
50
56
57
    private static final CacheValue nullTcclFactory = new CacheValue();
58
    private static ConcurrentMap<CacheKey, CacheValue> factoryCache
59
        = new ConcurrentHashMap<CacheKey, CacheValue>();
60
51
    static {
61
    static {
52
        if (IS_SECURITY_ENABLED) {
62
        if (IS_SECURITY_ENABLED) {
53
            SEP = AccessController.doPrivileged(
63
            SEP = AccessController.doPrivileged(
Lines 118-132 Link Here
118
        ExpressionFactory result = null;
128
        ExpressionFactory result = null;
119
129
120
        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
130
        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
121
        String className = discoverClassName(tccl);
122
131
132
        CacheValue cacheValue;
133
        Class<?> clazz;
134
135
        if (tccl == null) {
136
            cacheValue = nullTcclFactory;
137
        } else {
138
            CacheKey key = new CacheKey(tccl);
139
            cacheValue = factoryCache.get(key);
140
            if (cacheValue == null) {
141
                CacheValue newCacheValue = new CacheValue();
142
                cacheValue = factoryCache.putIfAbsent(key, newCacheValue);
143
                if (cacheValue == null) {
144
                    cacheValue = newCacheValue;
145
                }
146
            }
147
        }
148
149
        final Lock readLock = cacheValue.getLock().readLock();
150
        readLock.lock();
123
        try {
151
        try {
124
            Class<?> clazz = null;
152
            clazz = cacheValue.getFactoryClass();
125
            if (tccl == null) {
153
        } finally {
126
                clazz = Class.forName(className);
154
            readLock.unlock();
127
            } else {
155
        }
128
                clazz = tccl.loadClass(className);
156
157
        if (clazz == null) {
158
            String className = null;
159
            try {
160
                final Lock writeLock = cacheValue.getLock().writeLock();
161
                writeLock.lock();
162
                try {
163
                    className = cacheValue.getFactoryClassName();
164
                    if (className == null) {
165
                        className = discoverClassName(tccl);
166
                        cacheValue.setFactoryClassName(className);
167
                    }
168
                    if (tccl == null) {
169
                        clazz = Class.forName(className);
170
                    } else {
171
                        clazz = tccl.loadClass(className);
172
                    }
173
                    cacheValue.setFactoryClass(clazz);
174
                } finally {
175
                    writeLock.unlock();
176
                }
177
            } catch (ClassNotFoundException e) {
178
                throw new ELException(
179
                    "Unable to find ExpressionFactory of type: " + className,
180
                    e);
129
            }
181
            }
182
        }
183
184
        try {
130
            Constructor<?> constructor = null;
185
            Constructor<?> constructor = null;
131
            // Do we need to look for a constructor that will take properties?
186
            // Do we need to look for a constructor that will take properties?
132
            if (properties != null) {
187
            if (properties != null) {
Lines 146-166 Link Here
146
                    (ExpressionFactory) constructor.newInstance(properties);
201
                    (ExpressionFactory) constructor.newInstance(properties);
147
            }
202
            }
148
203
149
        } catch (ClassNotFoundException e) {
150
            throw new ELException(
151
                    "Unable to find ExpressionFactory of type: " + className,
152
                    e);
153
        } catch (InstantiationException e) {
204
        } catch (InstantiationException e) {
154
            throw new ELException(
205
            throw new ELException(
155
                    "Unable to create ExpressionFactory of type: " + className,
206
                    "Unable to create ExpressionFactory of type: " + clazz.getName(),
156
                    e);
207
                    e);
157
        } catch (IllegalAccessException e) {
208
        } catch (IllegalAccessException e) {
158
            throw new ELException(
209
            throw new ELException(
159
                    "Unable to create ExpressionFactory of type: " + className,
210
                    "Unable to create ExpressionFactory of type: " + clazz.getName(),
160
                    e);
211
                    e);
161
        } catch (IllegalArgumentException e) {
212
        } catch (IllegalArgumentException e) {
162
            throw new ELException(
213
            throw new ELException(
163
                    "Unable to create ExpressionFactory of type: " + className,
214
                    "Unable to create ExpressionFactory of type: " + clazz.getName(),
164
                    e);
215
                    e);
165
        } catch (InvocationTargetException e) {
216
        } catch (InvocationTargetException e) {
166
            Throwable cause = e.getCause();
217
            Throwable cause = e.getCause();
Lines 171-177 Link Here
171
                throw (VirtualMachineError) cause;
222
                throw (VirtualMachineError) cause;
172
            }
223
            }
173
            throw new ELException(
224
            throw new ELException(
174
                    "Unable to create ExpressionFactory of type: " + className,
225
                    "Unable to create ExpressionFactory of type: " + clazz.getName(),
175
                    e);
226
                    e);
176
        }
227
        }
177
228
Lines 179-184 Link Here
179
    }
230
    }
180
231
181
    /**
232
    /**
233
     * Key used to cache ExpressionFactory discovery information per class
234
     * loader. The class loader reference is never {@code null}, because
235
     * {@code null} tccl is handled separately.
236
     */
237
    private static class CacheKey {
238
        private final int hash;
239
        private final WeakReference<ClassLoader> ref;
240
241
        public CacheKey(ClassLoader cl) {
242
            hash = cl.hashCode();
243
            ref = new WeakReference<ClassLoader>(cl);
244
        }
245
246
        @Override
247
        public int hashCode() {
248
            return hash;
249
        }
250
251
        @Override
252
        public boolean equals(Object obj) {
253
            if (obj == this) {
254
                return true;
255
            }
256
            if (!(obj instanceof CacheKey)) {
257
                return false;
258
            }
259
            ClassLoader thisCl = ref.get();
260
            if (thisCl == null) {
261
                return false;
262
            }
263
            return thisCl == ((CacheKey) obj).ref.get();
264
        }
265
    }
266
267
    private static class CacheValue {
268
        private final ReadWriteLock lock = new ReentrantReadWriteLock();
269
        private String className;
270
        private WeakReference<Class<?>> ref;
271
272
        public CacheValue() {
273
        }
274
275
        public ReadWriteLock getLock() {
276
            return lock;
277
        }
278
279
        public String getFactoryClassName() {
280
            return className;
281
        }
282
283
        public void setFactoryClassName(String className) {
284
            this.className = className;
285
        }
286
287
        public Class<?> getFactoryClass() {
288
            return ref != null ? ref.get() : null;
289
        }
290
291
        public void setFactoryClass(Class<?> clazz) {
292
            ref = new WeakReference<Class<?>>(clazz);
293
        }
294
    }
295
296
    /**
182
     * Discover the name of class that implements ExpressionFactory.
297
     * Discover the name of class that implements ExpressionFactory.
183
     *
298
     *
184
     * @param tccl
299
     * @param tccl

Return to bug 52998