blob: 7f4a2401e13f59732e27d534e27f3df5efe91cbb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 javax.el;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Properties;
/**
*
* @since 2.1
*/
public abstract class ExpressionFactory {
private static final boolean IS_SECURITY_ENABLED =
(System.getSecurityManager() != null);
private static final String SERVICE_RESOURCE_NAME =
"META-INF/services/javax.el.ExpressionFactory";
private static final String PROPERTY_NAME = "javax.el.ExpressionFactory";
private static final String SEP;
private static final String PROPERTY_FILE;
static {
if (IS_SECURITY_ENABLED) {
SEP = AccessController.doPrivileged(
new PrivilegedAction<String>(){
@Override
public String run() {
return System.getProperty("file.separator");
}
}
);
PROPERTY_FILE = AccessController.doPrivileged(
new PrivilegedAction<String>(){
@Override
public String run() {
return System.getProperty("java.home") + SEP +
"lib" + SEP + "el.properties";
}
}
);
} else {
SEP = System.getProperty("file.separator");
PROPERTY_FILE = System.getProperty("java.home") + SEP + "lib" +
SEP + "el.properties";
}
}
public abstract Object coerceToType(Object obj, Class<?> expectedType)
throws ELException;
public abstract ValueExpression createValueExpression(ELContext context,
String expression, Class<?> expectedType)
throws NullPointerException, ELException;
public abstract ValueExpression createValueExpression(Object instance,
Class<?> expectedType);
public abstract MethodExpression createMethodExpression(ELContext context,
String expression, Class<?> expectedReturnType,
Class<?>[] expectedParamTypes) throws ELException,
NullPointerException;
/**
* Create a new {@link ExpressionFactory}. The class to use is determined by
* the following search order:
* <ol>
* <li>services API (META-INF/services/javax.el.ExpressionFactory)</li>
* <li>$JRE_HOME/lib/el.properties - key javax.el.ExpressionFactory</li>
* <li>javax.el.ExpressionFactory</li>
* <li>Platform default implementation -
* org.apache.el.ExpressionFactoryImpl</li>
* </ol>
* @return the new ExpressionFactory
*/
public static ExpressionFactory newInstance() {
return newInstance(null);
}
/**
* Create a new {@link ExpressionFactory} passing in the provided
* {@link Properties}. Search order is the same as {@link #newInstance()}.
*
* @param properties the properties to be passed to the new instance (may be null)
* @return the new ExpressionFactory
*/
public static ExpressionFactory newInstance(Properties properties) {
String className = null;
ExpressionFactory result = null;
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
// First services API
className = getClassNameServices(tccl);
if (className == null) {
if (IS_SECURITY_ENABLED) {
className = AccessController.doPrivileged(
new PrivilegedAction<String>() {
@Override
public String run() {
return getClassNameJreDir();
}
}
);
} else {
// Second el.properties file
className = getClassNameJreDir();
}
}
if (className == null) {
if (IS_SECURITY_ENABLED) {
className = AccessController.doPrivileged(
new PrivilegedAction<String>() {
@Override
public String run() {
return getClassNameSysProp();
}
}
);
} else {
// Third system property
className = getClassNameSysProp();
}
}
if (className == null) {
// Fourth - default
className = "org.apache.el.ExpressionFactoryImpl";
}
try {
Class<?> clazz = null;
if (tccl == null) {
clazz = Class.forName(className);
} else {
clazz = tccl.loadClass(className);
}
Constructor<?> constructor = null;
// Do we need to look for a constructor that will take properties?
if (properties != null) {
try {
constructor = clazz.getConstructor(Properties.class);
} catch (SecurityException se) {
throw new ELException(se);
} catch (NoSuchMethodException nsme) {
// This can be ignored
// This is OK for this constructor not to exist
}
}
if (constructor == null) {
result = (ExpressionFactory) clazz.newInstance();
} else {
result =
(ExpressionFactory) constructor.newInstance(properties);
}
} catch (ClassNotFoundException e) {
throw new ELException(
"Unable to find ExpressionFactory of type: " + className,
e);
} catch (InstantiationException e) {
throw new ELException(
"Unable to create ExpressionFactory of type: " + className,
e);
} catch (IllegalAccessException e) {
throw new ELException(
"Unable to create ExpressionFactory of type: " + className,
e);
} catch (IllegalArgumentException e) {
throw new ELException(
"Unable to create ExpressionFactory of type: " + className,
e);
} catch (InvocationTargetException e) {
throw new ELException(
"Unable to create ExpressionFactory of type: " + className,
e);
}
return result;
}
private static String getClassNameServices(ClassLoader tccl) {
InputStream is = null;
if (tccl == null) {
is = ClassLoader.getSystemResourceAsStream(SERVICE_RESOURCE_NAME);
} else {
is = tccl.getResourceAsStream(SERVICE_RESOURCE_NAME);
}
if (is != null) {
String line = null;
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
line = br.readLine();
if (line != null && line.trim().length() > 0) {
return line.trim();
}
} catch (UnsupportedEncodingException e) {
// Should never happen with UTF-8
// If it does - ignore & return null
} catch (IOException e) {
throw new ELException("Failed to read " + SERVICE_RESOURCE_NAME,
e);
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException ioe) {/*Ignore*/}
try {
is.close();
} catch (IOException ioe) {/*Ignore*/}
}
}
return null;
}
private static String getClassNameJreDir() {
File file = new File(PROPERTY_FILE);
if (file.canRead()) {
InputStream is = null;
try {
is = new FileInputStream(file);
Properties props = new Properties();
props.load(is);
String value = props.getProperty(PROPERTY_NAME);
if (value != null && value.trim().length() > 0) {
return value.trim();
}
} catch (FileNotFoundException e) {
// Should not happen - ignore it if it does
} catch (IOException e) {
throw new ELException("Failed to read " + PROPERTY_FILE, e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// Ignore
}
}
}
}
return null;
}
private static final String getClassNameSysProp() {
String value = System.getProperty(PROPERTY_NAME);
if (value != null && value.trim().length() > 0) {
return value.trim();
}
return null;
}
}