org.mvel2.ParserConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of virtdata-lib-realer Show documentation
Show all versions of virtdata-lib-realer Show documentation
With inspiration from other libraries
/**
* MVEL 2.0
* Copyright (C) 2007 The Codehaus
* Mike Brock, Dhanji Prasanna, John Graham, Mark Proctor
*
* 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 org.mvel2;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.mvel2.ast.Proto;
import org.mvel2.compiler.AbstractParser;
import org.mvel2.integration.Interceptor;
import org.mvel2.util.MethodStub;
import static org.mvel2.util.ParseTools.forNameWithInner;
/**
* The resusable parser configuration object.
*/
public class ParserConfiguration implements Serializable {
protected final Map imports = new ConcurrentHashMap();
protected HashSet packageImports;
protected Map interceptors;
protected transient ClassLoader classLoader;
private final transient Set nonValidImports = Collections.newSetFromMap( new ConcurrentHashMap() );
private boolean allowNakedMethCall = MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL;
private boolean allowBootstrapBypass = true;
public ParserConfiguration() {
}
public ParserConfiguration(Map imports, Map interceptors) {
addAllImports(imports);
this.interceptors = interceptors;
}
public ParserConfiguration(Map imports, HashSet packageImports,
Map interceptors) {
addAllImports(imports);
this.packageImports = packageImports;
this.interceptors = interceptors;
}
public HashSet getPackageImports() {
return packageImports;
}
public void setPackageImports(HashSet packageImports) {
this.packageImports = packageImports;
}
public Class getImport(String name) {
if (imports.containsKey(name) && imports.get(name) instanceof Class) {
return (Class) imports.get(name);
}
return (Class) (AbstractParser.LITERALS.get(name) instanceof Class ? AbstractParser.LITERALS.get(name) : null);
}
public MethodStub getStaticImport(String name) {
return (MethodStub) imports.get(name);
}
public Object getStaticOrClassImport(String name) {
return imports.containsKey(name) ? imports.get(name) : AbstractParser.LITERALS.get(name);
}
public void addPackageImport(String packageName) {
if (packageImports == null) packageImports = new LinkedHashSet();
packageImports.add(packageName);
if (!addClassMemberStaticImports(packageName)) packageImports.add(packageName);
}
private boolean addClassMemberStaticImports(String packageName) {
try {
Class c = Class.forName(packageName);
if (c.isEnum()) {
//noinspection unchecked
for (Enum e : (EnumSet>) EnumSet.allOf(c)) {
imports.put(e.name(), e);
}
return true;
}
else {
for (Field f : c.getDeclaredFields()) {
if ((f.getModifiers() & (Modifier.STATIC | Modifier.PUBLIC)) == (Modifier.STATIC | Modifier.PUBLIC)) {
imports.put(f.getName(), f.get(null));
}
}
}
}
catch (ClassNotFoundException e) {
// do nothing.
}
catch (IllegalAccessException e) {
throw new RuntimeException("error adding static imports for: " + packageName, e);
}
return false;
}
public void addAllImports(Map imports) {
if (imports == null) return;
Object o;
for (Map.Entry entry : imports.entrySet()) {
if ((o = entry.getValue()) instanceof Method) {
this.imports.put(entry.getKey(), new MethodStub((Method) o));
}
else {
this.imports.put(entry.getKey(), o);
}
}
}
private boolean checkForDynamicImport(String className) {
if (packageImports == null) return false;
if (!Character.isJavaIdentifierStart(className.charAt(0))) return false;
if (nonValidImports.contains(className)) return false;
int found = 0;
Class cls = null;
for (String pkg : packageImports) {
try {
cls = forNameWithInner( pkg + "." + className, getClassLoader() );
found++;
}
catch (Throwable cnfe) {
// do nothing.
}
}
if (found > 1) throw new RuntimeException("ambiguous class name: " + className);
if (found == 1) {
addImport(className, cls);
return true;
}
cacheNegativeHitForDynamicImport(className);
return false;
}
public boolean hasImport(String name) {
return (imports.containsKey(name)) ||
AbstractParser.CLASS_LITERALS.containsKey(name) ||
checkForDynamicImport(name);
}
public void addImport(Class cls) {
addImport(cls.getSimpleName(), cls);
}
public void addImport(String name, Class cls) {
this.imports.put(name, cls);
}
public void addImport(String name, Proto proto) {
this.imports.put(name, proto);
}
public void addImport(String name, Method method) {
addImport(name, new MethodStub(method));
}
public void addImport(String name, MethodStub method) {
this.imports.put(name, method);
}
public Map getInterceptors() {
return interceptors;
}
public void setInterceptors(Map interceptors) {
this.interceptors = interceptors;
}
public Map getImports() {
return imports;
}
public void setImports(Map imports) {
if (imports == null) return;
Object val;
for (Map.Entry entry : imports.entrySet()) {
if ((val = entry.getValue()) instanceof Class) {
addImport(entry.getKey(), (Class) val);
}
else if (val instanceof Method) {
addImport(entry.getKey(), (Method) val);
}
else if (val instanceof MethodStub) {
addImport(entry.getKey(), (MethodStub) val);
}
else if (val instanceof Proto) {
addImport(entry.getKey(), (Proto) entry.getValue());
}
else {
throw new RuntimeException("invalid element in imports map: " + entry.getKey() + " (" + val + ")");
}
}
}
public boolean hasImports() {
return !imports.isEmpty() || (packageImports != null && packageImports.size() != 0);
}
public ClassLoader getClassLoader() {
return classLoader == null ? classLoader = Thread.currentThread().getContextClassLoader() : classLoader;
}
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
public void setAllImports(Map imports) {
this.imports.clear();
if (imports != null) this.imports.putAll(imports);
}
public void setImports(HashMap imports) {
// TODO: this method is here for backward compatibility. Could it be removed/deprecated?
setAllImports(imports);
}
private void cacheNegativeHitForDynamicImport(String negativeHit) {
nonValidImports.add(negativeHit);
}
public void flushCaches() {
nonValidImports.clear();
}
public boolean isAllowNakedMethCall() {
return allowNakedMethCall;
}
public void setAllowNakedMethCall(boolean allowNakedMethCall) {
this.allowNakedMethCall = allowNakedMethCall;
}
public boolean isAllowBootstrapBypass() {
return allowBootstrapBypass;
}
public void setAllowBootstrapBypass(boolean allowBootstrapBypass) {
this.allowBootstrapBypass = allowBootstrapBypass;
}
}